My app crashes when I try to display an Notification on my HUAWEI P8 lite device running Android 5.0.1 (it works fine on Nexus and Samsung devices). Most of my code is taken from the video Media playback the right way (Big Android BBQ 2015) by Ian Lake. All of my code is inside an Android Service. If I remove the code:
builder.setStyle(new android.support.v7.app.NotificationCompat.MediaStyle()
.setShowActionsInCompactView(0, 1)
.setMediaSession(mMediaSessionCompat.getSessionToken()).setShowCancelButton(true)
.setCancelButtonIntent(MediaStyleHelper.getActionIntent(this, KeyEvent.KEYCODE_MEDIA_STOP)));
Then the app does not crash and a notification is shown with a image and a title. But the Media Action buttons are missing.
StackTrace:
FATAL EXCEPTION:
main Process: com.app.debug, PID: 21600 android.app.RemoteServiceException:
Bad notification posted from package com.app.demo.debug: Couldn't expand RemoteViews for:
StatusBarNotification(pkg=com.app.demo.debug user=UserHandle{0} id=1344663 tag=null score=0 key=0|com.app.demo.debug|1344663|null|10121: Notification(pri=0 contentView=com.app.demo.debug/0x109007f vibrate=null sound=null defaults=0x0 flags=0x62 color=0x00000000 category=transport actions=2 vis=PUBLIC))
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1534)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5538)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:960)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755)
Code:
private void setUpAsForeground(Book book)
{
updateMetaData(book);
startForeground(NOTIFICATION_ID, setupAudioNotification());
}
public void updateMetaData(Book book)
{
if(mMediaSessionCompat!=null)
{
MediaMetadataCompat.Builder builder = new MediaMetadataCompat.Builder();
Bitmap bitmap = null;
if(!TextUtils.isEmpty(book.imageUrl))
{
bitmap = getBookCover(book.imageUrl);
if (bitmap != null) {
builder.putBitmap(MediaMetadataCompat.METADATA_KEY_ALBUM_ART, bitmap);
builder.putString(MediaMetadataCompat.METADATA_KEY_ALBUM_ART_URI, book.imageUrl);
}
}
if(bitmap == null && !TextUtils.isEmpty(book.imageUrlList))
{
bitmap = getBookCover(book.imageUrlList);
if (bitmap != null) {
builder.putBitmap(MediaMetadataCompat.METADATA_KEY_ALBUM_ART, bitmap);
builder.putString(MediaMetadataCompat.METADATA_KEY_ALBUM_ART_URI, book.imageUrlList);
}
}
builder.putText(MediaMetadataCompat.METADATA_KEY_AUTHOR, book.authers);
builder.putText(MediaMetadataCompat.METADATA_KEY_TITLE, book.title);
builder.putText(MediaMetadataCompat.METADATA_KEY_DISPLAY_SUBTITLE, getString(R.string.app_name));
//builder.putText(MediaMetadataCompat.METADATA_KEY_DISPLAY_DESCRIPTION, "");
long duration = getDuration();
if(duration!=-1)
{
builder.putLong(MediaMetadataCompat.METADATA_KEY_DURATION, duration);
}
mMediaSessionCompat.setMetadata(builder.build());
}
}
private Notification setupAudioNotification()
{
android.support.v7.app.NotificationCompat.Builder builder = MediaStyleHelper.from(this, mMediaSessionCompat);
builder.setColor(ContextCompat.getColor(this, R.color.my_black));
builder.setSmallIcon(R.drawable.ic_stat_notify);
setNotificationButtons(builder);
builder.setStyle(new android.support.v7.app.NotificationCompat.MediaStyle()
.setShowActionsInCompactView(0, 1)
.setMediaSession(mMediaSessionCompat.getSessionToken()).setShowCancelButton(true)
.setCancelButtonIntent(MediaStyleHelper.getActionIntent(this, KeyEvent.KEYCODE_MEDIA_STOP)));
mNotification = builder.build();
return mNotification;
}
private void setNotificationButtons(android.support.v7.app.NotificationCompat.Builder builder)
{
if(isPlaying())
{
builder.addAction(new NotificationCompat.Action(getStopIcon(), getString(R.string.player_stop_accessibility), MediaStyleHelper.getActionIntent(this, KeyEvent.KEYCODE_MEDIA_STOP)));
builder.addAction(new NotificationCompat.Action(getPauseIcon(), getString(R.string.player_pause_accessibility), MediaStyleHelper.getActionIntent(this, KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE)));
}
else
{
builder.addAction(new NotificationCompat.Action(getStopIcon(), getString(R.string.player_stop_accessibility), MediaStyleHelper.getActionIntent(this, KeyEvent.KEYCODE_MEDIA_STOP)));
builder.addAction(new NotificationCompat.Action(getPlayIcon(), getString(R.string.player_play_accessibility), MediaStyleHelper.getActionIntent(this, KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE)));
}
}
private int getStopIcon()
{
if(AppConstants.SUPPORTS_LOLLIPOP)
{
return R.drawable.notification_btn_stop_black;
}
else
{
return R.drawable.notification_btn_stop_white;
}
}
private int getPlayIcon()
{
if(AppConstants.SUPPORTS_LOLLIPOP)
{
return R.drawable.notification_btn_play_black;
}
else
{
return R.drawable.notification_btn_play_white;
}
}
private int getPauseIcon()
{
if(AppConstants.SUPPORTS_LOLLIPOP)
{
return R.drawable.notification_btn_pause_black;
}
else
{
return R.drawable.notification_btn_pause_white;
}
}
public static NotificationCompat.Builder from(
Context context, MediaSessionCompat mediaSession)
{
MediaControllerCompat controller = mediaSession.getController();
MediaMetadataCompat mediaMetadata = controller.getMetadata();
MediaDescriptionCompat description = mediaMetadata.getDescription();
NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
builder
.setContentTitle(description.getTitle())
.setContentText(description.getSubtitle())
.setSubText(description.getDescription())
.setLargeIcon(description.getIconBitmap())
.setContentIntent(controller.getSessionActivity())
.setDeleteIntent(getActionIntent(context, KeyEvent.KEYCODE_MEDIA_STOP))
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC);
return builder;
}
The best solution for me, as suggested by @KasperFinneNielsen in the comments was to set the MediaStyle on devices that are not Huawei running
Build.VERSION_CODES.LOLLIPOP_MR1
or
Build.VERSION_CODES.LOLLIPOP
So;
boolean isLollipopHuawei = (android.os.Build.VERSION.SDK_INT == Build.VERSION_CODES.LOLLIPOP_MR1 ||
android.os.Build.VERSION.SDK_INT == Build.VERSION_CODES.LOLLIPOP) && Build.MANUFACTURER.equalsIgnoreCase("HUAWEI");
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With