startForegroundService() did not call startForeground(), but it did
You need to use a NotificationChannel for Android O API 26 and above, otherwise you'll get the error you have experienced. See the following statement from the Android docs - Create and Manage Notification Channels:
Starting in Android 8.0 (API level 26), all notifications must be assigned to a channel.
Here is an excerpt (take from it what you need) from a method I use for building our media notifications. You can see there is a check for Android O devices with a specific method to handle that case:
private fun compileNotification(context: Context, action: NotificationCompat.Action, mediaSession: MediaSessionCompat, controller: MediaControllerCompat, mMetadata: MediaMetadataCompat, art: Bitmap?, mPlaybackState: PlaybackStateCompat) {
val description = mMetadata.description
// https://stackoverflow.com/questions/45395669/notifications-fail-to-display-in-android-oreo-api-26
@TargetApi(26)
if(Utils.hasO()) {
val channelA = mNotificationManager?.getNotificationChannel(NotificationChannelID.MEDIA_SERVICE.name)
if(channelA == null) {
val channelB = NotificationChannel(NotificationChannelID.MEDIA_SERVICE.name,
"MediaService",
NotificationManager.IMPORTANCE_DEFAULT)
channelB.setSound(null, null)
mNotificationManager?.createNotificationChannel(channelB)
}
}
val notificationBuilder = if(Utils.hasLollipop()) {
NotificationCompat.Builder(context, NotificationChannelID.MEDIA_SERVICE.name)
} else {
NotificationCompat.Builder(context)
}
notificationBuilder
.setStyle(android.support.v4.media.app.NotificationCompat.MediaStyle()
// Show actions 0,2,4 in compact view
.setShowActionsInCompactView(0,2,4)
.setMediaSession(mediaSession.sessionToken))
.setSmallIcon(R.drawable.logo_icon)
.setShowWhen(false)
.setContentIntent(controller.sessionActivity)
.setContentTitle(description.title)
.setContentText(description.description)
.setLargeIcon(art)
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
.setOngoing(mPlaybackState.state == PlaybackStateCompat.STATE_PLAYING)
.setOnlyAlertOnce(true)
if(!Utils.hasLollipop()) {
notificationBuilder
.setStyle(android.support.v4.media.app.NotificationCompat.MediaStyle()
// Show actions 0,2,4 in compact view
.setShowActionsInCompactView(0,2,4)
.setMediaSession(mediaSession.sessionToken)
.setShowCancelButton(true)
.setCancelButtonIntent(MediaButtonReceiver.buildMediaButtonPendingIntent(context,
PlaybackStateCompat.ACTION_STOP)))
// Stop the service when the notification is swiped away
.setDeleteIntent(MediaButtonReceiver.buildMediaButtonPendingIntent(context,
PlaybackStateCompat.ACTION_STOP))
}
notificationBuilder.addAction(NotificationCompat.Action(
R.drawable.exo_controls_previous,
"Previous",
MediaButtonReceiver.buildMediaButtonPendingIntent(context,
PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS)))
notificationBuilder.addAction(NotificationCompat.Action(
R.drawable.ic_replay_10_white_24dp,
"Rewind",
MediaButtonReceiver.buildMediaButtonPendingIntent(context,
PlaybackStateCompat.ACTION_REWIND)))
notificationBuilder.addAction(action)
notificationBuilder.addAction(NotificationCompat.Action(
R.drawable.ic_forward_10_white_24dp,
"Fast Foward",
MediaButtonReceiver.buildMediaButtonPendingIntent(context,
PlaybackStateCompat.ACTION_FAST_FORWARD)))
notificationBuilder.addAction(NotificationCompat.Action(
R.drawable.exo_controls_next,
"Next",
MediaButtonReceiver.buildMediaButtonPendingIntent(context,
PlaybackStateCompat.ACTION_SKIP_TO_NEXT)))
(context as MediaService).startForeground(NOTIFICATION_ID, notificationBuilder.build())
}
In your onStop()
callback, you'll need to call stopSelf()
within the service. Then, when your service onDestroy()
method is called you need to clean up a few things (as applies to your case) as follows:
override fun onDestroy() {
super.onDestroy()
abandonAudioFocus()
unregisterReceiver(mNoisyReceiver)
//Deactivate session
mSession.isActive = false
mSession.release()
NotificationManagerCompat.from(this).cancelAll()
if(mWiFiLock?.isHeld == true) mWiFiLock?.release()
stopForeground(true)
}
I haven't included detail for some of the methods above, but the method names should be self commenting - let me know if I can include more detail. Some of them might be overkill, but in your case might solve the issue.
I'm pretty sure this will solve your issue. If it doesn't I have a few more ideas.
Just wasted way too many hours on this. I'm not sure that this is what you are experiencing, but in my case I kept getting this exception because my NOTIFICATION_ID
was 0
... Using any other value seems to fix this.-_-