Broadcast广播

广播是android中各个组件之间的一种通讯方式,一般的使用场景是:
1)APP内,单个组件相同或不同线程之间通信;
2)APP内,不同组件之间的通信(单个进程);
3)不同APP之间的通信;
4)APP和系统时间的通信;
除了第一个不常用之外,其他3个都比较适用,第二个有EventBus,一种更好的处理方式。

从实现原理看上,Android中的广播使用了观察者模式,基于消息的发布/订阅事件模型。因此,从实现的角度来看,Android中的广播将广播的发送者和接受者极大程度上解耦,使得系统能够方便集成,更易扩展。广播发送者和广播接收者的执行是异步的,发出去的广播不会关心有无接收者接收,也不确定接收者到底是何时才能接收到。

具体的用法是创建类继承BroadcastReceiver,并重写其中的onReceive方法。因为是四大组件之一,因此需要注册。广播的注册方式有2种:
1.在manifest中注册
application内,

<receiver
            android:name=".broadcast.MyReceiver"
            android:enabled="true"
            android:permission="string"
            android:process="string"                              android:exported="true"
>
 <intent-filter>
                <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
            </intent-filter>
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED" />
            </intent-filter>
</receiver>

使用的时候,直接在onReceive中判断广播种类,分类处理即可;其中需要注意的属性:
android:exported ——此broadcastReceiver能否接收其他App的发出的广播,这个属性默认值有点意思,其默认值是由receiver中有无intent-filter决定的,如果有intent-filter,默认值为true,否则为false。(同样的,activity/service中的此属性默认值一样遵循此规则)同时,需要注意的是,这个值的设定是以application或者application user id为界的,而非进程为界(一个应用中可能含有多个进程);
android:name —— 此broadcastReceiver类名;
android:permission ——如果设置,具有相应权限的广播发送方发送的广播才能被此broadcastReceiver所接收;
android:process ——broadcastReceiver运行所处的进程。默认为app的进程。可以指定独立的进程(Android四大基本组件都可以通过此属性指定自己的独立进程)
其中,intent-filter由于指定此广播接收器将用于接收特定的广播类型。本示例中给出的是用于接收网络状态改变或开启启动时系统自身所发出的广播。当此App首次启动时,系统会自动实例化MyBroadcastReceiver,并注册到系统中。

2.在activity中动态注册
一般在activity中创建广播接受者后,在oncreate()方法中,

  myReceiver2=new MyReceiver2();
        IntentFilter filter=new IntentFilter();
        filter.addAction("com.wy.XXXXX");
        registerReceiver(myReceiver2,filter);

这种注册方法需要在onDestroy()方法中注销广播:

 @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.d("vivi","onDestroy");
        unregisterReceiver(myReceiver2);
    }

发送广播:
事实上,广播的发送是以Intent形式实现的:

Intent intent = new Intent();
2 intent.setAction("com.wy.XXXXX");
3 intent.putExtra("aaa", "hello");
4 sendBroadcast(intent);

在onReceive方法中判断广播,从intent中取得相应数据。

注:在android3.1之前,静态注册的广播即使APP进程结束,广播接收者依然能工作,接收相应广播。但是在3.1之后,这种情况有可能不在成立。
Android 3.1开始系统在Intent与广播相关的flag增加了参数,分别是FLAG_INCLUDE_STOPPED_PACKAGES和FLAG_EXCLUDE_STOPPED_PACKAGES。

FLAG_INCLUDE_STOPPED_PACKAGES:包含已经停止的包(停止:即包所在的进程已经退出)

FLAG_EXCLUDE_STOPPED_PACKAGES:不包含已经停止的包。

自Android3.1开始,系统本身则增加了对所有app当前是否处于运行状态的跟踪。在发送广播时,不管是什么广播类型,系统默认直接增加值为FLAG_EXCLUDE_STOPPED_PACKAGES的flag,导致即使是静态注册的广播接收器,对于其所在进程已经退出的app,同样无法接收到广播。
由此,对于系统广播,由于是系统内部直接发出,无法更改此intent flag值,因此,3.1开始对于静态注册的接收系统广播的BroadcastReceiver,如果App进程已经退出,将不能接收到广播。

对于自定义的广播,可以通过复写此flag为FLAG_INCLUDE_STOPPED_PACKAGES,使得静态注册的BroadcastReceiver,即使所在App进程已经退出,也能能接收到广播,并会启动应用进程,但此时的BroadcastReceiver是重新新建的。

 Intent intent = new Intent();
2 intent.setAction(BROADCAST_ACTION);
3 intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
4 intent.putExtra("aaaa", "com.wy.xxxx");
5 sendBroadcast(intent);

一种替代方案:通过将Service与App本身设置成不同的进程。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值