四大组件之广播(Broadcast)
最近学习了安卓四大组件之广播的用法。下面简单的总结下:
广播其实是一种信息的传递,主要分为标准广播和有序广播。下面举例描述下,
广播分类
标准广播
在我们的日常工作中,如果单位要告诉全体员工周末全体加班,只需要给全体员工发一个邮件出去,这样员工就能收到周末加班的邮件,就可以在周末来加班了,这种方式是全体员工都能收到,不能被截断,这就是标准广播;
特点:
1. 同级别接收先后是随机的(无序的)
2. 级别低的后接收到广播
3. 接收器不能截断广播的继续传播,也不能处理广播
4. 同级别动态注册(代码中注册)高于静态注册(AndroidManifest中注册)
有序广播
有些时候,单位的老大并不想直接给全体员工都发邮件,那么邮件走向可能就是这样的情况,老大---总经理---副总经理---项目经理等等,这样加班的信息是根据职位的高低(广播的优先级)一级一级的传递的,到每一级都可以被继续传递或者停止传递,所以这种信息是有可能被截断的这就是有序广播。
特点:
- 同级别接收是随机的
- 能截断广播的继续传播,高级别的接收到广播之后,可以截断传播,是通过intent-filter中的priority声明的,范围是-1000到1000
- 能接收广播。也可以处理广播
- 同级别动态注册(代码中注册)高于静态注册(AndroidManifest中注册)
广播接收器的注册
注册广播一般有两种方式
1. 在代码中注册(动态注册)
顾名思义,就是在代码中注册的,比如在一个button的点击事件中点击时:
package com.css.sean.broadcasttest;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
private IntentFilter intentFilter;//用于处理过滤特定的intent
private NetworkChangeReceiver networkChangeReceiver;//广播接收器
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
intentFilter = new IntentFilter();
//指定过滤器的action,这里传入的是网络状态发生改变时发出的广播
intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
networkChangeReceiver = new NetworkChangeReceiver();
registerReceiver(networkChangeReceiver, intentFilter);//注册广播
}
@Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(networkChangeReceiver);//用完之后取消注册
}
//用于监听网络状态的广播接收器
private class NetworkChangeReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
//ConnectivityManager是系统服务类,专门用来管理网络连接的
ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();
if (networkInfo != null && networkInfo.isAvailable()) {
Toast.makeText(MainActivity.this, "网络状态可用!", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(MainActivity.this, "网络状态不可用!", Toast.LENGTH_SHORT).show();
}
}
}
}
2. 在配置文件AndroidManifest中注册(静态注册)
动态注册时必须程序在运行时才能注册的,有一定的局限性,如果我们需要在程序还没启动的时候就可以接收到注册的广播,就需要静态注册了,下面用接收开机启动开举例:
首先创建一个广播类:
public class BootCompleteReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context,"开机启动广播",Toast.LENGTH_SHORT).show();
}
}
然后再配置文件中注册:
<receiver android:name=".BootCompleteReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"></action>
</intent-filter>
</receiver>
发送广播
广播接收器不仅可以接收系统发出的广播,也可以接收自定义的广播。
发送标准广播
//创建一个intent,带有参数就是Filter的action
Intent intent = new Intent("com.sean.css.MY_BROADCAST");
//发送广播
sendBroadcast(intent);
是不是很简单,只需要两行代码,但是别忘了,这只是发出的广播,还要去写一个广播接收器去接受这个广播,然后去执行的操作,并且大家intent是可以传递数据的,当然也可以在intent中加入参数进行传递,这样就可以在广播接收器中拿到这个参数了
发送有序广播
//创建一个intent,带有参数就是Filter的action
Intent intent = new Intent("com.sean.css.MY_BROADCAST");
//发送广播
sendOrderBroadcast(intent,null);
看起来和发送普通广播也差不多,主要就是在发送的时候方法变了,并且参数也变成了两个,第二个参数是与权限有关的字符串,前面说过,有序广播是有顺序的,所以是涉及到多个广播接收器的,只需要在我们注册广播接收器的时候加入以下代码:
//动态注册
intentFilter.setPriority(100);
//静态注册
<intent-filter android:priority="200">
<action android:name="android.intent.action.BOOT_COMPLETED"></action>
</intent-filter>
这样priority为200的会先收到广播,然后priority为100的后收到广播,如果先收到的广播在执行完自己操作后执行abortBroadcast();那么优先级为100的就收不到该广播了。
本地广播
前面我们发出的广播,不仅仅是我们自己的程序可以收到,其他的应用程序也可以收到,这样的话有可能会引起一定的安全问题,比如其他的应用程序可以一直向我们的程序发送垃圾广播,干扰我们程序的正常运行。幸好Android中有一个本地广播的机制,如果使用本地广播管理,那么只能在本地接收、发送广播。使用起来非常方便,只需要在发送或者接收的时候调用LocalBroadcastManager就行了,比如:
//发送
localBroadcastManager.sendBroadcast(inetnt);
//接收
localBroadcastManager.registerReceiver(localReceiver,intentFilter);
注意事项
BroadcastReceiver的生命周期只有10秒左右,不能再里面做一些耗时的操作,如果要做耗时的操作,应该通过发送Intent给Service,由Service来完成耗时操作,并且不能在BroadcastReceiver中使用子线程
我在博客园的小例子:广播实现强制下线