前面已经写过Activity的启动流程:
http://blog.youkuaiyun.com/newhope1106/article/details/53355189 和 Service的启动流程:
http://blog.youkuaiyun.com/newhope1106/article/details/53843809 ,本篇是关于广播的,其实标题写得不准确,广播的注册、发送和接收应该是一起,下面开始讲解内容吧。
广播在android系统中,使用非常频繁,可以说是耦合度极低的一种通信方式。操作系统一方面为了让任务执行互不干扰,即使某个任务挂了,也不会影响其他的任务,因此才有了进程,但是任务之间通常又是相关的,又需要涉及到进程间的通信,当然进程间通信的方式有很多种,管道、信号、消息队列、共享内存等,socket也算是一种,android采用的是Binder,但是我们应用层开发的时候,基本上没有让我们直接操作Binder,也就是直接参与到进程间的通信细节,这样会给我们一种错觉,进程好像是一体的,通信很简单,android系统一方面将不同的任务放在不同的进程中,一方面又模糊进程的概念,让它看起来就是一个整体,确实相当了不起。废话不多说,直接看分析。
一、广播的注册过程
四大组件中,广播是唯一一个可以不需要在AndroidMenifest.xml中注册的组件,根据是否在AndroidMenifest.xml注册,分为静态广播和动态广播,此外还分为前台广播和后台广播,也分为有序广播和无序广播,分类挺多的,四大组件如果是在AndroidMenifest.xml注册的,注册过程由PMS来负责,我们这边只管动态广播,也就是在代码中注册的。先来看一个简单的广播注册例子:
//new出上边定义好的BroadcastReceiver
MyBroadCastReceiver smsBroadCastReceiver = new MyBroadCastReceiver();
//实例化过滤器并设置要过滤的广播
IntentFilter intentFilter = new IntentFilter("android.provider.Telephony.SMS_RECEIVED");
//注册广播
mContext.registerReceiver(smsBroadCastReceiver,intentFilter);
一个广播接收器,和一个过滤器,重点不是这个,主要讲register的过程,在Service的启动流程中,我们已经知道mContext就是ContextImpl,这里同样是这个类,从Activity和Service的启动流程应该已经看出来,基本都是套路了,涉及到进程间通信的,先转化为实现IBinder的对象,然后扔给AMS调用,接着再扔给某个对应的类来专门处理。广播的注册过程除了最后一个不满足(发送和接收是满足的),其实也是这个套路。先贴出几个调用的接口,最后都调用到了registerReceiverInternal里面。
@Override
public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
return registerReceiver(receiver, filter, null, null);
}
@Override
public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,
String broadcastPermission, Handler scheduler) {
return registerReceiverInternal(receiver, getUserId(),
filter, broadcastPermission, scheduler, getOuterContext());
}
@Override
public Intent registerReceiverAsUser(BroadcastReceiver receiver, UserHandle user,
IntentFilter filter, String broadcastPermission, Handler scheduler) {
return registerReceiverInternal(receiver, user.getIdentifier(),
filter, broadcastPermission, scheduler, getOuterContext());
}
再来看看这个方法的内容,由于广播涉及到进程间通信,它首先会讲receiver通过LoadedApk来转化为实现了IBinder接口的对象IIntentReceiver,再扔给AMS处理。
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();
}
rd = mPackageInfo.getReceiverDispatcher(
receiver, context, scheduler,
mMainThread.getInstrumentation(), true);
} else {
if (scheduler == null) {
scheduler = mMainThread.getHandler();
}
rd = new LoadedApk.ReceiverDispatcher(
receiver, context, scheduler, null, true).getIIntentReceiver();
}
}
try {
return ActivityManagerNative.getDefault().registerReceiver(
mMainThread.getApplicationThread(), mBasePackageName,
rd, filter, broadcastPermission, userId);
} catch (RemoteException e) {
return null;
}
}
可以关注下面这个代码,mPackageInfo是LoadedApk这个类的对象,具体代码是什么,感兴趣的可以自己看一下源码
rd = mPackageInfo.getReceiverDispatcher(
receiver, context, scheduler,
mMainThread.getInstrumentation(), true);
至于IIntentReceiver,它是在AIDL中写的,android编译的时候会把它先生成对应的类,可以看到只有一个performReceive接口,不多说,继续往下。
oneway interface IIntentReceiver {
void performReceive(in Intent intent, int resultCode, String data,
in Bundle extras, boolean ordered, boolean sticky, int sendingUser);
}
最后广播的注册过程都是调用到AMS的registerReceiver方法中,下面是方法的关键部分,最终receiver和intentfilter都被保存了起来。
public Intent registerReceiver(IApplicationThread caller, String callerPackage,
IIntentReceiver receiver, IntentFilter filter, String permission, int userId) {
......
synchronized (this) {
if (callerApp != null && (callerApp.thread == nul