У нас есть приложение для Android, которое в последнее время имеет много ошибок ANR. Это происходит только на Android 7.1 и 8.0 (не на, например, 4.4, 5.0 или 6.0). ANR:
Broadcast of Intent { act=com.google.firebase.INSTANCE_ID_EVENT flg=0x14 cmp=com.our.package.name/com.google.firebase.iid.FirebaseInstanceIdInternalReceiver (has extras) }
Вопрос: Почему мы получаем этот ANR и что можем сделать, чтобы этого избежать? Обратите внимание, что это работает на ранних версиях Android, что, на мой взгляд, доказывает, что мы не делать какие-либо ошибки новобранец, вызывающие ANR.
Мне очень сложно воспроизвести эту ошибку. Поскольку это только на Android 7.1 и 8.0, я думаю, что это может иметь отношение к новому режиму доза и экономии батареи, но даже при использовании adb shell dumpsys deviceidle force-idle
и т.д. В то время как тестирование не воспроизводит эту проблему, не помещает в SystemClock.sleep(20000);
несколько мест.
Наш код для InstanceIdService
:
public class InstanceIdService extends FirebaseInstanceIdService {
private Analytics mAnalytics;
@Override
public void onCreate() {
super.onCreate();
mAnalytics = new AnalyticsImpl();
boolean isFullVersion = getApplicationContext().getPackageName().endsWith("full");
mAnalytics.init(getApplicationContext(), isFullVersion);
}
@Override
public void onTokenRefresh() {
boolean initialLoginSucceeded = OurAppNameApplication.getInstance().getSettings().getInitialLoginSucceeded();
mAnalytics.logEvent("FCM_Token_Refresh_Triggered", "initialLoginSucceeded", String.valueOf(initialLoginSucceeded));
if (initialLoginSucceeded) { // We only report the FCM token to our server if the user has logged in at least once
OurAppNameApplication.getInstance().getOurAppNameService().registerDeviceWithRetry();
}
}
}
Мы используем Службы Google Play и Firebase версии 11.2.0. Наше targetSdkVersion - 25.
PS: код mAnalytics.init(...)
выше дает нам предупреждение StrictMode, так как этот инициализирует Flurry. Но это доступ к диску, а не сетевой трафик. И размещение SystemClock.sleep(20000);
в этом месте не вызывает никакого ANR.
Почему мы получаем ANR, и что мы можем сделать, чтобы этого избежать?
-
Изменить:. В соответствии с предложением в комментарии Боба Снайдера я попытался протестировать с помощью adb shell cmd appops set com.our.package.name RUN_IN_BACKGROUND ignore
. Тем не менее, это не дает никакого ANR, это только останавливает работу нашего широковещательного приемника, как показано в logcat:
09-21 10:39:25.314 943-6730/? W/ActivityManager: Background start not allowed: service Intent { act=com.google.firebase.INSTANCE_ID_EVENT pkg=com.our.package.name cmp=com.our.package.name/com.our.package.service.notifications.InstanceIdService (has extras) } to com.our.package.name/com.our.package.service.notifications.InstanceIdService from pid=4062 uid=10139 pkg=com.our.package.name
09-21 10:39:25.314 4062-4062/com.our.package.name E/FirebaseInstanceId: Error while delivering the message: ServiceIntent not found.
Мое заключение состоит в том, что это может быть неправильный способ воспроизвести эту ошибку ANR.
Для полноты: все команды ADB, используемые при тестировании:
adb shell dumpsys deviceidle force-idle
adb shell dumpsys battery unplug
adb shell am set-inactive com.our.package.name true
adb install -r our-app.apk
adb shell cmd appops set com.our.package.name RUN_IN_BACKGROUND ignore
(На самом деле - последняя строка выполняется много раз параллельно с adb install
, поэтому мы уверены, что она вступает в силу до того, как будет выполнена установка и восстановление (настроек), а токен регистрации Firebase автоматически обновится после установки. )