Fahid Nadeem
Fahid Nadeem

Reputation: 412

Bad notification for start Foreground, Invalid channel for service notification:

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);

Upvotes: 13

Views: 24297

Answers (5)

alphageek
alphageek

Reputation: 11

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);
    }
}

Upvotes: 0

Adolfo Celis
Adolfo Celis

Reputation: 163

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

Upvotes: 0

diogenesgg
diogenesgg

Reputation: 2839

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).

Upvotes: 0

Rahul Goswami
Rahul Goswami

Reputation: 782

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" />

Upvotes: 5

saikrishna279
saikrishna279

Reputation: 145

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.

Upvotes: 10

Related Questions