全局大喇叭,详解广播机制
2015-10-11 14:11
507 查看
1. 广播接收器(Broadcast Receiver)
android中的广播有两种类型:标准广播和有序广播标准广播 :一种完全异步执行的广播,在广播发出之后,所有的广播接受器几乎都会在同一时刻接收到这条广播信息,他们没有先后顺序可言,效率比较高,无法被截断的。
有序广播 :一种通病执行的广播,在广播发出之后,同一时刻只会有一个广播接收器收到这条广播消息,当这个广播接收器中的逻辑执行完毕后,广播才会继续传播,所有此时的广播接收器是有先后顺序的,优先级高的广播接收器就可以先收到广播消息,并且前面广播接收器还可以截断正在传递的广播,后面的广播接收器就无法收到广播消息了。
2.接收系统广播
android内置了很多系统级别的广播,比如手机开机完成后发出一条广播,电池的电量发送变化发出一条广播。广播接收器可以自由的对自己感兴趣的广播进行注册,当有相应的广播发出时,广播接收器就能收到该广播,然后处理相应的逻辑,
注册广播的方式:
在代码中注册(动态注册,动态注册的广播接收器一定要取消注册才行)
在AndroidManifest.xml中注册(静态注册)
创建一个广播接收器,很简单只需要继承BroadcastReceiver,重写父类的onReceiver()方法就行了,有广播到来时,onReceiver()方法就会被执行。
动态注册监听网络变化
public class MainActivity extends Activity { private IntentFilter intentFilter; private NetworkChangeReceiver networkChangeReceiver; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); intentFilter = new IntentFilter(); intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE"); networkChangeReceiver = new NetworkChangeReceiver(); //动态注册监听网络变化的广播 registerReceiver(networkChangeReceiver, intentFilter); } @Override protected void onDestroy() { super.onDestroy(); //取消注册的广播(动态注册的广播接收器一定要取消才行) unregisterReceiver(networkChangeReceiver); } /** * 监听网络变化的广播接收器 */ class NetworkChangeReceiver extends BroadcastReceiver { //当网络状态发生变化时,onReceive方法就会得到执行 @Override public void onReceive(Context context, Intent intent) { //用于管理网络连接 ConnectivityManager connManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo networkInfo = connManager.getActiveNetworkInfo(); //判断当前是否有网络 if(networkInfo!=null && networkInfo.isAvailable()){ Toast.makeText(context, "连接成功", Toast.LENGTH_SHORT).show(); }else { Toast.makeText(context, "网络在开小差,检查网络是否连接成功", Toast.LENGTH_SHORT).show(); } } } }
加一个权限:
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
如何测试广播接收器是否接收到消息呢?
打开数据流量就能看到,设置里面,流量使用情况
或者打开wifi,移动数据的按钮。
优缺点:动态注册的广播接收器可以自由的控制注册和注销,程序必须启动之后才能接收到广播。(京东手机客户端“网络在开小差检查后后在试吧”,解放号“网络异常,请稍后再试”)
静态注册实现开机启动
优点:可以在程序没有启动的情况下接收广播。
/** * 开机启动的广播 * */ public class BootCompleteReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { Toast.makeText(context, "开机启动了广播", Toast.LENGTH_SHORT).show(); } }
在AndroidManifest.xml中注册广播接收者
添加手机重启的权限:
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
注册开机启动的广播接收者
<receiver android:name=".BootCompleteReceiver"> <intent-filter > <action android:name="android.intent.action.BOOT_COMPLETED"/> </intent-filter> </receiver>
强调:不要在onReceive()方法中添加过多的逻辑或者执行任何的耗时的操作,
3.发送自定义广播
3.1 发送标准广播
广播是使用Intent传递数据的,我们可以在Intent中携带一些数据传递给广播接收器/** * 自定义广播接收器 * @author jzz * */ public class MyBroadcastReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { String name = intent.getStringExtra("name"); Toast.makeText(context, "发送自定义广播"+name, Toast.LENGTH_SHORT).show(); } }
Button button = (Button) findViewById(R.id.button); button.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { //发送自定义广播 Intent intent = new Intent("com.example.broadcasttest.MY_BROADCAST"); //可以携带一些数据传递给广播接收器 intent.putExtra("name", "helloworld"); sendBroadcast(intent); } });
3.2 发送有序广播
我们应用程序发出的广播,其他的应用程序也能接收到的。证明:
创建另一个项目:BroadcastTest2. 新建类AnotherBroadcastReceiver 继承BroadcastReceiver.
public class AnotherBroadcastReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { String name = intent.getStringExtra("name"); Toast.makeText(context, "在另一个广播接收器里面接收"+name, Toast.LENGTH_SHORT).show(); } }
在AndroidManifest.xml 文件里面注册静态广播接收器
<receiver android:name=".AnotherBroadcastReceiver"> <intent-filter > <action android:name="com.example.broadcasttest.MY_BROADCAST"/> </intent-filter> </receiver>
部署BroadcastTest2。
测试BroadcastTest2也能收到BroadcastTest发送的广播。
1.运行BroadcastTest2,按home键,
- 运行BroadcastTest,点击自定义广播发送。
- 会弹出2次提示信息,并且数据BroadcastTest2也是可以接收到BroadcastTest发送的内容的。
发送有序广播
//sendBroadcast(intent);//发送标准广播 sendOrderedBroadcast(intent, null);//发送有序广播
设定广播接收器的先后顺序
<!-- 自定义广播接收器 --> <receiver android:name=".MyBroadcastReceiver"> <!-- 通过设置优先级来设定广播接收器的先后顺序 --> <intent-filter android:priority="100"> <action android:name="com.example.broadcasttest.MY_BROADCAST"/> </intent-filter> </receiver>
广播的截断
public void onReceive(Context context, Intent intent) { String name = intent.getStringExtra("name"); Toast.makeText(context, "发送自定义广播"+name, Toast.LENGTH_SHORT).show(); abortBroadcast();//截断广播 }
部署运行BroadcastTest ,点击发送,只有MyBroadcastReceiver的信息弹出来,说明已经截断了广播。
3.3 使用本地广播
点击本地广播发送就进入本地广播发送的界面/** * 本地广播接收器 * @author jzz * */ public class MainActivity2 extends Activity{ private IntentFilter intentFilter; private LocalBroadcastManager localBroadcastManager; private LocalReceiver localReceiver; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main2); intentFilter = new IntentFilter(); localBroadcastManager = LocalBroadcastManager.getInstance(this); Button button3 = (Button) findViewById(R.id.button3); button3.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent("com.example.broadcasttest.LOCAL_BROADCAST"); localBroadcastManager.sendBroadcast(intent); } }); 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, "本地广播", Toast.LENGTH_SHORT).show(); } } }
本地广播比全局系统广播多了个LocalXXX
本地广播的优势:
1.本地广播无法通过静态注册的方式来接收
2.可以明确地知道正在发送的广播不会离开我们的程序,因此不需要担心机密数据泄
漏的问题。
3.其他的程序无法将广播发送到我们程序的内部,因此不需要担心会有安全漏洞的隐
患
4.发送本地广播比起发送系统全局广播将会更加高效。
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Manifest 用法
- [转载]Activity中ConfigChanges属性的用法
- Android之获取手机上的图片和视频缩略图thumbnails
- Android之使用Http协议实现文件上传功能
- Android学习笔记(二九):嵌入浏览器
- android string.xml文件中的整型和string型代替
- i-jetty环境搭配与编译
- android之定时器AlarmManager
- android wifi 无线调试
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- android 代码实现控件之间的间距
- android FragmentPagerAdapter的“标准”配置
- Android"解决"onTouch和onClick的冲突问题
- android:installLocation简析
- android searchView的关闭事件
- SourceProvider.getJniDirectories