1

I received a crash saying that it was caused by calling getCurrentUser(). Here's the relevant part of the crash logs from Crashlytics:

Fatal Exception: java.lang.NullPointerException: Attempt to invoke virtual method 'com.google.android.gms.c.f com.google.android.gms.common.api.e.b(com.google.android.gms.common.api.internal.aj)' on a null object reference
       at com.google.android.gms.internal.zzdvv.zzb(Unknown Source)
       at com.google.android.gms.internal.zzdwc.zza(Unknown Source)
       at com.google.firebase.auth.FirebaseAuth.getCurrentUser(Unknown Source)
       at com.google.firebase.auth.FirebaseAuth.getCurrentUser(Unknown Source)
       at <my.app.package>.<class1>.isUserNull(Unknown Source)
       at <my.app.package>.<class2>.requestUserLogin(Unknown Source)

I'm using the MVP architecture for my app and the corresponding Firebase function was called in a helper class. The structure/flow looks like this:

Activity > Presenter > Interactor > Helper

As soon as the activity starts, it initializes the presenter, which initializes the interactor, which initializes the helper class. The helper class looks like this:

public class Helper{

       private FirebaseAuth mAuth;

       public Helper(@NonNull Listener){
           mAuth = FirebaseAuth.getInstance();
       }

       public boolean isUserNull(){
           return mAuth.getCurrentUser() == null;
       }

}

As visible in the helper class, FirebaseAuth is properly initialized, so calling getCurrentUser() should be safe.

getCurrentUser() returns either a FirebaseUser or null, so I believe having a user currently signed in or not doesn't matter at all in this scenario.

We already did testing on our end and never experienced this before, which is why this is very confusing. Adding to it, among the dozens of users so far, this is the only instance that it happened.

Has anyone experienced something similar to this before or has any idea what could've caused it?

I'm considering changing the function to just directly get the FirebaseAuth instance like this:

public boolean isCurrenUserNull(){
    return FirebaseAuth.getInstance().getCurrentUser() == null;
}

But I'm not really sure if that would change anything.


Update: In response to Bob Snyder's answer/comment

The app currently starts with an initial activity that checks for the necessary requirements for the app, like for Google Play Services requirement. If it fails, it closes, if it doesn't it then checks if there is an already existing user via the getCurrentUser() function. This is probably where the error is happening for some reason.

With regards to "message receipt, notification intent.." -- FCM is currently implemented and it is possible to receive notifications, that when tapped, the user would be directed to the corresponding activity.

However, for that to work, the user should be able to go past the initial sign at least once, and should be kept signed in. Otherwise, they would no longer receive notifications (I'm handling the logout as I posted here).

And thinking about it, if FCM does work immediately, doesn't that make sure that Google Play Services is already up-to-date?

Thoughts and suggestions are highly appreciated!

AL.
  • 36,815
  • 10
  • 142
  • 281
  • Are you sure the line `mAuth = FirebaseAuth.getInstance();` executes correctly? Could it fail or throw an exception that you somehow catch without handling it? – Androidas Apr 06 '18 at 05:30
  • @Androidas I believe it does. If it fails/throws an exception at that point, a crash would occur and point towards there and I think the app won't be able to reach the part where it calls `isUserNull()` – AL. Apr 06 '18 at 05:42
  • My opinion is Null does not indicate `mAuth`, as exception stack shows `FirebaseAuth.getCurrentUser` has been invoked, and exception is actually thrown inner of `getCurrentUser`. – terry.qiao Apr 06 '18 at 05:56
  • According to your saying, there is only one failure among dozens of users, I think if it is about permission settings on that user's Android. – terry.qiao Apr 06 '18 at 06:00
  • @terry.qiao Yup. That's the point. Issue with the Permission settings how? – AL. Apr 06 '18 at 06:04
  • @AL. You may refer to https://stackoverflow.com/questions/46208917/getcurrentuser-functions-error?rq=1 – terry.qiao Apr 06 '18 at 06:20
  • @terry.qiao I've seen the post before. It's not similar. I'm aware that getting something *within* `getCurrentUser()` (i.e. FirebaseUser object) when its null would cause NPE. But I'm not. I'm just calling the actual getter for the current user. Which should be safe since I'm only checking if its null or not. But for some unknown reason, it caused an error. Thanks anyways. – AL. Apr 06 '18 at 06:29
  • @AL. Yeah, I was misunderstanding. But I have no idea about how this could happen. – terry.qiao Apr 06 '18 at 06:45

1 Answers1

0

The same stack trace has been reported for other Auth related NullPointerExceptions, for example this one and this one.

The cause is typically that the device does not have a compatible version of Google Play services installed. Because most of the Firebase SDKs require a compatible version of Google Play services, your app initialization should use GoogleApiAvailabilty to check that it is installed and take appropriate actions if not. This is discussed in the Guide for FCM.

In your comments on this answer you explain that you are checking for the availability of Google Play services and preventing the app from running if an update is required and does not complete successfully or is declined by the user. If you have any doubts that you are handling all cases of that, you could add this code immediately before the statement that is throwing the NPE:

if (GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(context) != ConnectionResult.SUCCESS) {
    throw new IllegalStateException("Play Services not available"));
    // or
    Crashlytics.logException(new IllegalStateException("Play Services not available"));
}
Bob Snyder
  • 37,759
  • 6
  • 111
  • 158
  • Hi Bob. Thanks for pointing those out. But unfortunately, I actually implemented the checking for Google Play Services (I also use FCM in the app, and being somewhat familiar with the usual issues, figured I have to implement them by the book), and already did the testing on actual devices. So I can say for certain that the check works. The app would show the message to update -- if the user chooses okay, they get redirected to the Play Store, if not, the app closes -- which keeps them from getting to the part where the FirebaseAuth call works. – AL. Apr 06 '18 at 18:02
  • Okay, thanks for the update. Interesting that the stack traces are identical, but apparently a different cause. – Bob Snyder Apr 06 '18 at 18:15
  • It is very odd. Crashlytics is now showing that there are two instances, one for an Asus device and one on Samsung. So the possibility of the issue being device type specific is off the table now. – AL. Apr 06 '18 at 18:23
  • Your comment explains that the app cannot be entered unless the user accepts the update. When I implemented that check, I found it required a lot of thought because the app could be entered in different ways: launch activity, message receipt, notification intent, etc. – Bob Snyder Apr 06 '18 at 18:43
  • Hi Bob. I added in some explanations on my post. Let me know if you have any suggestions. Cheers! :) – AL. Apr 07 '18 at 04:35
  • AL: Have you made any progress identifying the cause of the exception? – Bob Snyder Apr 12 '18 at 16:40
  • Hi Bob. Unfortunately not. I'm not seeing any crashes of the same source though. Still curious. If this happens again, I might send an email regarding the issue to Firebase Support. Cheers! – AL. Apr 12 '18 at 17:52