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

本文详细分析了Android应用程序发送广播的过程,从ContextWrapper.sendBroadcast开始,经过ActivityManagerService的层层处理,最后到达广播接收器。整个过程涉及Binder进程间通信,发送与处理是异步的,广播的传递包括从发送者到ActivityManagerService,再到接收者的两个Binder通信步骤。通过源代码分析,揭示了Android广播机制的工作原理。
摘要由CSDN通过智能技术生成
               

        前面我们分析了Android应用程序注册广播接收器的过程,这个过程只完成了万里长征的第一步,接下来它还要等待ActivityManagerService将广播分发过来。ActivityManagerService是如何得到广播并把它分发出去的呢?这就是本文要介绍的广播发送过程了。

《Android系统源代码情景分析》一书正在进击的程序员网(http://0xcc0xcd.com)中连载,点击进入!

        广播的发送过程比广播接收器的注册过程要复杂得多了,不过这个过程仍然是以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, 
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值