BroadcastReceiver源码分析系列(一):注册广播

来源:互联网 发布:文心雕龙数据库有吗 编辑:程序博客网 时间:2024/05/21 07:57

BroadcastReceiver源码分析系列(一):注册广播

BroadcastReceiver是Android组件中最基本也是最为常见用的四大组件之一,分析BroadcastReceiver相关流以及源码可以加深对BroadcastReceiver的了解。本文先分析注册广播有点内容。

注册类型


注册广播分为静态注册和动态注册

静态注册

  • 静态注册是在AndroidManifest中注册,根据需求填写不同的intent-filter,接收相应匹配规则的广播,代码如下
  • intent-filter的匹配规则可见博主之前的Android隐式启动intent-filter详解
... <receiver android:name=".xxx.xxxReceiver">            <intent-filter>                <action android:name="xxx"/>            </intent-filter>        </receiver> ...
  • 静态注册是在应用安装或开机重启时被解析并注册

动态注册

  • 动态注册代码如下
BroadcastReceiver receiver = new BroadcastReceiver() {        @Override        public void onReceive(Context context, Intent intent) {            String action = intent.getAction();            if (TextUtils.isEmpty(action)) {                Log.d(TAG, "onReceive: " + action);            }        }    }; private void f(){        IntentFilter intentFilter = new IntentFilter();        intentFilter.addAction("xxx");        registerReceiver(receiver, intentFilter)    }
  • registerReceiver的具体实现在ContextImpl,最终调用到registerReceiverInternal(BroadcastReceiver receiver, int userId,
    IntentFilter filter, String broadcastPermission,
    Handler scheduler, Context context)
  • registerReceiverInternal首先根据当前BroadcastReceiver创建(获取)一个IIntentReceiver对象,IIntentReceiver是一个Binder接口可以在进程间传递。接着调用ActivityManagerNative.getDefault().registerReceiver,其实就是Binder调用AMS registerReceiver。
private Intent registerReceiverInternal(BroadcastReceiver receiver, int userId,            IntentFilter filter, String broadcastPermission,            Handler scheduler, Context context) {        IIntentReceiver rd = null;        if (receiver != null) {            if (mPackageInfo != null && context != null) {                if (scheduler == null) {                    scheduler = mMainThread.getHandler();                }                // 第一步获取IIntentReceiver,mPackageInfo是LoadedApk                rd = mPackageInfo.getReceiverDispatcher(                    receiver, context, scheduler,                    mMainThread.getInstrumentation(), true);            }            ...        }        try {        // 第二步,调用AMS的registerReceiver            final Intent intent = ActivityManagerNative.getDefault().registerReceiver(                    mMainThread.getApplicationThread(), mBasePackageName,                    rd, filter, broadcastPermission, userId);            return intent;        }        ...    }

LoadedApk

Local state maintained about a currently loaded .apk.
LoadedApk对象是APK文件在内存中的表示。 Apk文件的相关信息,诸如Apk文件的代码和资源,甚至代码里面的Activity,Service、Receiver等组件的信息我们都可以通过此对象获取。

  • 第一步调用LoadedApk的getReceiverDispatcher,将BroadcastReceiver转化为能在进程间传递的Binder接口——IIntentReceiver,因为BroadcastReceiver的注册是跨进程的。
  • IIntentReceiver的实现类是ReceiverDispatcher.InnerReceiver,ReceiverDispatcher里面保存了当前的BroadcastReceiver和相应的InnerReceiver。
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;            if (registered) {                 // private final ArrayMap<Context,            // ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>> mServices            // 根据当前的Context获取ArrayMap<BroadcastReceiver,            // LoadedApk.ReceiverDispatcher>                map = mReceivers.get(context);                if (map != null) {                // 如果存在,尝试根据当前的BroadcastReceiver获取ReceiverDispatcher                    rd = map.get(r);                }            }            if (rd == null) {              // 如果与BroadcastReceiver对应的ReceiverDispatcher不存在,创建一个保存了当前BroadcastReceiver的ReceiverDispatcher对象,                // 并将之前传入的主线的Handle保存,同时创建一个InnerReceiver对象保存                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 {             // 如果最开始就获取到ReceiverDispatcher,比如多次registerReceiver,                // 就会调用ReceiverDispatcher的validate判断此次registerReceiver是否合法                // validate的判断逻辑比较简单,1.判断当前的context是否和之前registerReceiver的一样 2.判断当前handler是否是主线程的handle                // 以上两个条件都满足的情况下正常执行,反之抛出相应的异常                rd.validate(context, handler);            }            rd.mForgotten = false;            return rd.getIIntentReceiver();        }    }

ActivityManagerService

public abstract class ActivityManagerNative extends Binder implements IActivityManager
public interface IActivityManager extends IInterface
从中可以看出ActivityManagerNative是一个Binder类,Activity的启动已经通过Binder调用转交到系统服务中了。
IActivityManager Binder具体实现是ActivityManagerService,最终调用到ActivityManagerService的registerReceiver
调用进入ActivityManagerService的进程

  • ActivityManagerService的registerReceiver,registerReceiver将当前的IIntentReceiver当做KEY,将ReceiverList当做VALUE,保存在mRegisteredReceivers中。
    将广播的filter保存在之前的ReceiverList和mReceiverResolver中,代码如下
public Intent registerReceiver(IApplicationThread caller, String callerPackage,            IIntentReceiver receiver, IntentFilter filter, String permission, int userId) {        ...        synchronized (this) {            ...            // 创建ReceiverList            ReceiverList rl = mRegisteredReceivers.get(receiver.asBinder());            if (rl == null) {                rl = new ReceiverList(this, callerApp, callingPid, callingUid,                        userId, receiver);                if (rl.app != null) {                    rl.app.receivers.add(rl);                }                 //  HashMap<IBinder, ReceiverList> mRegisteredReceivers                // 将IIntentReceiver=KEY,ReceiverList=VALUE,保存在mRegisteredReceivers                mRegisteredReceivers.put(receiver.asBinder(), rl);            }             BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage,                    permission, callingUid, userId);            // ReceiverList保存Filter            // ReceiverList extends ArrayList<BroadcastFilter>,可以添加多个Filter            rl.add(bf);            // mReceiverResolver保存Filter            mReceiverResolver.addFilter(bf);            ...            return sticky;        }    }

结论


流程图待补充

阅读全文
0 0