Android 四大组件之Broadcast(广播)总结
在上篇文章中对四大组件之Activity进行进行总结,这篇文章是对另一个四大组件Broadcast
广播进行总结。
广播类型
广播可以分为两种类型:
- Normal broadcasts 标准广播:完全异步的,广播发出后,所有的广播接收器几乎都会在同一时刻收到这条广播消息。它的特点是,广播效率高,但是无法被截断。
- Ordered broadcasts 有序广播:同步执行的,广播发出后,同一时刻只能有一个广播接收器能够收到这条广播消息,只有当该广播接收器的逻辑处理完成后,广播才会继续传递给下一个广播接收器。优先级越高的广播接收器会优先接收到广播消息,另外广播接收器还可以对广播进行截断,这样后面的广播接收器就无法收到该广播消息。
广播接收器类型
创建广播接收器必须直接或间接地集成BroadcastReceiver
,重写onReceive
方法。
广播接收器根据注册的方式可以分成两类:动态注册、静态注册
动态注册
动态注册:通过代码方式注册广播接收器。动态注册的接收器,一定都要取消注册。
例如下面的代码动态创建广播接收器,在onCreate
中创建广播接收器并进行注册,在onDestroy
中取消注册:
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);
}
/**
* 检测网络变化的广播接收器
*/
class NetworkChangeReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "network change", Toast.LENGTH_LONG).show();
}
}
}
在AndroidManifest.xml
中加入权限:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.jyoryo.app.android.study.s0401">
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
</manifest>
静态注册
动态注册可以自由控制广播接收器的注册、注销,但也存在一个缺点:必须要在程序启动并运行后才能接收到广播。如果需要在程序未启动的情况下就能接收到广播,可以使用静态注册广播接收器。
静态注册:在AndroidManifest.xml
中注册的广播接收器。
1、创建广播接收器:
/**
* 开机广播接收器
*/
public class BootCompleteReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "Boot Complete!", Toast.LENGTH_LONG).show();
}
}
2、在AndroidManifest.xml
中注册静态广播接收器:
<receiver
android:name=".BootCompleteReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
3、根据是否需要相关权限在AndroidManifest.xml
申明需要的权限,比如上面的开机广播需要android.permission.RECEIVE_BOOT_COMPLETED
权限。
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.jyoryo.app.android.study.s0401">
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
</manifest>
发送自定义广播
发送标准广播
发送标准广播:新建一个Intent
,然后sendBroadcast(intent)
即可。
Intent intent = new Intent("com.jyoryo.app.android.study.MY_BROADCAST");
sendBroadcast(intent);
通过静态注册接收自定义广播。
在AndroidManifest.xml
注册MyBroadcast
广播接收器:
<receiver
android:name=".MyBroadcastReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="com.jyoryo.app.android.study.MY_BROADCAST" />
</intent-filter>
</receiver>
广播接收器MyBroadcastReceiver
:
/**
* 接收自定义广播
*/
public class MyBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "receive in MyBroadcastReceiver", Toast.LENGTH_LONG).show();
}
}
发送有序广播
发送有序广播:新建一个Intent
,然后sendOrderedBroadcast(intent, receiverPermission)
即可。
Intent intent = new Intent("com.jyoryo.app.android.study.MY_BROADCAST");
sendOrderedBroadcast(intent, null);
给广播接收器指定先后顺序,通过android:priority="100"
将该接收器的优先级设置为100。
<receiver
android:name=".MyBroadcastReceiver"
android:enabled="true"
android:exported="true">
<intent-filter android:priority="100">
<action android:name="com.jyoryo.app.android.study.MY_BROADCAST" />
</intent-filter>
</receiver>
如果广播接收器处理后,想要截断这条广播,需要在处理完逻辑后调用abortBroadcast()
方法。
public class MyBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "receive in MyBroadcastReceiver", Toast.LENGTH_LONG).show();
abortBroadcast();
}
}
使用本地广播
上面接收的广播都是属于系统全局广播,即发出的广播可以被其他所有的程序接收到。但有时为了安全,发送的广播携带关键或敏感的数据,我们需要发送的广播只能通过本应用接收。这时可以通过本地广播机制来解决。
本地广播主要使用LocalBroadcastManager
对广播进行管理,提供本地广播的注册localBroadcastManager.registerReceiver
和注销localBroadcastManager.unregisterReceiver
操作。
public class MainActivity extends AppCompatActivity {
private LocalBroadcastManager localBroadcastManager;
private IntentFilter intentFilter;
private LocalReceiver localReceiver;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// LocalBroadcastManager
localBroadcastManager = LocalBroadcastManager.getInstance(this);
// 注册动态广播接收器
intentFilter = new IntentFilter();
intentFilter.addAction("com.jyoryo.app.android.study.LOCAL_BROADCAST");
localReceiver = new LocalReceiver();
localBroadcastManager.registerReceiver(localReceiver, intentFilter);
// 通过按钮测试发送本地广播
Button button = (Button) findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent("com.jyoryo.app.android.study.LOCAL_BROADCAST");
sendOrderedBroadcast(intent, null);
sendBroadcast(intent);
}
});
}
@Override
protected void onDestroy() {
super.onDestroy();
// 取消注册广播接收器
localBroadcastManager.unregisterReceiver(localReceiver);
}
/**
* 本地广播接收器
*/
class LocalReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "receive local broadcast", Toast.LENGTH_LONG).show();
}
}
}
本地广播的特点:
- 本地广播无法通过静态注册方式来接收。
- 本地广播离不开本身的程序,因此不用担心敏感数据泄露。
- 本地广播的发送比系统全局广播的发送更高效。