Search code examples
androidfirebasekotlinfirebase-authenticationandroid-jetpack-navigation

Show signIn when user log out from Firebase


In my fragment i have dialog(with log out), when user click he log out from app:

override fun onClick(dialog: DialogInterface?, which: Int) {
    AuthUI.getInstance().signOut(requireContext())
}

But after that, I want to send the user to the authorization fragment, in my case this is MainFragment.

So i added next code in my nav_graph:

<fragment
    android:id="@+id/settings_list_fragment"
    android:name="com.mandarine.targetList.features.settings.SettingsListFragment"
    android:label="@string/settings"
    tools:layout="@layout/fragment_settings_list" >
    <action
        android:id="@+id/action_settings_list_fragment_to_mainFragment"
        app:destination="@id/mainFragment" />
</fragment>

Also add line in my function onClick():

override fun onClick(dialog: DialogInterface?, which: Int) {
        AuthUI.getInstance().signOut(requireContext())
        findNavController().navigate(R.id.action_settings_list_fragment_to_mainFragment)
    }

But always when i move to MainFragment my user isn't null.

Only if I kill the app then the user is null.

Here is code of my MainFragment:

class MainFragment : Fragment() {

    private lateinit var auth: FirebaseAuth
    private lateinit var mAuthStateListener: FirebaseAuth.AuthStateListener

    companion object {
        const val TAG = "MainFragment"
        const val SIGN_IN_RESULT_CODE = 1001
    }

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        return inflater.inflate(R.layout.fragment_main, container, false)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        signIn()
        launchSignInFlow()
    }

    override fun onResume() {
        super.onResume()
        auth.addAuthStateListener(mAuthStateListener)
    }

    override fun onPause() {
        super.onPause()
        auth.removeAuthStateListener(mAuthStateListener)
    }

    private fun signIn() {
        auth = FirebaseAuth.getInstance()
        mAuthStateListener = FirebaseAuth.AuthStateListener { firebaseAuth ->
            if (firebaseAuth.currentUser != null) {
                Log.d("some", "user not null")
                findNavController().navigate(R.id.show_goals)
            } else {
                Log.d("some", "null")
            }
        }
    }

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        if (requestCode == SIGN_IN_RESULT_CODE) {
            val response = IdpResponse.fromResultIntent(data)
            if (resultCode == Activity.RESULT_OK) {
                // User successfully signed in
                Log.i(TAG, "Successfully signed in user ${FirebaseAuth.getInstance().currentUser?.displayName}!")
            } else {
                // Sign in failed. If response is null the user canceled the
                // sign-in flow using the back button. Otherwise check
                // response.getError().getErrorCode() and handle the error.
                Log.i(TAG, "Sign in unsuccessful ${response?.error?.errorCode}")
            }
        }
    }

    private fun launchSignInFlow() {
        // Give users the option to sign in / register with their email
        // If users choose to register with their email,
        // they will need to create a password as well
        val providers = arrayListOf(
            AuthUI.IdpConfig.EmailBuilder().build(),
            AuthUI.IdpConfig.GoogleBuilder().build()
        )

        // Create and launch sign-in intent.
        // We listen to the response of this activity with the
        // SIGN_IN_RESULT_CODE code
        startActivityForResult(
            AuthUI.getInstance()
                .createSignInIntentBuilder()
                .setAvailableProviders(providers)
                .build(),
             SIGN_IN_RESULT_CODE
        )
    }
}

UPD: For example if i change my onClick in SettingsListFragment all works is correct:

override fun onClick(dialog: DialogInterface?, which: Int) {
    AuthUI.getInstance().signOut(requireContext())
    activity?.finish()
}

But I don't want the user to exit my app


Solution

  • Modified my nav_graph.xml:

    <fragment
        android:id="@+id/settings_list_fragment"
        android:name="com.mandarine.targetList.features.settings.SettingsListFragment"
        android:label="@string/settings"
        tools:layout="@layout/fragment_settings_list">
    
        <action
            android:id="@+id/sign_in"
            app:destination="@id/mainFragment"/>
    </fragment>
    

    And add next code:

    override fun onClick(dialog: DialogInterface?, which: Int) {
        activity?.let {
            AuthUI.getInstance().signOut(it).addOnCompleteListener {
                findNavController().navigate(R.id.sign_in)
            }
        }
    }
    

    That is solved my problem.