原文出處——>[Android應用程序發送廣播(sendBroadcast)的過程分析](http://blog.csdn.net/luoshengyang/article/details/6744448)
前面我們分析了Android應用程序注冊廣播接收器的過程,這個過程只完成了萬里長征的第一步,接下來它還要等待ActivityManagerService將廣播分發過來。ActivityManagerService是如何得到廣播并把它分發出去的呢?這就是本文要介紹的廣播發送過程了。
廣播的發送過程比廣播接收器的注冊過程要復雜得多了,不過這個過程仍然是以ActivityManagerService為中心。廣播的發送者將廣播發送到ActivityManagerService,ActivityManagerService接收到這個廣播以后,就會在自己的注冊中心查看有哪些廣播接收器訂閱了該廣播,然后把這個廣播逐一發送到這些廣播接收器中,但是ActivityManagerService并不等待廣播接收器處理這些廣播就返回了,因此,廣播的發送和處理是異步的。概括來說,廣播的發送路徑就是從發送者到ActivityManagerService,再從ActivityManagerService到接收者,這中間的兩個過程都是通過Binder進程間通信機制來完成的,因此,希望讀者在繼續閱讀本文之前,對Android系統的Binder進程間通信機制有所了解,具體可以參考Android進程間通信(IPC)機制Binder簡要介紹和學習計劃一文。
本文繼續以Android系統中的廣播(Broadcast)機制簡要介紹和學習計劃一文中所開發的應用程序為例子,并且結合上文Android應用程序注冊廣播接收器(registerReceiver)的過程分析的內容,一起來分析Android應用程序發送廣播的過程。
回顧一下Android系統中的廣播(Broadcast)機制簡要介紹和學習計劃一文中所開發的應用程序的組織架構,MainActivity向ActivityManagerService注冊了一個CounterService.BROADCAST_COUNTER_ACTION類型的計數器服務廣播接收器,計數器服務CounterService在后臺線程中啟動了一個異步任務(AsyncTask),這個異步任務負責不斷地增加計數,并且不斷地將當前計數值通過廣播的形式發送出去,以便MainActivity可以將當前計數值在應用程序的界面線程中顯示出來。
計數器服務CounterService發送廣播的代碼如下所示:
~~~
public class CounterService extends Service implements ICounterService {
......
public void startCounter(int initVal) {
AsyncTask<Integer, Integer, Integer> task = new AsyncTask<Integer, Integer, Integer>() {
@Override
protected Integer doInBackground(Integer... vals) {
......
}
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
int counter = values[0];
Intent intent = new Intent(BROADCAST_COUNTER_ACTION);
intent.putExtra(COUNTER_VALUE, counter);
sendBroadcast(intent);
}
@Override
protected void onPostExecute(Integer val) {
......
}
};
task.execute(0);
}
......
}
~~~
在onProgressUpdate函數中,創建了一個BROADCAST_COUNTER_ACTION類型的Intent,并且在這里個Intent中附加上當前的計數器值,然后通過CounterService類的成員函數sendBroadcast將這個Intent發送出去。CounterService類繼承了Service類,Service類又繼承了ContextWrapper類,成員函數sendBroadcast就是從ContextWrapper類繼承下來的,因此,我們就從ContextWrapper類的sendBroadcast函數開始,分析廣播發送的過程。
在繼承分析廣播的發送過程前,我們先來看一下廣播發送過程的序列圖,然后按照這個序圖中的步驟來一步一步分析整個過程。

**Step 1. ContextWrapper.sendBroadcast**
這個函數定義在frameworks/base/core/java/android/content/ContextWrapper.java文件中:
~~~
public class ContextWrapper extends Context {
Context mBase;
......
@Override
public void sendBroadcast(Intent intent) {
mBase.sendBroadcast(intent);
}
......
}
~~~
這里的成員變量mBase是一個ContextImpl實例,這里只簡單地調用ContextImpl.sendBroadcast進一行操作。
**Step 2. ContextImpl.sendBroadcast**
這個函數定義在frameworks/base/core/java/android/app/ContextImpl.java文件中:
~~~
class ContextImpl extends Context {
......
@Override
public void sendBroadcast(Intent intent) {
String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
try {
ActivityManagerNative.getDefault().broadcastIntent(
mMainThread.getApplicationThread(), intent, resolvedType, null,
Activity.RESULT_OK, null, null, null, false, false);
} catch (RemoteException e) {
}
}
......
}
~~~
這里的resolvedType表示這個Intent的MIME類型,我們沒有設置這個Intent的MIME類型,因此,這里的resolvedType為null。接下來就調用ActivityManagerService的遠程接口ActivityManagerProxy把這個廣播發送給ActivityManagerService了。
**Step 3. ActivityManagerProxy.broadcastIntent**
這個函數定義在frameworks/base/core/java/android/app/ActivityManagerNative.java文件中:
~~~
class ActivityManagerProxy implements IActivityManager
{
......
public int broadcastIntent(IApplicationThread caller,
Intent intent, String resolvedType, IIntentReceiver resultTo,
int resultCode, String resultData, Bundle map,
String requiredPermission, boolean serialized,
boolean sticky) 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.writeString(requiredPermission);
data.writeInt(serialized ? 1 : 0);
data.writeInt(sticky ? 1 : 0);
mRemote.transact(BROADCAST_INTENT_TRANSACTION, data, reply, 0);
reply.readException();
int res = reply.readInt();
reply.recycle();
data.recycle();
return res;
}
......
}
~~~
這里的實現比較簡單,把要傳遞的參數封裝好,然后通過Binder驅動程序進入到ActivityManagerService的broadcastIntent函數中。
**Step 4. ctivityManagerService.broadcastIntent**
這個函數定義在frameworks/base/services/java/com/android/server/am/ActivityManagerService.java文件中:
~~~
public final class ActivityManagerService extends ActivityManagerNative
implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
......
public final int broadcastIntent(IApplicationThread caller,
Intent intent, String resolvedType, IIntentReceiver resultTo,
int resultCode, String resultData, Bundle map,
String requiredPermission, boolean serialized, boolean sticky) {
synchronized(this) {
intent = verifyBroadcastLocked(intent);
final ProcessRecord callerApp = getRecordForAppLocked(caller);
final int callingPid = Binder.getCallingPid();
final int callingUid = Binder.getCallingUid();
final long origId = Binder.clearCallingIdentity();
int res = broadcastIntentLocked(callerApp,
callerApp != null ? callerApp.info.packageName : null,
intent, resolvedType, resultTo,
resultCode, resultData, map, requiredPermission, serialized,
sticky, callingPid, callingUid);
Binder.restoreCallingIdentity(origId);
return res;
}
}
......
}
~~~
這里調用broadcastIntentLocked函數來進一步處理。
**Step 5. ActivityManagerService.broadcastIntentLocked**
這個函數定義在frameworks/base/services/java/com/android/server/am/ActivityManagerService.java文件中:
~~~
public final class ActivityManagerService extends ActivityManagerNative
implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
......
private final int broadcastIntentLocked(ProcessRecord callerApp,
String callerPackage, Intent intent, String resolvedType,
IIntentReceiver resultTo, int resultCode, String resultData,
Bundle map, String requiredPermission,
boolean ordered, boolean sticky, int callingPid, int callingUid) {
intent = new Intent(intent);
......
// Figure out who all will receive this broadcast.
List receivers = null;
List<BroadcastFilter> registeredReceivers = null;
try {
if (intent.getComponent() != null) {
......
} else {
......
registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);
}
} catch (RemoteException ex) {
......
}
final boolean replacePending =
(intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
if (!ordered && NR > 0) {
// If we are not serializing this broadcast, then send the
// registered receivers separately so they don't wait for the
// components to be launched.
BroadcastRecord r = new BroadcastRecord(intent, callerApp,
callerPackage, callingPid, callingUid, requiredPermission,
registeredReceivers, resultTo, resultCode, resultData, map,
ordered, sticky, false);
......
boolean replaced = false;
if (replacePending) {
for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
if (intent.filterEquals(mParallelBroadcasts.get(i).intent)) {
......
mParallelBroadcasts.set(i, r);
replaced = true;
break;
}
}
}
if (!replaced) {
mParallelBroadcasts.add(r);
scheduleBroadcastsLocked();
}
registeredReceivers = null;
NR = 0;
}
......
}
......
}
~~~
這個函數首先是根據intent找出相應的廣播接收器:
~~~
// Figure out who all will receive this broadcast.
List receivers = null;
List<BroadcastFilter> registeredReceivers = null;
try {
if (intent.getComponent() != null) {
......
} else {
......
registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);
}
} catch (RemoteException ex) {
......
}
~~~
回憶一下前面一篇文章Android應用程序注冊廣播接收器(registerReceiver)的過程分析中的Step 6(ActivityManagerService.registerReceiver)中,我們將一個filter類型為BROADCAST_COUNTER_ACTION類型的BroadcastFilter實例保存在了ActivityManagerService的成員變量mReceiverResolver中,這個BroadcastFilter實例包含了我們所注冊的廣播接收器,這里就通過mReceiverResolver.queryIntent函數將這個BroadcastFilter實例取回來。由于注冊一個廣播類型的接收器可能有多個,所以這里把所有符合條件的的BroadcastFilter實例放在一個List中,然后返回來。在我們這個場景中,這個List就只有一個BroadcastFilter實例了,就是MainActivity注冊的那個廣播接收器。
繼續往下看:
~~~
final boolean replacePending =
(intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
~~~
這里是查看一下這個intent的Intent.FLAG_RECEIVER_REPLACE_PENDING位有沒有設置,如果設置了的話,ActivityManagerService就會在當前的系統中查看有沒有相同的intent還未被處理,如果有的話,就有當前這個新的intent來替換舊的intent。這里,我們沒有設置intent的Intent.FLAG_RECEIVER_REPLACE_PENDING位,因此,這里的replacePending變量為false。
再接著往下看:
~~~
int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
if (!ordered && NR > 0) {
// If we are not serializing this broadcast, then send the
// registered receivers separately so they don't wait for the
// components to be launched.
BroadcastRecord r = new BroadcastRecord(intent, callerApp,
callerPackage, callingPid, callingUid, requiredPermission,
registeredReceivers, resultTo, resultCode, resultData, map,
ordered, sticky, false);
......
boolean replaced = false;
if (replacePending) {
for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
if (intent.filterEquals(mParallelBroadcasts.get(i).intent)) {
......
mParallelBroadcasts.set(i, r);
replaced = true;
break;
}
}
}
if (!replaced) {
mParallelBroadcasts.add(r);
scheduleBroadcastsLocked();
}
registeredReceivers = null;
NR = 0;
}
~~~
前面我們說到,這里得到的列表registeredReceivers的大小為1,且傳進來的參數ordered為false,表示要將這個廣播發送給所有注冊了BROADCAST_COUNTER_ACTION類型廣播的接收器,因此,會執行下面的if語句。這個if語句首先創建一個廣播記錄塊BroadcastRecord,里面記錄了這個廣播是由誰發出的以及要發給誰等相關信息。由于前面得到的replacePending變量為false,因此,不會執行接下來的if語句,即不會檢查系統中是否有相同類型的未處理的廣播。
這樣,這里得到的replaced變量的值也為false,于是,就會把這個廣播記錄塊r放在ActivityManagerService的成員變量mParcelBroadcasts中,等待進一步處理;進一步處理的操作由函數scheduleBroadcastsLocked進行。
**Step 6. ActivityManagerService.scheduleBroadcastsLocked**
這個函數定義在frameworks/base/services/java/com/android/server/am/ActivityManagerService.java文件中:
~~~
public final class ActivityManagerService extends ActivityManagerNative
implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
......
private final void scheduleBroadcastsLocked() {
......
if (mBroadcastsScheduled) {
return;
}
mHandler.sendEmptyMessage(BROADCAST_INTENT_MSG);
mBroadcastsScheduled = true;
}
......
}
~~~
這里的mBroadcastsScheduled表示ActivityManagerService當前是不是正在處理其它廣播,如果是的話,這里就先不處理直接返回了,保證所有廣播串行處理。
注意這里處理廣播的方式,它是通過消息循環來處理,每當ActivityManagerService接收到一個廣播時,它就把這個廣播放進自己的消息隊列去就完事了,根本不管這個廣播后續是處理的,因此,這里我們可以看出廣播的發送和處理是異步的。
這里的成員變量mHandler是一個在ActivityManagerService內部定義的Handler類變量,通過它的sendEmptyMessage函數把一個類型為BROADCAST_INTENT_MSG的空消息放進ActivityManagerService的消息隊列中去。這里的空消息是指這個消息除了有類型信息之外,沒有任何其它額外的信息,因為前面已經把要處理的廣播信息都保存在mParcelBroadcasts中了,等處理這個消息時,從mParcelBroadcasts就可以讀回相關的廣播信息了,因此,這里不需要把廣播信息再放在消息內容中。
**Step 7. Handler.sendEmptyMessage**
這個自定義的Handler類實現在frameworks/base/services/java/com/android/server/am/ActivityManagerService.java文件中,它是ActivityManagerService的內部類,調用了它的sendEmptyMessage函數來把一個消息放到消息隊列后,一會就會調用它的handleMessage函數來真正處理這個消息:
~~~
public final class ActivityManagerService extends ActivityManagerNative
implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
......
final Handler mHandler = new Handler() {
public void handleMessage(Message msg) {
switch (msg.what) {
......
case BROADCAST_INTENT_MSG: {
......
processNextBroadcast(true);
} break;
......
}
}
}
......
}
~~~
這里又調用了ActivityManagerService的processNextBroadcast函數來處理下一個未處理的廣播。
**Step 8. ActivityManagerService.processNextBroadcast**
這個函數定義在frameworks/base/services/java/com/android/server/am/ActivityManagerService.java文件中:
~~~
public final class ActivityManagerService extends ActivityManagerNative
implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
......
private final void processNextBroadcast(boolean fromMsg) {
synchronized(this) {
BroadcastRecord r;
......
if (fromMsg) {
mBroadcastsScheduled = false;
}
// First, deliver any non-serialized broadcasts right away.
while (mParallelBroadcasts.size() > 0) {
r = mParallelBroadcasts.remove(0);
......
final int N = r.receivers.size();
......
for (int i=0; i<N; i++) {
Object target = r.receivers.get(i);
......
deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false);
}
addBroadcastToHistoryLocked(r);
......
}
......
}
}
......
}
~~~
這里傳進來的參數fromMsg為true,于是把mBroadcastScheduled重新設為false,這樣,下一個廣播就能進入到消息隊列中進行處理了。前面我們在Step 5中,把一個廣播記錄塊BroadcastRecord放在了mParallelBroadcasts中,因此,這里就把它取出來進行處理了。廣播記錄塊BroadcastRecord的receivers列表中包含了要接收這個廣播的目標列表,即前面我們注冊的廣播接收器,用BroadcastFilter來表示,這里while循環中的for循環就是把這個廣播發送給每一個訂閱了該廣播的接收器了,通過deliverToRegisteredReceiverLocked函數執行。
**Step 9. ActivityManagerService.deliverToRegisteredReceiverLocked**
這個函數定義在frameworks/base/services/java/com/android/server/am/ActivityManagerService.java文件中:
~~~
public final class ActivityManagerService extends ActivityManagerNative
implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
......
private final void deliverToRegisteredReceiverLocked(BroadcastRecord r,
BroadcastFilter filter, boolean ordered) {
boolean skip = false;
if (filter.requiredPermission != null) {
......
}
if (r.requiredPermission != null) {
......
}
if (!skip) {
// If this is not being sent as an ordered broadcast, then we
// don't want to touch the fields that keep track of the current
// state of ordered broadcasts.
if (ordered) {
......
}
try {
......
performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,
new Intent(r.intent), r.resultCode,
r.resultData, r.resultExtras, r.ordered, r.initialSticky);
......
} catch (RemoteException e) {
......
}
}
}
......
}
~~~
函數首先是檢查一下廣播發送和接收的權限,在我們分析的這個場景中,沒有設置權限,因此,這個權限檢查就跳過了,這里得到的skip為false,于是進入下面的if語句中。由于上面傳時來的ordered參數為false,因此,直接就調用performReceiveLocked函數來進一步執行廣播發送的操作了。
**Step 10. ActivityManagerService.performReceiveLocked**
這個函數定義在frameworks/base/services/java/com/android/server/am/ActivityManagerService.java文件中:
~~~
public final class ActivityManagerService extends ActivityManagerNative
implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
......
static void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver,
Intent intent, int resultCode, String data, Bundle extras,
boolean ordered, boolean sticky) throws RemoteException {
// Send the intent to the receiver asynchronously using one-way binder calls.
if (app != null && app.thread != null) {
// If we have an app thread, do the call through that so it is
// correctly ordered with other one-way calls.
app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
data, extras, ordered, sticky);
} else {
......
}
}
......
}
~~~
注意,這里傳進來的參數app是注冊廣播接收器的Activity所在的進程記錄塊,在我們分析的這個場景中,由于是MainActivity調用registerReceiver函數來注冊這個廣播接收器的,因此,參數app所代表的ProcessRecord就是MainActivity所在的進程記錄塊了;而參數receiver也是注冊廣播接收器時傳給ActivityManagerService的一個Binder對象,它的類型是IIntentReceiver,具體可以參考上一篇文章Android應用程序注冊廣播接收器(registerReceiver)的過程分析中的Step 2。
MainActivity在注冊廣播接收器時,已經把自己的ProcessRecord記錄下來了,所以這里的參數app和app.thread均不為null,于是,ActivityManagerService就調用app.thread.scheduleRegisteredReceiver函數來把這個廣播分發給MainActivity了。這里的app.thread是一個Binder遠程對象,它的類型是ApplicationThreadProxy,我們在前面介紹應用程序的Activity啟動過程時,已經多次看到了,具體可以參考主題Android應用程序的Activity啟動過程簡要介紹和學習計劃。
**Step 11. ApplicationThreadProxy.scheduleRegisteredReceiver**
這個函數定義在frameworks/base/core/java/android/app/ApplicationThreadNative.java文件中:
~~~
class ApplicationThreadProxy implements IApplicationThread {
......
public void scheduleRegisteredReceiver(IIntentReceiver receiver, Intent intent,
int resultCode, String dataStr, Bundle extras, boolean ordered, boolean sticky)
throws RemoteException {
Parcel data = Parcel.obtain();
data.writeInterfaceToken(IApplicationThread.descriptor);
data.writeStrongBinder(receiver.asBinder());
intent.writeToParcel(data, 0);
data.writeInt(resultCode);
data.writeString(dataStr);
data.writeBundle(extras);
data.writeInt(ordered ? 1 : 0);
data.writeInt(sticky ? 1 : 0);
mRemote.transact(SCHEDULE_REGISTERED_RECEIVER_TRANSACTION, data, null,
IBinder.FLAG_ONEWAY);
data.recycle();
}
......
}
~~~
這里通過Binder驅動程序就進入到ApplicationThread.scheduleRegisteredReceiver函數去了。ApplicationThread是ActivityThread的一個內部類,具體可以參考Activity啟動主題Android應用程序的Activity啟動過程簡要介紹和學習計劃。
**Step 12. ApplicaitonThread.scheduleRegisteredReceiver**
這個函數定義在frameworks/base/core/java/android/app/ActivityThread.java文件中:
~~~
public final class ActivityThread {
......
private final class ApplicationThread extends ApplicationThreadNative {
......
// This function exists to make sure all receiver dispatching is
// correctly ordered, since these are one-way calls and the binder driver
// applies transaction ordering per object for such calls.
public void scheduleRegisteredReceiver(IIntentReceiver receiver, Intent intent,
int resultCode, String dataStr, Bundle extras, boolean ordered,
boolean sticky) throws RemoteException {
receiver.performReceive(intent, resultCode, dataStr, extras, ordered, sticky);
}
......
}
......
}
~~~
這里的receiver是在前面一篇文章Android應用程序注冊廣播接收器(registerReceiver)的過程分析中的Step 4中創建的,它的具體類型是LoadedApk.ReceiverDispatcher.InnerReceiver,即定義在LoadedApk類的內部類ReceiverDispatcher里面的一個內部類InnerReceiver,這里調用它的performReceive函數。
**Step 13. InnerReceiver.performReceive**
這個函數定義在frameworks/base/core/java/android/app/LoadedApk.java文件中:
~~~
final class LoadedApk {
......
static final class ReceiverDispatcher {
final static class InnerReceiver extends IIntentReceiver.Stub {
......
public void performReceive(Intent intent, int resultCode,
String data, Bundle extras, boolean ordered, boolean sticky) {
LoadedApk.ReceiverDispatcher rd = mDispatcher.get();
......
if (rd != null) {
rd.performReceive(intent, resultCode, data, extras,
ordered, sticky);
} else {
......
}
}
}
......
}
......
}
~~~
這里,它只是簡單地調用ReceiverDispatcher的performReceive函數來進一步處理,這里的ReceiverDispatcher類是LoadedApk類里面的一個內部類。
Step 14. ReceiverDispatcher.performReceive
這個函數定義在frameworks/base/core/java/android/app/LoadedApk.java文件中:
~~~
final class LoadedApk {
......
static final class ReceiverDispatcher {
......
public void performReceive(Intent intent, int resultCode,
String data, Bundle extras, boolean ordered, boolean sticky) {
......
Args args = new Args();
args.mCurIntent = intent;
args.mCurCode = resultCode;
args.mCurData = data;
args.mCurMap = extras;
args.mCurOrdered = ordered;
args.mCurSticky = sticky;
if (!mActivityThread.post(args)) {
......
}
}
......
}
......
}
~~~
這里mActivityThread成員變量的類型為Handler,它是前面MainActivity注冊廣播接收器時,從ActivityThread取得的,具體可以參考前面一篇文章Android應用程序注冊廣播接收器(registerReceiver)的過程分析中的Step 3。這里ReceiverDispatcher借助這個Handler,把這個廣播以消息的形式放到MainActivity所在的這個ActivityThread的消息隊列中去,因此,ReceiverDispatcher不等這個廣播被MainActivity處理就返回了,這里也體現了廣播的發送和處理是異步進行的。
注意這里處理消息的方式是通過Handler.post函數進行的,post函數的參數是Runnable類型的,這個消息最終會調用這個這個參數的run成員函數來處理。這里的Args類是LoadedApk類的內部類ReceiverDispatcher的一個內部類,它繼承于Runnable類,因此,可以作為mActivityThread.post的參數傳進去,代表這個廣播的intent也保存在這個Args實例中。
**Step 15. Hanlder.post**
這個函數定義在frameworks/base/core/java/android/os/Handler.java文件中,這個函數我們就不看了,有興趣的讀者可以自己研究一下,它的作用就是把消息放在消息隊列中,然后就返回了,這個消息最終會在傳進來的Runnable類型的參數的run成員函數中進行處理。
**Step 16. Args.run**
這個函數定義在frameworks/base/core/java/android/app/LoadedApk.java文件中:
~~~
final class LoadedApk {
......
static final class ReceiverDispatcher {
......
final class Args implements Runnable {
......
public void run() {
BroadcastReceiver receiver = mReceiver;
......
Intent intent = mCurIntent;
......
try {
ClassLoader cl = mReceiver.getClass().getClassLoader();
intent.setExtrasClassLoader(cl);
if (mCurMap != null) {
mCurMap.setClassLoader(cl);
}
receiver.setOrderedHint(true);
receiver.setResult(mCurCode, mCurData, mCurMap);
receiver.clearAbortBroadcast();
receiver.setOrderedHint(mCurOrdered);
receiver.setInitialStickyHint(mCurSticky);
receiver.onReceive(mContext, intent);
} catch (Exception e) {
......
}
......
}
......
}
......
}
......
}
~~~
這里的mReceiver是ReceiverDispatcher類的成員變量,它的類型是BroadcastReceiver,這里它就是MainActivity注冊廣播接收器時創建的BroadcastReceiver實例了,具體可以參考前面一篇文章Android應用程序注冊廣播接收器(registerReceiver)的過程分析中的Step 2。
有了這個ReceiverDispatcher實例之后,就可以調用它的onReceive函數把這個廣播分發給它處理了。
**Step 17. BroadcastReceiver.onReceive**
這個函數定義Android系統中的廣播(Broadcast)機制簡要介紹和學習計劃一文中所介紹的Android應用程序Broadcast的工程目錄下的src/shy/luo/broadcast/MainActivity.java文件中:
~~~
public class MainActivity extends Activity implements OnClickListener {
......
private BroadcastReceiver counterActionReceiver = new BroadcastReceiver(){
public void onReceive(Context context, Intent intent) {
int counter = intent.getIntExtra(CounterService.COUNTER_VALUE, 0);
String text = String.valueOf(counter);
counterText.setText(text);
Log.i(LOG_TAG, "Receive counter event");
}
}
......
}
~~~
這樣,MainActivity里面的定義的BroadcastReceiver實例counterActionReceiver就收到這個廣播并進行處理了。
至此,Android應用程序發送廣播的過程就分析完成了,結合前面這篇分析廣播接收器注冊過程的文章Android應用程序注冊廣播接收器(registerReceiver)的過程分析,就會對Android系統的廣播機制且個更深刻的認識和理解了。
最后,我們總結一下這個Android應用程序發送廣播的過程:
1. Step 1 - Step 7,計數器服務CounterService通過sendBroadcast把一個廣播通過Binder進程間通信機制發送給ActivityManagerService,ActivityManagerService根據這個廣播的Action類型找到相應的廣播接收器,然后把這個廣播放進自己的消息隊列中去,就完成第一階段對這個廣播的異步分發了;
2. Step 8 - Step 15,ActivityManagerService在消息循環中處理這個廣播,并通過Binder進程間通信機制把這個廣播分發給注冊的廣播接收分發器ReceiverDispatcher,ReceiverDispatcher把這個廣播放進MainActivity所在的線程的消息隊列中去,就完成第二階段對這個廣播的異步分發了;
3. Step 16 - Step 17, ReceiverDispatcher的內部類Args在MainActivity所在的線程消息循環中處理這個廣播,最終是將這個廣播分發給所注冊的BroadcastReceiver實例的onReceive函數進行處理。
這樣,Android系統廣播機制就學習完成了,希望對讀者有所幫助。重新學習Android系統的廣播機制,請回到Android系統中的廣播(Broadcast)機制簡要介紹和學習計劃一文中。
- 前言
- Android組件設計思想
- Android源代碼開發和調試環境搭建
- Android源代碼下載和編譯
- Android源代碼情景分析法
- Android源代碼調試分析法
- 手把手教你為手機編譯ROM
- 在Ubuntu上下載、編譯和安裝Android最新源代碼
- 在Ubuntu上下載、編譯和安裝Android最新內核源代碼(Linux Kernel)
- 如何單獨編譯Android源代碼中的模塊
- 在Ubuntu上為Android系統編寫Linux內核驅動程序
- 在Ubuntu上為Android系統內置C可執行程序測試Linux內核驅動程序
- 在Ubuntu上為Android增加硬件抽象層(HAL)模塊訪問Linux內核驅動程序
- 在Ubuntu為Android硬件抽象層(HAL)模塊編寫JNI方法提供Java訪問硬件服務接口
- 在Ubuntu上為Android系統的Application Frameworks層增加硬件訪問服務
- 在Ubuntu上為Android系統內置Java應用程序測試Application Frameworks層的硬件服務
- Android源代碼倉庫及其管理工具Repo分析
- Android編譯系統簡要介紹和學習計劃
- Android編譯系統環境初始化過程分析
- Android源代碼編譯命令m/mm/mmm/make分析
- Android系統鏡像文件的打包過程分析
- 從CM刷機過程和原理分析Android系統結構
- Android系統架構概述
- Android系統整體架構
- android專用驅動
- Android硬件抽象層HAL
- Android應用程序組件
- Android應用程序框架
- Android用戶界面架構
- Android虛擬機之Dalvik虛擬機
- Android硬件抽象層
- Android硬件抽象層(HAL)概要介紹和學習計劃
- Android專用驅動
- Android Logger驅動系統
- Android日志系統驅動程序Logger源代碼分析
- Android應用程序框架層和系統運行庫層日志系統源代碼分析
- Android日志系統Logcat源代碼簡要分析
- Android Binder驅動系統
- Android進程間通信(IPC)機制Binder簡要介紹和學習計劃
- 淺談Service Manager成為Android進程間通信(IPC)機制Binder守護進程之路
- 淺談Android系統進程間通信(IPC)機制Binder中的Server和Client獲得Service Manager接口之路
- Android系統進程間通信(IPC)機制Binder中的Server啟動過程源代碼分析
- Android系統進程間通信(IPC)機制Binder中的Client獲得Server遠程接口過程源代碼分析
- Android系統進程間通信Binder機制在應用程序框架層的Java接口源代碼分析
- Android Ashmem驅動系統
- Android系統匿名共享內存Ashmem(Anonymous Shared Memory)簡要介紹和學習計劃
- Android系統匿名共享內存Ashmem(Anonymous Shared Memory)驅動程序源代碼分析
- Android系統匿名共享內存Ashmem(Anonymous Shared Memory)在進程間共享的原理分析
- Android系統匿名共享內存(Anonymous Shared Memory)C++調用接口分析
- Android應用程序進程管理
- Android應用程序進程啟動過程的源代碼分析
- Android系統進程Zygote啟動過程的源代碼分析
- Android系統默認Home應用程序(Launcher)的啟動過程源代碼分析
- Android應用程序消息機制
- Android應用程序消息處理機制(Looper、Handler)分析
- Android應用程序線程消息循環模型分析
- Android應用程序輸入事件分發和處理機制
- Android應用程序鍵盤(Keyboard)消息處理機制分析
- Android應用程序UI架構
- Android系統的開機畫面顯示過程分析
- Android幀緩沖區(Frame Buffer)硬件抽象層(HAL)模塊Gralloc的實現原理分析
- SurfaceFlinger
- Android系統Surface機制的SurfaceFlinger服務
- SurfaceFlinger服務簡要介紹和學習計劃
- 啟動過程分析
- 對幀緩沖區(Frame Buffer)的管理分析
- 線程模型分析
- 渲染應用程序UI的過程分析
- Android應用程序與SurfaceFlinger服務的關系
- 概述和學習計劃
- 連接過程分析
- 共享UI元數據(SharedClient)的創建過程分析
- 創建Surface的過程分析
- 渲染Surface的過程分析
- Android應用程序窗口(Activity)
- 實現框架簡要介紹和學習計劃
- 運行上下文環境(Context)的創建過程分析
- 窗口對象(Window)的創建過程分析
- 視圖對象(View)的創建過程分析
- 與WindowManagerService服務的連接過程分析
- 繪圖表面(Surface)的創建過程分析
- 測量(Measure)、布局(Layout)和繪制(Draw)過程分析
- WindowManagerService
- WindowManagerService的簡要介紹和學習計劃
- 計算Activity窗口大小的過程分析
- 對窗口的組織方式分析
- 對輸入法窗口(Input Method Window)的管理分析
- 對壁紙窗口(Wallpaper Window)的管理分析
- 計算窗口Z軸位置的過程分析
- 顯示Activity組件的啟動窗口(Starting Window)的過程分析
- 切換Activity窗口(App Transition)的過程分析
- 顯示窗口動畫的原理分析
- Android控件TextView的實現原理分析
- Android視圖SurfaceView的實現原理分析
- Android應用程序UI硬件加速渲染
- 簡要介紹和學習計劃
- 環境初始化過程分析
- 預加載資源地圖集服務(Asset Atlas Service)分析
- Display List構建過程分析
- Display List渲染過程分析
- 動畫執行過程分析
- Android應用程序資源管理框架
- Android資源管理框架(Asset Manager)
- Asset Manager 簡要介紹和學習計劃
- 編譯和打包過程分析
- Asset Manager的創建過程分析
- 查找過程分析
- Dalvik虛擬機和ART虛擬機
- Dalvik虛擬機
- Dalvik虛擬機簡要介紹和學習計劃
- Dalvik虛擬機的啟動過程分析
- Dalvik虛擬機的運行過程分析
- Dalvik虛擬機JNI方法的注冊過程分析
- Dalvik虛擬機進程和線程的創建過程分析
- Dalvik虛擬機垃圾收集機制簡要介紹和學習計劃
- Dalvik虛擬機Java堆創建過程分析
- Dalvik虛擬機為新創建對象分配內存的過程分析
- Dalvik虛擬機垃圾收集(GC)過程分析
- ART虛擬機
- Android ART運行時無縫替換Dalvik虛擬機的過程分析
- Android運行時ART簡要介紹和學習計劃
- Android運行時ART加載OAT文件的過程分析
- Android運行時ART加載類和方法的過程分析
- Android運行時ART執行類方法的過程分析
- ART運行時垃圾收集機制簡要介紹和學習計劃
- ART運行時Java堆創建過程分析
- ART運行時為新創建對象分配內存的過程分析
- ART運行時垃圾收集(GC)過程分析
- ART運行時Compacting GC簡要介紹和學習計劃
- ART運行時Compacting GC堆創建過程分析
- ART運行時Compacting GC為新創建對象分配內存的過程分析
- ART運行時Semi-Space(SS)和Generational Semi-Space(GSS)GC執行過程分析
- ART運行時Mark-Compact( MC)GC執行過程分析
- ART運行時Foreground GC和Background GC切換過程分析
- Android安全機制
- SEAndroid安全機制簡要介紹和學習計劃
- SEAndroid安全機制框架分析
- SEAndroid安全機制中的文件安全上下文關聯分析
- SEAndroid安全機制中的進程安全上下文關聯分析
- SEAndroid安全機制對Android屬性訪問的保護分析
- SEAndroid安全機制對Binder IPC的保護分析
- 從NDK在非Root手機上的調試原理探討Android的安全機制
- APK防反編譯
- Android視頻硬解穩定性問題探討和處理
- Android系統的智能指針(輕量級指針、強指針和弱指針)的實現原理分析
- Android應用程序安裝過程源代碼分析
- Android應用程序啟動過程源代碼分析
- 四大組件源代碼分析
- Activity
- Android應用程序的Activity啟動過程簡要介紹和學習計劃
- Android應用程序內部啟動Activity過程(startActivity)的源代碼分析
- 解開Android應用程序組件Activity的"singleTask"之謎
- Android應用程序在新的進程中啟動新的Activity的方法和過程分析
- Service
- Android應用程序綁定服務(bindService)的過程源代碼分析
- ContentProvider
- Android應用程序組件Content Provider簡要介紹和學習計劃
- Android應用程序組件Content Provider應用實例
- Android應用程序組件Content Provider的啟動過程源代碼分析
- Android應用程序組件Content Provider在應用程序之間共享數據的原理分析
- Android應用程序組件Content Provider的共享數據更新通知機制分析
- BroadcastReceiver
- Android系統中的廣播(Broadcast)機制簡要介紹和學習計劃
- Android應用程序注冊廣播接收器(registerReceiver)的過程分析
- Android應用程序發送廣播(sendBroadcast)的過程分析