Reputation: 412
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
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
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
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.
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
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
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