android - 无法在华为设备上展开 RemoteViews : MediaSessionCompat and NotificationCompat. MediaStyle

标签 android android-notifications android-mediasession

当我尝试在运行 Android 5.0.1 的 HUAWEI P8 lite 设备上显示通知时,我的应用程序崩溃(它在 Nexus 和三星设备上运行良好)。我的大部分代码取自 Ian Lake 的视频媒体播放正确方式(Big Android BBQ 2015)。我所有的代码都在 Android 服务中。如果我删除代码:

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)));

然后应用程序不会崩溃,并且会显示带有图像和标题的通知。但是缺少媒体操作按钮。

堆栈跟踪:

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)

代码:

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;
}

最佳答案

正如@KasperFinneNielsen 在评论中所建议的,对我来说最好的解决方案是在非华为运行的设备上设置 MediaStyle

Build.VERSION_CODES.LOLLIPOP_MR1 

Build.VERSION_CODES.LOLLIPOP

所以;

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");

关于android - 无法在华为设备上展开 RemoteViews : MediaSessionCompat and NotificationCompat. MediaStyle,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34851943/

相关文章:

android - 电话 session 应用程序

java - 在另一个 View 周围的圆圈中动态添加 View

android - import com.handmark 无法解析

android - 单击耳机按钮时应用程序崩溃

java - 服务器重置后无法通过 firebase 接收消息

push-notification - 使用 getStream.io 推送通知

android - 使用 Intent.FLAG_ACTIVITY_MULTIPLE_TASK 安全吗?

java - 当 MySQL 中有任何更新时在 android 中获取通知

android - Android 媒体 Controller 与传输控件的区别

android - 无法解析符号 'MediaSessionCompat'