I was having a problem implementing the Firebase anonymous sign-in function with Kotlin coroutine.
Following is the code for that:
Repository.kt
suspend fun getUserId(){
firebaseHelper.getUserId().collect{
if (it == "Successful"){
emit(it)
} else {
emit("Task unsuccessful")
}
}
}
FirebaseHelper.kt
fun getUserId() = flow {
val firebaseLoginAsync = Firebase.auth.signInAnonymously().await()
if (firebaseLoginAsync.user != null && !firebaseLoginAsync.user?.uid.isNullOrEmpty()) {
emit("Successful")
} else {
emit("Failed")
}
}
It works fine when the android device is connected to the internet.
But when I test this code without the internet it never completes, that is, the execution never reaches the if else
block of FirebaseHelper.kt
.
I was unable to find any resource that would help me understand the cause of this problem and any possible solution.
One idea that I can think of on the solution side is to forcefully cancel the await()
functions execution after some time but I can't find anything related to implementation.
CodePudding user response:
It works fine when the android device is connected to the internet.
Since an authentication operation requires an internet connection, then that's the expected behavior.
But when I test this code without the internet it never completes.
Without the internet, there is no way you can reach Firebase servers, hence that behavior. However, according to the official documentation of await() function:
This suspending function is cancellable. If the Job of the current coroutine is canceled or completed while this suspending function is waiting, this function immediately resumes with CancellationException.
Or you can simply check if the user is connected to the internet before performing the authentication.
CodePudding user response:
The way that I made it work is with help of try catch
block and withTimeout()
function in FirebaseHelper.kt
file. Following is the code of solution:
fun getUserID() = flow {
try {
val signInTask = Firebase.auth.signInAnonymously()
kotlinx.coroutines.withTimeout(5000) {
signInTask.await()
}
if (signInTask.isSuccessful){
emit("Successful")
} else {
emit("Failed")
}
} catch (e: Exception){
emit("Can't connect to the server\nPlease check your internet connection and retry")
}
}
withTimeout(timeMillis: Long, block: suspend CoroutineScope.() -> T)
runs the given suspend block
for timeMillis
milliseconds and throws TimeoutCancellationException
if the timeout was exceeded.