Android开发随笔

玩转Android广播机制

2017-05-17  本文已影响125人  loser先生

作为Android的四大组件之一,广播机制一直萦绕在我们生活中,比如手机开机完成后会发出一条广播,手机电量不足时也会发出一条广播等等,这些广播和我们传统意义上的广播有相似之处,即它只负责“说”而不管你“听不听”,更不会管你如何处理。如同电台广播的听众可能不止一个,Android中的广播也可以被多个应用程序所接收,当然,也可能不被任何应用程序所接收。

什么是广播

作为Android系统中一种组件间的通信方式,广播(Broadcast),相比于传统的广播会更加灵活,因为Android中的每个应用程序都可以对自己感兴趣的广播进行注册,这​样该程序就只会接收到自己所关心的广播内容,这些广播可能是来自于系统的,也可能是来自于其他的应用程序,Android提供了一套完整的API,允许应用程序自由地发送和接收广播。其中,发送广播借助于Intent,而接收广播则需要广播接收器(Broadcast Receiver)。

广播的类型

根据广播接收时能否被截断,可以分为标准广播和有序广播;根据广播的来源可以分为系统广播和非系统广播;根据广播的有效范围可以分为系统全局广播和本地广播。

Normal broadcasts.png Ordered broadcasts.png

1.其他应用程序可能会针对性的发出与当前应用程序intent-filter相匹配的广播,由此导致当前应用程序不断接收到广播并处理;
2.其他应用程序可以注册与当前应用程序一致的intent-filter用于接收广播,获取广播具体信息。

为此,Android引入了一套本地广播机制,使用这个机制发出的广播只能在应用程序的内部进行传递,并且广播接收器也只能接收来自于本应用程序发出的广播。相比于系统全局广播,本地广播安全性更高更加高效
本地广播的用法和系统全局广播几乎相同,Android v4兼容包中给出了封装好的LocalBroadcastManager类,我们主要使用该类来对广播进行管理,并提供了发送广播和注册广播接收器的方法。

解决广播安全性的方法:
1.发送广播时,可以设置广播的权限:sendBroadcast(Intent,String) 第二个参数为权限,为一个字符串,可以设置指定接收广播的应用程序的包:Intent.setPackage("com.xqx.app")
2.接收广播时 ,设置可以接收广播的权限Context.registBroadcast(Intent,String),
第二个参数String为接收广播的权限,
可设置不接受外部应用程序的广播<receiver androd:exported="false">
3.使用本地广播

注册广播接收器(BroadcastReceiver)

在注册广播接收器之前首先要先生成一个广播接收器,即新建一个类继承自BroadcastReceiver,然后重写其中的onReceive()方法,在该方法中写处理接收到的广播的具体逻辑。
- 不要在onReceive()方法中添加过多的逻辑或者进行任何的耗时操作,因为在广播接收器中是不允许开线程的,当onReceive()方法运行了较长时间而没有结束时,程序就会报错。因此广播接收器更多的是扮演一种打开程序其他组件的角色。
有了广播接收器之后,就需要对其进行注册了,总体上可以分为两种注册类型:静态注册和动态注册。

其中,以上属性说明如下:

1.android:enabled:是否启用这个广播接收器,true则启用;
2.android:exported:此BroadcastReceiver能否接收其他应用程序发出的广播,其默认值是由receiver中有无intent-filter决定的,如果有intent-filter,则默认值为true(可以接收其他应用发出的广播),否则为false。同时,这个值的设定是以application为界的,而非进程为界;
3.android:name:此BroadcastReceiver的类名;
4.android:permission:如果设置的话,则具有相应权限的广播发送方发送的广播才能被此BroadcastReceiver所接收;
5.android:process:BroadcastReceiver运行所处的进程,默认为该应用程序的进程,当然,也可以指定独立的进程(Android四大基本组件都可以通过此属性指定自己的独立进程)。

示例如下,intent-filter用于指定广播接收器接收的广播类型,因此MyBroadcastReceiver这个广播接收器将用于接收网络状态改变所发出的广播或开机启动时系统自身所发出的广播,同时记得访问手机的网络状态和监听系统开机广播都是需要声明相对应的权限的。

<receiver android:name=".MyBroadcastReceiver" >
<intent-filter>
    <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
</intent-filter>
<intent-filter>
    <action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>

1.创建该自定义广播接收器的实例。
2.创建一个intentFilter实例,调用addAction()方法配置具体要接收什么广播消息。
3.调用registerReceiver()方法关联intentFilter和自定义广播接收器,完成注册。
4.在onDestroy()方法调用unRegisterReceiver()解除注册。

经典实例代码如下:

public class MainActivity extends AppCompatActivity {

private IntentFilter intentFilter;
private NetworkChangeReceiver networkChangeReceiver;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

networkChangeReceiver = new NetworkChangeReceiver();
intentFilter = new IntentFilter();
intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
registerReceiver(networkChangeReceiver, intentFilter);
}    
@Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver( networkChangeReceiver );
  }

class NetworkChangeReceiver extends BroadcastReceiver{
   @Override
public void onReceive(Context context,Intent intent){
  //这里写接收到广播后执行的操作  
  }
 }
}

发送自定义广播

发送本地广播

本地广播相当于一个局部广播,发送广播的和接收广播的都属于同一个应用程序,对于LocalBroadcastManager方式发送的本地广播,只能通过LocalBroadcastManager动态注册的ContextReceiver才有可能接收到(还需要action匹配),静态注册或其他方式动态注册的ContextReceiver接收不到。
具体用法如下:

    private LocalReceiver localReceiver;
    private IntentFiter intentFilter;
    //动态注册本地广播接收器
    LocalBroadcastManager  localBroadcastManager=   
    LocalBroadcastManager.getInstance(this);
    localBroadcastManager.registerReceiver(localReceiver, intentFilter);

    //取消注册本地广播接收器
    //localBroadcastManager.unregisterReceiver(receiver);

    Intent intent = new Intent();
    intent.setAction("com.xqx.broadcast.xxx");
    intent.putExtra("key", "hello world!");
    //发送本地广播
    localBroadcastManager.sendBroadcast(intent);

   class LocalReceiver extends BroadcastReceiver{
     @Override
   public void onReceive(Context context,Intent intent){
   //这里写接收到本地广播后执行的操作  
     }
   }
上一篇 下一篇

猜你喜欢

热点阅读