android开发之 广播机制
广播接收器(BroadcastReceiver)
Android中的广播主要可以分为两种类型,标准广播和有序广播。
标准广播(Normal broadcasts):
是一种完全异步执行的广播,在广播发出之后,所有的 广播接收器几乎都会在同一时刻接收到这条广播消息,
因此它们之间没有任何先后顺序可 言。这种广播的效率会比较高,但同时也意味着它是无法被截断的。
有序广播(Orderedbroadcasts):
则是一种同步执行的广播,在广播发出之后,同一时刻 只会有一个广播接收器能够收到这条广播消息,当这个
广播接收器中的逻辑执行完毕后,广 播才会继续传递。所以此时的广播接收器是有先后顺序的,优先级高的广
播接收器就可以先 收到广播消息,并且前面的广播接收器还可以截断正在传递的广播,这样后面的广播接收器
就无法收到广播消息了。
想要接收到广播,就需要使用广播接收器了。
注册广播的方式一般有两种,在代码中注册和在 AndroidManifest.xml中注册,其中前者也被称为动态注册,
后者也被称为静态注册。
这是就收广播的方法:
下面是 动态注册监听网络变化
那么该如何创建一个广播接收器呢?其实只需要新建一个类,让它继承自BroadcastReceiver, 并重写父类的
onReceive()方法就行了。这样当有广播到来时,onReceive()方法就会得到执行, 具体的逻辑就可以在这个方
法中处理。 那我们就先通过动态注册的方式编写一个能够监听网络变化的程序,借此学习一下广播 接收器的基本
用法吧。新建一个 BroadcastTest项目,然后修改 MainActivity中的代码:
public class MainActivity extends Activity { private IntentFilter intentFilter; private NetworkChangeReceiver networkChangeReceiver; @Override protected 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); } @Override protected void onDestroy() { super.onDestroy(); unregisterReceiver(networkChangeReceiver); } class NetworkChangeReceiver extends BroadcastReceiver { @Override public 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键→Systemsettings→Datausage进入到数据使用详情
界面,然后尝试着 开关 MobileData来启动和禁用网络,你就会看到有 Toast提醒你网络发生了变化。 不过只
是提醒网络发生了变化还不够人性化,最好是能准确地告诉用户当前是有网络还 是没有网络,因此我们还需要
对上面的代码进行进一步的优化。修改 MainActivity中的代码:
public class MainActivity extends Activity { class NetworkChangeReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { ConnectivityManager connectionManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfonetworkInfo = 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()方法中,首先通过get 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-sdk android:minSdkVersion="14" android:targetSdkVersion="19" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> …… </manifest>
然后就可以再android的应用中查看这些已经声明的权限了。
现在再次运行就看里看到来自系统的提示了。
还有一个就是
静态注册实现开机启动 这个我还不是太明白所以没打算写 等等明白了就决定写下来。