前面文章《android--監聽SMS》中簡單實現了接受短信信息的功能,下面棘突分析一下源碼是怎麼實現的。 java
廣播接收者的註冊分爲靜態註冊和動態註冊,在AndroidManifest.xml中配置的屬於靜態註冊,而動態註冊須要調用context中的registerReceiver方法進行註冊。 android
此次咱們對動態註冊進行分析 app
一、代碼以下: ide
IntentFilter counterActionFilter = new IntentFilter(CounterService.BROADCAST_COUNTER_ACTION); registerReceiver(counterActionReceiver, counterActionFilter);
註釋: this
(1)、IntentFilter 顧名思義,IntentFilter對象負責過濾掉組件沒法響應和處理的Intent,只將本身關心的Intent接收進來進行處理。 IntentFilter實行「白名單」管理,即只列出組件樂意接受的Intent,但IntentFilter只會過濾隱式Intent,顯式的Intent會直接傳送到目標組件。 Android組件能夠有一個或多個IntentFilter,每一個IntentFilter之間相互獨立,只須要其中一個驗證經過則可。 spa
建立IntentFilter對象的源碼: debug
public class IntentFilter implements Parcelable { private int mPriority; private final ArrayList<String> mActions; public IntentFilter(String action) { mPriority = 0; mActions = new ArrayList<String>(); addAction(action); } 。。。 }
把CounterService.BROADCAST_COUNTER_ACTION字符串放到了mActions中。 代理
2、registerReceiver的源碼: code
public class ContextWrapper extends Context { Context mBase; public ContextWrapper(Context base) { mBase = base; } @Override public Intent registerReceiver( BroadcastReceiver receiver, IntentFilter filter) { return mBase.registerReceiver(receiver, filter); } 。。。 }
mBase是ContextImpl對象。 xml
三、mBase.registerReceiver(receiver, filter)的源碼:
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, filter, broadcastPermission, scheduler, getOuterContext()); } private Intent registerReceiverInternal(BroadcastReceiver receiver, 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(), rd, filter, broadcastPermission); } catch (RemoteException e) { return null; } } 。。。 }
註釋:
(1)經過getReceiverDispatcher()將廣播接收者封裝成實現IintentReceiver接口的binder本地對象rd。
3.1 mPackageInfo.getReceiverDispatcher()的源碼:
public IIntentReceiver getReceiverDispatcher(BroadcastReceiver r, Context context, Handler handler, Instrumentation instrumentation, boolean registered) { synchronized (mReceivers) { LoadedApk.ReceiverDispatcher rd = null; HashMap<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 HashMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>(); mReceivers.put(context, map); } map.put(r, rd); } } else { rd.validate(context, handler); } return rd.getIIntentReceiver(); } }
3.2 new ReceiverDispatcher 的源碼:
final static class InnerReceiver extends IIntentReceiver.Stub { final WeakReference<LoadedApk.ReceiverDispatcher> mDispatcher; final LoadedApk.ReceiverDispatcher mStrongRef; InnerReceiver(LoadedApk.ReceiverDispatcher rd, boolean strong) { mDispatcher = new WeakReference<LoadedApk.ReceiverDispatcher>(rd); mStrongRef = strong ? rd : null; } } final IIntentReceiver.Stub mIIntentReceiver; final BroadcastReceiver mReceiver; final Context mContext; final Handler mActivityThread; final Instrumentation mInstrumentation; final boolean mRegistered; ReceiverDispatcher(BroadcastReceiver receiver, Context context, Handler activityThread, Instrumentation instrumentation, boolean registered) { if (activityThread == null) { throw new NullPointerException("Handler must not be null"); } mIIntentReceiver = new InnerReceiver(this, !registered); mReceiver = receiver; mContext = context; mActivityThread = activityThread; mInstrumentation = instrumentation; mRegistered = registered; mLocation = new IntentReceiverLeaked(null); mLocation.fillInStackTrace(); } IIntentReceiver getIIntentReceiver() { return mIIntentReceiver; }
mReceiver表示廣播接受者
mContext表示activity組件,也就是這個廣播接受者在哪個activity中註冊的。
mActivityThread表示與activity相關的handle
mIIntentReceiver指向了建立的ReceiverDispatcher對象。
(2)ActivityManagerNative. getDefault()得到是ActivityManagerProxy對象
總結:activity組件在註冊一個廣播接收者時,並非真的將廣播接收者註冊到ActivityManagerService中,而是將與它相關聯的IntentReceiver對象註冊到ActivityManagerService中,當ActivityManagerService接受到一個廣播的時候,他就會根據廣播的類型在內部找到對應的IntentReceiver對象,而後再經過他找到廣播接收者。
四、ActivityManagerProxy中怎麼實現的registerReceiver方法 ,源碼:
public Intent registerReceiver(IApplicationThread caller, IIntentReceiver receiver, IntentFilter filter, String perm) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeInterfaceToken(IActivityManager.descriptor); data.writeStrongBinder(caller != null ? caller.asBinder() : null); data.writeStrongBinder(receiver != null ? receiver.asBinder() : null); filter.writeToParcel(data, 0); data.writeString(perm); 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代理對象mRemote向ActivityManagerService發送一個類型爲REGISTER_RECEIVER_TRANSACTION的進程間通訊請求。
五、ActivityManagerService中的源碼:
public final class ActivityManagerService extends ActivityManagerNative implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback { public Intent registerReceiver(IApplicationThread caller, IIntentReceiver receiver, IntentFilter filter, String permission) { synchronized(this) { ProcessRecord callerApp = null; if (caller != null) { callerApp = getRecordForAppLocked(caller); if (callerApp == null) { throw new SecurityException( "Unable to find app for caller " + caller + " (pid=" + Binder.getCallingPid() + ") when registering receiver " + receiver); } } List allSticky = null; // Look for any matching sticky broadcasts... Iterator actions = filter.actionsIterator(); if (actions != null) { while (actions.hasNext()) { String action = (String)actions.next(); allSticky = getStickiesLocked(action, filter, allSticky); } } else { allSticky = getStickiesLocked(null, filter, allSticky); } // The first sticky in the list is returned directly back to // the client. Intent sticky = allSticky != null ? (Intent)allSticky.get(0) : null; if (DEBUG_BROADCAST) Slog.v(TAG, "Register receiver " + filter + ": " + sticky); if (receiver == null) { return sticky; } ReceiverList rl = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder()); if (rl == null) { rl = new ReceiverList(this, callerApp, Binder.getCallingPid(), Binder.getCallingUid(), 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, permission); 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); BroadcastRecord r = new BroadcastRecord(intent, null, null, -1, -1, null, receivers, null, 0, null, null, false, true, true); if (mParallelBroadcasts.size() == 0) { scheduleBroadcastsLocked(); } mParallelBroadcasts.add(r); } } return sticky; } } 。。。 }
註釋:
建立一個BroadcastFilter,用來描述正在註冊的廣播接收者。廣播註冊到這就分析完了。