我们有一个Android应用程序,最近有很多ANR错误报告。这只发生在Android 7.1和8.0(不在例如4.4,5.0或6.0)。该ANR是:ANR错误“广播意图{act = com.google.firebase.INSTANCE_ID_EVENT”...“FirebaseInstanceIdInternalReceiver”适用于Android 7.1和8.0
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的任何菜鸟错误。
我很难再生这个bug。由于它只适用于Android 7.1和8.0,我认为它可能与新的打盹模式和节省电池有关,但即使使用adb shell dumpsys deviceidle force-idle
etc.而测试不会再现此问题,也不会在几个地方放置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();
}
}
}
我们使用谷歌播放服务和火力地堡版本11.2.0。我们的targetSdkVersion是25.
PS:上面的代码mAnalytics.init(...)
给了我们StrictMode警告,因为这个initializes 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注册令牌在安装后自动刷新。)
也看到这个,它对我来说是99.9%的Android 8.0。 –
[This adb command](https://developer.android.com/topic/performance/background-optimization.html#further-optimization)可能有助于重现此问题:'adb shell cmd appops set RUN_IN_BACKGROUND ignore '。 _模拟隐式广播和后台服务不可用的情况_ –
与我一样,大概100%的Android 8.0都有此ANR – ARLabs