概述:
在Android系统中,广播体现在方方面面,例如当开机完成后系统会产生一条广播,接收到这条广播就能实现开机启动服务的功能;当网络状态改变时系统会产生一条广播,接收到这条广播就能及时地做出提示和保存数据等操作;当电池电量改变时,系统会产生一条广播,接收到这条广播就能在电量低时告知用户及时保存进度,等等。
BroadcastReceiver 自身并不实现图形用户界面,但是当它收到某个通知后, BroadcastReceiver 可以启动Activity 作为响应,或者通过 NotificationMananger 提醒用户,或者启动 Service 等等
广播之间信息的传递是通过Intent对象来传递的;由于这里能通知到所有的接收者,所以肯定不能利用显示调用,只有利用隐式调用Intent对象了。(这里的隐式调用,并不是真正意义上的Intent隐式调用,因为Intent隐式调用,当出现很多匹配应用时,会以列表形式提示用户选择一个启动,而这里不同的地方在于,当有很多匹配项时,会给所有的匹配项都发一个消息,我说隐式调用,只是方便大家理解构造Intent的方法,即必须利用构造隐式Intent的方法来构造)
实现:(以收到短信)
第一种方式:
(1)创建自己的BroadcastReceiver对象,我们需要继承android.content.BroadcastReceiver,并实现其onReceive方法。
public class MyBroadcastReceiver extends BroadcastReceiver {
// action 名称
String SMS_RECEIVED = "android.provider.Telephony.SMS_RECEIVED" ;
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals( SMS_RECEIVED )) {
// 相关处理 : 地域变换、电量不足、来电来信;
}
}
}
(2) 系统注册:在 AndroidManifest.xml 中注册
注意,这种方式的注册是常驻型的,也就是说当应用关闭后,如果有广播信息传来,MyReceiver也会被系统调用而自动运行。
< receiver android:name = ".MyBroadcastReceiver" >
< intent-filter android:priority = "1000" >
<span style="white-space:pre"> </span> <span style="white-space:pre"> </span>< action android:name = " android.provider.Telephony.SMS_RECEIVED" />
</ intent-filter >
</ receiver >
注意这个例子需要权限
< uses-permission android:name = "android.permission.RECEIVE_SMS" />
< uses-permission android:name = "android.permission.SEND_SMS" />
// 广播接收者 - 广播的接收
private BroadcastReceiver myBroadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
// 相关处理,如收短信,监听电量变化信息
}
};
代码中注册:
比如在onResume()中registerReceiver,在onPause()中unregisterReceiver()。这种方式在程序不运行时是收不到广播的。
myBroadcastReceiver receiver = new myBroadcastReceiver ();
IntentFilter filter = new IntentFilter();
filter.addAction("android.provider.Telephony.SMS_RECEIVED");
registerReceiver(receiver, filter);
使用的时候(短信是系统发出,如果自己要发送广播如下)
Intent intent = new Intent();
intent.setAction("android.provider.Telephony.SMS_RECEIVED");
sendBroadcast(intent);
生命周期
运行原理很简单如下图:
每次广播到来时 , 会重新创建 BroadcastReceiver 对象 , 并且调用 onReceive() 方法 , 执行完以后 , 该对象即被销毁 . 所以
BroadcastReceiver 里不能做一些比较耗时的操作 , 否侧会弹出 ANR 的对话框 .
不能在里面开子线程解决这个问题,因为 BroadcastReceiver 的生命周期很短 , 子线程可能还没有结束
BroadcastReceiver 就先结束了 .BroadcastReceiver 一旦结束 , 此时 BroadcastReceiver 的
所在进程很容易在系统需要内存时被优先杀死 , 那么正在工作的子线程也会被杀死
解决方法:
如果需要完成一项比较耗时的工作 , 应该通过发送 Intent 给 Service, 由 Service 来完成 。也可以跳转Activity,在Activity里面开线程做耗时工作。
比如:
public class AlarmReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals("android.hjnote.ALARM_ACTION")) {
<strong>Intent noteList = new Intent(context, AlarmActivity.class);
noteList.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(noteList);</strong>
}
}
}
广播类型:
参考http://blog.csdn.net/liuhe688/article/details/6955668
普通广播(Normal Broadcast)
普通广播对于多个接收者来说是完全异步的,通常每个接收者都无需等待即可以接收到广播,接收者相互之间不会有影响。对于这种广播,接收者无法终止广播,即无法阻止其他接收者的接收动作。
有序广播(Ordered Broadcast)
有序广播比较特殊,它每次只发送到优先级较高的接收者那里,然后由优先级高的接受者再传播到优先级低的接收者那里,优先级高的接收者有能力终止这个广播。
有序广播的注册:
AndroidMainfest.xml文件:
我们看到,现在这三个接收者的<intent-filter>多了一个android:priority属性,并且依次减小。这个属性的范围在-1000到1000,数值越大,优先级越高。
发送普通广播:sendBroadcast(intent);
发送有序广播:sendOrderedBroadcast(intent, receiverPermission);
注意,receiverPermission发送有序广播时需要一个权限参数。
如果为null则表示不要求接收者声明指定的权限,如果不为null,则表示接收者若要接收此广播,需声明指定权限。这样做是从安全角度考虑的,例如系统的短信就是有序广播的形式,一个应用可能是具有拦截垃圾短信的功能,当短信到来时它可以先接受到短信广播,发现是垃圾短信的时候终止广播传递(也就是拦截功能),这样的软件就必须声明接收短信的权限。