13

So, i have an app on store with 50000 users. Recently i updated my android studio and compiled SDK to 27. I made some changes to support android 8 changes including Notification changes(e.g. Notification should have unique channel). Tested this on Android One phone(Running android 8). And everything went smooth. After updating the app on playstore i see these crashes on android 8 devices(mostly Google Pixel phones)

Fatal Exception: android.app.RemoteServiceException: Bad notification for startForeground: java.lang.RuntimeException: invalid channel for service notification: Notification(channel=null pri=-2 contentView=null vibrate=null sound=null defaults=0x0 flags=0x40 color=0xffffcf00 actions=3 vis=PRIVATE)
   at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1768)
   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)

I see 7 of these Errors on Crashlytics. Each has same logs and there are about 5000+ crashes for around 10 users. So, apprently app was crashing on loop.

The problem i am having is these logs don't provide any log from where i can see the source in my app that is initiating this crash. Is there any way i can find out which class is throwing this crash? Any help?

Also i have this code for notifications:

if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {

            int importance = NotificationManager.IMPORTANCE_HIGH;
            NotificationChannel mChannel = notificationManager.getNotificationChannel(id);
            if (mChannel == null) {
                mChannel = new NotificationChannel(id, name, importance);
                mChannel.setDescription(description);
                notificationManager.createNotificationChannel(mChannel);
            }
        }



    NotificationCompat.Builder builder = new NotificationCompat.Builder(context,id);
            builder.setContentTitle(pushMessages.size() + context.getString(R.string.new_notification))
                    .setContentIntent(pendingIntent)
                    .setContentText(pushMessages.get(0))
                    .setStyle(inboxStyle)
                    .setGroup(GROUP_KEY_NOTIFICATIONS)
                    .setGroupSummary(true)
                    .setAutoCancel(true);

            if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                builder.setSmallIcon(R.drawable.notification_img)
                        .setColor(context.getResources().getColor(R.color.settings_yellow));


            } else {
                builder.setSmallIcon(R.mipmap.ic_launcher);
            }
            summaryNotification = builder.build();
notificationManager.notify(i, summaryNotification);
Boken
  • 4,825
  • 10
  • 32
  • 42
Fahid Nadeem
  • 412
  • 2
  • 7
  • 19
  • 1
    Possible duplicate of [startForeground fail after upgrade to Android 8.1](https://stackoverflow.com/questions/47531742/startforeground-fail-after-upgrade-to-android-8-1) – Sukhbir Jul 30 '18 at 06:15
  • @sukhbir i have done everything that is in the link you've provided. And nothing helped. – Fahid Nadeem Jul 30 '18 at 06:25
  • @FahidNadeem I'm facing the same problem as you described. Did you find any solution? Thanks – Royz Nov 13 '18 at 11:31
  • Check the error.. It says channel is null.. I hope that helps – mboy Dec 04 '18 at 23:34

5 Answers5

9

You forgot to set channel id for the notification.

if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) builder.setChannelId(youChannelID);

The if statement is optional and depends on your Min SDK level.

saikrishna279
  • 135
  • 1
  • 10
  • 1
    All other solutions was creating about your own channel and method but noboddy said the DIFFRENCE IS you must set channel id if SDK >= O Thanks for the awesome answer – Mahir Özdin Apr 03 '19 at 14:34
  • 1
    No need to do an if check for the API level, from the Javadoc of setChannelId: _No-op on versions prior to {@link android.os.Build.VERSION_CODES#O}_ – Mustafa Berkay Mutlu Oct 15 '19 at 12:17
5

it appears that you in 8.1 must create your own notification channel.

 private void startForeground() {
    String channelId ="";
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        createNotificationChannel("my_service", "My Background Service");
    }else{
        NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(getApplicationContext(), channelId);
        Notification notification = notificationBuilder.setOngoing(true)
                .setSmallIcon(R.mipmap.ic_launcher)
                .setPriority(PRIORITY_MIN)
                .setCategory(Notification.CATEGORY_SERVICE)
                .build();
        startForeground(101, notification);
    }


}

and after

 @RequiresApi(Build.VERSION_CODES.O)
private String createNotificationChannel(String channelId ,String channelName){
    NotificationChannel chan = new NotificationChannel(channelId,
            channelName, NotificationManager.IMPORTANCE_NONE);
    chan.setLightColor(Color.BLUE);
    chan.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
    NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
    manager.createNotificationChannel(chan);
    return channelId;
}

Update: Also don't forget to add the foreground permission as required Android P:

<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
Rahul Goswami
  • 762
  • 6
  • 18
0

Yes, there is a way you can find out which class is throwing this error. So, first of all, you need to find out which class is calling Service.startForeground. That class could be throwing it.

Using Android Studio, go to the source code for Service class and find the startForeground method. Hold ctrl (or Command on Mac) and click on the method signature. It will list classes from all libs that are calling that method, including documentation references.

enter image description here

I'm still facing this same problem. I think RoboSpice (which is archived now) is throwing these errors. The only way to find out is to refactor all codebase to use something else (Rx+Retrofit maybe).

diogenesgg
  • 2,601
  • 2
  • 20
  • 29
0

I just just solved this problem in my application, what happened is that in the class that used my notifications, I kept the CHANNEL_ID and CHANNEL_NAME of the NotificationChannel in a String and Constant, Static or Final variable, but I moved those values ​​to the XML Resource.String since they are values ​​that I never change and I get them with GetString (Resource.String.CH_NAME_GPS_ERROR_ID) and I don't know why but it worked, I hope this also solves your problem

Adolfo Celis
  • 143
  • 2
  • 11
0

It seems you need to create the notification channel that you are passing to the foreground service.

You can create the channel as follows, just have this method in your application class and create the channel their:

private void createChannel(Context context, String channelId, String name) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        NotificationChannel serviceChannel = new NotificationChannel(
                channelId,
                name,
                NotificationManager.IMPORTANCE_DEFAULT
        );
        serviceChannel.setSound(null, null);
        NotificationManager manager = context.getSystemService(NotificationManager.class);
        manager.createNotificationChannel(serviceChannel);
    }
}
alphageek
  • 11
  • 1