广播机制

      在计算机网络里,假如某个网络的IP地址是192.168.0.XXX,子网掩码是255.255.255.0,那么这个网络的广播地址就是192.168.0.255,广播数据包会被发送到同意网络上的所有端口,这样在该网络中的每台主机都会收到这条广播。Android也引入了一套类似的广播消息体制。

      Android中的每个应用程序都可以对自己感兴趣的广播进行注册,这样程序只会接收到自己关心的广播内容,这些广播可能来自于系统,也可能来自于其它应用程序。Android提供了一套完整的API,允许程序自由地发送和接收广播。Android中的广播可以分为两类,标准广播和有序广播。

标准广播

     标准广播是一种完全异步执行的广播,在广播发出之后,所有的广播接收器几乎都会在同一时刻接收到这条广播消息,因此它们之间没有先后顺序可言。这种广播的效率比较高,但同时也意味着它是无法被截断的。其工作流程如下:

    

有序广播

     有序广播则是一种同步执行的广播,在广播发出之后,同一时刻只会有一个广播接收器能够接收到这条广播消息,当这个广播接收器中的逻辑执行完毕之后,广播才会继续传递。所以此时的广播接收器是有先后顺序的,优先级高的接收器可以先收到广播消息,并且前面的广播接收器还可以截断正在传递的广播,这样后面的接收器就无法接收到广播消息了。其工作流程如下:

   

接收系统的广播

      Android内置了很多系统级别的广播,可以在应用程序中通过监听这些广播来得到各种系统的状态信息。比如手机开机完成之后会发出一条广播,电池的电量发生变化会发生一条广播,时间或时区发生改变也会发出一条广播。如果想要接收到这些广播,就需要使用广播接收器。

    广播接收器可以自由地对自己感兴趣的广播进行注册,这样当有相应的广播发出时,广播接收器就能够收到该广播,并在内部处理相应的逻辑。注册广播的方式一般有两种,在代码中注册和在AndroidMainfest.xml中注册,前者称为动态注册,后者称为静态注册。建立广播接收器只需要新建一个继承自BroadcastReceiver的类,并重写onReceive()方法就行了。这样当广播到达时,onReceive()方法就会得到执行,具体的逻辑就可以在这个方法中处理。

    下面就是一个监听网络变化的程序,借此学习一下广播接收器的基本用法。

    

         每当网络发生变化,上面的程序就会显示一条信息。为IntentFilter添加一个android.net.com.CONNECTIVITY_CHANGE的广播,因为当网络发生变化时,系统就会发出一个值为android.net.com.CONNECTIVITY_CHANGE的广播,也就是广播接收器想要监听什么广播,就在里面添加相应的action就行了。最后一定要记得,动态注册的广播接收器一定要取消注册才行。

       不过只是提醒网络发生了变化还是不够人性化,最好是能告诉用户当前有网络还是没有网络,因此还需要对代码进行优化,修改NetworkChangeReceiver中的代码如下:

    

             在onReceive()方法中,首先通过getSystemService()方法得到了ConnectivityManager的实例,这是一个系统的服务类,专门用于管理网络连接的,然后调用它的getActiveNetworkInfo()方法可以得到NetworkInfo的实例,接着调用NetworkInfo的isAvailable()方法就可以判断出是否有网络了。

     另外,Android系统为了保证应用程序的安全性做了规定,如果程序需要访问一些系统的关键性信息,必须在配置文件中声明权限才可以,否则程序会直接崩溃,比如上面的程序,在AndroidMainfest.xml文件里加入权限,如下:

访问http://developer.android.com/reference/android/Mainfest.permission.html可以查看Android系统所有可声明的权限。

静态注册实现开机启动

       动态注册的广播接收器可以自由地控制注册和注销,在灵活性上有很大的优势,但是存在一个缺点,即必须要在程序启动之后才能接收到广播,因为注册的逻辑是写在onCreate()方法中的。这里准备让程序接收一条开机广播,当收到这条广播时就可以在onReceive()方法里执行相应的逻辑,从而实现开机启动的功能,新建一个BootCompleteReceiver类,继承自BroadcastReceiver,代码如下:

      

然后修改AndroidMainfest.xml文件,如下:

      到目前为止,在广播接收器的onReceive()方法中都只是简单地使用Toast提示了一段文本内容,当真正使用的时候可以在里面写上合适的逻辑,但是不要在onReceive()方法中添加过多的逻辑或者进行耗时的操作,因为在广播接收器中是不允许开启线程的,当onReceive()方法运行了较长的时间而没有结束时,程序会报错。因此,广播接收器更多的是扮演一种打开程序其它组件的角色,比如,创建一条状态栏通知,或者是启动一个服务等。

原文地址:https://www.cnblogs.com/hujingwei/p/5111130.html