James Ele
James Ele

Reputation: 43

Android Firebase logout app crashes AFTER I logout

I have my MainActivity in which I handle the logout. Problem is after I log out, the app crashes in verifyUserExistance() at line:

String userID = Objects.requireNonNull(mAuth.getCurrentUser()).getUid();

Which gives :

E/AndroidRuntime: FATAL EXCEPTION: main Process: com.google.firebase.quickstart.auth, PID: 8459 java.lang.NullPointerException at java.util.Objects.requireNonNull(Objects.java:203) at com.google.firebase.quickstart.auth.social.Main_Chat_Activity$3.lambda$null$1$Main_Chat_Activity$3(Main_Chat_Activity.java:372) at com.google.firebase.quickstart.auth.social.-$$Lambda$Main_Chat_Activity$3$87CwjFnoJAhucBGNsLP_MxK833o.onComplete(Unknown Source:2) at com.google.android.gms.tasks.zzj.run(com.google.android.gms:play-services-tasks@@17.2.0:4) at android.os.Handler.handleCallback(Handler.java:873) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loop(Looper.java:214) at android.app.ActivityThread.main(ActivityThread.java:7050) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:494) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:965)

Below is the code I use:

@Override
protected void onStart() {
    super.onStart();
    usersRef.child(mAuth.getCurrentUser().getUid()).addListenerForSingleValueEvent(new ValueEventListener() {
        @Override
        public void onDataChange(@NonNull DataSnapshot snapshot) {
            if (!snapshot.hasChild("name"))
            {
                sendUserToLoginActivity();
            }
        }

        @Override
        public void onCancelled(@NonNull DatabaseError error) {

        }
    });
    if (mAuth == null || currentUser == null || mAuth.getCurrentUser().getUid() == null ){
        finish();
        sendUserToLoginActivity();
    }
    else {
        if(mAuth.getCurrentUser().getProviderId() == "google.com"){
            user.setmGoogleSignInClient(mGoogleSignInClient);
        }
        user.setMauth(mAuth);
        if (loginOutFlag>-1)
            verifyUserExistence();
    }
    checkLocation();
    if (isNew!=null)
    {
        if (isNew.equals("true")){
            sendUserToSettingsActivity();
        }
    }
}

The method verifyUserExistance is;

 private void verifyUserExistence() {
    if (!verified && loginOutFlag > -1) {
        String currentUserID = mAuth.getCurrentUser().getUid();
        try {


            rootRef.child("Users").child(currentUserID).addValueEventListener(new ValueEventListener() {
                @Override
                public void onDataChange(@NonNull DataSnapshot dataSnapshot) {

                    if (dataSnapshot.child("name").exists()) {
                        loginOutFlag = 1;
                        Toast.makeText(Main_Chat_Activity.this, "Welcome" + dataSnapshot.child("name").getValue().toString(), Toast.LENGTH_SHORT).show();
                        Log.w("Reportname:", dataSnapshot.child("name").getValue().toString());
                        Calendar cal = Calendar.getInstance();
                        final String timeNDate = cal.getTime().toString();
                        HashMap<String, Object> profileMap = new HashMap<>();
                        profileMap.put("connection", timeNDate);
                        rootRef.child("Users").child(currentUserID).updateChildren(profileMap)
                                .addOnCompleteListener(task ->
                                {
                                    if (task.isSuccessful()) {
                                        Toast.makeText(Main_Chat_Activity.this, "Success ", Toast.LENGTH_SHORT).show();
                                        verified = true;
                                        FirebaseMessaging.getInstance().getToken()
                                                .addOnCompleteListener(task13 -> {
                                                    String userID = Objects.requireNonNull(mAuth.getCurrentUser()).getUid();
                                                    if (!task13.isSuccessful()) {
                                                        Log.w("FCM", "Fetching FCM registration token failed", task13.getException());
                                                        return;
                                                    }

                                                    // Get new FCM registration token
                                                    String deviceToken = task13.getResult();

                                                    // Log and toast

                                                    Log.d("FCM", deviceToken);
                                                    Toast.makeText(Main_Chat_Activity.this, deviceToken, Toast.LENGTH_SHORT).show();
                                                    final int[] no = {0};
                                                    DatabaseReference tokens = usersRef.child(userID).child("device_tokens");
                                                    ValueEventListener valueEventListener = new ValueEventListener() {
                                                        @Override
                                                        public void onDataChange(@NonNull DataSnapshot snapshot) {
                                                            no[0] = (int) snapshot.getChildrenCount();
                                                        }

                                                        @Override
                                                        public void onCancelled(@NonNull DatabaseError error) {

                                                        }
                                                    };
                                                    tokens.addListenerForSingleValueEvent(valueEventListener);
                                                    String devName = "device" + no[0];
                                                    String token = deviceToken.split(":")[1];
                                                    usersRef.child(userID).child("device_tokens").child(devName)
                                                            .setValue(token)
                                                            .addOnCompleteListener(task12 -> {
                                                                if (task12.isSuccessful()) {
                                                                    Toast.makeText(Main_Chat_Activity.this, "Token updated succesfully.", Toast.LENGTH_LONG).show();
                                                                }
                                                            });

                                                });
                                    } else {
                                        String errorMSG = Objects.requireNonNull(task.getException()).toString();
                                        //user.setMauth(null);
                                        Toast.makeText(Main_Chat_Activity.this, "Error : " + errorMSG, Toast.LENGTH_SHORT).show();
                                    }

                                });

                    }
                }

                @Override
                public void onCancelled(@NonNull DatabaseError databaseError) {

                }
            });
        }
        catch (Exception e)
        {
            Log.d("EXCEPTION", e.toString());
        }
    }


}

and this is how I handle the logout;

 @Override
public boolean onOptionsItemSelected(MenuItem item) {
    super.onOptionsItemSelected(item);

    if (item.getItemId() == R.id.main_logout_option) {
        updateUserStatus("offline");
        String currentUserID = mAuth.getCurrentUser().getUid();

        rootRef.child("Users").child(currentUserID).addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(@NonNull DataSnapshot dataSnapshot) {

                if (dataSnapshot.child("name").exists()) {

                    Calendar cal = Calendar.getInstance();
                    final String timeNDate = cal.getTime().toString();
                    HashMap<String, Object> profileMap = new HashMap<>();
                    profileMap.put("connection", timeNDate);
                    rootRef.child("Users").child(currentUserID).updateChildren(profileMap)
                            .addOnCompleteListener(task ->
                            {
                                if (task.isSuccessful()) {
                                    loginOutFlag = -1;
                                } else {
                                    String errorMSG = Objects.requireNonNull(task.getException()).toString();
                                    Toast.makeText(Main_Chat_Activity.this, "This error : " + errorMSG, Toast.LENGTH_SHORT).show();
                                }
                                mGoogleSignInClient.signOut().addOnCompleteListener(task1 -> {
                                    if (task1.isSuccessful()){
                                        mAuth.signOut(); // very important if you are using firebase.
                                        LoginManager.getInstance().logOut();
                                        sendUserToLoginActivity();
                                        finish();
                                    }
                                });
                            });
                }

            }

            @Override
            public void onCancelled(@NonNull DatabaseError databaseError) {

            }
        });

        sendUserToLoginActivity();
    }

    if (item.getItemId() == R.id.main_settings_option) {
        sendUserToSettingsActivity();
    }
    if (item.getItemId() == R.id.main_find_friends_option) {
        sendUserToFindFriendsActivity();
    }
    return true;
}

Upvotes: 1

Views: 451

Answers (1)

Alex Mamo
Alex Mamo

Reputation: 138979

Problem is after I log out, the app crashes:

at line String userID = Objects.requireNonNull(mAuth.getCurrentUser()).getUid()

When you log out, the mAuth objct becomes null. So calling getCurrentUser() on a such an object, instead of returning a FirebaseUser object, it will return null, hence the presence of the NullPointerExcepetion.

Returns the currently signed-in FirebaseUser or null if there is none.

So the solution for your problem is to wait for the asynchronous operation to finish, and right after that to sign out, otherwise, you'll always get NullPointerExcepetion.

Here is an example of you can wait until the data is finished loading from the Realtime Database:

Upvotes: 2

Related Questions