broadcast与Activity和Service不同,它不具有完整的生命周期,它本质上是一个系统级的监听器——负责监听各程序发出的Broadcast(OnXXXListener()只是程序级的监听器,当程序退出时这些Listener也关闭,而Broadcast拥有自己的进程,只要有匹配的Intent,就会激发相应的BroadcastReceiver),所以实现BroadcastReceiver时只需实现onReceive()方法。
与Activity不同,系统通过Intent启动指定的Activity时,若找不到该Activity会导致程序异常终止,但找不到指定的Broadcast就没有任何问题。
同时注意,不要再onReceive()方法中执行任何耗时操作,如果该方法在10s内不能执行完成,就会ANR。如果必须要在Broadcast内完成耗时操作,采取用Intent启动一个Service的方法,不要启动一个新线程,因为Broadcast生命周期很短,有可能子线程没有执行完,BroadcastReceiver就结束了。这样虽然该进程内还有用户启动的线程,但是已经没有任何活动组件,所以在内存紧张时该进程会被优先结束。
广播可以跨进程,在应用程序内发出的广播,别的应用程序也可以收到
广播种类有普通广播和有序广播
普通广播
是一种完全异步执行的广播,执行效率较高,发出去后能同一时间被不同应用 不同的广播接受者接受,不安全。
android的广播注册方法有动态注册和静态注册
动态注册的广播随着注册时的Context对象的销毁而销毁。也可以主动注销掉动态注册的广播接受者。(1-3条都是在onCreate中)
1.创建过滤器
- @Override
- protected void onCreate(Bundle savedInstanceState){
- IntentFilter filter = new IntentFilter();
- filter.addAction(LOCAL_ACTION);
- BroadcastReceiver mReceiver = new BroadcastReceiver() { //如果是自定义广播就建一个内部类:class Receiver extends BroadcastReceiver,然后重写onReceive
- @Override
- public void onReceive(Context context, Intent intent) {
- if (LOCAL_ACTION.equals(intent.getAction())) {
- }
- }
- };
- registerReceiver(mReceiver, filter);
- }
- @Override
- protected void onDestroy() {
- super.onDestroy();
- unregisterReceiver(mReceiver);
- }
静态注册将会驻留在系统中,随着系统启动而启动,即开机启动,一直工作。如果没有必要,我推荐使用动态注册的方式来注册广播,灵活性较大,并且这样将会节省系统cpu资源和电量,
静态广播
只要设备开启,广播接受者就是打开的,不用担心广播接受者被挂掉。
1.继承实现BroadcastReceiver
- public class LocalBroadReceiver extends BroadcastReceiver {
- @Override
- public void onReceive(Context context, Intent intent) {
- if (LOCAL_ACTION.equals(intent.getAction())) {
- }
- }
- }
- <receiver android:name="com.example.androiddemo.LocalBroadReceiver" >
- <intent-filter >
- <action android:name="com.test.localbroad" />
- </intent-filter>
- </receiver>
注意:不要再onReceive种进行耗时操作,因为在广播接收器中不允许开启线程。
有序广播
特点:执行效率较低,发出的广播按照优先级的高低,从高到底依次传递,可以在传递的过程中消耗掉该广播不让较低优先级的广播接受者接受到该广播。可以把处理结果传递给下一个广播,也可以终止Broadcast Intent的传播。
有序广播跟无序广播使用上最大的不同是,要为注册的广播接受者设置一个优先级。其他部分流程类似。
广播发送方式:
- sendOrderedBroadcast(mIntent, null);
设置优先级
1.动态注册的广播接受者
- IntentFilter filter = new IntentFilter();
- filter.addAction(LOCAL_ACTION);
- registerReceiver(mReceiver, filter);
- filter.setPriority(1000);//优先级
- registerReceiver(mReceiver, filter);
- <receiver android:name="com.example.androiddemo.LocalBroadReceiver" >
- <intent-filter android:priority="500">
- <action android:name="com.test.localbroad" />
- </intent-filter>
- </receiver>
- Bundle bundle=intent.getExtras();
- setResultExtras(bundle); //将处理结果存入Broadcast,传递给下一级广播
- //abortBroadcast(); //终止广播的传递
- //是否接受上一个广播接收器传来的的数据
- Bundle bundle=getResultExtras(true);
在Android系统中,BroadcastReceiver的设计初衷就是从全局考虑的,可以方便应用程序和系统、应用程序之间、应用程序内的通信,所以对单个应用程序而言BroadcastReceiver是存在安全性问题的,相应问题及解决如下:
1、当应用程序发送某个广播时系统会将发送的Intent与系统中所有注册的BroadcastReceiver的IntentFilter进行匹配,若匹配成功则执行相应的onReceive函数。可以通过类似sendBroadcast(Intent, String)的接口在发送广播时指定接收者必须具备的permission。或通过Intent.setPackage设置广播仅对某个程序有效。
2. 当应用程序注册了某个广播时,即便设置了IntentFilter还是会接收到来自其他应用程序的广播进行匹配判断。对于动态注册的广播可以通过类似registerReceiver(BroadcastReceiver, IntentFilter, String, android.os.Handler)的接口指定发送者必须具备的permission,对于静态注册的广播可以通过android:exported="false"属性表示接收者对外部应用程序不可用,即不接受来自外部的广播。