Android-广播机制
1.技术概述
- 我们都知道网络通信原理中,一个Ip网络范围中,最大的IP地址是被保留作为广播地址使用的,那么其实Android也引入了类似一套广播消息机制,而且对比来看显得更加灵活。因为Android中每个应用程序都可以对自己感兴趣的广播进行注册(可以来自系统也可以来自其他应用程序),自由地发送和接收广播。
2.技术详述
2.1 动态注册-监听网络变化
- 注册广播的方式一般有两种,在代码中注册和在AndroidMainfest.xml中注册,前者即是动态注册,后者为静态注册。我们新建一个类,让它继承自Broadcast-Receiver,再重写父类的onReceive()方法即可。我们先修改项目中MainActivity中的代码:
'''
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);
//localBroadcastManager.unregisterReceiver(localReceiver);
}
class NetworkChangeReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "network is unavailable",
Toast.LENGTH_SHORT).show();
}
}
}
'''
- 内部类NetworkChangeReceiver是继承自BroadcastReceiver的,onReceive()方法也得到了重写,它是在网络状态发生变化的时候就会执行的。在onCreate()方法中,创建了IntentFilter的实例,并添加了一个值为android.net.conn.CONNECTIVITY_CHANGE的action,这是因为系统在网络状态发出变化时发出的广播就是这个值,也就是这个就是我们想要监听的广播,所以我们添加了相应的action。接下来创建NetworkChangeRecevier的实例,然后调用registerReceiver()方法进行注册,将NetworkChangeReceiver的实例和IntentFilter的实例都传了进去,这样NetworkChangeReceived就会收到所有值为android.net.conn.CONNECTIVITY_CHANGE的广播,从而实现了网络监听的功能;最后我们要取消注册,在onDestroy()方法中通过调用unregisterReceiver()方法实现。
2.2 静态注册-开机启动
- 动态注册很灵活没错,但是有一个缺点,就是要在程序启动之后才能接收到广播,因为注册的操作是在onCreat()方法中进行的,所以我们还需要掌握静态注册的方式。
- 静态的广播接收器一定要在AndroidManifest.xml文件中注册才能使用,我们再AndroidStudio中直接找到这个进行修改,因为系统启动后发出一条值为android.intent.action.BOOT_COMPLETED的广播,所以在
标签中需要添加这个相应action。
'''
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver
android:name=".BootCompleteReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
<receiver
android:name=".MyBroadcastReceiver"
android:enabled="true"
android:exported="true">
<intent-filter android:priority="100">
<action android:name="com.example.broadcasttest.MY_BROADCAST"/>
</intent-filter>
</receiver>
</application>
'''
-
标签内出现了一个新的标签 ,所有的静态的广播接收器都是在这里进行注册的,它也是通过android:name来指定具体注册哪一个广播接收器,接下来我们还需要对AndroidManifest.xml进行一些小修改才行: -
'<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /'>,这句话就是声明权限的作用,这样就完成了。
3.技术问题以及相应的解决过程
权限问题
- 一开始不知道Android系统对于用户设备的安全隐私有严格规定,所以我直接进行了一些比较敏感的操作,导致程序直接崩溃了,后面查阅资料才知道我们必须在配置文件中声明权限,最简单来说,访问系统的网络状态需要声明权限
'''
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.broadcasttest">
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
'''
- 同样的,后面的许多操作都是需要申明权限才能进行的;还有一个容易忘记的问题就是动态注册的广播接收器一定都要取消注册,onDestroy()方法需要多多注意。
4.总结
- 广播技术的话,总体来讲代码是比较简单的,但是要多多联系和网络IP那边的相关类型知识,比如Android的广播有两种类型:标准广播和有序广播,我们在使用的时候具体需要哪种,标准的完全异步执行,效率高但是也意味着它无法被截断,有序广播是同步执行的,但是同一时刻只会有一个接收器能收到信息,待执行完毕后才能往下接着传递,深层次需要的也得拥戴发送自定义广播的方法,总之广播属于Android四大组件之一,对于它的学习是需要多加练习和牢固的。
5.参考文献
- 《第一行代码》,csdn平台。