5.1 广播机制简介
在一个IP网络范围中,最大的IP地址是被保留作为广播地址来使用的
Android中的广播类型:
标准广播:是一种完全异步执行的广播,在广播发出之后,所有的广播接收器几乎同时都会在同一时刻接收到这条广播消息,无先后顺序可言,同时也意味着无法被截断
有序广播:是一种同步执行的广播,在广播发出之后,同一时刻只会有一个广播接收器能够收到这条广播信息,在此接收器中的逻辑执行完毕后广播才会继续传递,因此是有先后顺序的,优先级高的广播接收器可以先收到广播消息并且可以截断广播。
5.2 (应用程序)接收系统广播
5.2.1 动态注册监听网络变化
广播接收器的注册方法分为两种:①动态注册——在代码中注册;②静态注册——在AndroidManifest.xml文件中注册
如何创建一个广播接收器?——新建一个内部类,继承BroadcastReceiver,并重写其中的onRceive()方法,这样当有广播时,该方法就会得到执行,具体的逻辑就可以在这地方中处理。
我们以监听网络变化为例:
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.com.CONNECTIVITY_CHANCE");//,获取实例,创建需要被监听的系统信息
networkChangeReceiver = new NetworkChangeReceiver();//实例化广播接收器
registerReceiver(networkChangeReceiver,intentFilter);//传入广播接收器和监听信息的实例,成功注册广播接收器
}
//取消注册广播接收器
@Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(networkChangeReceiver);//取消注册
}
//在MainActivity类中定义了一个内部类NetworkChangeReceiver,并且继承BroadcastReceiver类,并重写其中的onRceive()方法,每当网络发生变化时就会执行onReceive()中的语句
class NetworkChangeReceiver extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
//Toast.makeText(context,"network changes",Toast.LENGTH_SHORT).show();一个简单的提示
//系统服务类,专门用于管理网络连接的
ConnectivityManager connectivityManager = (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connectivityManager.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();
}
}
}
}
注意:由于访问系统的网络状态是要声明权限的,因此要在AndroidManifest.xml文件中声明:
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
5.2.2 静态注册实现开机功能
动态注册的广播接收器必须在程序启动之后才能接收到广播,而静态注册的广播接收器在程序未启动的情况下也可以接收到广播
在如上操作中弹出的界面下的Exported属性表示是否允许这个广播接收器接受本程序以外的广播,Enabled属性表示是否启用这个广播接收器。
首先我们创建一个广播接收器BootCompleteReceiver,并修改BootCompleteReceiver 里的代码:
public class BootCompleteReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context,"Boot Complete",Toast.LENGTH_LONG).show();
}
}
注意:静态注册的广播接收器要在AndroidManifest.xml文件中进行注册,如下代码就是注册好的代码:
(所有静态的广播接收器都是在receiver注册器里进行注册的)
<receiver
android:name=".BootCompleteReceiver"
android:enabled="true"
android:exported="true">
</receiver>
我们继续设置开机权限,并且修改代码写下要被接收的广播信息,使得BootCompleteReceiver能够接受到开机广播:
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
........
<receiver
android:name=".BootCompleteReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>//添加对应的广播信息,使得可以实现开机广播
</intent-filter>
</receiver>
注意:onReceive()方法不宜添加过多的逻辑或者进行任何耗时的操作,因为在广播接收器中是不允许开线程的
5.3 发送自定义广播
5.3.1 发送标准广播
1、定义一个广播接收器来准备接受此广播,这里新建一个MyBroadcastReceiver类
public class MyBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context,"received in MyBroadcastReceiver",Toast.LENGTH_LONG).show();
}
}
2、在AndroidManifest.xml文件中修改,进行注册并且写下要接受的广播信息
<receiver
android:name=".MyBroadcastReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="com.example.broadcasttest.MY_BROADCAST"/>
</intent-filter>
</receiver>
3、activity_main中定义一个按钮,作为发送广播的触发点
<Button
android:id="@+id/button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Send Broadcast"
/>
4、修改MainActivity中的代码
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button button = (Button)findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent("com.example.broadcasttest.MY_BROADCAST");
sendBroadcast(intent);//将广播发送出去
}
});
}
5.3.2 发送有序广播
广播是一种可以跨进程的通信方式,当我们应用程序内发出的广播,其他的应用程序也是可以收到的
我们以上面的例子为例:
1、新建一个BroadcastTest2项目,并且新建一个AnotherBroadcastReceiver类
public class AnotherBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context,"received in AnotherBroadcastReceiver",Toast.LENGTH_LONG).show();
}
}
2、同样地,在AndroidManifest.xml文件中修改,进行注册并且写下要接受的广播信息
<receiver
android:name=".AnotherBroadcastReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="com.example.broadcasttest.MY_BROADCAST"/>
</intent-filter>
</receiver>
3、现在我们回到BroadcastTest项目,修改MainActivity中的代码:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button button = (Button)findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent("com.example.broadcasttest.MY_BROADCAST");
sendOrderedBroadcast(intent,null);//将广播发送出去
}
});
}
此时我们的有序广播已经创建好了,但是如何设定广播接收器的先后顺序呢?
我们只需在注册的时候设置一下优先级就可以了,现在我们要设置MyBroadcastReceiver优先,则:
<receiver
android:name=".MyBroadcastReceiver"
android:enabled="true"
android:exported="true">
<intent-filter android:priority = "100">//将该广播接收器的优先级设置为100,使得它能够优先实现
<action android:name="com.example.broadcasttest.MY_BROADCAST"/>
</intent-filter>
</receiver>
那么如何截断广播呢?
只要在优先级高的的广播接收器的**onReceive()**方法中调用abortBroadcast()方法即可截断广播
public class MyBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context,"received in MyBroadcastReceiver",Toast.LENGTH_LONG).show();
abortBroadcast();
}
}
5.4 使用本地广播
用途:用于解决广播的安全性问题,本地广播机制使得使用这个机制发出的广播只能够在应用程序的内部进行传递,并且广播接收器也只能接收来自本应用程序发出的广播
注:本地广播是无法通过静态注册的方式来接收的。
本地广播的优势:
1、可以明确地知道正在发送的广播不会离开我们的程序,因此不必担心机密数据泄露
2、其他的应用程序无法将广播发送到我们程序的内部,因此不需要担心会有安全漏洞的隐患
3、发送本地广播比发送系统全局广播将会更高效
本地广播机制用法:
public class MainActivity extends AppCompatActivity {
private IntentFilter intentFilter;
private LocalReceiver localReceiver;//创建一个本地广播接收器
private LocalBroadcastManager localBroadcastManager;//创建一个本地广播管理类对本地广播进行管理
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
localBroadcastManager = LocalBroadcastManager.getInstance(this);//实例化管理类
Button button = (Button)findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent("com.example.broadcasttest.LOCAL_BROADCAST");
localBroadcastManager.sendBroadcast(intent);//发送广播信息
}
});
intentFilter = new IntentFilter();
intentFilter.addAction("com.example.broadcasttest.LOCAL_BROADCAST");//获取实例,创建学要被监听的信息
localReceiver = new LocalReceiver();//实例化广播接收器
localBroadcastManager.registerReceiver(localReceiver,intentFilter);//传入广播接收器和监听信息的实例,成功注册广播接收器
}
//取消注册
@Override
protected void onDestroy() {
super.onDestroy();
localBroadcastManager.unregisterReceiver(localReceiver);
}
//创建本地广播接受器类
class LocalReceiver extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context,"received local broadcast",Toast.LENGTH_SHORT).show();
}
}
}
这样,一个本地广播机制就创建完成了
5.5 小结
1、广播地址简介——在一个IP网络范围中,最大的IP地址是被保留作为广播地址来使用的
2、Android中的广播类型——标准广播;有序广播
3、广播接收器的注册方法:①动态注册——在代码中注册;②静态注册——在AndroidManifest.xml文件中注册
4、(应用程序)接收系统广播举例:①接收网络变化广播;②接收开机广播
5、发送自定义广播举例:①发送自定义广播;②发送标准广播
6、设定广播接收器的先后顺序
7、截断广播
8、本地广播机制——本地广播机制使得使用这个机制发出的广播只能够在应用程序的内部进行传递,并且广播接收器也只能接收来自本应用程序发出的广播