android发说说功能,说说Android的广播(1)

说说Android的广播

对于Activity的启动流程,我们已经有了几个版本的分析了。这里我们分析一个更容易一些的,四大组件中最简单的Broadcast Receiver。

关于Broadcast,有几点需要了解。首先是广播的类型,然后是广播的发送方法,最后是广播是如何被接收的。这三者相辅相承的,比如普通广播和有序广播只有在详细了解了广播的接收过程了之后,才能真正明白它的含义。

广播的类型:普通广播,有序广播和粘性广播

普通的广播是不在意顺序的,最简单的理解是同时可以收到这个广播。如果应用是动态注册这个广播的,且广播发送时这个进程还活着,那么当然可以并发的把广播尽快地传送出去是最好的。

但是,如果是通过AndroidManifest.xml静态注册的情况,也就是说这个广播首先要把一个进程启动起来,这时并发启动很多进程就是个问题了。Android目前的做法是,对这种静态的广播接收者,自动按有序广播的方式来串行处理。但是这对应用是透明的,应用不能假设系统已经把静态的无序广播当成有序广播来处理。

这个时候讲粘性广播有福了,因为从Android 5.0(API 21)开始,因为安全性的问题,官方已经正式废弃了粘性广播。

普通广播的发送

Context类提供两个方法可以用于发送普通广播:

sendBroadcast(Intent intent);

sendBroadcast(Intent intent, String receiverPermission);

差别是第二个设置权限。

发给特定的用户:

sendBroadcastAsUser(Intent intent, UserHandle user);

sendBroadcastAsUser(Intent intent, UserHandle user, String receiverPermission);

有序广播的发送

有序广播因为要处理消息的处理结果,所以要复杂一些。

sendOrderedBroadcast(Intent intent, String receiverPermission, BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, String initialData, Bundle initialExtras);

如果只是想让广播可以按优先级来收取,并不在意处理的结果,可以用下面的版本:

sendOrderedBroadcast(Intent intent, String receiverPermission);

同样,在多用户环境下,也可以选择给哪个用户发广播:

sendOrderedBroadcastAsUser(Intent intent, UserHandle user, String receiverPermission, BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, String initialData, Bundle initialExtras);

过时的粘性广播

不管是普通的还是有序的广播都对应有粘性的版本:

sendStickyBroadcast(Intent intent);

sendStickyBroadcastAsUser(Intent intent, UserHandle user);

sendStickyOrderedBroadcast(Intent intent, BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, String initialData, Bundle initialExtras);

sendStickyOrderedBroadcastAsUser(Intent intent, UserHandle user, BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, String initialData, Bundle initialExtras);

首先我们先看看发送端是如何发送的。

我们首先先放一个大图,让大家先有一个直观的印象,不管普通广播、有序广播、粘性广播如何组合,最终都汇集到一个大方法中。

e2a8cf82284e

Android_broadcast

graph TD;

Context_sendbroadcast[Context.sendBroadcast Intent];

Context_sendbroadcast_asUser[Context.sendBroadcastAsUser Intent,UserHandle];

Context_sendOrderedBroadcast[Context.sendOrderedBroadcast Intent,String,BroadcastReceiver,Handler,int,String,Bundle];

Context_sendOrderedBroadcast2[Context.sendOrderedBroadcast Intent,String];

Context_sendStickyBroadcast[Context.sendStickyBroadcast Intent];

Context_sendStickyBroadcast2[Context.sendStickyOrderedBroadcast Intent,BroadcastReceiver,Handler,int,String,Bundle];

ContextWrapper_sendBroadcast[ContextWrapper.sendBroadcast Intent];

ContextWrapper_sendOrderedBroadcast2[ContextWrapper.sendOrderedBroadcast Intent,String];

ContextWrapper_sendOrderedBroadcast[ContextWrapper.sendOrderedBroadcast Intent,String,BroadcastReceiver,Handler,int,String,Bundle];

ContextWrapper_sendStickyBroadcast[ContextWrapper.sendStickyBroadcast Intent];

ContextWrapper_sendStickyBroadcast2[ContextWrapper.sendStickyOrderedBroadcast Intent,BroadcastReceiver,Handler,int,String,Bundle];

ContextWrapper_sendbroadcast_asUser[ContextWrapper.sendBroadcastAsUser Intent,UserHandle];

ContextImpl_sendBroadcast[ContextImpl.sendBroadcast Intent];

ContextImpl_sendOrderedBroadcast2[ContextImpl.sendOrderedBroadcast Intent,String];

ContextImpl_sendOrderedBroadcast[ContextImpl.sendOrderedBroadcast Intent,String,BroadcastReceiver,Handler,int,String,Bundle];

ContextImpl_sendStickyBroadcast[ContextImpl.sendStickyBroadcast Intent];

ContextImpl_sendStickyBroadcast2[ContextImpl.sendStickyOrderedBroadcast Intent,BroadcastReceiver,Handler,int,String,Bundle];

ContextImpl_sendbroadcast_asUser[ContextImpl.sendBroadcastAsUser Intent,UserHandle];

ContextImpl_sendOrderedBroadcast_all(ContextImpl.sendOrderedBroadcast Intent,String,int,BroadcastReceiver,Handler,int,String,Bundle,Bundle);

ActivityManagerService_broadcastIntent(ActivityManagerService.broadcastIntent IApplicationThread,Intent,String,IIntentReceiver,int,String,Bundle,String,int,Bundle,boolean,boolean,int);

Context_sendbroadcast --> ContextWrapper_sendBroadcast;

ContextWrapper_sendBroadcast --> ContextImpl_sendBroadcast;

ContextImpl_sendBroadcast --> ActivityManagerService_broadcastIntent;

Context_sendbroadcast_asUser --> ContextWrapper_sendbroadcast_asUser;

ContextWrapper_sendbroadcast_asUser --> ContextImpl_sendbroadcast_asUser;

ContextImpl_sendbroadcast_asUser --> ActivityManagerService_broadcastIntent;

Context_sendOrderedBroadcast2 --> ContextWrapper_sendOrderedBroadcast2;

ContextWrapper_sendOrderedBroadcast2 --> ContextImpl_sendOrderedBroadcast2;

ContextImpl_sendOrderedBroadcast2 --> ActivityManagerService_broadcastIntent;

Context_sendOrderedBroadcast --> ContextWrapper_sendOrderedBroadcast;

ContextWrapper_sendOrderedBroadcast --> ContextImpl_sendOrderedBroadcast;

ContextImpl_sendOrderedBroadcast --> ContextImpl_sendOrderedBroadcast_all;

ContextImpl_sendOrderedBroadcast_all --> ActivityManagerService_broadcastIntent;

Context_sendStickyBroadcast --> ContextWrapper_sendStickyBroadcast;

ContextWrapper_sendStickyBroadcast --> ContextImpl_sendStickyBroadcast;

ContextImpl_sendStickyBroadcast --> ActivityManagerService_broadcastIntent;

Context_sendStickyBroadcast2 --> ContextWrapper_sendStickyBroadcast2;

ContextWrapper_sendStickyBroadcast2 --> ContextImpl_sendStickyBroadcast2;

ContextImpl_sendStickyBroadcast2 --> ActivityManagerService_broadcastIntent;

应用发送广播的过程

普通广播的发送

我们先看应用发送普通广播的一个简单的例子:

Intent intent = new Intent("android.intent.action.TestAction");

intent.putExtra(EXTRA_TIME, System.currentTimeMillis());

MainActivity.this.sendBroadcast(intent);

非常简单,调用ContentWrapper的sendBroadcast方法就可以了。

然后我们顺藤摸瓜就好了。

Activity中的sendBroadcast,实际上调用的是:

void android.content.ContextWrapper.sendBroadcast(Intent intent);

ContextWrapper.sendBroadcast

我们来看frameworks/base/core/java/android/content/ContextWrapper.java中对sendBroadcast的定义:

@Override

public void sendBroadcast(Intent intent) {

mBase.sendBroadcast(intent);

}

ContextWrapper只是一个包装,真正的实现在ContextImpl中

ContextImpl.sendBroadcast

我们来看/frameworks/base/core/java/android/app/ContextImpl.java中真正实现sendBroadcast的功能:

@Override

public void sendBroadcast(Intent intent) {

...

try {

...

ActivityManagerNative.getDefault().broadcastIntent(

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

Activity.RESULT_OK, null, null, null, AppOpsManager.OP_NONE, null, false, false,

getUserId());

} catch (RemoteException e) {

throw new RuntimeException("Failure from system", e);

}

}

它会通过IPC去调用AMS的broadcastIntent。由于我们这个普通的广播的方法参数最少,所以好多都是传null。

ActivityManagerService.broadcastIntent

public final int broadcastIntent(IApplicationThread caller,

Intent intent, String resolvedType, IIntentReceiver resultTo,

int resultCode, String resultData, Bundle resultExtras,

String[] requiredPermissions, int appOp, Bundle options,

boolean serialized, boolean sticky, int userId) {

enforceNotIsolatedCaller("broadcastIntent");

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, resultExtras,

requiredPermissions, appOp, null, serialized, sticky,

callingPid, callingUid, userId);

Binder.restoreCallingIdentity(origId);

return res;

}

}

加锁,定参数,然后调用真正的逻辑的实现。

有序广播的发送

我们先把broadcastIntentLocked的真正逻辑放一下,先看看有序广播是如何发送的。

ContextWrapper.sendOrderedBroadcast

Context是abstract方法,调用的是ContextWrapper的实现:

@Override

public void sendOrderedBroadcast(Intent intent,

String receiverPermission) {

mBase.sendOrderedBroadcast(intent, receiverPermission);

}

跟普通广播一样,还是会调用到ContextImpl.sendOrderedBroadcast

public void sendOrderedBroadcast(Intent intent, String receiverPermission) {

warnIfCallingFromSystemProcess();

String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());

String[] receiverPermissions = receiverPermission == null ? null

: new String[] {receiverPermission};

try {

intent.prepareToLeaveProcess();

ActivityManagerNative.getDefault().broadcastIntent(

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

Activity.RESULT_OK, null, null, receiverPermissions, AppOpsManager.OP_NONE,

null, true, false, getUserId());

} catch (RemoteException e) {

throw new RuntimeException("Failure from system", e);

}

}

有序广播调用broadcastIntent的区别在于serialized参数,普通广播为false,有序广播为true.

原型为:

public final int broadcastIntent(IApplicationThread caller,

Intent intent, String resolvedType, IIntentReceiver resultTo,

int resultCode, String resultData, Bundle resultExtras,

String[] requiredPermissions, int appOp, Bundle options,

boolean serialized, boolean sticky, int userId) {

多参数的版本

前面讲过带有回调的版本,我们看看它是如何实现的:

@Override

public void sendOrderedBroadcast(

Intent intent, String receiverPermission, BroadcastReceiver resultReceiver,

Handler scheduler, int initialCode, String initialData,

Bundle initialExtras) {

mBase.sendOrderedBroadcast(intent, receiverPermission,

resultReceiver, scheduler, initialCode,

initialData, initialExtras);

}

当然还是调用ContextImpl.sendOrderedBroadcast

@Override

public void sendOrderedBroadcast(Intent intent,

String receiverPermission, BroadcastReceiver resultReceiver,

Handler scheduler, int initialCode, String initialData,

Bundle initialExtras) {

sendOrderedBroadcast(intent, receiverPermission, AppOpsManager.OP_NONE,

resultReceiver, scheduler, initialCode, initialData, initialExtras, null);

}

这次变成只是一个封装了,它会调用一个更多参数的版本:

void sendOrderedBroadcast(Intent intent,

String receiverPermission, int appOp, BroadcastReceiver resultReceiver,

Handler scheduler, int initialCode, String initialData,

Bundle initialExtras, Bundle options) {

warnIfCallingFromSystemProcess();

IIntentReceiver rd = null;

if (resultReceiver != null) {

if (mPackageInfo != null) {

if (scheduler == null) {

scheduler = mMainThread.getHandler();

}

rd = mPackageInfo.getReceiverDispatcher(

resultReceiver, getOuterContext(), scheduler,

mMainThread.getInstrumentation(), false);

} else {

if (scheduler == null) {

scheduler = mMainThread.getHandler();

}

rd = new LoadedApk.ReceiverDispatcher(

resultReceiver, getOuterContext(), scheduler, null, false).getIIntentReceiver();

}

}

String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());

String[] receiverPermissions = receiverPermission == null ? null

: new String[] {receiverPermission};

try {

intent.prepareToLeaveProcess();

ActivityManagerNative.getDefault().broadcastIntent(

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

initialCode, initialData, initialExtras, receiverPermissions, appOp,

options, true, false, getUserId());

} catch (RemoteException e) {

throw new RuntimeException("Failure from system", e);

}

}

这次是一个全参数调用broadcastIntent的版本了,除了sticky就齐了

粘性广播

我们也不绕圈子了,直接看ContextImpl.sendStickyBroadcast.

@Override

@Deprecated

public void sendStickyBroadcast(Intent intent) {

warnIfCallingFromSystemProcess();

String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());

try {

intent.prepareToLeaveProcess();

ActivityManagerNative.getDefault().broadcastIntent(

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

Activity.RESULT_OK, null, null, null, AppOpsManager.OP_NONE, null, false, true,

getUserId());

} catch (RemoteException e) {

throw new RuntimeException("Failure from system", e);

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值