————————————广播机制简介————————————
我们先看一下什么是广播机制:
Android中的广播机制非常灵活,Android中的每个应用程序都可以对自己感兴趣的广播进行注册,这个程序也只会收到自己所关心的广播内容,这些广播可能是来自于系统的,也可能是来自于其他应用程序的。
Android提供了一套完整的API,允许应用程序自由地发送和接受广播。
Android中的广播主要可以分为两种类型,标准广播 和有序广播。
标准广播(Normal broadcasts):标准广播是一种 完全异步 执行的广播,在广播发出之后,所有的广播接收器几乎会在同一时刻接收到这条广播消息。这种广播效率比较高,但同时也意味着它是无法被截断的。
有序广播(Ordered broadcasts):有序广播则是一种 同步 执行的广播,在广播发出之后,同一时刻只会有一个广播接收器能够收到这条广播消息,当这个广播接收器中的逻辑执行完毕之后,广播才会继续传递。
————————————接受系统广播————————————
Android内置了很多系统级别的广播,可以在应用程序中通过监听这些广播来得到各种系统的状态信息。
手机开机完成后会发出一条广播,电池的电量发生变化会发出一条广播,时间改变也会发出一条广播……如果想要接受到这些广播,就需要使用广播接收器。
广播接收器可以自由地对自己感兴趣的广播进行注册,当有相应的广播发出时,广播接收器就能够收到该广播,并在内部处理相对应的逻辑。
我们来看一下两种注册方式:
- 在代码中注册(动态注册)
- 在 AndroidManifest.xml 中注册(静态注册)
创建广播接收器只需要新建一个类,让它继承自BroadcastReceiver,并重写父类的onReceiver()方法。当有消息通过广播传递过来时,onReceive()方法就会得到执行。
让我们先看第一种注册,动态注册监听网络变化:
看代码:
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);
intentFilter = new IntentFilter();
//为过滤器添加处理规则
intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
networkChangeReceiver = new NetworkChangeReceiver();
//注册广播接收器
registerReceiver(networkChangeReceiver, intentFilter);
}
@Override
protected void onDestroy() {
super.onDestroy();
//动态的广播接收器最后一定要取消注册
unregisterReceiver(networkChangeReceiver);
}
//自定义内部类,继承自BroadcastReceiver
public class NetworkChangeReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
//实现onReceive()方法的逻辑
Toast.makeText(context, "网络状态改变", Toast.LENGTH_SHORT).show();
}
}
}
接下来让我们分析一下这段代码:
NetworkChangeReceiver extends BroadcastReceiver 这段代码就是在MainActivity中定义了一个内部类,并且继承了BroadcastReceiver,然后重写了父类的onReceive
IntentFilter 的 addAction() 方法中添加了一个值为 android.net.conn.CONNECTIVITY_CHANGE 的 action,用于接收系统对网络状态改变而发出的一条广播。(广播接收器想要监听什么广播,就在这里添加相应的action)
调用 registerReceiver() 方法对广播接收器进行注册,将 networkChangeReceiver(继承了BroadcastReceiver) 和 IntentFilter 的实例传递进去即可。
最后要记得,动态注册的广播接收器一定都要取消注册才行。通过调用 unregisterReceiver() 方法取消注册。
这样我们看起来这一段代码还是十分简单的。
我们现在只是提醒网络发生变换,但是这是不够人性化的,我们应该能直接准确的告诉用户有网络还是没有网络,这样我们对上面的代码进行优化:
修改 NetworkChangeReceiver 的 onReceiver() 方法,使之能够准确告诉用户当前网络状态:
Android系统规定,如果程序需要访问系统关键信息,必须在配置文件中声明权限才可以,否则程序直接崩溃。
这里查询网络状态需要声明权限,打开AndroidManifest.xml文件,为添加权限(之前),代码如下:
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
修改 NetworkChangeReceiver 中的代码:
public class NetworkChangeReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
//connectivityManger是一个系统服务类,专门用于管理网络连接
ConnectivityManager connectivityManager = (ConnectivityManager)
getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();
//调用NetworkInfo的isAvailable()方法判断是否联网
if(networkInfo != null && networkInfo.isAvailable()){
Toast.makeText(context,"网络已连接",Toast.LENGTH_SHORT).show();
}else{
Toast.makeText(context,"网络不可用",Toast.LENGTH_SHORT).show();
}
}
}