0

Please don't mark this as a duplicate of some generic null pointer exception question, as you can see, the exception isn't directly in my code, it is deep within the Android notification classes.

I've never actually reproduced this myself, I only get it on Crashlytics. Happens on Android 7 and 8 across several manufacturers. It seems similar to Android.app.Notification.extras null but there is no answer there and their stacktrace is slightly different. Here is the exception:

 java.lang.NullPointerException: Attempt to read from field 'android.os.Bundle android.app.Notification.extras' on a null object reference
           at android.app.Notification.addFieldsFromContext(Notification.java:2439)
           at android.app.Notification.addFieldsFromContext(Notification.java:2432)
           at android.app.NotificationManager.notifyAsUser(NotificationManager.java:300)
           at android.app.NotificationManager.notify(NotificationManager.java:289)
           at android.app.NotificationManager.notify(NotificationManager.java:273)
           at mypackageMyService.notify(MyService.java:812)
           at mypackageMyService.createNotificationAfterCheckOfStatus(MyService.java:1040)
           at mypackageMyService.onStartCommand(MyService.java:173)
           at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:3474)
           at android.app.ActivityThread.-wrap20(Unknown Source)
           at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1692)
           at android.os.Handler.dispatchMessage(Handler.java:106)
           at android.os.Looper.loop(Looper.java:164)
           at android.app.ActivityThread.main(ActivityThread.java:6494)
           at java.lang.reflect.Method.invoke(Method.java)
           at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
           at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)

And here is my code:

Intent intent = new Intent(this, SomeClass.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, PENDING_ID, intent, PendingIntent.FLAG_UPDATE_CURRENT); 
NotificationCompat.Builder builder = NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID)
                .setSmallIcon(R.drawable.ic_stat_notification_icon)
                .setOngoing(true)
                .setAutoCancel(false)
                .setContentIntent(pendingIntent)
                .setPriority(NotificationCompat.PRIORITY_LOW);
builder.setContentText(getString(R.string.please_wait));
if (oreoOrHigher) {
            NotificationManager notificationManager =
                    (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
            NotificationChannel notificationChannel = notificationManager.getNotificationChannel(NOTIFICATION_CHANNEL_ID);
            if (notificationChannel == null) {

      /* Create or update. */
                CharSequence channelName = getString(R.string.my_channel_label);
                int importance = NotificationManager.IMPORTANCE_LOW;
                notificationChannel = new NotificationChannel(NOTIFICATION_CHANNEL_ID, channelName, importance);
                notificationChannel.enableLights(false);
                notificationChannel.enableVibration(false);
                notificationManager.createNotificationChannel(notificationChannel);
            }
            builder.setChannelId(NOTIFICATION_CHANNEL_ID);
}
builder.setOngoing(false);
//fake extra to see if it fixes null pointer
Bundle fakeExtra = new Bundle();
fakeExtra.putString("test", "test");
builder.addExtras(fakeExtra);
Notification notification = builder.build();
NotificationManager notificationManager = (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(NOTIFICATION_ID, notification);
startForeground(NOTIFICATION_ID, notification);

I even tried adding a fake extra bundle and that didn't help.

What am I doing wrong?

Thanks.

Edit: It has been pointed out that builder.build() is probably returning null. I still haven't been able to reproduce that but it would make a bit of sense given the message of the exception. I just don't know why the build() method would fail to create a notification object.

casolorz
  • 6,790
  • 15
  • 74
  • 161
  • You're passing a null to the notification manager. Step through your code with a debugger and look for nulls, specifically look at this line `Notification notification = builder.build();` and see if your notification actually got built out. – Chris Stillwell Feb 13 '18 at 16:13
  • You are probably correct looking at the message of the exception. Why would it be null though? Is it normal for the `build()` method to return null sometimes? I don't ever get null when I step through the code myself. – casolorz Feb 13 '18 at 16:18
  • I remember there being some issue with singleTask apps causing strange behavior with the NotificationBuilder. However, if you aren't running as a singleTask you shouldn't have to worry... If it isn't null, then it might be getting recycled. Is the notification dismissed when you get that error? – Chris Stillwell Feb 13 '18 at 16:27
  • I also wonder if it is a permissions thing. Have you tried testing to see if you get the error when the user denies notifications from the app? – Chris Stillwell Feb 13 '18 at 16:33
  • Actually I am running SingleTask. I'll test by denying notifications. – casolorz Feb 13 '18 at 16:49
  • Notifications disabled for the app and the `build()` method still works fine and I don't get the exception. But I've never reproduced this myself. – casolorz Feb 13 '18 at 16:56

1 Answers1

2

Try to replace this with getApplicationContext() when creating a notification:

NotificationCompat.Builder builder = NotificationCompat.Builder(getApplicationContext(), NOTIFICATION_CHANNEL_ID)

Your notification is not null, as you can see in stacktrace you have successful calls to the notification instance. But the exception is in Notification.addFieldsFromContext, so looks like Bundle of Context is null.

Orest Savchak
  • 4,303
  • 1
  • 15
  • 26