概述
最近打算把Android基础的一些知识再深入一点,所以就打算从四大组件开始入手,广播是经常使用的,但是也仅仅只停留在会用,却不知其原理,就着这个机会把源码给撸一遍吧。
public class MainActivity extends Activity{
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
registerReceiver(broadcastReceiver, new IntentFilter("broadcast_test"));
sendBroadcast(new Intent("broadcast_test"));
}
BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if(intent.getAction().equals("broadcast_test")){
Log.d("broadcast","receice");
}
}
};
@Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(broadcastReceiver);
}
}
本文不打算讲解广播的使用方法,就直接从动态注册广播开始好了,涉及到的源码为Android API 23。
上面demo中的registerReceiver(broadcastReceiver, new IntentFilter("broadcast_test"))执行的是ContextWrapper的方法:
@Override
public Intent registerReceiver(
BroadcastReceiver receiver, IntentFilter filter) {
return mBase.registerReceiver(receiver, filter);
}
ContextWrapper的真正方法实现类为ContextImpl,也就是说mBase是ContextImpl的实例,对于这一块不是很了解的朋友可以看郭霖大神的这篇博客Android Context完全解析,你所不知道的Context的各种细节,由于这部分源码很多加了/** {@hide} */的注释,所以在Android Studio里面不能直接看到相关代码,我们要到SDK的路径sdksourcesandroid-23androidapp下去查看相关代码。
class ContextImpl extends Context {
/*省略其它无关代码*/
@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());
}
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();//获取主线程的Handler
}
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的实例对象,mMainThread是ActivityThread的实例对象,IIntentReceiver是有一个接口,其对象rd是一个实现了Binder对象(我没有找到IIntentReceiver的源码,是查阅相关资料才知道的)。
public final class LoadedApk {
/*省略其它代码*/
private final ArrayMap<Context, ArrayMap<BroadcastReceiver, ReceiverDispatcher>> mReceivers
= new ArrayMap<Context, ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>>();
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) {
map = mReceivers.get(context);
if (map != null) {
rd = map.get(r);
}
}
if (rd == null) {
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();//最终返回一个Binder对象
}
}
static final class ReceiverDispatcher {
final static class InnerReceiver extends IIntentReceiver.Stub {
/*省略其它代码*/
}
final IIntentReceiver.Stub mIIntentReceiver;
ReceiverDispatcher(BroadcastReceiver receiver, Context context,
Handler activityThread, Instrumentation instrumentation,
boolean registered) {
/*省略其它代码*/
mIIntentReceiver = new InnerReceiver(this, !registered);
}
IIntentReceiver getIIntentReceiver() {
return mIIntentReceiver;
}
}
}
从LoadedApk的getReceiverDispatcher方法我们可以知道几点:
1、每一个注册的广播接收器都有对应的ReceiverDispatcher(即Binder对象)。
2、广播接收器和ReceiverDispatcher以键值对的形式存在map中。
3、存储广播接收器和ReceiverDispatcher的map与context也以键值对的形式存储在map中。
那么有一个问题来了,LoadedApk到底有什么用?它的注释文档就一句话“Local state maintained about a currently loaded .apk.”,大概意思就是当前加载的APK在内存中的状态,如果查看代码还会发现,它存储的还有Service等。
这时候该走到ContextWrapper.registerReceiverInternal的try-catch代码块了,在try中ActivityManagerNative.getDefault()方法返回一个ActivityManagerProxy对象,ActivityManagerProxy相关代码:
class ActivityManagerProxy implements IActivityManager {
/*省略其它代码*/
public ActivityManagerProxy(IBinder remote) {
mRemote = remote;
}
public Intent registerReceiver(IApplicationThread caller, String packageName,
IIntentReceiver receiver,
IntentFilter filter, String perm, int userId) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeStrongBinder(caller != null ? caller.asBinder() : null);
data.writeString(packageName);
data.writeStrongBinder(receiver != null ? receiver.asBinder() : null);
filter.writeToParcel(data, 0);
data.writeString(perm);
data.writeInt(userId);
//此处与ActivityServiceManager通信
mRemote.transact(REGISTER_RECEIVER_TRANSACTION, data, reply, 0);
reply.readException();
Intent intent = null;
int haveIntent = reply.readInt();
if (haveIntent != 0) {
intent = Intent.CREATOR.createFromParcel(reply);
}
reply.recycle();
data.recycle();
return intent;
}
}
关键代码mRemote.transact(REGISTER_RECEIVER_TRANSACTION, data, reply, 0);涉及到的进程间通信不是今天的内容,真要说我也说不清,我们就不深究了,只要知道它的作用就是调用了ActivityManagerService的注册方法。
ActivityManagerService的代码就不贴了,简单来说它的注册方法就是以调用方法的App的进程ID为唯一标识,生成一个ReceiverList存放所有注册的广播接收器。至此,就完成了广播接收器的注册过程,也就是说所有app的广播接收器都会存在ActivityManagerService中。
接下来就是广播的发送了,同样sendBroadcast(new Intent("broadcast_test"))方法的真正实现也是在ContextImpl中
class ContextImpl extends Context {
/*省略其它代码*/
public void sendBroadcast(Intent intent) {
warnIfCallingFromSystemProcess();
String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
try {
intent.prepareToLeaveProcess();
ActivityManagerNative.getDefault().broadcastIntent(
mMainThread.getApplicationThread(), intent, resolvedType, null,
Activity.RESULT_OK, null, null, null, AppOpsManager.OP_NONE, null, false, false,
getUserId());
} catch (RemoteException e) {
throw new RuntimeException("Failure from system", e);
}
}
}
ActivityManagerNative.getDefault()是不是很熟悉呢,没错,和注册一样都是调用了
ActivityManagerProxy的方法
class ActivityManagerProxy implements IActivityManager {
/*省略其它代码*/
public int broadcastIntent(IApplicationThread caller,
Intent intent, String resolvedType, IIntentReceiver resultTo,
int resultCode, String resultData, Bundle map,
String[] requiredPermissions, int appOp, Bundle options, boolean serialized,
boolean sticky, int userId) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeStrongBinder(caller != null ? caller.asBinder() : null);
intent.writeToParcel(data, 0);
data.writeString(resolvedType);
data.writeStrongBinder(resultTo != null ? resultTo.asBinder() : null);
data.writeInt(resultCode);
data.writeString(resultData);
data.writeBundle(map);
data.writeStringArray(requiredPermissions);
data.writeInt(appOp);
data.writeBundle(options);
data.writeInt(serialized ? 1 : 0);
data.writeInt(sticky ? 1 : 0);
data.writeInt(userId);
//此处与ActivityServiceManager通信
mRemote.transact(BROADCAST_INTENT_TRANSACTION, data, reply, 0);
reply.readException();
int res = reply.readInt();
reply.recycle();
data.recycle();
return res;
}
}
不一样的方法,还是熟悉的味道。发送广播也是调用的ActivityManagerService的方法,具体代码也不贴了(主要是我没有在6.0的源码里找到这个类)。
ActivityManagerService在发送的过程中的工作就是根据发送的广播的Action找到相应的广播接收器(手机上所有注册的广播接收器都在这里存着了,找一个还不容易嘛)。ActivityManagerService内部有一个Handler会循环处理发送的广播,处理的过程就是利用Binder机制将广播分发给相应的广播接收器的ReceiverDispatcher
static final class ReceiverDispatcher {
/*省略其它代码*/
final static class InnerReceiver extends IIntentReceiver.Stub {
final class Args extends BroadcastReceiver.PendingResult implements Runnable {
public void run() {
try {
ClassLoader cl = mReceiver.getClass().getClassLoader();
intent.setExtrasClassLoader(cl);
setExtrasClassLoader(cl);
receiver.setPendingResult(this);
receiver.onReceive(mContext, intent);
} catch (Exception e) {
}
}
}
}
}
ReceiverDispatcher实现了Runnable接口,最终会回调到相应BroadcastReceiver的onReceive方法。那么会在哪个线程中处理这个任务呢,还记得注册广播时的scheduler吗,就是在这个里面被post进去的。这样一来,整个广播的注册和发送接收事件就完成了。
我这里只是大致梳理了最基础的广播使用过程,没有对细节深入,仔细探索的话还有粘性广播的处理、广播优先级的处理、广播注销的处理等等,那我就不再多啰嗦啦。(再啰嗦一句,广播的这种订阅--发布过程就是观察者模式的体现)
参考资料 《Android源码设计模式解析与实践》
最后
以上就是瘦瘦睫毛为你收集整理的Android广播的源码解析的全部内容,希望文章能够帮你解决Android广播的源码解析所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复