您的位置:首页 > 移动开发 > Android开发

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方法中写了一个Toast

public 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已经详细介绍完了,希望给读者能有一个好的帮助,如果博客中有哪里写的不对的还恳请读者指出。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息