Android Broadcast------详解广播机制
2016-03-18 23:10
597 查看
简介
我们知道,Broadcast是安卓四大组件之一。安卓为了方便进行系统级别的消息通知,引入了一套广播消息机制。打个比方,记得原来在上课的时候,每个班级的教室里都会装有一个喇叭,这些喇叭都是接入到学校的广播室的,一旦有什么重要通知,如上课铃下课铃,学校就会播放一条广播来告知全校的师生。这是一个非常形象容易理解的句子,很好的解释了Broadcast大概的意思,不过,Android中的广播机制更加灵活。为什么会说Android中的广播机制更加灵活呢?这是因为Android中的每个应用程序都可以对自己感兴趣的广播进行注册,这样该程序就只会接收到自己所关心的广播内容,这些广播可能来自于系统,也可能是来自于其他应用程序的。Android提供了一套完整的API,允许应用程序自由的发送和接收广播。接下来就先详细解释广播接收器。
广播接收器
Android中广播接收器主要可分两种类型,标准广播和有序广播。标准广播
标准广播是一种完全异步执行的广播,在广播发出去之后,所有的广播接收器几乎都会在同一时刻接收到这条消息,因此它们之间无任何先后顺序可言。这种广播的效率会比较高,但同时也意味着它是无法被截断的。有序广播
有序广播则是一种同步执行的广播,在广播发出去之后,同一时刻只会有一个广播接收器能够收到这条消息,当这个广播接收器中的逻辑执行完毕后,广播才会继续传递。所以此时的广播接收器是有先后顺序的,优先级高的广播接收器就可以先接收到广播消息,并且前面的广播接收器还可以截断正在传递的关公,这样的广播接收器就无法接收到消息了。掌握了这些基本概念之后,我就用代码来尝试广播的用法。
接收广播系统
广播接收器可以自由地对自己感兴趣的广播进行注册,这样当有相应的广播发出时,广播接收器就能够收到广播,并在内部处理相应的逻辑。注册广播的方式一般有两种,在代码注册和在AndroidManifest.xml中注册,其中前者也被称为动态注册,后者也被称为静态注册。动态注册广播监听
动态注册广播的方法非常简单,只需要新建一个类,然后让它继承自BroadcastReceiver并重写父类的onReceive()方法就行了。当广播到来时,onReceive()方法会得到执行,开发者就可以在这个方法中进行处理相应的逻辑。public class DynamicRegistReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { //相应逻辑处理 } }
最后要记得,动态注册的广播接收器一定都要取消注册才行,使用unregisterReceive()方法取消注册。
静态注册广播监听
动态注册的广播接收器可以自由的控制注册于注销,在灵活性方面有很大的优势,但是它也存在一个缺点,即必须要在程序启动之后才能接收广播。静态注册就可以很好的弥补这个缺点,想要使用静态注册同样是要新建一个类继承BroadcastReceiver并重写onReceive()方法,还需要在AndroidManifest.xml中奖这个广播接收器的类名注册进去。<receiver android:name=".staticregist.StaticRegistReceiver"/>
注册好了之后同样是在onReceive()方法中进行相应的逻辑。
发送自定义广播
上面详细介绍了通过广播接收器来接收广播。发送的广播主要分为两种类型:标准广播和有序广播,接下来就通过代码来演示这两种广播具体的区别。发送标准广播
在发送广播之前,还是需要先定义一个广播接收器来准备接受此广播才行,在onReceive方法中写了一个Toastpublic static class MyBroadcastReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { Toast.makeText(context, "接收到了自定义广播", Toast.LENGTH_SHORT).show(); } }
然后在AndroidManifest.xml中对这个广播接收器注册
<receiver android:name=".sendbroadcast.SendBroadcastActivity$MyBroadcastReceiver"> <intent-filter> <action android:name="com.example.broadcastdemo.MY_BROADCAST" /> </intent-filter> </receiver>
可以看到,这里让MyBroadcastReceive接收一条值为com.example.broadcastdemo.MY_BROADCAST的广播。为了发送广播,我添加了一个button来写发送广播。
button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent("com.example.broadcastdemo.MY_BROADCAST"); sendBroadcast(intent); } });
可以看到,在点击事件里加入了发送自定义广播的逻辑。首先构建出了一个Intent对象,并把要发送的广播的值传入,然后调用了Context的sendBroadcast()方法将广播发送出去,这样所有监听com.example.broadcastdemo.MY_BROADCAST这条广播的广播接收器都会收到消息,此时发出去的广播就是一条标准广播。
发送自定义广播的功能已经实现了,另外,由于广播使用的是Intent进行传递的因此你还可以在Intent中携带一些数据传递给广播接收器。
有序广播
为了能够更直观方便的研究有序广播,我又新建了一个项目。这个项目的内容和之前的一样,只是为了要发送有序广播,要在Button的点击上进行修改,写成这样:button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent("com.example.broadcastdemo.MY_BROADCAST"); sendOrderedBroadcast(intent, null); } });
发送有序广播只需要改动一行代码,即将sendBroadcast()方法改成sendOrderedBroadcast()方法。sendOrderedBroadcast()方法接收两个参数,第一个仍是Intent,第二个参数是与权限相关的字符串,这里传入null就行了。那么如何设定广播接收器的先后顺序呢?当然是在注册的时候进行设定了,修改AndroidManifest.xml中的代码:
<receiver android:name=".MainActivity$AnotherBroadcastReceiver"> <intent-filter android:priority="100"> <action android:name="com.example.broadcastdemo.MY_BROADCAST" /> </intent-filter> </receiver>
通过android:priority属性给广播接收器设置了优先级,优先级比较高的接收器就可以先收到广播。我这里设置了100,那MyBroadcastReceivr肯定是比另一个接收器优先收到广播,既然已经获得了优先权,那么我就可以让MyBroadcastReceive选择是否允许广播继续传递了,可以在onReceive()方法中添加abortBroadcast()方法,用来截断广播。
public static class MyBroadcastReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { Toast.makeText(context, "接收到了自定义广播", Toast.LENGTH_SHORT).show(); abortBroadcast(); } }
现在重新运行程序,再点击一下按钮会发现,只有MyBroadcastReceiver中的Toast信息能够弹出,另一个接收器却不能,这说明MyBroadcastReceiver确实将广播拦截了。
本地广播
之前所讲的发送和接收广播都是属于系统全局广播,也就是说发出的广播可以被其他任何应用程序接收到,这样大大降低了安全性。因此Android中引入了一套本地广播机制,使用这个机制发出的广播只能够在应用程序的内部进行传递,并且广播接收器也只接收来自本地应该程序发出的广播,大大的解决了广播的安全性问题。用法并不复杂,主要就是使用了一个LocalBroadcastManager来对广播进行管理,并提供了发送广播和注册广播接收器的方法。代码演示:public class LocalBroadcastMngActivity extends AppCompatActivity { private IntentFilter intentFilter; private LocalReceiver localReceiver; private LocalBroadcastManager localBroadcastManager; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_local_broadcast_mng); localBroadcastManager = localBroadcastManager.getInstance(this);//获取实例 Button button = (Button) findViewById(R.id.button); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent("com.example.broadcasttest.LOCAL_BROADCAST"); 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(LocalBroadcastMngActivity.this, "接收到本地广播", Toast.LENGTH_SHORT).show(); } } @Override protected void onDestroy() { super.onDestroy(); unregisterReceiver(localReceiver);//取消注册 } }
可以看到,本地广播的用法和之前动态注册广播的用法大致相同,只不过现在首先是通过LocalBroadcastManager的getInstance()方法得到了它的一个实例;然后再注册广播接收器的时候调用的是LocalBraodcastManager的sendBroadcast()方法,仅此而已。另外一点还需要说明,本地广播是无法通过静态注册的方式来接收的。
最后再来判断一下使用本地广播的几点优势吧:
1.可以明确的知道正在发送的广播不会离开我们的程序,因此不需要担心机密数据泄露问题。
2.其他的程序无法将广播发送到我们程序的内部,因此不需要担心会有安全漏洞的隐患。
3.发送本地广播比起发送系统全局广播将会更加高效。
总结
安卓的广播机制Broadcast已经详细介绍完了,希望给读者能有一个好的帮助,如果博客中有哪里写的不对的还恳请读者指出。相关文章推荐
- 使用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