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

简介:

        前面我们分析了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发送广播的代码如下所示:


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

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


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

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

         Step 2. ContextImpl.sendBroadcast

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


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

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

        Step 3. ActivityManagerProxy.broadcastIntent

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


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

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

         Step 4. ctivityManagerService.broadcastIntent

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


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

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

         Step 5. ActivityManagerService.broadcastIntentLocked

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


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

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


  
  
  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注册的那个广播接收器。






本文转自 Luoshengyang 51CTO博客,原文链接:http://blog.51cto.com/shyluo/966384,如需转载请自行联系原作者

目录
相关文章
|
2月前
|
开发框架 前端开发 Android开发
Flutter 与原生模块(Android 和 iOS)之间的通信机制,包括方法调用、事件传递等,分析了通信的必要性、主要方式、数据传递、性能优化及错误处理,并通过实际案例展示了其应用效果,展望了未来的发展趋势
本文深入探讨了 Flutter 与原生模块(Android 和 iOS)之间的通信机制,包括方法调用、事件传递等,分析了通信的必要性、主要方式、数据传递、性能优化及错误处理,并通过实际案例展示了其应用效果,展望了未来的发展趋势。这对于实现高效的跨平台移动应用开发具有重要指导意义。
203 4
|
2月前
|
安全 Android开发 数据安全/隐私保护
深入探讨iOS与Android系统安全性对比分析
在移动操作系统领域,iOS和Android无疑是两大巨头。本文从技术角度出发,对这两个系统的架构、安全机制以及用户隐私保护等方面进行了详细的比较分析。通过深入探讨,我们旨在揭示两个系统在安全性方面的差异,并为用户提供一些实用的安全建议。
|
1月前
|
JSON Java API
探索安卓开发:打造你的首个天气应用
在这篇技术指南中,我们将一起潜入安卓开发的海洋,学习如何从零开始构建一个简单的天气应用。通过这个实践项目,你将掌握安卓开发的核心概念、界面设计、网络编程以及数据解析等技能。无论你是初学者还是有一定基础的开发者,这篇文章都将为你提供一个清晰的路线图和实用的代码示例,帮助你在安卓开发的道路上迈出坚实的一步。让我们一起开始这段旅程,打造属于你自己的第一个安卓应用吧!
60 14
|
1月前
|
Java Linux 数据库
探索安卓开发:打造你的第一款应用
在数字时代的浪潮中,每个人都有机会成为创意的实现者。本文将带你走进安卓开发的奇妙世界,通过浅显易懂的语言和实际代码示例,引导你从零开始构建自己的第一款安卓应用。无论你是编程新手还是希望拓展技术的开发者,这篇文章都将为你打开一扇门,让你的创意和技术一起飞扬。
|
1月前
|
Java 开发工具 Android开发
安卓与iOS开发环境对比分析
在移动应用开发的广阔天地中,安卓和iOS两大平台各自占据半壁江山。本文深入探讨了这两个平台的开发环境,从编程语言、开发工具到用户界面设计等多个角度进行比较。通过实际案例分析和代码示例,我们旨在为开发者提供一个清晰的指南,帮助他们根据项目需求和个人偏好做出明智的选择。无论你是初涉移动开发领域的新手,还是寻求跨平台解决方案的资深开发者,这篇文章都将为你提供宝贵的信息和启示。
32 8
|
1月前
|
搜索推荐 前端开发 测试技术
打造个性化安卓应用:从设计到开发的全面指南
在这个数字时代,拥有一个定制的移动应用不仅是一种趋势,更是个人或企业品牌的重要延伸。本文将引导你通过一系列简单易懂的步骤,从构思你的应用理念开始,直至实现一个功能齐全的安卓应用。无论你是编程新手还是希望拓展技能的开发者,这篇文章都将为你提供必要的工具和知识,帮助你将创意转化为现实。
|
3月前
|
缓存 Java Shell
Android 系统缓存扫描与清理方法分析
Android 系统缓存从原理探索到实现。
93 15
Android 系统缓存扫描与清理方法分析
|
2月前
|
安全 Android开发 数据安全/隐私保护
深入探索Android与iOS系统安全性的对比分析
在当今数字化时代,移动操作系统的安全已成为用户和开发者共同关注的重点。本文旨在通过比较Android与iOS两大主流操作系统在安全性方面的差异,揭示两者在设计理念、权限管理、应用审核机制等方面的不同之处。我们将探讨这些差异如何影响用户的安全体验以及可能带来的风险。
44 1
|
1月前
|
Java Android开发 开发者
探索安卓开发:构建你的第一个“Hello World”应用
在安卓开发的浩瀚海洋中,每个新手都渴望扬帆起航。本文将作为你的指南针,引领你通过创建一个简单的“Hello World”应用,迈出安卓开发的第一步。我们将一起搭建开发环境、了解基本概念,并编写第一行代码。就像印度圣雄甘地所说:“你必须成为你希望在世界上看到的改变。”让我们一起开始这段旅程,成为我们想要见到的开发者吧!
37 0
|
2月前
|
JSON Java Android开发
探索安卓开发之旅:打造你的第一个天气应用
【10月更文挑战第30天】在这个数字时代,掌握移动应用开发技能无疑是进入IT行业的敲门砖。本文将引导你开启安卓开发的奇妙之旅,通过构建一个简易的天气应用来实践你的编程技能。无论你是初学者还是有一定经验的开发者,这篇文章都将成为你宝贵的学习资源。我们将一步步地深入到安卓开发的世界中,从搭建开发环境到实现核心功能,每个环节都充满了发现和创造的乐趣。让我们开始吧,一起在代码的海洋中航行!