Как исправить 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)
Я нашел много подобных сообщений о сбоях и статей в сети. Вот несколько из них:
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 - это мип-карта. Может быть это так? Но я не смог найти никаких проблем, касающихся Xiaomi и mipmaps.
В отчете о сбое всегда упоминается один и тот же идентификатор ресурса в нескольких версиях приложения: 0x7f0200ad. Это особенное по какой-то причине? Как я могу перепроектировать наше приложение, чтобы получить имя ресурса для этого?
РЕДАКТИРОВАТЬ 2:
- Я выполнил обратное проектирование приложения с помощью apktool, но идентификатор ресурса отсутствует в public.xml, что, по-видимому, эквивалентно R.java. Наши ic_notification и ic_launcher находятся в списке с другим идентификатором. Так это системный ресурс, который 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, и вы должны использовать уведомление по приведенной выше ссылке.
Кто-нибудь еще пострадал использовать это?
2 ответа
У меня та же проблема, что и у пользователя. Я считаю, что это вызвано следующим кодом - декомпилирован из APK У меня нет исходного кода, это из ярлыка
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);
Обновить:
Я понимаю, что происходит сейчас... Какой-то странный код в ярлыке. resolInfo - это стандартное домашнее средство запуска (MIUI home), а resolInfo.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, и это должно происходить только в приложениях, использующих приведенный выше код.
Мы купили Redmi Note 4X. Вот что случилось:
Устройство было на MIUI 8.5. Уведомления работают как положено. Не вылетает.
Мы обновились до MIUI 9.5 через OTA обновления. Странные уведомления начали появляться, когда мы открывали приложение или переключались между определенными экранами. Нет сбоев до сих пор.
Мы обновились до MIUI 10.1 через OTA обновления. Сбой приложения при запуске с предыдущей версией приложения. Сбой исчез, когда я обновил ShortcutBadger до версии 1.1.22. Ясно, что это произошло из-за того, что устройства Xiaomi не выполняют метод applyCount() в новой версии библиотеки (вместо этого они должны использовать applyNotification()), но я не стал копать глубже.
Я оставляю вопрос и награду открытой для всех, кто может подробно объяснить, что произошло. В противном случае мы довольны этим результатом. В следующем выпуске я, вероятно, постараюсь исправить значки и уведомления для Xiaomi, так как они не отображаются должным образом.