BroadcastReceiver详细分析之主要流程

本文详细分析了Android的BroadcastReceiver的注册、发送和接收流程。BroadcastReceiver作为Android四大组件之一,涉及进程间通信。注册过程从registerReceiver开始,通过AMS将广播注册。广播发送和接收都经过AMS,BroadcastQueue用于管理和调度广播。文中还强调了Android O后静态注册广播的限制,以及在进程未启动时如何处理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本篇代码基于原生Android Q

一.广播的基本使用

BroadcastReceiver是Android的四大组件之一,其重要性不言而喻。广播可以用来进程内主线程和子线程进行通信,也可以用于进程间通信。下面是广播的基本使用方法:

//定义广播
BroadcastReceiver receiver=new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        Toast.makeText(MainActivity.this,"这是xiaomiapp2",Toast.LENGTH_LONG).show();
    }
};
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    IntentFilter intentFilter=new IntentFilter("a.b.c");
    registerReceiver(receiver,intentFilter);            //注册广播
 
    ......
    Intent intent=new Intent();                         //发送广播
    intent.setAction("a.b.c");
    sendBroadcast(intent);

二.广播的注册过程

广播的注册过程从registerReceiver方法开始,我们知道,Context是个抽象类,子类有ContextImpl和ContextWrapper,ContextWrapper的子类有ContextThemeWrapper,我们的Activity继承于ContextThemeWrapper,而Service和Application则是直接继承于ContextWrapper。

registerReceiver方法Activity里面没有,ContextThemeWrapper里面也没有,ContextWrapper里面有,但是是调用的Context的registerReceiver方法,Context是抽象类,ContextImpl实现了这个方法,最终调用到了registerReceiverInternal方法:

这个方法主要干了两件事:

1.通过LoadedApk获得IIntentReceiver实例

2.通过ActivityManagerService将广播注册到AMS当中

    private Intent registerReceiverInternal(BroadcastReceiver receiver, int userId,
            IntentFilter filter, String broadcastPermission,
            Handler scheduler, Context context, int flags) {
        IIntentReceiver rd = null;
        if (receiver != null) {
            if (mPackageInfo != null && context != null) {
                if (scheduler == null) {
                    scheduler = mMainThread.getHandler(); //获取主线程的handler
                }
                rd = mPackageInfo.getReceiverDispatcher(  //获取IIntentReceiver实例
                    receiver, context, scheduler,
                    mMainThread.getInstrumentation(), true);
            } else {
                if (scheduler == null) {
                    scheduler = mMainThread.getHandler();
                }
                rd = new LoadedApk.ReceiverDispatcher(
                        receiver, context, scheduler, null, true).getIIntentReceiver();
            }
        }
        try {  //注册receiver注册到AMS
            final Intent intent = ActivityManager.getService().registerReceiver(
                    mMainThread.getApplicationThread(), mBasePackageName, rd, filter,
                    broadcastPermission, userId, flags);
            if (intent != null) {
                intent.setExtrasClassLoader(getClassLoader());
                intent.prepareToEnterProcess();
            }
            return intent;
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

1.LoadedApk获取IIntentReceiver实例,loadedApk为每个receiver生成一个receiverDispatcher,在receiverDispatcher的构造函数里面初始化IIntentReceiver,然后返回。

    public IIntentReceiver getReceiverDispatcher(BroadcastReceiver r,
            Context context, Handler handler,
            Instrumentation instrumentation, boolean registered) {
        synchronized (mReceivers) {
            LoadedApk.ReceiverDispatcher rd = null;
            ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> map = null; //定义map
            if (registered) {
                map = mReceivers.get(context);
                if (map != null) {
                    rd = map.get(r);
                }
            }
            if (rd == null) {
                //初始化ReceiverDispatcher
                rd = new ReceiverDispatcher(r, context, handler,  
                        instrumentation, registered);
                if (registered) {
                    if (map == null) {
                        map = new ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>();
                        mReceivers.put(context, map);
                    }
                    map.put(r, rd);
                }
            } else {
                rd.validate(context, handler);
            }
            rd.mForgotten = false;
            return rd.getIIntentReceiver(); //返回IIntentReceiver
        }
    }


        //ReceiverDispatcher构造函数
        ReceiverDispatcher(BroadcastReceiver receiver, Context context,
                Handler activityThread, Instrumentation instrumentation,
                boolean registered) {
            if (activityThread == null) {
                throw new NullPointerException("Handler must not be null");
            }

            //初始化IIntentReceiver,显然,是个InnerReceiver对象,关于这个,后面会讲到
            mIIntentReceiver = new InnerReceiver(this, !registered);
            mReceiver = receiver;
            mContext = context;
            mActivityThread = activityThread;
            mInstrumentation = instrumentation;
            mRegistered = registered;
            mLocation = new IntentReceiverLeaked(null);
            mLocation.fillInStackTrace();
        }

2.AMS注册广播,对于传入的IIntentReceiver,都会生成一个ReceiverList实例,每个ReceiverList实例对应多个BroadcastFilter,这里多说一句,同一个receiver可以注册多次,每次不同的filter都可以,这表示该receiver可以接收到的所有过滤器。

//IBinder对应前面传入的IIntentReceiver
final HashMap<IBinder, ReceiverList> mRegisteredReceivers = new HashMap<>();

   

 public Intent registerReceiver(IApplicationThread caller, String callerPackage,
            IIntentReceiver receiver, IntentFilter filter, String permission, int userId,
            int flags) {
        //......粘性广播的一些处理
        synchronized (this) {
            if (callerApp != null && (callerApp.thread == null
                    || callerApp.thread.asBinder() != caller.asBinder())) {  //校验
                // Original caller already died
                return null;
            }
            //获取receiverList,首次肯定没有
            ReceiverList rl = mRegisteredReceivers.get(receiver.asBinder());
            if (rl == null) {
                rl = new ReceiverList(this, callerApp, callingPid, callingUid,
                        userId, receiver);
                if (rl.app != null) { //校验app的receiver总数,最多1000
                    final int totalReceiversForApp = rl.app.receivers.size();
                    if (totalReceiversForApp >= MAX_RECEIVERS_ALLOWED_PER_APP) {
                        throw new IllegalStateException("Too many receivers, total of "
                                + totalReceiversForApp + ", registered for pid: "
                                + rl.pid + ", callerPackage: " + callerPackage);
                    }
                    rl.app.receivers.add(rl); //加入到APP的receiver列表中
                } else {
                    try {
                        receiver.asBinder().linkToDeath(rl, 0);
                    } catch (RemoteException e) {
                        return sticky;
                    }
                    rl.linkedToDeath = true;
                }
                //加入到mRegisteredReceivers中
                mRegisteredReceivers.put(receiver.asBinder(), rl); 
            } else if (rl.uid != callingUid) {
                throw new IllegalArgumentException(
                        "Receiver requested to register for uid " + callingUid
                        + " was previously registered for uid " + rl.uid
                        + " callerPackage is " + callerPackage);
            } else if (rl.pid != callingPid) {
                throw new IllegalArgumentException(
                        "Receiver requested to register for pid " + callingPid
                        + " was previously registered for pid " + rl.pid
                        + " callerPackage is " + callerPackage);
            } else if (rl.userId != userId) {
                throw new IllegalArgumentException(
                        "Receiver requested to register for user " + userId
                        + " was previously registered for user " + rl.userId
                        + " callerPackage is " + callerPackage);
            }
            //new一个BroadcastFilter
            BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage,
                    permission, callingUid, userId, instantApp, visibleToInstantApps);
            if (rl.containsFilter(filter)) {//校验rl里面是否已有,没
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值