FrameWork BroadcastReceiver 导致的can't deliver broadcast崩溃

294 阅读1分钟

前言

崩溃方法栈在ActivityThread中H(Handler)对象。由system_server进程通过binder发送过来的。

  1. 在onResume和onPause中注册/解注册BroadcastReceiver导致有几率出现上面崩溃,建议把BroadcastReceiver的注册放到onCreate和onDestory中。
  2. 使用LocalBroadcastManager来发送本地广播,如果监听的是系统广播,则没有办法使用

崩溃基本在API 30及以下机型,在Activity进入onPause生命周期后导致崩溃。

    void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver,
            Intent intent, int resultCode, String data, Bundle extras,
            boolean ordered, boolean sticky, int sendingUser)
            throws RemoteException {
        // Send the intent to the receiver asynchronously using one-way binder calls.
        if (app != null) {
            if (app.thread != null) {
                // If we have an app thread, do the call through that so it is
                // correctly ordered with other one-way calls.
                try {
                    // 通过 binder 通知客户端,最后会触发对应的 Broadcast#onReceive() 方法回调
                    app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
                            data, extras, ordered, sticky, sendingUser, app.getReportedProcState());
                // TODO: Uncomment this when (b/28322359) is fixed and we aren't getting
                // DeadObjectException when the process isn't actually dead.
                //} catch (DeadObjectException ex) {
                // Failed to call into the process.  It's dying so just let it die and move on.
                //    throw ex;
                } catch (RemoteException ex) {
                    // 通过 binder 通知应用进程出现错误
                    // Failed to call into the process. It's either dying or wedged. Kill it gently.
                    synchronized (mService) {
                        Slog.w(TAG, "Can't deliver broadcast to " + app.processName
                                + " (pid " + app.pid + "). Crashing it.");
                        // 将广播错误的信息,通知给应用进程        
                        app.scheduleCrash("can't deliver broadcast");
                    }
                    throw ex;
                }
            } else {
                // Application has died. Receiver doesn't exist.
                throw new RemoteException("app.thread must not be null");
            }
        } else {
            receiver.performReceive(intent, resultCode, data, extras, ordered,
                    sticky, sendingUser);
        }
    }
  1. 远端binder Service本身实现方法报错
  2. 通信本身中断导致报错