Как исправить специфичное для Xiaomi исключение RemoteServiceException со значком уведомления?

У нас есть много сбоев, характерных для телефонов Xiaomi на Android 6 и 7:

Fatal Exception: android.app.RemoteServiceException: Bad notification posted from package x.y.z: Couldn't create icon: StatusBarIcon(icon=Icon(typ=RESOURCE pkg=x.y.z id=0x7f0200ad) visible user=0 )
   at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1715)
   at android.os.Handler.dispatchMessage(Handler.java:102)
   at android.os.Looper.loop(Looper.java:163)
   at android.app.ActivityThread.main(ActivityThread.java:6358)
   at java.lang.reflect.Method.invoke(Method.java)
   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:880)
   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:770)

Я нашел много подобных отчетов о сбоях и статей в сети. Вот некоторые из них:

Как исправить: android.app.RemoteServiceException: Плохое уведомление отправлено из пакета *: Не удалось создать значок: StatusBarIcon

https://medium.com/@Miqubel/the-story-of-a-hard-to-fix-bug-ac6ed819cb49

Но разница в том, что у нас эти проблемы только на телефонах Xiaomi (Android 6 и 7) и, вероятно, не во время обновлений, так как у одних и тех же пользователей несколько раз происходит сбой в одной и той же версии выпуска.

Интересно, что я не смог найти ничего в сети по этому конкретному случаю, и у нас нет телефонов Xiaomi.

Я установил уведомление примерно так:

NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
        int importance = NotificationManager.IMPORTANCE_HIGH;
        NotificationChannel notificationChannel = new NotificationChannel(NOTIFICATION_CHANNEL_ID, NOTIFICATION_CHANNEL_NAME, importance);
        notificationChannel.enableLights(true);
        notificationManager.createNotificationChannel(notificationChannel);
    }
    NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID)
            .setSmallIcon(R.drawable.ic_notification)
            .setPriority(NotificationCompat.PRIORITY_MAX)
            .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher))
            .setContentText(body == null ? "" : body)
            .setAutoCancel(true)
            .setContentIntent(PendingIntent.getActivity(
                    context,
                    0,
                    pendingIntent,
                    PendingIntent.FLAG_UPDATE_CURRENT
            ));

У нас также есть уведомления Facebook, которые нужно настроить аналогичным образом, но в другом классе уведомлений. Я не знаю, актуально ли это. Кто-нибудь сталкивался с этим или имел какие-либо рекомендации, как это исправить, кроме переноса методов setSmallIcon и/или setLargeIcon в проверку версии производителя и Android?

РЕДАКТИРОВАТЬ: я не смог найти решение, но вот несколько новых мыслей:

  • Мы выпустили новую версию, но исключение пользователей Xiaomi из уведомления не помогло! Теперь я думаю, что проблема вызвана пользовательским кодом в ActivityThread.java. MIUI, вероятно, запускает уведомление отсюда о каком-то событии. Здесь есть несколько десятков событий в стоковом Android, но ни одно из них не вызывает уведомление. Но что-то не так с нашими иконками, поэтому они вылетают.

  • А что не так с нашими иконами? У нас есть ic_notification, который, вероятно, не используется для этого. С другой стороны, ic_launcher — это mipmap. Может быть, это? Но я не смог найти никаких проблем, связанных с Xiaomi и mipmaps.

  • В отчете о сбое всегда упоминается один и тот же идентификатор ресурса в нескольких версиях приложения: 0x7f0200ad. Это по какой-то причине особенное? Как я могу перепроектировать наше приложение, чтобы получить имя ресурса для этого?

РЕДАКТИРОВАТЬ 2:

  • Я реконструировал приложение с помощью apktool, но идентификатора ресурса нет в public.xml, который кажется эквивалентным R.java. Наши ic_notification и ic_launcher находятся в списке с другим id. Так это системный ресурс, который MIUI не может найти?

РЕДАКТИРОВАТЬ 3:

  • Первое свидетельство того, что у других такая же проблема:

https://xiaomi.eu/community/threads/miui-9.47247/

  • Временное решение найдено на польском форуме:

https://pl.forum.elvenar.com/index.php?threads/problem-z-uruchomieniem-23566.3348/

Последний комментарий переводится как: «У нас есть временное решение проблемы с Xiaomi, попробуйте отключить принудительные уведомления из приложения Elvenar в настройках телефона. После перезапуска приложения ошибка должна исчезнуть».

РЕДАКТИРОВАТЬ 4:

Мы используем ShortcutBadger (версия 1.1.13). Здесь говорится, что мы должны использовать другой метод для значков Xiaomi:

https://github.com/leolin310148/ShortcutBadger/wiki/Xiaomi-Device-Support

Сразу после версии 1.1.13 они удалили поддержку по умолчанию для Xiaomi, и вам нужно использовать уведомление по ссылке выше.

Кто-нибудь еще пострадавший использует это?


person Herrbert74    schedule 10.12.2018    source источник
comment
Вы когда-нибудь пытались использовать drawable-anydpi-v21?   -  person 6155031    schedule 17.12.2018
comment
Нет, ic_notification — это простой png в пяти плотностях. Но ic_launcher — это мипмап. Интересно, MIUI умеет обрабатывать мипмапы? Через несколько часов я обновлю свой вопрос новыми выводами по этому вопросу (пока нет решения, это еще хуже).   -  person Herrbert74    schedule 17.12.2018
comment
подсказка: Xiaomi имеет собственную систему уведомлений.   -  person Martin Zeitler    schedule 18.12.2018
comment
В моем приложении с начала декабря 2018 года также началось много сбоев на устройствах Redmi, и этого не происходит на других устройствах.   -  person KgaboL    schedule 18.12.2018
comment
0x7f0200ad. Это по какой-то причине особенное? Как я могу перепроектировать наше приложение, чтобы получить имя ресурса для этого? Нажмите ctrl и нажмите «R», чтобы найти идентификатор. проверьте ic_launcher и ic_notification. Посмотрите, совпадают ли они.   -  person Aaditya Brahmbhatt    schedule 19.12.2018
comment
@AadityaBrahmbhatt Я думаю, это дает мне только локальные идентификаторы, и они отличаются от идентификаторов выпуска. И мы уже установили выше (на основе реального реверс-инжиниринга), что в приложении нет совпадения id.   -  person Herrbert74    schedule 19.12.2018


Ответы (2)


У меня такая же проблема как у пользователя. Я полагаю, что это вызвано следующим кодом - декомпилирован из APK. У меня нет исходного кода, он взят из shortcutbadger

ResolveInfo.getIconResource() вернул недопустимый идентификатор ресурса (0x7f0200ad, одинаковый для всех приложений и похоже, что только в MIUI10), что привело к сбою.

iget-object v1, p0, Lme/leolin/shortcutbadger/impl/XiaomiHomeBadger;->a:Landroid/content/pm/ResolveInfo;

invoke-virtual/range {v1 .. v1}, Landroid/content/pm/ResolveInfo;->getIconResource()I

move-result v1

invoke-virtual {p1, v1}, Landroid/app/Notification$Builder;->setSmallIcon(I)Landroid/app/Notification$Builder;

Простое решение для пользователя — полностью отключить уведомление для этого приложения — по крайней мере, сделать его пригодным для использования.

Как разработчик, может быть проще использовать вместо этого собственный значок или добавить некоторую обработку ошибок в ярлыке.

builder.setSmallIcon(R.drawable.myicon);

Обновление:

Теперь я понимаю, что происходит... Какой-то странный код в ярлык. resolveInfo — это действие по умолчанию для домашней программы запуска (MIUI home), а resolveInfo.getIconResource() — это значок домашней панели miui.

@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
private void tryNewMiuiBadge(Context context, int badgeCount) throws ShortcutBadgeException {
if (resolveInfo == null) {
    Intent intent = new Intent(Intent.ACTION_MAIN);
    intent.addCategory(Intent.CATEGORY_HOME);
    resolveInfo = context.getPackageManager().resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY);
}

if (resolveInfo != null) {
    NotificationManager mNotificationManager = (NotificationManager) context
            .getSystemService(Context.NOTIFICATION_SERVICE);
    Notification.Builder builder = new Notification.Builder(context)
            .setContentTitle("")
            .setContentText("")
            .setSmallIcon(resolveInfo.getIconResource());
    Notification notification = builder.build();

и декомпилировал из miuihome.apk, вот 0x7f0200ad.

<public type="drawable" name="icon_launcher" id="0x7f0200ad" />

Итак, почему стороннее приложение пытается установить значок уведомления со значком miui home? это какой-то хак для совместимости или просто ошибка? Я пишу простое приложение с приведенным выше фрагментом кода, тестирую на эмуляторе, и оно терпит неудачу, но не приводит к сбою приложения, может быть такой же случай на старой MIUI, поскольку setSmallIcon(resID) ищет значок с resID из собственного пакета. Хорошая новость заключается в том, что это не ошибка MIUI10, и она должна происходить только в приложениях, использующих приведенный выше код.

person Chris.C    schedule 21.12.2018
comment
Итак, почему стороннее приложение пытается установить значок уведомления со значком miui home? Я думаю, они сделали это, пытаясь заставить его работать на Xiaomi. Реальный вопрос заключается в том, почему (почти) каждый производитель должен делать настройки, которые не нужны и просто вызывают у нас головную боль? - person Herrbert74; 15.01.2019
comment
Теперь я думаю, что это просто какой-то ошибочный код, который никогда не обнаруживался, поскольку он не имеет никакого смысла ... В старом MIUI getIconResource () либо возвращает (более низкое) значение, которое оказалось доступным в большинстве приложений, так что даже это не работает , это не приведет к сбою, или он решит продолжить работу вместо сбоя. - person Chris.C; 18.01.2019

Мы купили Redmi Note 4X. Вот что произошло:

  • Устройство было на MIUI 8.5. Уведомления работают как положено. Никаких сбоев.

  • Мы обновились до MIUI 9.5 через OTA-обновления. Странные уведомления стали появляться, когда мы открывали приложение или переключались между определенными экранами. Сбоев до сих пор нет.

  • Мы обновились до MIUI 10.1 через обновления OTA. Приложение вылетало при запуске с предыдущей версией приложения. Сбой исчез, когда я обновил ShortcutBadger до 1.1.22. Понятно, что это произошло из-за того, что устройства Xiaomi не выполняют метод applyCount() в новой версии библиотеки (вместо них приходится использовать applyNotification()), но я не стал копать глубже.

Я держу вопрос и щедрость открытыми для всех, кто может подробно объяснить, что произошло. В остальном мы пока довольны этим результатом. В следующем выпуске я, вероятно, попытаюсь исправить значки и уведомления для Xiaomi, так как они не отображаются должным образом.

person Herrbert74    schedule 21.12.2018
comment
Я не использую ShortcutBadger, и пользователь только что сообщил об этом сегодня, вы нашли основную причину? любое решение? - person SagiLow; 19.03.2019
comment
@SagiLow решение состоит в том, чтобы обновиться до последней версии, я не копал глубже. С библиотекой много проблем, а точнее с множеством типов телефонов и лаунчеров, так что у вас может быть другая проблема. - person Herrbert74; 20.03.2019