整理自《第一行代码》第五章
Android中的每个应用程序都可以对自己感兴趣的广播进行注册,这样该程序就只会接收到自己所关心的广播内容。这些广播可能是来自于系统的,也可能是来自于其他应用程序的。
标准广播 完全异步执行的广播,在广播发出后,所有广播接收器几乎在同时收到广播信息。效率高,但无法被截断。
有序广播 同步执行的广播,同一时刻只有一个广播接收器能够收到这条广播消息,当逻辑执行完毕后,广播才会继续传递。优先级高的广播接收器可以先收到广播消息,并且前面的广播接收器还可以截断正在传递的广播。
接收系统广播
广播接收器receive方法中逻辑过多或任何其他运行时间过长都会导致程序报错。因此广播接收器更多扮演一种打开程序其他组件如创建状态栏通知,或启动一个服务等。
动态接收
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();//字面意义为“意图过滤器”
//匹配测试只考虑 动作、数据(URI及数据类型)和类别
//addAction添加想要监听的广播
intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
networkChangeReceiver = new NetworkChangeReceiver();
//registerReceiver方法注册广播
registerReceiver(networkChangeReceiver,intentFilter);
}
protected void onDestroy(){
super.onDestroy();
//动态注册的广播接收器需要取消
unregisterReceiver(networkChangeReceiver);
}
//内部类继承BroadcastReceiver类,当网络状态发生变化时,onReceive方法就会执行
class NetworkChangeReceiver extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context,"network changes",Toast.LENGTH_SHORT).show();
}
}
}
静态注册实现开机启动
右击com.example.broadcasttest
包——>New——>Other——>Broadcast Receiver,在窗口中设置名字。Exported属性表示是否允许广播接收器接收本程序以外的广播,Enabled属性表示是否启用。完成后可以重写onReceive
方法。
在AndroidMainfest.xml
中已经有<receiver>标签了。但仍需要添加权限。
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<action android:name="android.intent.action.BOOT_COMPLETED" />
//此条语句没有提示跳出,验证也并不成功,有待考究
发送自定义广播
发送标准广播
新建一个自定义的广播接收类,在AndroidMainfest.xml
中声明接收这样的广播。最后的效果是点击按钮即会显示自定义的toast
语句。
public class MyBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context,"received in MyBroadcastReceiver",Toast.LENGTH_SHORT).show();
}
}
//接收到信息即输出这句话
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);
}
});
//对按钮设置事件监听,可以看到,广播信息是通过intent进行传递的,将其送出。
<receiver android:name=".MyBroadcastReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="com.example.broadcasttest.MY_BROADCAST"/>
</intent-filter>
</receiver>
发送有序广播
相同的方法定义新的广播接收器,可以发现在点击按钮后都能收到广播信息。
如果需要发送有序广播,只需要将sendBroadcast
改为sendOrderedBroadcast
方法即可。sendOrderedBroadcast
中的两个参数,第一个是意图,第二个是有关权限的字符串,此时传null
.
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);
}
});
广播接收器的先后顺序在注册时设定。此时在先接收到广播的onReceive
方法中调用abortBroadcast()
方法,即可截断这条广播,优先级小于其的接收器将无法接收。
<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>
本地广播
注意要导入support-v4包
首先通过LocalBroadcastManager
的getInstantce()
方法得到实例,注册时调用LocalBroadcastManager
的registerReceiver()
方法,发送广播调用LocalBroadcastManager
的sendBroadcast()
方法。
本地广播只会在程序内部传播。本地广播无法通过静态注册方式来接收。
优势:
- 可以明确知道正在发送的广播不会离开程序,不必担心数据泄露
- 其他程序无法发送广播至程序内部,没有安全漏洞的隐患
- 发送本地广播比发送系统全局广播更高效
private localReceiver localReceiver;
private LocalBroadcastManager localBroadcastManager;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
localBroadcastManager = LocalBroadcastManager.getInstance(this);
Button button = findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
localBroadcastManager.sendBroadcast(intent);
}
});
intentFilter = new IntentFilter();
intentFilter.addAction("com.android.broadcasttest.LOCAL_BROADCAST");
localReceiver = new localReceiver();
localBroadcastManager.registerReceiver(localReceiver,intentFilter);
}
protected void onDestroy(){
super.onDestroy();
localBroadcastManager.unregisterReceiver(localReceiver);
}
class localReceiver extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context,"local broadcast",Toast.LENGTH_SHORT).show();
}
}