1

I am integrating FirebaseAuth into an Android app that I am building. I have successfully integrated firebase into the app by adding the SDK, downloading and adding the google-services.json file.

The problem occurs when I try to Sign Up a new user. The user gets added to firebase console but I cannot retrieve the signed in user to update the name. This is the code from the fragment I am using it in.

requireActivity().let {
    val user = authenticationService.signUpWithEmailAndPassword(email, password)

    user?.let {
            authenticationService.updateUser(it, name)
            navigationService.openHomeScreen()//open next creen
    }
}

the signup function in the authenticationService

fun signUpWithEmailAndPassword(email: String, password: String): FirebaseUser? {
    signOutCurrentUser()
     firebaseAuth.createUserWithEmailAndPassword(email, password)
    return firebaseAuth.currentUser
}

the update user function

fun updateUser(user: FirebaseUser?, name: String) {
    val profileUpdates = UserProfileChangeRequest.Builder().apply {
        displayName = name
    }.build()
    user?.updateProfile(profileUpdates)?.addOnCompleteListener { task ->
        if (task.isSuccessful) {
            Timber.d("User profile updated.")
        }
    }
}

the sign out current user function

private fun signOutCurrentUser() {
    firebaseAuth.currentUser?.let {
        firebaseAuth.signOut()
    }
}

The issue is that user is Added successfully but firebaseAuth.currentUser returns null always.

Things I have tried:

  • Adding authStateListener
  • Adding onSuccessListener
  • Adding onCompleteListener

Please help a brother out

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
cranium44
  • 13
  • 3

1 Answers1

2

Creating a user in Firebase is (like most calls involving cloud-based APIs) an asynchronous operation, which may take time to complete. By the time your return firebaseAuth.currentUser code runs, the user creation has not been completed yet.

If you simply the code to run in a single block, with a completion handler, you'll see that it works fine:

firebaseAuth.createUserWithEmailAndPassword(email, password)
  .addOnCompleteListener(this) { task ->
    if (task.isSuccessful) {
        val user = auth.currentUser

        val profileUpdates = UserProfileChangeRequest.Builder().apply {
            displayName = name
        }.build()
        user?.updateProfile(profileUpdates)?.addOnCompleteListener { task ->
            if (task.isSuccessful) {
                Timber.d("User profile updated.")
            }
        }
    } else {
        // If sign in fails, display a message to the user.
        Log.w(TAG, "createUserWithEmail:failure", task.exception)
        Toast.makeText(baseContext, "Authentication failed.",
                Toast.LENGTH_SHORT).show()
        updateUI(null)
    }

    // ...
  }

Also see:

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
  • Thanks a lot. But is it possible to block the execution of the return statement until the user has been created? – cranium44 May 28 '20 at 10:52
  • Blocking execution would be a really bad experience for the user, as they wouldn't be able to use the app. The best approach to deal with asynchronicity is to reframe your flow from "first do this, then do that" to "start doing this, when that is done do that", which is what the code above does. There are ways to make this more modular, but these don't include blocking a return statement. I've added some links with more info. – Frank van Puffelen May 28 '20 at 13:05