Android中每个应用进程都可以对自己感兴趣的广播进行注册,这些广播可以来自系统,也可以来自其他应用程序。接受广播可以轻松实现跨进程或应用内异步交流,比如App开机自启、App内强制下线。
- 广播的种类
- 接收广播
- 发送自定义广播
- 使用本地广播
广播的种类
-
标准广播:
是一种完全异步执行的广播,广播发出后,所有注册该广播的接收器几乎在同一时刻接收到该广播,没有先后顺序。因为这种广播没有先后顺序,所以它的效率比较高,但也意味着它不能被截断。
-
有序广播:
与标准广播相反,有序广播是一种同步的广播,广播发出后,同一时刻只有一个接收器接收到广播,且该接收器可以截断广播。此时广播是有先后顺序的。
接收广播
Android中有很多系统广播,我们可以在应用中监听这些广播获得系统的状态信息。如开机后发送一条信息,网络状态更改时发送一条信息等。
-
动态注册:
在代码中注册,也就是需要打开应用程序才能注册接受器,可用于监听网络状态的变化等。
- 新建一个类继承BroadcastReceiver。
- 重写onReceive(),在方法中实现业务逻辑。
- 新建一个IntentFilter并添加action,action表示监听什么广播。
- 新建广播类实例。
- onCreate()注册,onDestroy()中注销。
以下为监听网络状态实例:
public class BroadcastActivity extends AppCompatActivity {
private NetworkReceive receive;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_broadcast);
//第三至第五步
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
receive = new NetworkReceive();
registerReceiver(receive, intentFilter);
}
@Override
protected void onDestroy() {
super.onDestroy();
//第五步
unregisterReceiver(receive);
}
//第一步
class NetworkReceive extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
//第二步,由于该广播为监听网络状态,我们还要具体判断网络是否有连接
ConnectivityManager manager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = manager.getActiveNetworkInfo();
if (networkInfo != null && networkInfo.isConnected()){
Toast.makeText(context, "network is available", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(context, "network is unavailable", Toast.LENGTH_SHORT).show();
}
}
}
}
//AndroidManifest.xml中申请网络权限
-
静态注册
虽然动态注册可以自由控制广播的注册与注销,但它一个缺点就是需要应用启动时才能接受广播。而静态注册可以在应用未启动时接收广播,可实现开机自启这一类的需求。
- 使用Android Studio提供的快捷方式新建Broadcast Receiver
- 在AndroidManifest.xml中注册广播
- 重写onReceive实现业务逻辑
- 声明需要的权限
以下实现开机自启:
//第一步,新建Receiver...
//第二、四步,AndroidManiefest中
//声明权限
//静态注册
//第三步
public class BootCompleteReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
// TODO: This method is called when the BroadcastReceiver is receiving
// an Intent broadcast.
//实现业务逻辑
Toast.makeText(context, "Boot Complete", Toast.LENGTH_SHORT).show();
}
}
两种注册均有优缺点,应结合使用。需要注册的是,不可在onRecevie()中添加过多的逻辑或者进行任何耗时操作。
因为广播接收器是不允许开启线程的。如果onReceive()执行了较长时间而没有结束,程序就会报错。因此,广播一般是一种打开程序其他组件的角色,如创建一条通知,启动一个服务等。
发送自定义广播
-
发送标准广播:
//activity中
//构造函数传入action,接受广播需要这个action
Intent intent = new Intent("com.example.broadcasttest.MY_BROADCAST");
sendBroadcast(intent);
除此之外,还可以在Intent中携带一些数据传递到广播接收器中。
-
发送有序广播
//与标准广播类似
Intent intent = new Intent("com.example.broadcasttest.MY_BROADCAST");
sendOrderedBroadcast(intent, null);
第二个参数null表示与权限相关的字符串,这里传null就行。
有序广播的优先顺序,在AndroidManifest.xml中对应的receiver声明 android:priority
即可,数值越大,优先级越高。
有序广播还可以截断广播,在接收器onReceive()中调用abortBroadcast()即可。
public class BootCompleteReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
// TODO: This method is called when the BroadcastReceiver is receiving
// an Intent broadcast.
//实现业务逻辑
Toast.makeText(context, "Boot Complete", Toast.LENGTH_SHORT).show();
abortBroadcast();
}
}
使用本地广播
以上提到的都是属于系统全局广播,发出的广播可被系统任何一个应用接收到,这就容易引起安全性问题。因此,在本应用内传递数据,我们可以使用本地广播,本地广播其他应用无法接收,只允许本应用接收。
发送本地广播:
- 新建LocalBroadcastManager实例
- 新建Intent,与全局广播类似
- 通过LocalBroadcastManager发送Intent
接受本地广播: - 与全局广播类似,新建一个类继承BroadcastReceiver
- 添加IntentFilter
- 通过LocalBroadcastManager动态注册与注销
public class BroadcastActivity extends AppCompatActivity {
private LocalReceive receive;
private LocalBroadcastManager localBroadcastManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_broadcast);
//第一步
localBroadcastManager = LocalBroadcastManager.getInstance(this);
//第二、三步
Intent intent = new Intent("com.example.learnapplication.LOCAL_BROADCAST");
localBroadcastManager.sendBroadcast(intent);
//第五、六步
receive = new LocalReceive();
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("com.example.learnapplication.LOCAL_BROADCAST");
localBroadcastManager.registerReceiver(receive, intentFilter);
}
@Override
protected void onDestroy() {
super.onDestroy();
localBroadcastManager.unregisterReceiver(receive);
}
//第四步
class LocalReceive extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
//处理具体逻辑
Toast.makeText(context, "receive local broadcast", Toast.LENGTH_SHORT).show();
}
}
}
需要强调的是,本地广播接收器不能静态注册,且发送本地广播比发送全局广播更加高效。本地广播通常用于实现本应用全局通知,如强制下线、推送等。
结合之前Activity的BaseActivity用法,可实现应用内全局接收广播并做出响应。
参考:
《第一行代码》