Adnroid广播总结

BroadcastReceiver广播接收者是Android四大组件之一。一般的都要在AndroidManifest中静态注册,但是只有广播接收者可以使用Java代码的方法来动态注册。
BroadcastReceiver是用于接收广播的组件用于组件与组件之间进行通信,可以跨应用程序传递.如操作系统电池电量低会发送一个广播,这样我们的程序里面可以去监听这个广播,可以关闭程序里面比较耗电的功能,提示用户注意保存进度什么的,还如其它安装新应用等,还有普通应 用程序,例如启动特定线程,文件下载完毕等。
Android中的广播机制设计的非常出色,很多事情原本需要开发者亲自操作的,现在只需等待广播告知自己就可以了,大大减少了开发的工作量和开发周期。
广播的发送的一般应用场合:发送频率低的情况可以使用,数据量小的情况可以使用。

接收广播

创建BroadcastReceiver子类, 且实现onReceive()方法. 相当于创建一个收音机

1
2
3
4
5
6
public class MyBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
//对接收到的广播进行处理,intent里面包含数据
}
}

以上代码只是对接收的广播进行操作, 但是接收什么广播和谁来接收这个广播就要注册广播了. 注册广播相当于收音机调频

静态注册

静态注册是在AndroidManifest.xml文件中配置的.

1
2
3
4
5
<receiver android:name="com.hua.bcreceiver.MyBroadcastReceiver" >
<intent-filter>
<action android:name="android.intent.action.MY_BROADCAST" />
</intent-filter>
</receiver>

动态注册

动态注册需要在代码中动态的指定广播地址并注册, 由于registerReceiver是android.content.ContextWrapper类中的方法,Activity 和Service都继承了ContextWrapper,所以可以直接调用

补充:某些频繁的广播事件需要动态注册才能接收到此广播, 例如手机屏幕解锁和息屏.

注册

1
2
3
4
MyBroadcastReceiver mbcr = new MyBroadcastReceiver(); // 创建广播对象
IntentFilter filter = new IntentFilter(); // 意图过滤器添加动作
filter.addAction(MyBroadcastReceiver.MY_BC_FIRST);
registerReceiver(mbcr, filter);// 注册

解除注册代码

一般在页面销毁时也就是onDestroy()内操作, 如果没有解除注册程序运行时会自动解除注册, 不过会抛出一个异常停止.

1
2
3
4
5
6
@Override
protected void onDestroy() {
unregisterReceiver(mbcr); // 取消注册
mbcr = null; // 对象置为空
super.onDestroy();
}

通过上面两步其实已经完成了一个简单功能的广播接收者,已经可以具有接受广播功能了。在onReceive方法里面就可以做自己想要的处理。

但是上面的BroadcastReceiver注册时的action动作意图值是自己定义的字符串,需要自己发送对应意图的广播才能让上面的广播接收到消息,如果是上面使用系统定义好的动作意图action,那么,就可以接收到系统发过来的广播信息,比如手机接收到短信,手机底层是会发送一条广播,查看手机系统内是否有符合条件的广播接收者,如果有就会向它发送信息。。。

静态注册的广播的程序运行一次后,以后能一直保持广播接收的状态,只要有对应的广播就能接收它的广播信息。而动态注册的广播需要程序在运行中才能接收广播。

接收有序广播

区分

  • 一般广播是异步执行, 所有接收者同时收到广播

  • 有序广播

有序广播是有优先级之分, 优先级高的能比优先级低的广播接收者先接收到广播并且能中断广播.拦截方法: abortBroadcast();

在静态代码块中定义:

1
<intent-filter android:priority="999">

使用动态java代码设置:

1
filter.setPriority(999);

优先级的值越大它的优先级就越高。
那么priority的最大值是多少呢?
网上或有些书说的是1000,但是都不正确,正确答案是2147483647这是我通过几个实验得出的数据。优先级的值比它大1都会报错。并且优先级1001确实比优先级1000更快接收到广播。
优先级的范围是:-2147483647到2147483647
刚好它的长度范围是Integer类型数据的最大值4294967296(2的32次方)。
所有我们要知道优先级1000并不是最高的优先级,不信的话你可以试试看效果。

发送广播

上面在广播定义好的情况下,我们可以接收系统的广播信息,也可以接收自己发送的广播信息。
问题来了:
如果有多个接收者都注册了相同的广播地址,又会是什么情况呢,能同时接收到同一条广播吗,相互之间会不会有干扰呢?这就涉及到普通广播和有序广播的概念了。

普通广播

普通广播对于多个接收者来说是完全异步的,通常每个接收者都无需等待即可以接收到广播,接收者相互之间不会有影响。对于这种广播,接收者无法终止广播,即无法阻止其他接收者的 接收动作。

1
2
3
Intent intent = new Intent(“myBroadcastReceiver”); 
intent.putExtra(“msg”, “这是MainActivity页面发送的广播—-》》”); 
sendBroadcast(intent);

有序广播

有序广播比较特殊,它每次只发送到优先级较高的接收者那里,然后由优先级高的接受者再传播到优先级低的接收者那里,优先级高的接收者有能力终止这个广播。可以在广播注册时使用intent-filter里面的android: priority=”xxx”去解决或在java代码中用setPriority(xxx)来设置。

1
2
3
Intent intent = new Intent(“myBroadcastReceiver”); 
intent.putExtra(“msg”, “这是MainActivity页面发送的广播—-》》”); 
sendOrderedBroadcast(intent,null);//如果是该自定义的广播接收者发送广播,第二个参数一般为null

对比有序广播和无序广播:
发现他们的使用方式没什么不同,只是有序广播比无序广播要多一个参数;
但是它们的作用是非常不同的,无序广播是不可被截断的,每一个广播接收者都可以收到这个无序广播发送的广播信息;而无序广播时候根据优先级数的大小来判断谁先接收到广播信息,并且可以选择是否截断这个广播信息,如果在某个广播接收者截断信息,在它的优先级之下的广播接收者都接收不到广播信息。

有序广播才能拦截。

本地广播

上述所说的广播都是全局广播, 所有进程共享的数据传递. 其实这种操作是不安全的, 因为只要知道了动作名, 你发送的广播可以被任何应用接收到, 也能往你的广播接收者发送很多垃圾广播. 如果广播携带了某些隐私的数据被抓包到就不好了. 所以Android也引入了本地广播的机制, 关键类LocalBroadcastManager

本地广播只能在自生程序内部发送和接收, 常用于数据的同步.

发送本地广播

1
2
3
4
Intent intent = new Intent();
intent.setAction("广播动作名");
LocalBroadcastManager localBroadcastManager = LocalBroadcastManager.getInstance(this);
localBroadcastManager.sendBroadcast(intent);

接收本地广播

1
2
3
4
MyReceiver myReceiver = new MyReceiver();
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("广播动作名");
registerReceiver(myReceiver, intentFilter);

记得解除广播注册. 本地广播同样支持有序广播, 但是不支持静态注册, 这也可以理解发送广播的时候程序肯定在运行中, 动态注册完全能满足.

注意

发送频率低的可以使用 数据量小在可使用 intent携带的数据不能太大 广播的操作一定要在5秒钟内完成(10秒不能完成,ANR),如果耗时时间太长,开启服务。广播接受者内不能进行异步线程操作, 因为广播生命周期结束后会关闭进程.

两种注册方法

静态注册,manifest文件中注册,广播应该是一个外部类

  1. 优点:程序不启动,一样能收到广播,一般用于推送(自己搭建)。系统的处理。
  2. 缺点:占用资源较多。只有广播,系统会去匹配所有的接受者。

动态注册 一般都是匿名类代码中通过Content的方法 registerReceiver(receiver,intentfilter)注册广播; 在退出的时候一定需要解绑,否则抛异常。unRegisterReceiver 用于程序组件之间的消息传递。需要刷新UI

  1. 优点:程序占用资源少,及时释放
  2. 缺点:一定需要组件启动,注册广播。