Android之广播机制简介一

来源:互联网 发布:软件新品发布会 ppt 编辑:程序博客网 时间:2024/04/30 07:04

Android之广播机制简介一

一,广播分类

Android 中的广播主要可以分为两种类型,标准广播和有序广播。
标准广播(Normal broadcasts)是一种完全异步执行的广播,在广播发出之后,所有的
广播接收器几乎都会在同一时刻接收到这条广播消息,因此它们之间没有任何先后顺序可
言。这种广播的效率会比较高,但同时也意味着它是无法被截断的。标准广播的工作流程如
图所示。


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


二,接收系统广播

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

三,动态注册监听网络变化

广播接收器可以自由地对自己感兴趣的广播进行注册,这样当有相应的广播发出时,广
播接收器就能够收到该广播,并在内部处理相应的逻辑。注册广播的方式一般有两种,在代
码中注册和在 AndroidManifest.xml 中注册, 其中前者也被称为动态注册, 后者也被称为静态
注册。
那么该如何创建一个广播接收器呢?其实只需要新建一个类, 让它继承自BroadcastReceiver,
并重写父类的 onReceive()方法就行了。 这样当有广播到来时, onReceive()方法就会得到执行,
具体的逻辑就可以在这个方法中处理。
那我们就先通过动态注册的方式编写一个能够监听网络变化的程序, 借此学习一下广播
接收器的基本用法吧。新建一个 BroadcastTest项目,然后修改 MainActivity 中的代码,如下
所示:

public class MainActivity extends Activity {private IntentFilter intentFilter;private NetworkChangeReceiver networkChangeReceiver;@Overrideprotected 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);}@Overrideprotected void onDestroy() {super.onDestroy();unregisterReceiver(networkChangeReceiver);}class NetworkChangeReceiver extends BroadcastReceiver {@Overridepublic void onReceive(Context context, Intent intent) {Toast.makeText(context, "network changes",Toast.LENGTH_SHORT).show();}}}

可以看到,我们在 MainActivity 中定义了一个内部类 NetworkChangeReceiver,这个类
是继承自 BroadcastReceiver 的, 并重写了父类的 onReceive()方法。 这样每当网络状态发生变
化时,onReceive()方法就会得到执行,这里只是简单地使用 Toast 提示了一段文本信息。
然后观察 onCreate()方法,首先我们创建了一个 IntentFilter 的实例,并给它添加了一个
值为 android.net.conn.CONNECTIVITY_CHANGE 的 action,为什么要添加这个值呢?因为
当网络状态发生变化时,系统发出的正是一条值为 android.net.conn.CONNECTIVITY_
CHANGE 的广播,也就是说我们的广播接收器想要监听什么广播,就在这里添加相应的
action 就行了。 接下来创建了一个 NetworkChangeReceiver 的实例, 然后调用 registerReceiver()
方法进行注册,将 NetworkChangeReceiver 的实例和 IntentFilter 的实例都传了进去,这样
NetworkChangeReceiver就会收到所有值为 android.net.conn.CONNECTIVITY_CHANGE的广
播,也就实现了监听网络变化的功能。
最后要记得,动态注册的广播接收器一定都要取消注册才行,这里我们是在 onDestroy()
方法中通过调用 unregisterReceiver()方法来实现的。
整体来说,代码还是非常简单的,现在运行一下程序。首先你会在注册完成的时候收到
一条广播,然后按下 Home 键回到主界面(注意不能按 Back 键,否则 onDestroy()方法会执
行) ,接着按下 Menu 键→System settings→Datausage 进入到数据使用详情界面,然后尝试着
开关 Mobile Data 来启动和禁用网络,你就会看到有 Toast提醒你网络发生了变化。
不过只是提醒网络发生了变化还不够人性化, 最好是能准确地告诉用户当前是有网络还
是没有网络, 因此我们还需要对上面的代码进行进一步的优化。 修改 MainActivity 中的代码,
如下所示:

public class MainActivity extends Activity {……class NetworkChangeReceiver extends BroadcastReceiver {@Overridepublic void onReceive(Context context, Intent intent) {ConnectivityManager connectionManager = (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);NetworkInfo networkInfo = connectionManager.getActiveNetworkInfo();if (networkInfo != null && networkInfo.isAvailable()) {Toast.makeText(context, "network is available",Toast.LENGTH_SHORT).show();} else {Toast.makeText(context, "network is unavailable",Toast.LENGTH_SHORT).show();}}}}

在 onReceive()方法中,首先通过 getSystemService()方法得到了 ConnectivityManager 的
实例, 这是一个系统服务类, 专门用于管理网络连接的。 然后调用它的 getActiveNetworkInfo()
方法可以得到 NetworkInfo 的实例,接着调用 NetworkInfo 的 isAvailable()方法,就可以判断
出当前是否有网络了,最后我们还是通过 Toast 的方式对用户进行提示。
另外,这里有非常重要的一点需要说明,Android 系统为了保证应用程序的安全性做了
规定,如果程序需要访问一些系统的关键性信息,必须在配置文件中声明权限才可以,否则
程序将会直接崩溃,比如这里查询系统的网络状态就是需要声明权限的。打开
AndroidManifest.xml 文件,在里面加入如下权限就可以查询系统网络状态了:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"package="com.example.broadcasttest"android:versionCode="1"android:versionName="1.0" ><uses-sdkandroid:minSdkVersion="14"android:targetSdkVersion="19" /><uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>……</manifest>

访问 

http://developer.android.com/reference/android/Manifest.permission.html

可以查看 Android
系统所有可声明的权限。




1 0