广播机制做为android进程间通信的一个重要机制被广泛的使用。我承认已经到了滥用的地步。正因为如此,各方案公司甚至google都已经对它做修改限制,来达到控制大家滥用的目的。(这说明这个机制本身的设计还是很成功的,说明它对于使用者来说,简单、方便,耦合度低的特点)。 那么android是设计broadcast的这套机制的。我们来看一下大致的流程。 android的广播机制分为注册和接收两块。使用者将自己感兴趣的广播向系统注册,系统在接收到相应的广播后,会找到各个注册者,并调用onReceive。 看调用方式,以在activity中调用为例:
public class MainActivity extends Activity { private static final String Tag="TEST"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); IntentFilter filter = new IntentFilter("com.test.broadcast"); registerReceiver(receiver, filter); } @Override protected void onDestroy() { // TODO Auto-generated method stub super.onDestroy(); unregisterReceiver(receiver); } private BroadcastReceiver receiver = new BroadcastReceiver(){ public void onReceive(Context context, Intent intent) { Log.i(TAG, "Receive ...."); } }; }然后看Activity中是怎样处理registerReceiver(receiver, filter);的。发现Activity类中并没有直接实现该函数。再找它的父类ContextThemeWrapper,也没有,接着找ContextThemeWrapper的父类ContextWrapper:
public Intent registerReceiver( BroadcastReceiver receiver, IntentFilter filter) { return mBase.registerReceiver(receiver, filter); }调用了mBase的registerReceiver,mBase又是个什么东西呢? 它是一个ContextImpl ,为什么? 这要从launch一个android的应用说起,我把代码贴上来: 在ActivityThread.java中有:
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) { .... Context appContext = createBaseContextForActivity(r, activity); CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager()); Configuration config = new Configuration(mCompatConfiguration); if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity " + r.activityInfo.name + " with config " + config); activity.attach(appContext, this, getInstrumentation(), r.token, r.ident, app, r.intent, r.activityInfo, title, r.parent, r.embeddedID, r.lastNonConfigurationInstances, config); ..... 而createBaseContextForActivity代码是这样的: private Context createBaseContextForActivity(ActivityClientRecord r, final Activity activity) { ContextImpl appContext = new ContextImpl(); ... Context baseContext = appContext; ... return baseContext; }Activity.java的attach函数:
final void attach(Context context, ActivityThread aThread, Instrumentation instr, IBinder token, int ident, Application application, Intent intent, ActivityInfo info, CharSequence title, Activity parent, String id, NonConfigurationInstances lastNonConfigurationInstances, Configuration config) { attachBaseContext(context); . @Override protected void attachBaseContext(Context newBase) { super.attachBaseContext(newBase); mBase = newBase; }所以,mBase是一个ContextImpl的实例。 这是套路! 我们来看Context,ContextThemeWrapper,ContextWrapper和ContextImpl这几个类之间的关系类图(公司限制不能上传图片或文件,所以或许有一天这张图片失效了):
再看套路之装饰模式:
是不是很相似的感觉! 这就是套路! 这里说一下android的命名,其实android的命名还是很统一的,基本上从类或文件的命名上,就能看出端倪来。XXXWrapper就说明了问题,这对于我们看android代码很有帮助,后续会陆续说到android命名来看相关的代码。我们不可能把整个android的代码都背下来,但是,如果我们掌握了规律,找起代码来就会快一些。
继续跟踪ContextImpl里的
@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()); }转到registerReceiverInternal:
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的实例。看一下它的成员变量。
private final ActivityThread mActivityThread; private final ApplicationInfo mApplicationInfo; final String mPackageName; private final String mAppDir; private final String mResDir; private final String[] mSharedLibraries; private final String mDataDir; private final String mLibDir; private final File mDataDirFile; private final ClassLoader mBaseClassLoader; private final boolean mSecurityViolation; private final boolean mIncludeCode; private final DisplayAdjustments mDisplayAdjustments = new DisplayAdjustments(); Resources mResources; private ClassLoader mClassLoader; private Application mApplication; private final ArrayMap<Context, ArrayMap<BroadcastReceiver, ReceiverDispatcher>> mReceivers = new ArrayMap<Context, ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>>(); private final ArrayMap<Context, ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>> mUnregisteredReceivers = new ArrayMap<Context, ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>>(); private final ArrayMap<Context, ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>> mServices = new ArrayMap<Context, ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>>(); private final ArrayMap<Context, ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>> mUnboundServices = new ArrayMap<Context, ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>>();从它的成员变量看的出,这是个挺重要的类。尤其是成员变量ActivityThread mActivityThread。注意到mReceivers,看上去这个变量记录了应用的所有Receiver。
if (scheduler == null) { scheduler = mMainThread.getHandler(); }获得了主线程的handler.
rd = mPackageInfo.getReceiverDispatcher( receiver, context, scheduler, mMainThread.getInstrumentation(), true);这里的getReceiverDispatcher返回的是IIntentReceiver类型实例,Binder对象。而Binder用于IPC通信的,那么这个Binder对象要和谁进行IPC通信呢?应该是ActivityManagerService。 这个函数的实现:
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(); } }先从mReceivers中找rd,这里为空,所以就new 了一个ReceiverDispatcher,并将它放入mReceivers中记录下来。key是一个Context,这里指的就是我们的MainActiviy,所以通过一个activity可以找到对应的map,再通过BroadcastReceiver就可以找到相应的广播接收发布器ReceiverDispatcher了。(引:http://blog.csdn.net/luoshengyang/article/details/6737352)在新建广播接收发布器ReceiverDispatcher时,会在构造函数里面创建一个InnerReceiver实例,这是一个Binder对象,实现了IIntentReceiver接口,可以通过ReceiverDispatcher.getIIntentReceiver函数来获得,获得后就会把它传给ActivityManagerService,以便接收广播。在ReceiverDispatcher类的构造函数中,还会把传进来的Handle类型的参数activityThread保存下来,以便后面在分发广播的时候使用。 这样说来,ActivityManagerService就能找到对应的BroadcastReceiver,并且往对应的线程中发送消息了。而这个消息的响应函数应该就是BroadcastReceiver的onReceive函数了。 回到ContextImpl.registerReceiverInternal函数中,
return ActivityManagerNative.getDefault().registerReceiver( mMainThread.getApplicationThread(), mBasePackageName, rd, filter, broadcastPermission, userId);调用了ActivityManagerNative的内部类ActivityManagerProxy.registerReceiver:
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); 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; }这里直接调用Binder驱动,说明这个过程在使用IPC通信。所以真正的执行体转移到远程对象去了。这里使用了代理模式,特征命名ActivityManagerProxy。实际的实现者是在远端的ActivityManagerService. ActivityManagerService.registerReceiver:
public Intent registerReceiver(IApplicationThread caller, String callerPackage, IIntentReceiver receiver, IntentFilter filter, String permission, int userId) { ... ReceiverList rl = (ReceiverList)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); } else { try { receiver.asBinder().linkToDeath(rl, 0); } catch (RemoteException e) { return sticky; } rl.linkedToDeath = true; } mRegisteredReceivers.put(receiver.asBinder(), rl); ... BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage, permission, callingUid, userId); rl.add(bf); if (!bf.debugCheck()) { Slog.w(TAG, "==> For Dynamic broadast"); } mReceiverResolver.addFilter(bf); // Enqueue broadcasts for all existing stickies that match // this filter. if (allSticky != null) { ArrayList receivers = new ArrayList(); receivers.add(bf); int N = allSticky.size(); for (int i=0; i<N; i++) { Intent intent = (Intent)allSticky.get(i); BroadcastQueue queue = broadcastQueueForIntent(intent); BroadcastRecord r = new BroadcastRecord(queue, intent, null, null, -1, -1, null, null, AppOpsManager.OP_NONE, receivers, null, 0, null, null, false, true, true, -1); queue.enqueueParallelBroadcastLocked(r); queue.scheduleBroadcastsLocked(); } }mRegisteredReceivers.put(receiver.asBinder(), rl);将receiver记录下来, BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage, permission, callingUid, userId); rl.add(bf); 这里将filter与receiver关联在了一起,然后记录下来: mReceiverResolver.addFilter(bf);
到这里,整个注册过程完成。注册的信息由客户端调用最终被ActivityManagerService记录在两个成员变量mReceiverResolver和mRegisteredReceivers中。
