如何解决:android.app.RemoteServiceException: Bad notification posted from package *: Couldn't create icon: StatusBarIcon。

153
我在崩溃日志中看到了以下异常信息:
android.app.RemoteServiceException: Bad notification posted from package com.my.package: Couldn't create icon: StatusBarIcon(pkg=com.my.package user=0 id=0x7f02015d level=0 visible=true num=0 )
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1456)
    at android.os.Handler.dispatchMessage(Handler.java:102)
    at android.os.Looper.loop(Looper.java:146)
    at android.app.ActivityThread.main(ActivityThread.java:5487)
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:515)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1283)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1099)
    at dalvik.system.NativeStart.main(Native Method)

我正在使用以下方法从AlarmManager设置的PendingIntent中的IntentService发布我的通知。所有传递的值都来自PendingIntent / IntentService中的bundle extras。

/**
 * Notification 
 *
 * @param c
 * @param intent
 * @param notificationId
 * @param title
 * @param message
 * @param largeIcon
 * @param smallIcon
 */
public static void showNotification(Context c, Intent intent,
        int notificationId, String title, String message, int largeIcon,
        int smallIcon) {
    PendingIntent detailsIntent = PendingIntent.getActivity(c,
            notificationId, intent, PendingIntent.FLAG_UPDATE_CURRENT);

    // BUILD
    NotificationCompat.Builder mNotifyBuilder = new NotificationCompat.Builder(
            c);
    // TITLE
    mNotifyBuilder.setContentTitle(title).setContentText(message);

    // ICONS
    mNotifyBuilder.setSmallIcon(smallIcon);
    if (Util.isAndroidOSAtLeast(Build.VERSION_CODES.HONEYCOMB)) {
        Bitmap large_icon_bmp = ((BitmapDrawable) c.getResources()
                .getDrawable(largeIcon)).getBitmap();
        mNotifyBuilder.setLargeIcon(large_icon_bmp);
    }

    mNotifyBuilder.setContentIntent(detailsIntent);
    mNotifyBuilder.setVibrate(new long[] { 500, 1500 });
    mNotifyBuilder.setTicker(message);
    mNotifyBuilder.setContentText(message);

    // NOTIFY
    NotificationManager nm = (NotificationManager) c
            .getSystemService(Context.NOTIFICATION_SERVICE);
    nm.notify(notificationId, mNotifyBuilder.build());
}

从我看到的其他答案来看,我遇到的异常是因为setSmallIcon()没有被正确调用。

我已经检查并重复检查了传递的资源ID都是正确的。


3
我遇到了同样的错误(来自实时应用程序的崩溃报告),但在我的设备上无法复现。我目前认为这可能是因为有人修改了.apk文件。 - darken
大家好,我想问一下有什么方法可以解决这个问题?我使用PNG格式的图片,但是有时会导致应用程序崩溃。 - Roman Soviak
26个回答

114

发生的情况是,我在PendingIntent bundle中包含了图标的整数引用,而该整数稍后在发布到NotificationManager时被引用。

在获取整数引用和执行pending intent之间,应用程序已经更新,所有可绘制资源的引用都发生了变化。曾经引用正确可绘制资源的整数现在可能引用错误的可绘制资源或根本不引用任何一个(没有引用任何可绘制资源 - 导致崩溃)。


13
奇怪。换句话说,这不能被修复了吗?我在我的应用程序中也看到了相同的崩溃。 - mxk
看起來似乎無法修復。將來我必須想出一種不同的方法來發布帶有圖像的通知... - FishStix
2
当应用程序被杀死以进行更新时,清除通知和所有相关内容是否可能?(假设这将使应用程序避免出现问题) - NoHarmDan
4
如果您想引用R.drawable.my_image,请将其作为字符串保存到bundle中(bundle.putString("img", "my_image")),然后在需要时将其转换为实际的@DrawableRes整数,如下所示:ctx.resources.getIdentifier(bundle.getString("img"), "drawable", ctx.packageName) - vanomart
请问您能否展示一下您在代码中的操作?不太确定您所说的“整数引用”是什么意思 - 难道它们不都是整数引用吗? - strangetimes
显示剩余6条评论

57

使用VectorXml在您的通知中已知会导致此问题。请使用PNG。


5
只使用PNG格式的图片。 - FishStix
1
在我的情况下,我有一个向量在drawable文件夹中,而png文件在drawable-hdpixhdpi等文件夹中。但是在drawable-mdpi中没有png文件,在发布通知时在MDPI设备上崩溃了。 - Vadim Kotov

38

不要在Kitkat上使用SVG!

每次我想在Kitkat上显示通知时都会遇到相同的问题。导致问题的原因是我用XML(从SVG)定义了每个图标,包括小图标和操作图标。当我把它们替换成PNG时,问题就解决了。


8
我可以确认,通知中的矢量图会在KitKat上引起RemoteServiceException异常。 - Khizhny Andrey
2
在KitKat的情况下,当我将XML替换为PNG时,问题得到了解决:new NotificationCompat.Builder(context, CHANNEL_ID).setSmallIcon(R.drawable.my_icon)。 - Andrew Glukhoff
1
这对我有用。我正在运行API 19,并使用SVG文件作为通知图标,但一直出现错误,直到我将其切换为小的png图标。 - WHOATEMYNOODLES

12

我的问题是我使用的图标在

.setSmallIcon(R.drawable.ic_stat_push_notif)

根据官方文档,需要提供适合各种屏幕密度的图标。为此,最好使用Roman Nurik在https://romannurik.github.io/AndroidAssetStudio/index.html上提供的Notification Generator来生成通知图标的不同大小。

这样做的最重要的一点是,如果图标生成器在浏览您要使用的图像后显示了一个白色填充的圆形或正方形,则说明您的图像存在问题,可能是因为它没有任何透明度,因此请确保您已经解决了这个问题。


2
在我的情况下,我有一个向量在drawable文件夹中,而png文件在drawable-hdpixhdpi等文件夹中。但是在drawable-mdpi中没有png文件,在发布通知时在MDPI设备上崩溃了。 - Vadim Kotov

11

android.app.RemoteServiceException: 通知发布出错

我也遇到过同样的问题,但已解决。我的问题出在远程视图的 ".xml 文件" 上。

在我的 xml 文件中,我在 LinearLayout 中间添加了一个 View 当作分隔线。

<View
    android:layout_width="match_parent"
    android:layout_height="1dp"
    android:id="@+id/view"
    android:background="#000000" />

上面的View组件创建了错误通知异常。这个异常原因只有Remoteviews的xml文件。

移除那个View组件后,我的代码正常执行,没有任何异常。所以我感觉通知抽屉不接受任何自定义视图。

因此,在RemoteView对象的.xml文件中不要绘制任何类似上面的视图。


“View” 不受支持? - Shubham AgaRwal

9
在我的应用程序中,这种错误只会在升级期间发生。如果资源ID在新版本中更改,则Android RemoteView可能无法找到该资源并抛出RemoteServiceException。如果您发布第3个版本并且不更改资源ID,则错误可能仅暂时消失。
通过编辑res/values/public.xmlres/values/ids.xml可以减少此类错误。如果资源ID不在public.xmlids.xml中,则编译器将生成单独的资源ID。当您更改资源名称或添加一些新资源时,ID可能会更改,某些设备可能无法找到它。
因此,步骤如下:
  1. 反编译apk文件,在res/values中找到public.xmlids.xml
  2. 查找与您的应用程序中的RemoteView相关的所有资源,并复制它们(字符串、dimen、drawable、layout、id、color...)
  3. 在您的源代码中的res/values下创建public.xmlids.xml,并粘贴刚刚复制的行
注意:
Gradle 1.3.0及以上版本忽略本地public.xml。为使其正常工作,您需要在build.gradle中添加一些脚本。
afterEvaluate {
    for (variant in android.applicationVariants) {
        def scope = variant.getVariantData().getScope()
        String mergeTaskName = scope.getMergeResourcesTask().name
        def mergeTask = tasks.getByName(mergeTaskName)
        mergeTask.doLast {
            copy {
                int i=0
                from(android.sourceSets.main.res.srcDirs) {
                    include 'values/public.xml'
                    rename 'public.xml', (i == 0? "public.xml": "public_${i}.xml")
                    i++
                }
                into(mergeTask.outputDir)
            }
        }
    }
}

注意: 此脚本不支持子模块项目。我正在尝试修复它。


6
在Android Studio 3.0.0及以上版本中,向drawable文件夹添加新图像时,请选择drawable而不是drawable-v24。enter image description here如果您使用的图像已经是(v24),只需将其复制并粘贴到相同的目录中(例如drawables)。这次它会问你要常规还是v24-确保不是v24,然后再试一次,这应该可以解决错误。

1
注意 - 如果您在“Android”视图中,请切换到“项目”视图。在Android视图中,您可能看不到drawables v24目录。 - Richard Miller
我认为这对我来说很好用。你可以将那个向量 XML 文件放在 drawable 和 drawable v24 中。那些 Android 版本小于或等于 Marsha Mellow 的设备将从 drawable 文件夹中获取它,而新版本将从 drawable v24 中获取它。 - Yosidroid
是的,这在我的情况下发生过,我的Mipmap只适用于v26。 - ashishdhiman2007

5

如果图标不重要,你可以进行替换。

R.drawable.your_icon

To

android.R.drawable.some_standard_icon

这个有效!


所以你打算妥协使用自定义/个人图标啦 :) - undefined

4
当我在继承自FirebaseMessagingService的类中使用通知时,出现了RemoteServiceException。我已经在AndroidManifest.xml中添加了以下代码:
<meta-data
android:name="com.google.firebase.messaging.default_notification_icon"
android:resource="@drawable/ic_small" />

另外,通过方法setSmallIcon(int icon)可以在Notification.Builder类的实例中设置资源ic_small。


这些元数据必须添加在<service></service>标签内部吗? - Andrey Solera

4

如果您的应用程序正在更新时有可见通知,则可能会遇到此问题。您可能需要创建一个等待 PACKAGE_CHANGED 消息的广播接收器,此时您需要关闭所有服务,这也将关闭它们关联的通知。

 <receiver android:name=".MyBroadcastReceiver">
    <intent-filter>
        <action android:name="android.intent.action.PACKAGE_CHANGED" />
    </intent-filter>
</receiver>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接