首页 > 解决方案 > 取消注册在 Activity 上下文中注册的 BroadcastReceiver 会导致 IllegalArgumentException 崩溃

问题描述

坠机是非常奇怪的一次。

onStart中,注册了存储在 Activity 字段中的 BroadcastReceiver。在onStop中,此 BroadcastReceiver 未注册。当 BroadcastReceiver 注册成功后,我也设置了isRegisteredfieldtrue

但是,在 Crashlytics 中,我看到有时这会失败,并且整个应用程序因消息而崩溃IllegalArgumentExceptionReceiver not registered该消息源自android.app.LoadedApk#forgetReceiverDispatcher. 考虑到我检查了标志,这很奇怪,对吧?

在我查看了处理注册/注销ContextImplLoadedApk类并添加了一些基于反射的诊断之后,它变得更加神秘。简而言之,在每次这样的崩溃中,我都会提取现有的映射ContextBroadcastReceiver(参见ContextImpl.java:1590LoadedApk.java:1361)。

当它正常注销时,没有崩溃,我可以看到这样的地图:

com.mypackage.myapp.MyAppContext instance -> list of instances that are registered app wide
com.mypackage.myapp.MyActivity1 instance -> list of instances that are registered for Activity1
com.mypackage.myapp.MyActivity2 instance -> list of instances that are registered for Activity2
...

但是,如果发生崩溃,此地图将如下所示:

com.mypackage.myapp.MyAppContext instance -> list of instances that are registered app wide

即没有我BroadcastReceiver注册的活动,即使我从未打过电话unregisterReceiver

它只发生在一个特定的活动中,所以我的第一个猜测是这个活动以某种方式泄漏,onDestroy生命周期被调用,活动条目从接收者映射中删除,然后当我们尝试注销它时显然接收者不会在那里。但是,如果是这样的话,为什么在那onStop之后被调用onDestroy呢?为什么接收者列表完全是空的?

如果不是泄漏,那么什么会导致这种令人费解的行为呢?我真的希望其他人经历过这样的奇怪事件,并且可以帮助我,因为现在我完全没有想法。

标签: javaandroidbroadcastreceiver

解决方案


已编辑

只能说我感受到了痛苦。为了我自己的问题,我刚刚找到了一个解决方法,但是,为了回答你的问题,我真的深入研究了文档,所以更老的问题甚至写了简单的代码并自己检查了一些生命周期测试(虽然我已经找到了答案我错了)。我找不到此事件发生的原因,但要修复它,我建议将 register/unRegister 包装在 try catch 块中:

private void registerBroadcastReceiver() {
    try {
        appUpdateReceiver = new AppUpdateReceiver();
        registerReceiver(appUpdateReceiver, appUpdateIntentFilter);
    } catch (IllegalArgumentException e) {
        // already registered
    }
}

private void unRegisterBroadCastReceiver() {
    try {
        unregisterReceiver(appUpdateReceiver);
    } catch (IllegalArgumentException e) {
        // already unregistered
    }
}

请提供一些代码,以便社区可以更深入地研究这个问题。并感谢您提到 LoadedApk 类。


推荐阅读