广播机制(Broadcast Receiver)——第一行代码阅读笔记
转自http://blog.csdn.net/zhoubin1992/article/details/44924081
广播的类型
- 标准广播
Normal broadcasts,一种完全异步执行的广播,在广播发出之后,所有的广播接收器几乎都会在同一时刻接收到这条广播消息,因此它们之间没有任何先后顺序可言。 无法被截断的。 - 有序广播
Ordered broadcasts,一种同步执行的广播, 在广播发出之后, 同一时刻只会有一个广播接收器能够收到这条广播消息,当这个广播接收器中的逻辑执行完毕后, 广播才会继续传递。可被截断的。
接收系统广播
注册广播的方式一般有两种, 在代码中注册和在 AndroidManifest.xml 中注册, 其中前者也被称为动态注册, 后者也被称为静态注册。
动态注册
新建一个类, 让它继承自 BroadcastReceiver,并重写父类的 onReceive()方法。
动态注册监听网络变化:
我们在 MainActivity 中定义了一个内部类 NetworkChangeReceiver,这个类
是继承自 BroadcastReceiver 的, 并重写了父类的 onReceive()方法。
class NetworkChangeReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, “network changes”,
Toast.LENGTH_SHORT).show();
}
}
在onCreate()方法中:当网络状态发生变化时,系统发出的正是一条值为 android.net.conn.CONNECTIVITY_CHANGE 的广播。
intentFilter = new IntentFilter();
intentFilter.addAction(“android.net.conn.CONNECTIVITY_CHANGE”);
networkChangeReceiver = new NetworkChangeReceiver();
registerReceiver(networkChangeReceiver, intentFilter);
接下来创建了一个 NetworkChangeReceiver 的实例, 然后调用 registerReceiver()方法进行注册,将 NetworkChangeReceiver 的实例和 IntentFilter 的实例都传了进去,这样NetworkChangeReceiver 就会收到所有值为 android.net.conn.CONNECTIVITY_CHANGE 的广播,也就实现了监听网络变化的功能。
记得, 动态注册的广播接收器一定都要取消注册才行, 这里我们是在onDestroy()方法中通过调用 unregisterReceiver()方法来实现的。
静态注册
动态注册的广播接收器存在着一个缺点,即必须要在程序启动之后才能接收到广播,因为注册的逻辑是写在onCreate()方法中的。让程序在未启动的情况下就能接收到广播就需要使用静态注册的方式了。
新建一个 BootCompleteReceiver 继承自BroadcastReceiver,代码如下所示:
public class BootCompleteReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
Toast.makeText(context, "开机完成", Toast.LENGTH_SHORT).show();
}
}
不再使用内部类的方式来定义广播接收器,我们需要在AndroidManifest.xml 中将这个广播接收器的类名注册进去。
首先通过 android:name来指定具体注册哪一个广播接收器, 然后在标签里加入想要接收的广播就行了,由于 Android系统启动完成后会发出一条值为 android.intent.action.BOOT_COMPLETED 的广播,因此我们在这里添加了相应的 action。
注意:不要在 onReceive()方法中添加过多的逻辑或者进行任何的耗时操作, 因为在广播接收器中是不允许开启线程的, 当 onReceive()方法运行了较长时间而没有结束时, 程序就会报错。
因此广播接收器更多的创建一条状态栏通知, 或者启动一个服务等。
发送自定义广播
发送标准广播
新建一个 MyBroadcastReceiver继承自 BroadcastReceiver,代码如下所示:
public class MyBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, “我收到了”,
Toast.LENGTH_SHORT).show();
}
}
在 AndroidManifest.xml 中对这个广播接收器进行注册:
在布局文件中定义了一个按钮, 用于作为发送广播的触发点。 然后修改 MainActivity中的代码,如下所示:
Button button=(Button)findViewById(R.id.button);
button.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
Intent intent=new Intent("com.example.broadcasttest.MY_BROADCAST");
sendBroadcast(intent);
}
});
首先构建出了一
个 Intent 对象, 并把要发送的广播的值传入, 然后调用了 Context 的 sendBroadcast()方法将广播发送出去, 这样所有监听 com.example.broadcasttest.MY_BROADCAST 这条广播的广播接收器就会收到消息。
发送有序广播
在我们应用程序内发出的广播, 其他的应用程序应该也是可以收到的。
我们需要再新建一个 BroadcastTest2 项目。新建 AnotherBroadcastReceiver 继承自 BroadcastReceiver:
public class AnotherBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
Toast.makeText(context, "另一个也收到了",
Toast.LENGTH_SHORT).show();
}
}
然 后 在AndroidManifest.xml 中对这个广播接收器进行注册。 同 样 接 收 的 是 com.example.broadcasttest.MY_BROADCAST 这条广播。
发送有序广播:
1. 发送有序广播只需要改动一行代码,即将 sendBroadcast() 方法改 成sendOrderedBroadcast()方法。 sendOrderedBroadcast()方法接收两个参数,第一个参数仍然是Intent, 第二个参数是一个与权限相关的字符串, 这里传入 null 就行了。
2. 在注册的时候进行设定广播接收器的先后顺序
通过 android:priority 属性给广播接收器设置了优先级.
3. 如果在 onReceive()方法中调用了 abortBroadcast()方法, 就表示将这条广播截断, 后面的广播接收器将无法再接收到这条广播。
使用本地广播
为了能够简单地解决广播的安全性问题, Android 引入了一套本地广播机制,使用这个机制发出的广播只能够在应用程序的内部进行传递, 并且广播接收器也只能接收来自本应用程序发出的广播,这样所有的安全性问题就都不存在了。
使用了一个 LocalBroadcastManager 来对广播进行管理, 并提供了发送广播和注册广播接收器的方法。
localBroadcastManager = LocalBroadcastManager.getInstance(this);
Button button=(Button)findViewById(R.id.button);
button.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
Intent intent=new Intent("com.example.broadcasttest.LOCAL_BROADCAST");
//sendBroadcast(intent);
//sendOrderedBroadcast(intent, null);
localBroadcastManager.sendBroadcast(intent);
}
});
intentFilter = new IntentFilter();
intentFilter.addAction("com.example.broadcasttest.LOCAL_BROADCAST");
localReceiver = new LocalReceiver();
localBroadcastManager.registerReceiver(localReceiver, intentFilter);
class LocalReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "received local broadcast",
Toast.LENGTH_SHORT).show();
}
}
首先是通过 LocalBroadcastManager的 getInstance()方法得到了它的一个实例,然后在注册广播接收器的时候调用的是 LocalBroadcastManager
的 registerReceiver()方法,在发送广播的时候调用的是LocalBroadcastManager 的 sendBroadcast()方法,仅此而已。这里我们在按钮的点击事件里面发出了一条 com.example.broadcasttest.LOCAL_BROADCAST 广播,然后在 LocalReceiver 里去接收这条广播。
本地广播是无法通过静态注册的方式来接收的。
本地广播的几点优势:
1. 可以明确地知道正在发送的广播不会离开我们的程序, 因此不需要担心机密数据泄
漏的问题。
2. 其他的程序无法将广播发送到我们程序的内部, 因此不需要担心会有安全漏洞的隐
患。
3. 发送本地广播比起发送系统全局广播将会更加高效。