之前的博客中分析过Android广播机制相关的源码。
我们知道,如果仅将广播分类为有序广播和无序广播,
那么二者最大的区别在于:
Android系统(AMS)向一个广播接收器发送无序广播时,
并不需要等待该广播接收器返回结果,就会继续向下一个广播接收器发送广播。
因此,无序广播可近似地看作同步发送到所有的广播接收器。
但是,当Android系统发送有序广播时,将会等待前一个广播接收器返回结果后(除非处理超时),
才会继续发送向下一个广播接收器发送广播。
因此,有序广播将会按照先后顺序,依次递交给每个广播接收器。
根据有序广播发送的特点,前一个广播接收器可以向后一个广播接收器传递消息。
例如,假设有如下场景:
后台服务完成一些业务后,需要决定是否弹出一个通知栏。
如果判断应用没有在前台运行,就弹出通知栏;否则,就不弹出通知栏。
这个需求有很多种实现方式,我们仅以此场景为例,
看看如果使用有序广播的话,如何来解决这个问题。
//假设后台服务完成业务,调用该接口发送通知
private void showBackgroundNotification(int requestCode, Notification notification) {
//构造一个Intent
Intent i = new Intent(ACTION_SHOW_NOTIFICATION);
i.putExtra(REQUEST_CODE, requestCode);
i.putExtra(NOTIFICATION, notification);
//Service继承Context,具有发送有序广播的接口
//这里仅传入的intent、要求的权限及广播初始携带的Result Code
sendOrderedBroadcast(i, PERM_PRIVATE, null, null, Activity.RESULT_OK,null,null);
}
现在,在前台的Fragment中动态注册一个广播接收器:
public class VisibleFragment extends Fragment {
..............
//Fragment在前台时,就注册广播接收器
@Override
public void onStart() {
super.onStart();
IntentFilter filter = new IntentFilter(JobPollService.ACTION_SHOW_NOTIFICATION);
getActivity().registerReceiver(
mOnShowNotification, filter, JobPollService.PERM_PRIVATE, null);
}
//Fragment离开前台时,就反注册广播接收器
@Override
public void onStop() {
super.onStop();
getActivity().unregisterReceiver(mOnShowNotification);
}
private BroadcastReceiver mOnShowNotification = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
............
//调用BroadcastReceiver中的接口,更改广播携带的Result Code
setResultCode(Activity.RESULT_CANCELED);
}
};
..............
}
从上面的代码我们知道,当应用在前台时,就会收到后台发送的有序广播,然后修改广播携带的Result Code。
然后,我们再定义一个静态广播接收器:
//AndroidManifest.xml中的定义
............
<receiver android:name=".receiver.NotificationReceiver"
//外部应用无法发送消息给该BroadcastReceiver
android:exported="false">
//指定其优先级最低,确保其最后收到有序广播
//实际上,从之前博客分析的源码来看,广播本来就会先发送给动态注册的接收器,其次才会发送给静态广播接收器
<intent-filter android:priority="-999">
<action android:name="stark.a.is.zhang.photogallery.SHOW_NOTIFICATION"/>
</intent-filter>
</receiver>
............
在该静态广播接收器的实现代码中:
public class NotificationReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
//判断Result Code
if (getResultCode() != Activity.RESULT_OK) {
return;
}
int requestCode = = intent.getIntExtra(JobPollService.REQUEST_CODE, 0);
Notification notification = intent.getParcelableExtra(JobPollService.NOTIFICATION);
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context);
notificationManager.notify(requestCode, notification);
}
}
静态广播接收器在发送通知前,先判断广播携带的Result Code是否满足条件。
根据上文的代码容易看出,如果应用在前台,那么动态注册的广播接收器将会先收到有序广播,
并修改其中的Result Code,于是静态广播接收器收到广播后,就不会弹出通知;
反之,如果应用不在前台,那么静态广播接收器收到广播时,其携带的Result Code与初始时一致,
就会弹出通知栏。
以上案例仅作为静态广播的使用示例,实际上静态广播还可以携带一些其它的数据,
具体使用方式,可以参考对应的api。