Android应用程序发送广播(sendBroadcast)的过程分析

文章转载至CSDN社区罗升阳的安卓之旅,原文地址: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发送广播的代码如下所示:

[java] view plaincopy

  1. public class CounterService extends Service implements ICounterService {
  2. ......
  3. public void startCounter(int initVal) {
  4. AsyncTask<Integer, Integer, Integer> task = new AsyncTask<Integer, Integer, Integer>() {
  5. @Override
  6. protected Integer doInBackground(Integer... vals) {
  7. ......
  8. }
  9. @Override
  10. protected void onProgressUpdate(Integer... values) {
  11. super.onProgressUpdate(values);
  12. int counter = values[0];
  13. Intent intent = new Intent(BROADCAST_COUNTER_ACTION);
  14. intent.putExtra(COUNTER_VALUE, counter);
  15. sendBroadcast(intent);
  16. }
  17. @Override
  18. protected void onPostExecute(Integer val) {
  19. ......
  20. }
  21. };
  22. task.execute(0);
  23. }
  24. ......
  25. }

在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文件中:

[java] view plaincopy

  1. public class ContextWrapper extends Context {
  2. Context mBase;
  3. ......
  4. @Override
  5. public void sendBroadcast(Intent intent) {
  6. mBase.sendBroadcast(intent);
  7. }
  8. ......
  9. }

这里的成员变量mBase是一个ContextImpl实例,这里只简单地调用ContextImpl.sendBroadcast进一行操作。

Step 2. ContextImpl.sendBroadcast

这个函数定义在frameworks/base/core/java/android/app/ContextImpl.java文件中:

[java] view plaincopy

  1. class ContextImpl extends Context {
  2. ......
  3. @Override
  4. public void sendBroadcast(Intent intent) {
  5. String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
  6. try {
  7. ActivityManagerNative.getDefault().broadcastIntent(
  8. mMainThread.getApplicationThread(), intent, resolvedType, null,
  9. Activity.RESULT_OK, null, null, null, false, false);
  10. } catch (RemoteException e) {
  11. }
  12. }
  13. ......
  14. }

这里的resolvedType表示这个Intent的MIME类型,我们没有设置这个Intent的MIME类型,因此,这里的 resolvedType为null。接下来就调用ActivityManagerService的远程接口ActivityManagerProxy把 这个广播发送给ActivityManagerService了。

Step 3. ActivityManagerProxy.broadcastIntent

这个函数定义在frameworks/base/core/java/android/app/ActivityManagerNative.java文件中:

[java] view plaincopy

  1. class ActivityManagerProxy implements IActivityManager
  2. {
  3. ......
  4. public int broadcastIntent(IApplicationThread caller,
  5. Intent intent, String resolvedType,  IIntentReceiver resultTo,
  6. int resultCode, String resultData, Bundle map,
  7. String requiredPermission, boolean serialized,
  8. boolean sticky) throws RemoteException
  9. {
  10. Parcel data = Parcel.obtain();
  11. Parcel reply = Parcel.obtain();
  12. data.writeInterfaceToken(IActivityManager.descriptor);
  13. data.writeStrongBinder(caller != null ? caller.asBinder() : null);
  14. intent.writeToParcel(data, 0);
  15. data.writeString(resolvedType);
  16. data.writeStrongBinder(resultTo != null ? resultTo.asBinder() : null);
  17. data.writeInt(resultCode);
  18. data.writeString(resultData);
  19. data.writeBundle(map);
  20. data.writeString(requiredPermission);
  21. data.writeInt(serialized ? 1 : 0);
  22. data.writeInt(sticky ? 1 : 0);
  23. mRemote.transact(BROADCAST_INTENT_TRANSACTION, data, reply, 0);
  24. reply.readException();
  25. int res = reply.readInt();
  26. reply.recycle();
  27. data.recycle();
  28. return res;
  29. }
  30. ......
  31. }

这里的实现比较简单,把要传递的参数封装好,然后通过Binder驱动程序进入到ActivityManagerService的broadcastIntent函数中。

Step 4. ctivityManagerService.broadcastIntent

这个函数定义在frameworks/base/services/java/com/android/server/am/ActivityManagerService.java文件中:

[java] view plaincopy

  1. public final class ActivityManagerService extends ActivityManagerNative
  2. implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
  3. ......
  4. public final int broadcastIntent(IApplicationThread caller,
  5. Intent intent, String resolvedType, IIntentReceiver resultTo,
  6. int resultCode, String resultData, Bundle map,
  7. String requiredPermission, boolean serialized, boolean sticky) {
  8. synchronized(this) {
  9. intent = verifyBroadcastLocked(intent);
  10. final ProcessRecord callerApp = getRecordForAppLocked(caller);
  11. final int callingPid = Binder.getCallingPid();
  12. final int callingUid = Binder.getCallingUid();
  13. final long origId = Binder.clearCallingIdentity();
  14. int res = broadcastIntentLocked(callerApp,
  15. callerApp != null ? callerApp.info.packageName : null,
  16. intent, resolvedType, resultTo,
  17. resultCode, resultData, map, requiredPermission, serialized,
  18. sticky, callingPid, callingUid);
  19. Binder.restoreCallingIdentity(origId);
  20. return res;
  21. }
  22. }
  23. ......
  24. }

这里调用broadcastIntentLocked函数来进一步处理。

Step 5. ActivityManagerService.broadcastIntentLocked

这个函数定义在frameworks/base/services/java/com/android/server/am/ActivityManagerService.java文件中:

[java] view plaincopy

  1. public final class ActivityManagerService extends ActivityManagerNative
  2. implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
  3. ......
  4. private final int broadcastIntentLocked(ProcessRecord callerApp,
  5. String callerPackage, Intent intent, String resolvedType,
  6. IIntentReceiver resultTo, int resultCode, String resultData,
  7. Bundle map, String requiredPermission,
  8. boolean ordered, boolean sticky, int callingPid, int callingUid) {
  9. intent = new Intent(intent);
  10. ......
  11. // Figure out who all will receive this broadcast.
  12. List receivers = null;
  13. List<BroadcastFilter> registeredReceivers = null;
  14. try {
  15. if (intent.getComponent() != null) {
  16. ......
  17. } else {
  18. ......
  19. registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);
  20. }
  21. } catch (RemoteException ex) {
  22. ......
  23. }
  24. final boolean replacePending =
  25. (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
  26. int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
  27. if (!ordered && NR > 0) {
  28. // If we are not serializing this broadcast, then send the
  29. // registered receivers separately so they don‘t wait for the
  30. // components to be launched.
  31. BroadcastRecord r = new BroadcastRecord(intent, callerApp,
  32. callerPackage, callingPid, callingUid, requiredPermission,
  33. registeredReceivers, resultTo, resultCode, resultData, map,
  34. ordered, sticky, false);
  35. ......
  36. boolean replaced = false;
  37. if (replacePending) {
  38. for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
  39. if (intent.filterEquals(mParallelBroadcasts.get(i).intent)) {
  40. ......
  41. mParallelBroadcasts.set(i, r);
  42. replaced = true;
  43. break;
  44. }
  45. }
  46. }
  47. if (!replaced) {
  48. mParallelBroadcasts.add(r);
  49. scheduleBroadcastsLocked();
  50. }
  51. registeredReceivers = null;
  52. NR = 0;
  53. }
  54. ......
  55. }
  56. ......
  57. }

这个函数首先是根据intent找出相应的广播接收器:

[java] view plaincopy

  1. // Figure out who all will receive this broadcast.
  2. List receivers = null;
  3. List<BroadcastFilter> registeredReceivers = null;
  4. try {
  5. if (intent.getComponent() != null) {
  6. ......
  7. } else {
  8. ......
  9. registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);
  10. }
  11. } catch (RemoteException ex) {
  12. ......
  13. }

回忆一下前面一篇文章Android应用程序注册广播接收器(registerReceiver)的过程分析中 的Step 6(ActivityManagerService.registerReceiver)中,我们将一个filter类型为 BROADCAST_COUNTER_ACTION类型的BroadcastFilter实例保存在了ActivityManagerService的成 员变量mReceiverResolver中,这个BroadcastFilter实例包含了我们所注册的广播接收器,这里就通过 mReceiverResolver.queryIntent函数将这个BroadcastFilter实例取回来。由于注册一个广播类型的接收器可能有 多个,所以这里把所有符合条件的的BroadcastFilter实例放在一个List中,然后返回来。在我们这个场景中,这个List就只有一个 BroadcastFilter实例了,就是MainActivity注册的那个广播接收器。

继续往下看:

[java] view plaincopy

  1. final boolean replacePending =
  2. (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。

再接着往下看:

[java] view plaincopy

  1. int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
  2. if (!ordered && NR > 0) {
  3. // If we are not serializing this broadcast, then send the
  4. // registered receivers separately so they don‘t wait for the
  5. // components to be launched.
  6. BroadcastRecord r = new BroadcastRecord(intent, callerApp,
  7. callerPackage, callingPid, callingUid, requiredPermission,
  8. registeredReceivers, resultTo, resultCode, resultData, map,
  9. ordered, sticky, false);
  10. ......
  11. boolean replaced = false;
  12. if (replacePending) {
  13. for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
  14. if (intent.filterEquals(mParallelBroadcasts.get(i).intent)) {
  15. ......
  16. mParallelBroadcasts.set(i, r);
  17. replaced = true;
  18. break;
  19. }
  20. }
  21. }
  22. if (!replaced) {
  23. mParallelBroadcasts.add(r);
  24. scheduleBroadcastsLocked();
  25. }
  26. registeredReceivers = null;
  27. NR = 0;
  28. }

前面我们说到,这里得到的列表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文件中:

[java] view plaincopy

  1. public final class ActivityManagerService extends ActivityManagerNative
  2. implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
  3. ......
  4. private final void scheduleBroadcastsLocked() {
  5. ......
  6. if (mBroadcastsScheduled) {
  7. return;
  8. }
  9. mHandler.sendEmptyMessage(BROADCAST_INTENT_MSG);
  10. mBroadcastsScheduled = true;
  11. }
  12. ......
  13. }

这里的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函数来真正处理这个消息:

[java] view plaincopy

  1. public final class ActivityManagerService extends ActivityManagerNative
  2. implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
  3. ......
  4. final Handler mHandler = new Handler() {
  5. public void handleMessage(Message msg) {
  6. switch (msg.what) {
  7. ......
  8. case BROADCAST_INTENT_MSG: {
  9. ......
  10. processNextBroadcast(true);
  11. } break;
  12. ......
  13. }
  14. }
  15. }
  16. ......
  17. }

这里又调用了ActivityManagerService的processNextBroadcast函数来处理下一个未处理的广播。

Step 8. ActivityManagerService.processNextBroadcast

这个函数定义在frameworks/base/services/java/com/android/server/am/ActivityManagerService.java文件中:

[java] view plaincopy

  1. public final class ActivityManagerService extends ActivityManagerNative
  2. implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
  3. ......
  4. private final void processNextBroadcast(boolean fromMsg) {
  5. synchronized(this) {
  6. BroadcastRecord r;
  7. ......
  8. if (fromMsg) {
  9. mBroadcastsScheduled = false;
  10. }
  11. // First, deliver any non-serialized broadcasts right away.
  12. while (mParallelBroadcasts.size() > 0) {
  13. r = mParallelBroadcasts.remove(0);
  14. ......
  15. final int N = r.receivers.size();
  16. ......
  17. for (int i=0; i<N; i++) {
  18. Object target = r.receivers.get(i);
  19. ......
  20. deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false);
  21. }
  22. addBroadcastToHistoryLocked(r);
  23. ......
  24. }
  25. ......
  26. }
  27. }
  28. ......
  29. }

这里传进来的参数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文件中:

[java] view plaincopy

  1. public final class ActivityManagerService extends ActivityManagerNative
  2. implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
  3. ......
  4. private final void deliverToRegisteredReceiverLocked(BroadcastRecord r,
  5. BroadcastFilter filter, boolean ordered) {
  6. boolean skip = false;
  7. if (filter.requiredPermission != null) {
  8. ......
  9. }
  10. if (r.requiredPermission != null) {
  11. ......
  12. }
  13. if (!skip) {
  14. // If this is not being sent as an ordered broadcast, then we
  15. // don‘t want to touch the fields that keep track of the current
  16. // state of ordered broadcasts.
  17. if (ordered) {
  18. ......
  19. }
  20. try {
  21. ......
  22. performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,
  23. new Intent(r.intent), r.resultCode,
  24. r.resultData, r.resultExtras, r.ordered, r.initialSticky);
  25. ......
  26. } catch (RemoteException e) {
  27. ......
  28. }
  29. }
  30. }
  31. ......
  32. }

函数首先是检查一下广播发送和接收的权限,在我们分析的这个场景中,没有设置权限,因此,这个权限检查就跳过了,这里得到的skip为false,于是进 入下面的if语句中。由于上面传时来的ordered参数为false,因此,直接就调用performReceiveLocked函数来进一步执行广播 发送的操作了。

Step 10. ActivityManagerService.performReceiveLocked

这个函数定义在frameworks/base/services/java/com/android/server/am/ActivityManagerService.java文件中:

[java] view plaincopy

  1. public final class ActivityManagerService extends ActivityManagerNative
  2. implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
  3. ......
  4. static void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver,
  5. Intent intent, int resultCode, String data, Bundle extras,
  6. boolean ordered, boolean sticky) throws RemoteException {
  7. // Send the intent to the receiver asynchronously using one-way binder calls.
  8. if (app != null && app.thread != null) {
  9. // If we have an app thread, do the call through that so it is
  10. // correctly ordered with other one-way calls.
  11. app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
  12. data, extras, ordered, sticky);
  13. } else {
  14. ......
  15. }
  16. }
  17. ......
  18. }

注意,这里传进来的参数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文件中:

[java] view plaincopy

  1. class ApplicationThreadProxy implements IApplicationThread {
  2. ......
  3. public void scheduleRegisteredReceiver(IIntentReceiver receiver, Intent intent,
  4. int resultCode, String dataStr, Bundle extras, boolean ordered, boolean sticky)
  5. throws RemoteException {
  6. Parcel data = Parcel.obtain();
  7. data.writeInterfaceToken(IApplicationThread.descriptor);
  8. data.writeStrongBinder(receiver.asBinder());
  9. intent.writeToParcel(data, 0);
  10. data.writeInt(resultCode);
  11. data.writeString(dataStr);
  12. data.writeBundle(extras);
  13. data.writeInt(ordered ? 1 : 0);
  14. data.writeInt(sticky ? 1 : 0);
  15. mRemote.transact(SCHEDULE_REGISTERED_RECEIVER_TRANSACTION, data, null,
  16. IBinder.FLAG_ONEWAY);
  17. data.recycle();
  18. }
  19. ......
  20. }

这里通过Binder驱动程序就进入到ApplicationThread.scheduleRegisteredReceiver函数去了。
ApplicationThread是ActivityThread的一个内部类,具体可以参考Activity启动主题Android应用程序的Activity启动过程简要介绍和学习计划

Step 12. ApplicaitonThread.scheduleRegisteredReceiver
        这个函数定义在frameworks/base/core/java/android/app/ActivityThread.java文件中:

[java] view plaincopy

  1. public final class ActivityThread {
  2. ......
  3. private final class ApplicationThread extends ApplicationThreadNative {
  4. ......
  5. // This function exists to make sure all receiver dispatching is
  6. // correctly ordered, since these are one-way calls and the binder driver
  7. // applies transaction ordering per object for such calls.
  8. public void scheduleRegisteredReceiver(IIntentReceiver receiver, Intent intent,
  9. int resultCode, String dataStr, Bundle extras, boolean ordered,
  10. boolean sticky) throws RemoteException {
  11. receiver.performReceive(intent, resultCode, dataStr, extras, ordered, sticky);
  12. }
  13. ......
  14. }
  15. ......
  16. }

这里的receiver是在前面一篇文章Android应用程序注册广播接收器(registerReceiver)的过程分析
的Step
4中创建的,它的具体类型是LoadedApk.ReceiverDispatcher.InnerReceiver,即定义在LoadedApk类的内
部类ReceiverDispatcher里面的一个内部类InnerReceiver,这里调用它的performReceive函数。

Step 13. InnerReceiver.performReceive

这个函数定义在frameworks/base/core/java/android/app/LoadedApk.java文件中:

[java] view plaincopy

  1. final class LoadedApk {
  2. ......
  3. static final class ReceiverDispatcher {
  4. final static class InnerReceiver extends IIntentReceiver.Stub {
  5. ......
  6. public void performReceive(Intent intent, int resultCode,
  7. String data, Bundle extras, boolean ordered, boolean sticky) {
  8. LoadedApk.ReceiverDispatcher rd = mDispatcher.get();
  9. ......
  10. if (rd != null) {
  11. rd.performReceive(intent, resultCode, data, extras,
  12. ordered, sticky);
  13. } else {
  14. ......
  15. }
  16. }
  17. }
  18. ......
  19. }
  20. ......
  21. }

这里,它只是简单地调用ReceiverDispatcher的performReceive函数来进一步处理,这里的ReceiverDispatcher类是LoadedApk类里面的一个内部类。

Step 14. ReceiverDispatcher.performReceive

这个函数定义在frameworks/base/core/java/android/app/LoadedApk.java文件中:

[java] view plaincopy

  1. final class LoadedApk {
  2. ......
  3. static final class ReceiverDispatcher {
  4. ......
  5. public void performReceive(Intent intent, int resultCode,
  6. String data, Bundle extras, boolean ordered, boolean sticky) {
  7. ......
  8. Args args = new Args();
  9. args.mCurIntent = intent;
  10. args.mCurCode = resultCode;
  11. args.mCurData = data;
  12. args.mCurMap = extras;
  13. args.mCurOrdered = ordered;
  14. args.mCurSticky = sticky;
  15. if (!mActivityThread.post(args)) {
  16. ......
  17. }
  18. }
  19. ......
  20. }
  21. ......
  22. }

这里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文件中:

[java] view plaincopy

  1. final class LoadedApk {
  2. ......
  3. static final class ReceiverDispatcher {
  4. ......
  5. final class Args implements Runnable {
  6. ......
  7. public void run() {
  8. BroadcastReceiver receiver = mReceiver;
  9. ......
  10. Intent intent = mCurIntent;
  11. ......
  12. try {
  13. ClassLoader cl =  mReceiver.getClass().getClassLoader();
  14. intent.setExtrasClassLoader(cl);
  15. if (mCurMap != null) {
  16. mCurMap.setClassLoader(cl);
  17. }
  18. receiver.setOrderedHint(true);
  19. receiver.setResult(mCurCode, mCurData, mCurMap);
  20. receiver.clearAbortBroadcast();
  21. receiver.setOrderedHint(mCurOrdered);
  22. receiver.setInitialStickyHint(mCurSticky);
  23. receiver.onReceive(mContext, intent);
  24. } catch (Exception e) {
  25. ......
  26. }
  27. ......
  28. }
  29. ......
  30. }
  31. ......
  32. }
  33. ......
  34. }

这里的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文件中:

[java] view plaincopy

  1. public class MainActivity extends Activity implements OnClickListener {
  2. ......
  3. private BroadcastReceiver counterActionReceiver = new BroadcastReceiver(){
  4. public void onReceive(Context context, Intent intent) {
  5. int counter = intent.getIntExtra(CounterService.COUNTER_VALUE, 0);
  6. String text = String.valueOf(counter);
  7. counterText.setText(text);
  8. Log.i(LOG_TAG, "Receive counter event");
  9. }
  10. }
  11. ......
  12. }

这样,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)机制简要介绍和学习计划一文中。

老罗的新浪微博:http://weibo.com/shengyangluo,欢迎关注!

时间: 2024-10-24 05:01:34

Android应用程序发送广播(sendBroadcast)的过程分析的相关文章

Android应用程序注册广播接收器(registerReceiver)的过程分析

前 面我们介绍了Android系统的广播机制,从本质来说,它是一种消息订阅/发布机制,因此,使用这种消息驱动模型的第一步便是订阅消息:而对 Android应用程序来说,订阅消息其实就是注册广播接收器,本文将探讨Android应用程序是如何注册广播接收器以及把广播接收器注册到哪里去的. 在Android的广播机制中,ActivityManagerService扮演着广播中心的角色,负责系统中所有广播的注册和发布操作,因 此,Android应用程序注册广播接收器的过程就把是广播接收器注册到Activ

Android应用程序签名过程和解析过程分析

在正式解释Android应用程序签名过程之前,作为铺垫,还得先讲讲最基本的一些概念. 非对称加密算法 非对称加密算法需要两个密钥:公开密钥(简称公钥)和私有密钥(简称私钥).公钥与私钥是一对,如果用公钥对数据进行加密,只有用对应的私钥才能解密:如果用私钥对数据进行加密,那么只有用对应的公钥才能解密.因为加密和解密使用的是两个不同的密钥,所以这种算法叫作非对称加密算法. 非对称加密算法是数字签名和数字证书的基础,大家非常熟悉的RSA就是非对称加密算法的一种实现. 消息摘要算法 消息摘要算法(Mes

android Alarm闹钟发送广播播放音乐

通过网上的例子  自己根据相关功能修改的  如有不合理的地方  请提出来  互相学习 一共有3个类 MainActivity.java 主程序 AlarmReceiver.java 广播接收器 MusicService.java service播放音乐 MainActivity.java package com.yqy.yqy_alarm; import java.util.Calendar; import android.app.Activity; import android.app.Ala

Android应用程序消息处理机制(Looper、Handler)分析

文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6817933 Android应用程序是通过消息来驱动的,系统为每一个应用程序维护一个消息队例,应用程序的主线程不断地从这个消息 队例中获取消息(Looper),然后对这些消息进行处理(Handler),这样就实现了通过消息来驱动应用程序的执行,本文将详细分析Android 应用程序的消息处理机制. 前面我们学习Android应用程序中的Activ

初学Android,BroadcastReceiver之发送接收广播

BroadcastReceiver用于监听系统全局广播消息,由于BroadcastReceiver是一种全局的监听器,因此它可以非常方便地实现系统中不同组件之间通信 启动它需要两步 1.创建需要启动的BroadcastReceiver的Intent 2.调用Context的SendBroadcast或sendOrederedBroadcast方法来启动指定的BroadcastReceiver 这其中关键是创建Intent时,要setAction("xxx"),而BroadcastRec

android四大组件之广播接收器BroadcastReceiver

Android有一个非常重要的特性,就是广播.也可以将广播看做是通信机制.  Android四大组件: Activity, service, broadcastReceiver 和contentProvider, 只有Activity和service有完整的生命周期, 其他 broadcastReceiver 和contentProvider 都没有.  broadcastReceiver 本质上是一个监听器, 负责监听系统应用发出的广播(BroadCast). broadcastReceive

Android应用程序注冊广播接收器(registerReceiver)的过程分析

前面我们介绍了Android系统的广播机制,从本质来说,它是一种消息订阅/公布机制,因此,使用这样的消息驱动模型的第一步便是订阅消息:而对Android应用程序来说,订阅消息事实上就是注冊广播接收器,本文将探讨Android应用程序是怎样注冊广播接收器以及把广播接收器注冊到哪里去的. 在Android的广播机制中,ActivityManagerService扮演着广播中心的角色,负责系统中全部广播的注冊和公布操作,因此,Android应用程序注冊广播接收器的过程就把是广播接收器注冊到Activi

MIUI7,Android版本5.0.2,一个程序发送自定义广播,另一个程序没有接收到

对照<第一行代码——Android>进行学习,第五章中说到广播包的相关知识,前面获取广播等程序例程都可以跑的通,但是在5.3.2节中,程序A发送自定义广播,并接收自定义广播,同时程序B也接收该自定义广播.实际编写代码测试程序A发送之后只有程序A收到了改自定义广播,程序B并没有接收到,我认为是我工程配置的问题,因此下载了书本中的例程直接跑,现象任然是这样,程序A发送广播之后只有程序A可以收到,程序B没有收到. 不知道是什么原因,测试的手机是小米2s,系统MIUI7,Android版本5.0.2.

Android 两种注册、发送广播的区别

前言:前面文章记录了Service的使用,这次来记录另一个四个组件之一的BroadcastReceiver.主要介绍两种发送和注册广播的区别. BroadcastReceiver广播接收者用于接收系统或其他程序(包括自己程序)发送的广播. 一.注册广播 在android中,我们如果想接收到广播信息,必须自定义我们的广播接收者.要写一个类来继承BroadcastReceiver,并且重写其onReceive()方法,实现接收到特定广播所要做的事情. 这是一个自定义的广播接收者: public cl