Currently, I am trying to implement facebook-login in combination with cloud firestore inside my app. Everything works fine like it should (login, registration, Firebase.auth.currentUser != null).
The only problem I have is that when I log out of my app and then log in again with facebook I get the message "Up to now you have registered with xyz via Facebook. Do you want to continue."
I don't know why this message is coming. Even deleting the created facebook account from my cloud-firestore did not resolve the problem.
Here is a screenshot:
My Login Process
Fragment
class UserLogInRegistrationFragment : Fragment(R.layout.fragment_user_log_in_registration) {
private val viewModel: LoginViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Register Facebook Callback
viewModel.onEvent(LoginRegistrationEvent.RegisterFacebookCallback)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
initExternalLogins()
observeSignInOptions()
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
viewModel.onEvent(LoginRegistrationEvent.SignInWithFacebook(requestCode, resultCode, data))
}
override fun onDestroyView() {
super.onDestroyView()
// Unregister Facebook Callback
viewModel.onEvent(LoginRegistrationEvent.UnregisterFacebookCallback)
}
private fun initExternalLogins() {
facebookSignInBtn.setOnClickListener { viewModel.onEvent(LoginRegistrationEvent.OnStartFacebookSignIn) }
}
private fun observeSignInOptions() {
viewModel.signInOption.observe(viewLifecycleOwner) { event ->
when(event) {
is SignInOption.FacebookSignIn -> {
// Starting Login Process. This will be executed by the viewmodel
facebookManager().logInWithReadPermissions(this, listOf("email", "public_profile"))
}
}
}
}
}
Viewmodel
class LoginViewModel @Inject constructor(
private val loginValidator: LoginValidator
) : ViewModel() {
val signInOption = loginValidator.signInOption
val signInResult = loginValidator.signInResult
fun onEvent(event: LoginRegistrationEvent) {
when (event) {
LoginRegistrationEvent.RegisterFacebookCallback -> viewModelScope.launch { loginValidator.registerFacebookCallback() }
LoginRegistrationEvent.UnregisterFacebookCallback -> loginValidator.unregisterFacebookCallback()
LoginRegistrationEvent.OnStartFacebookSignIn -> loginValidator.startFacebookSignIn()
is LoginRegistrationEvent.SignInWithFacebook -> viewModelScope.launch {
loginValidator.handleFacebookSignInActivity(event.requestCode, event.resultCode, event.data)
}
}
}
}
LoginValidator (Use Case)
class LoginValidator @Inject constructor(
private val loginRepository: LoginRepository,
) {
private val _signInOption = MutableLiveData<SignInOption>()
val signInOption: LiveData<SignInOption> get() = _signInOption
private val _signInResult = MutableLiveData<LoginStateEvent>()
val signInResult: LiveData<LoginStateEvent> get() = _signInResult
fun startFacebookSignIn() {
_signInOption.value = SignInOption.FacebookSignIn
}
suspend fun registerFacebookCallback() {
loginRepository.signInWithFacebook().collect {
_signInResult.value = it
}
}
fun unregisterFacebookCallback() {
loginRepository.unregisterFacebookCallback()
}
fun handleFacebookSignInActivity(requestCode: Int, resultCode: Int, data: Intent?) {
loginRepository.handleFacebookSignInActivity(requestCode, resultCode, data)
}
fun signOut() = loginRepository.signOutUser()
}
LoginRepository
class LoginRepositoryImpl @Inject constructor(
@ApplicationContext private val context: Context,
private val callbackManager: CallbackManager,
private val dbAuth: FirebaseAuth,
private val dbFirestore: FirebaseFirestore
) : LoginRepository {
override fun isUserLogedIn(): Boolean = when (dbAuth.currentUser) {
null -> false
else -> true
}
override fun signOutUser() {
dbAuth.signOut()
facebookManager().logOut()
}
@ExperimentalCoroutinesApi
override suspend fun signInWithFacebook(): Flow<LoginStateEvent> = flow {
val result = facebookManager().registerMCallback(callbackManager)
emit(LoginStateEvent.Loading(context.getString(R.string.login_registration_progress_verify_facebook)))
val credential = FacebookAuthProvider.getCredential(result.accessToken.token)
emit(LoginStateEvent.Loading(context.getString(R.string.login_registration_progress_loggin_in)))
dbAuth.signInWithCredential(credential).await()
emit(LoginStateEvent.Loading(context.getString(R.string.login_regisration_progress_verifiy_rsb)))
createUserIfNotExist(
User(
eMail = dbAuth.currentUser!!.email ?: "",
lastName = splitToLastName(dbAuth.currentUser!!.displayName) ?: "",
firstName = splitToFirstName(dbAuth.currentUser!!.displayName) ?: "",
oAuth = OAuth.FACEBOOK
)
)
emit(LoginStateEvent.LoggedIn)
}.catch { e ->
emit(convertExceptionToState(e as Exception))
}
override fun handleFacebookSignInActivity(requestCode: Int, resultCode: Int, data: Intent?) {
callbackManager.onActivityResult(requestCode, resultCode, data)
}
override fun unregisterFacebookCallback() {
facebookManager().unregisterCallback(callbackManager)
}
Extension Function for Facebook Login
@ExperimentalCoroutinesApi
suspend fun LoginManager.registerMCallback(
manager: CallbackManager
) = suspendCancellableCoroutine<LoginResult> { cont ->
val callback = object : FacebookCallback<LoginResult> {
override fun onSuccess(result: LoginResult) = cont.resume(result, cont::resumeWithException)
override fun onCancel() { }
override fun onError(error: FacebookException?) {
error?.let { cont.resumeWithException(it) }
}
}
registerCallback(manager, callback)
}
fun facebookManager(): LoginManager = LoginManager.getInstance()
Callback Manager
@Provides
fun provideCallbackManager(): CallbackManager = CallbackManager.Factory.create()
Sign-In Flow
https://i.stack.imgur.com/nNxN6.jpg
Dependencies I use
implementation "com.google.firebase:firebase-auth-ktx"
implementation 'com.facebook.android:facebook-login:8.1.0'
I have tried to stick to the cloud firestore documentation here and I've read this Stackoverflow post.
