Android应用程序发送广播sendBroadcast的过程分析.docx

上传人:b****0 文档编号:17940953 上传时间:2023-08-05 格式:DOCX 页数:30 大小:99.22KB
下载 相关 举报
Android应用程序发送广播sendBroadcast的过程分析.docx_第1页
第1页 / 共30页
Android应用程序发送广播sendBroadcast的过程分析.docx_第2页
第2页 / 共30页
Android应用程序发送广播sendBroadcast的过程分析.docx_第3页
第3页 / 共30页
Android应用程序发送广播sendBroadcast的过程分析.docx_第4页
第4页 / 共30页
Android应用程序发送广播sendBroadcast的过程分析.docx_第5页
第5页 / 共30页
Android应用程序发送广播sendBroadcast的过程分析.docx_第6页
第6页 / 共30页
Android应用程序发送广播sendBroadcast的过程分析.docx_第7页
第7页 / 共30页
Android应用程序发送广播sendBroadcast的过程分析.docx_第8页
第8页 / 共30页
Android应用程序发送广播sendBroadcast的过程分析.docx_第9页
第9页 / 共30页
Android应用程序发送广播sendBroadcast的过程分析.docx_第10页
第10页 / 共30页
Android应用程序发送广播sendBroadcast的过程分析.docx_第11页
第11页 / 共30页
Android应用程序发送广播sendBroadcast的过程分析.docx_第12页
第12页 / 共30页
Android应用程序发送广播sendBroadcast的过程分析.docx_第13页
第13页 / 共30页
Android应用程序发送广播sendBroadcast的过程分析.docx_第14页
第14页 / 共30页
Android应用程序发送广播sendBroadcast的过程分析.docx_第15页
第15页 / 共30页
Android应用程序发送广播sendBroadcast的过程分析.docx_第16页
第16页 / 共30页
Android应用程序发送广播sendBroadcast的过程分析.docx_第17页
第17页 / 共30页
Android应用程序发送广播sendBroadcast的过程分析.docx_第18页
第18页 / 共30页
Android应用程序发送广播sendBroadcast的过程分析.docx_第19页
第19页 / 共30页
Android应用程序发送广播sendBroadcast的过程分析.docx_第20页
第20页 / 共30页
亲,该文档总共30页,到这儿已超出免费预览范围,如果喜欢就下载吧!
下载资源
资源描述

Android应用程序发送广播sendBroadcast的过程分析.docx

《Android应用程序发送广播sendBroadcast的过程分析.docx》由会员分享,可在线阅读,更多相关《Android应用程序发送广播sendBroadcast的过程分析.docx(30页珍藏版)》请在冰点文库上搜索。

Android应用程序发送广播sendBroadcast的过程分析.docx

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

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

前面我们分析了Android应用程序注册广播接收器的过程,这个过程只完成了万里长征的第一步,接下来它还要等待ActivityManagerService将广播分发过来。

ActivityManagerService是如何得到广播并把它分发出去的呢?

这就是本文要介绍的广播发送过程了。

广播的发送过程比广播接收器的注册过程要复杂得多了,不过这个过程仍然是以ActivityManagerService为中心。

广播的发送者将广播发送到ActivityManagerService,ActivityManagerService接收到这个广播以后,就会在自己的注册中心查看有哪些广播接收器订阅了该广播,然后把这个广播逐一发送到这些广播接收器中,但是ActivityManagerService并不等待广播接收器处理这些广播就返回了,因此,广播的发送和处理是异步的。

概括来说,广播的发送路径就是从发送者到ActivityManagerService,再从ActivityManagerService到接收者,这中间的两个过程都是通过Binder进程间通信机制来完成的,因此,希望读者在继续阅读本文之前,对Android系统的Binder进程间通信机制有所了解,具体可以参考一文。

本文继续以一文中所开发的应用程序为例子,并且结合上文的内容,一起来分析Android应用程序发送广播的过程。

回顾一下一文中所开发的应用程序的组织架构,MainActivity向ActivityManagerService注册了一个CounterService.BROADCAST_COUNTER_ACTION类型的计数器服务广播接收器,计数器服务CounterService在后台线程中启动了一个异步任务(AsyncTask),这个异步任务负责不断地增加计数,并且不断地将当前计数值通过广播的形式发送出去,以便MainActivity可以将当前计数值在应用程序的界面线程中显示出来。

计数器服务CounterService发送广播的代码如下所示:

[java]viewplaincopy在CODE上查看代码片派生到我的代码片

publicclassCounterServiceextendsServiceimplementsICounterService{

......

publicvoidstartCounter(intinitVal){

AsyncTasktask=newAsyncTask(){

@Override

protectedIntegerdoInBackground(Integer...vals){

......

}

@Override

protectedvoidonProgressUpdate(Integer...values){

super.onProgressUpdate(values);

intcounter=values[0];

Intentintent=newIntent(BROADCAST_COUNTER_ACTION);

intent.putExtra(COUNTER_VALUE,counter);

sendBroadcast(intent);

}

@Override

protectedvoidonPostExecute(Integerval){

......

}

};

task.execute(0);

}

......

}

在onProgressUpdate函数中,创建了一个BROADCAST_COUNTER_ACTION类型的Intent,并且在这里个Intent中附加上当前的计数器值,然后通过CounterService类的成员函数sendBroadcast将这个Intent发送出去。

CounterService类继承了Service类,Service类又继承了ContextWrapper类,成员函数sendBroadcast就是从ContextWrapper类继承下来的,因此,我们就从ContextWrapper类的sendBroadcast函数开始,分析广播发送的过程。

在继承分析广播的发送过程前,我们先来看一下广播发送过程的序列图,然后按照这个序图中的步骤来一步一步分析整个过程。

Step1.ContextWrapper.sendBroadcast

这个函数定义在frameworks/base/core/Java/android/content/ContextWrapper.java文件中:

[java]viewplaincopy在CODE上查看代码片派生到我的代码片

publicclassContextWrapperextendsContext{

ContextmBase;

......

@Override

publicvoidsendBroadcast(Intentintent){

mBase.sendBroadcast(intent);

}

......

}

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

Step2.ContextImpl.sendBroadcast

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

[java]viewplaincopy在CODE上查看代码片派生到我的代码片

classContextImplextendsContext{

......

@Override

publicvoidsendBroadcast(Intentintent){

StringresolvedType=intent.resolveTypeIfNeeded(getContentResolver());

try{

ActivityManagerNative.getDefault().broadcastIntent(

mMainThread.getApplicationThread(),intent,resolvedType,null,

Activity.RESULT_OK,null,null,null,false,false);

}catch(RemoteExceptione){

}

}

......

}

这里的resolvedType表示这个Intent的MIME类型,我们没有设置这个Intent的MIME类型,因此,这里的resolvedType为null。

接下来就调用ActivityManagerService的远程接口ActivityManagerProxy把这个广播发送给ActivityManagerService了。

Step3.ActivityManagerProxy.broadcastIntent

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

[java]viewplaincopy在CODE上查看代码片派生到我的代码片

classActivityManagerProxyimplementsIActivityManager

{

......

publicintbroadcastIntent(IApplicationThreadcaller,

Intentintent,StringresolvedType,IIntentReceiverresultTo,

intresultCode,StringresultData,Bundlemap,

StringrequiredPermission,booleanserialized,

booleansticky)throwsRemoteException

{

Parceldata=Parcel.obtain();

Parcelreply=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();

intres=reply.readInt();

reply.recycle();

data.recycle();

returnres;

}

......

}

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

Step4.ctivityManagerService.broadcastIntent

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

[java]viewplaincopy在CODE上查看代码片派生到我的代码片

publicfinalclassActivityManagerServiceextendsActivityManagerNative

implementsWatchdog.Monitor,BatteryStatsImpl.BatteryCallback{

......

publicfinalintbroadcastIntent(IApplicationThreadcaller,

Intentintent,StringresolvedType,IIntentReceiverresultTo,

intresultCode,StringresultData,Bundlemap,

StringrequiredPermission,booleanserialized,booleansticky){

synchronized(this){

intent=verifyBroadcastLocked(intent);

finalProcessRecordcallerApp=getRecordForAppLocked(caller);

finalintcallingPid=Binder.getCallingPid();

finalintcallingUid=Binder.getCallingUid();

finallongorigId=Binder.clearCallingIdentity();

intres=broadcastIntentLocked(callerApp,

callerApp!

=null?

callerApp.info.packageName:

null,

intent,resolvedType,resultTo,

resultCode,resultData,map,requiredPermission,serialized,

sticky,callingPid,callingUid);

Binder.restoreCallingIdentity(origId);

returnres;

}

}

......

}

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

Step5.ActivityManagerService.broadcastIntentLocked

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

[java]viewplaincopy在CODE上查看代码片派生到我的代码片

publicfinalclassActivityManagerServiceextendsActivityManagerNative

implementsWatchdog.Monitor,BatteryStatsImpl.BatteryCallback{

......

privatefinalintbroadcastIntentLocked(ProcessRecordcallerApp,

StringcallerPackage,Intentintent,StringresolvedType,

IIntentReceiverresultTo,intresultCode,StringresultData,

Bundlemap,StringrequiredPermission,

booleanordered,booleansticky,intcallingPid,intcallingUid){

intent=newIntent(intent);

......

//Figureoutwhoallwillreceivethisbroadcast.

Listreceivers=null;

ListregisteredReceivers=null;

try{

if(intent.getComponent()!

=null){

......

}else{

......

registeredReceivers=mReceiverResolver.queryIntent(intent,resolvedType,false);

}

}catch(RemoteExceptionex){

......

}

finalbooleanreplacePending=

(intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING)!

=0;

intNR=registeredReceivers!

=null?

registeredReceivers.size():

0;

if(!

ordered&&NR>0){

//Ifwearenotserializingthisbroadcast,thensendthe

//registeredreceiversseparatelysotheydon'twaitforthe

//componentstobelaunched.

BroadcastRecordr=newBroadcastRecord(intent,callerApp,

callerPackage,callingPid,callingUid,requiredPermission,

registeredReceivers,resultTo,resultCode,resultData,map,

ordered,sticky,false);

......

booleanreplaced=false;

if(replacePending){

for(inti=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找出相应的广播接收器:

[java]viewplaincopy在CODE上查看代码片派生到我的代码片

//Figureoutwhoallwillreceivethisbroadcast.

Listreceivers=null;

ListregisteredReceivers=null;

try{

if(intent.getComponent()!

=null){

......

}else{

......

registeredReceivers=mReceiverResolver.queryIntent(intent,resolvedType,false);

}

}catch(RemoteExceptionex){

......

}

回忆一下前面一篇文章中的Step6(ActivityManagerService.registerReceiver)中,我们将一个filter类型为BROADCAST_COUNTER_ACTION类型的BroadcastFilter实例保存在了ActivityManagerService的成员变量mReceiverResolver中,这个BroadcastFilter实例包含了我们所注册的广播接收器,这里就通过mReceiverResolver.queryIntent函数将这个BroadcastFilter实例取回来。

由于注册一个广播类型的接收器可能有多个,所以这里把所有符合条件的的BroadcastFilter实例放在一个List中,然后返回来。

在我们这个场景中,这个List就只有一个BroadcastFilter实例了,就是MainActivity注册的那个广播接收器。

继续往下看:

[java]viewplaincopy在CODE上查看代码片派生到我的代码片

finalbooleanreplacePending=

(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]viewplaincopy在CODE上查看代码片派生到我的代码片

intNR=registeredReceivers!

=null?

registeredReceivers.size():

0;

if(!

ordered&&NR>0){

//Ifwearenotserializingthisbroadcast,thensendthe

//registeredreceiversseparatelysotheydon'twaitforthe

//componentstobelaunched.

BroadcastRecordr=newBroadcastRecord(intent,callerApp,

callerPackage,callingPid,callingUid,requiredPermission,

registeredReceivers,resultTo,resultCode,resultData,map,

ordered,sticky,false);

......

booleanreplaced=false;

if(replacePending){

for(inti=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();

}

registeredRecei

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 医药卫生

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2