I get Unknown error communicating with server when trying to log in from the ViewModel, using a coroutine.
A brief description of the scenario:
- ParticleCloudSDK.init(this) is called in the MainActivity
- AndroidManifest has:
- <uses-permission android:name="android.permission.INTERNET"
- android:usesCleartextTraffic=“true”
- minSdkVersion = 23
- Dependencies: implementation 'io.particle:cloudsdk:1.0.1'
From the ViewModel I try to log in like this:
fun onLoginRequest(){
viewModelScope.launch {
try {
ParticleCloudSDK.getCloud().logIn(“xxxxxxx@gmail.com”, “thePassword”)
_sLoginResult.value = “Logged in!”
}
catch (e: ParticleCloudException) {
_sLoginResult.value = e.bestMessage
}
}
}
I consistently get Unknown error communicating with server, whether using an emulator or a real phone. Logcat shows the following:
2022-06-15 06:52:14.315 485-485/? E/netmgr: qemu_pipe_open_ns:62: Could not connect to the ‘pipe:qemud:network’ service: Invalid argument
2022-06-15 06:52:14.315 485-485/? E/netmgr: Failed to open QEMU pipe ‘qemud:network’: Invalid argument
2022-06-15 06:52:16.715 493-493/? E/wifi_forwarder: qemu_pipe_open_ns:62: Could not connect to the ‘pipe:qemud:wififorward’ service: Invalid argument
2022-06-15 06:52:16.715 493-493/? E/wifi_forwarder: RemoteConnection failed to initialize: RemoteConnection failed to open pipe
I thought I had covered all bases based on what the forums recommend, but just cannot get this working. Can someone please help - schedule is suffering…
Is onLoginRequest called in response to a UI element?
The Cloud SDK calls, including logIn are blocking, so you can’t make them from the UI thread. You instead need make them async first.
Thanks for the response @rickkas7. Indeed, onLoginRequest is called in response to a button click, but a Kotlin coroutine is launched to call ParticleCloudSDK.getCloud().logIn within the braces of viewModelScope.launch{}.
Is this not achieving what you call making the call async ?
You know, I can kick myself sometimes (if I had enough dexterity). I solved the issue, thanks again @rickkas7 for your answer. The solution code:
fun onLoginRequest(){
_sLoginResult.value = "Logging in..."
viewModelScope.launch {
try {
doLogIn()
_sLoginResult.value = "Logged in!"
} catch (e: ParticleCloudException) {
_sLoginResult.value = e.bestMessage
}
}
}
fun doLogIn() = viewModelScope.async{
ParticleCloudSDK.getCloud().logIn("myEmailAddress@gmail.com", "myPassword")
}
1 Like
I’m sorry @rickkas7, it looks like I was fooling myself. When I do this I still get the same Unknown error communicating with server exception:
fun onLoginRequest(){
_sLoginResult.value = "Logging in..."
viewModelScope.launch {
doLogin()
}
}
fun doLogin() = viewModelScope.async{
try {
ParticleCloudSDK.getCloud().logIn("myEmailAddress@gmail.com", "myPassword")
_sLoginResult.value = "Logged in!"
} catch (e: ParticleCloudException) {
_sLoginResult.value = e.bestMessage
}
}
Interestingly, working from the MainActivity’s OnCreate, does work. Just not from the viewModel. Boggles my mind, any ideas ? The code is below:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val binding: PlainActivityBinding =
DataBindingUtil.setContentView(this, R.layout.plain_activity)
binding.lifecycleOwner = this // use Fragment.viewLifecycleOwner for fragments
binding.viewmodel = viewModel
ParticleCloudSDK.init(this)
GlobalScope.launch(){
try {
ParticleCloudSDK.getCloud().logIn("email@gmail.com", "password")
println("Logged in")
}
catch(e: ParticleCloudException){
println(e.bestMessage)
}
}
GlobalScope.launch(){
try {
val devices = ParticleCloudSDK.getCloud().getDevices()
for (device in devices) {
println("${device.name} \n")
}
}
catch(e: ParticleCloudException){
println(e.bestMessage)
}
}
}