20

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;
}
Kasper Finne Nielsen
  • 2,086
  • 2
  • 17
  • 28
  • 1
    Got same issue on the same device running same system version. So it's probably issue with that phone model & Android version. Have you found what exactly causes this problem? – Kocus Feb 17 '16 at 10:04
  • 8
    No. I have filed a bug report to Huewei, but I dont know if they are doing anything about it. My solution right now is to have an if condition like this: boolean isHuawei = (android.os.Build.VERSION.SDK_INT == Build.VERSION_CODES.LOLLIPOP_MR1 || android.os.Build.VERSION.SDK_INT == Build.VERSION_CODES.LOLLIPOP) && Build.MANUFACTURER.toLowerCase(Locale.getDefault()).contains("huawei"); and then remove this line if isHuawei is true: builder.setStyle(new android.support.v7.app.NotificationCompat.MediaStyle() – Kasper Finne Nielsen Feb 17 '16 at 13:02
  • Well, that is exactly the same solution as mine. I have blacklisted setStyle on all 5.0 and 5.1 huawei's. If you will get the answer from Huawei, please post it! – Kocus Feb 17 '16 at 16:17
  • Thanks, i've been looking for this. I would accept @KasperFinneNielsen as answer :) – Rui Santos Feb 23 '16 at 12:27
  • @Kocus: Are there reasons to blacklist 5.1? I got a 13k crashes, but all on 5.0. – Roy Solberg May 02 '16 at 07:56
  • @KasperFinneNielsen: Is there a public URL to the Huawei bug? And thank you for the workaround btw. :) – Roy Solberg May 02 '16 at 07:56
  • 1
    this is the answer I received: Thank you for contacting Huawei. We apologize for the inconvenience caused. This request has been escalated to the relevant department. Please be advised that, you may receive a call or email regard this issue from the relevant department. Should you have further enquiries, please do not hesitate to contact us at 1800 22 0086. Our lines are open Mondays to Sundays from 9.00AM to 9.00PM and for further support, please visit http://consumer.huawei.com/my/support/ Thank you and best regards, Thinnesh. Huawei Support Team. – Kasper Finne Nielsen May 03 '16 at 05:25
  • I just had the same issue here with users using the model 503HW OS: 5.0.1 Anyone knows if it needs to blacklist 5.1 as well? – gaijinboy Jul 30 '16 at 04:44
  • 1
    I have come to the conclusion that you should avoid custom notifications layout in general – Kasper Finne Nielsen Jul 31 '16 at 08:12
  • @gaijinboy this does affect 5.1 as well unfortunately (i tried and got a few crashes with 5.1 on at least 2 or 3 Huawei devices). – ahmedre Sep 01 '16 at 04:41

1 Answers1

2

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");
Ndivhuwo
  • 280
  • 2
  • 10
  • Thanks, this works for me except for now I get a weird message asking me to allow pushing of messages to notifications, any idea how to get around that? https://stackoverflow.com/q/54874512/704836 – casolorz Feb 26 '19 at 02:55
  • Hi @casolorz, I am not 100% sure how to get rid of that, but it seems to me that the device is prompting you for notifications permissions that would usually be found in the apps permissions. Have you tried testing on different devices to see if this occurs? Also, I don't know if you've tried using the latest constructor for NotificationCompat: NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(context, Constants.NOTIFICATION_CHANNEL_ID) – Ndivhuwo Feb 26 '19 at 08:42
  • Doesn't happen on any other devices as far as I can tell. Very weird. – casolorz Feb 26 '19 at 17:08