Background
I have a spare time app that I've been working on for some years (here), and I try to handle as many crashes as I can (I hate seeing crash reports!).
The problem
One recent crash that seem quite new, is this one:
android.app.RemoteServiceException:
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)
And that's all that I see...
It seems to occur only for Android 8.1. Since the app has got to be quite popular, I'm very sure it will still occur only on Android 8.1.
What I've tried
Searching the Internet, I could find similar crashes, but in all of them, they had more clues.
So I tried to recall what the recent changes that I've done. The only changes were of migrating the support library to Android-X. The rest of the changes are very minor and I don't think they can be the cause for it.
Because I don't have any further clues, I decided to report about the Android-X part here (more information there, if needed), as I don't believe it's because of me trying to fix issues, and it looks like something very specific.
Later I integrated Firebase Crashlytics, and got this tiny additional clue above each such log:
Fatal Exception: android.app.RemoteServiceException
Bad notification for startForeground: java.lang.RuntimeException: invalid channel for service notification: Notification(channel=channel_id__app_monitor pri=0 contentView=null vibrate=null sound=null defaults=0x0 flags=0x40 color=0x00000000 category=service vis=SECRET)
This is weird, because I do open the service correctly, otherwise it wouldn't have worked at all, and this is especially weird that this occurs only on Android 8.1, and not on 8.0 for example, which has the same requirement of how to start a foreground service.
This problematic notification is of a foreground service that I use to globally monitor app-related events (only from Android O, which has restrictions of BroadcastReceivers). It gets updated on 2 cases:
- Locale change
- Ticking a checkbox on some dialog that appears at some point (upon clicking on the dialog).
When I've tested both of those, they work fine, on both Android 8.0 and 8.1.
Here's the code to create/update the notification:
@JvmStatic
fun getUpdatedAppMonitorNotification(context: Context): Notification {
val builder = Builder(context, context.getString(R.string.channel_id__app_monitor)).setSmallIcon(R.drawable.ic_stat_app_icon)//
.setPriority(Notification.PRIORITY_DEFAULT).setCategory(Notification.CATEGORY_SERVICE)
builder.setVisibility(NotificationCompat.VISIBILITY_SECRET)
builder.setShowWhen(false)
if (!PreferenceUtil.getBooleanPref(context, R.string.pref__avoid_showing_app_monitor_notification_dialog, false))
builder.setContentTitle(context.getString(R.string.app_monitor__notification_title))
if (VERSION.SDK_INT < VERSION_CODES.P) {
val mainIntent = Intent(context, MainActivity::class.java)
.putExtra(MainActivity.EXTRA_OPENED_FROM_NOTIFICATION, true)
builder.setContentIntent(PendingIntent.getActivity(context, 0, mainIntent, PendingIntent.FLAG_UPDATE_CURRENT))
} else {
val intent = Intent(Settings.ACTION_CHANNEL_NOTIFICATION_SETTINGS)
.putExtra(Settings.EXTRA_APP_PACKAGE, context.packageName)
.putExtra(Settings.EXTRA_CHANNEL_ID, context.getString(R.string.channel_id__app_monitor))
val pendingIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)
builder.setContentIntent(pendingIntent)
}
return builder.build()
}
And the code I use in the service:
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
NotificationId.initNotificationsChannels(this)
val notification = getUpdatedAppMonitorNotification(this)
startForeground(NotificationId.APP_MONITOR, notification)
...
return super.onStartCommand(intent, flags, startId)
}
And this is the code I call from other places, to update the notification:
@JvmStatic
fun updateAppMonitorNotification(context: Context) {
if (VERSION.SDK_INT < VERSION_CODES.O)
return
val notification = AppMonitorService.getUpdatedAppMonitorNotification(context)
val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
notificationManager.notify(NotificationId.APP_MONITOR, notification)
}
The questions
Why does it occur? Is it about Android X ? Or something wrong with the notification building?
Why does it occur only on Android 8.1 ?