广播的注册方式:
- 动态注册
- 静态注册
广播的发送方式:
- 普通广播
- 有序广播
- 本地广播
特殊说明
- 不要在onreceive中添加过多的逻辑或超时操作
- 本地广播无法通过静态注册方式来接受
关于动态注册&关于静态注册
一种是在活动里通过代码动态注册,另一种在配置文件里静态注册。动态注册的接收器必须要在程序启动之后才能接收到广播,而静态注册的接收器即便程序未启动也能接收到广播,比如想接收到手机开机完成后系统发出的广播就只能用静态注册了。
//动态注册
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实例,,
* 添加了android.net.conn.CONNECTIVITY_CHANGE的action,当系统发出这个广播时,我们就能收到
* 创建了NetworkchangeReceiver实例,
* 调用registerReceiver对广播进行动态注册
*/
intentFilter = new IntentFilter();
intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
networkchangeReceiver = new NetworkchangeReceiver();
registerReceiver(networkchangeReceiver, intentFilter);
}
@Override
protected void onDestroy() {
super.onDestroy();
//动态注册的广播必须取消注册。在onDestroy调用unregisterReceiver方法
unregisterReceiver(networkchangeReceiver);
}
/**
* 定义内部类,NetworkchangeReceiver,
* 继承BroadcastReceiver,重写父类的onReceive方法
* 每当网络状态发生变化时,就会执行,这里简单toast。
*/
private class NetworkchangeReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "network changes", Toast.LENGTH_SHORT).show();
}
}
}
//静态注册
//1、new other broadcast Receiver,创建广播器MyReceiver,重写onReceive方法
//2、在配置文件中添加<intent-filter>
//3、添加网络权限 <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
public class MyReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "network changes", Toast.LENGTH_SHORT).show();
}
}
//AndroidManifest的配置文件里
<receiver
android:name=".MyReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE"/>
</intent-filter>
</receiver>
关于普通广播
也就是标准广播,普通广播是一种完全异步执行的广播,在广播发出之后,所有的广播接收器几乎都会在同一时刻接收到这条广播消息,因此它们接收的先后是随机的。另外,接收器不能截断普通广播。
- 创建广播接收器
- AndroidManifest进行静态注册,添加对应的权限
- 界面添加按钮,mainactivity里对按钮添加单击事件,发送广播。
public class MyReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "received BroadcastReceiver", Toast.LENGTH_SHORT).show();
}
}
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<receiver
android:name=".MyReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>
public void onclick(View view) {
Intent intent = new Intent("firstcode.zs.com.fc_5.MyReceiver");
sendBroadcast(intent);
}
关于有序广播
它是一种同步执行的广播,在广播发出之后,同一时刻只会有一个广播接收器能够收到这条广播消息,当这个广播接收器中的逻辑执行完毕后,广播才会继续传递,所以此时的广播接收器是有先后顺序的,且优先级(priority)高的广播接收器会先收到广播消息。有序广播可以被接收器截断使得后面的接收器无法收到它。
- 发送一个有序广播和普通广播的方法有细微的区别,只需要将sendBroadcast()方法改成sendOrderedBroadcast()方法, 它接收两个参数,第一个参数仍是Intent,第二个参数是一个与权限相关的字符串,这里传入 null就行。
- 只要在注册的时候设定它的优先级android:priority为100,数值越大优先级就越高,现在就能保证它一定会在MyReceiver之前收到广播。
- 如果在AnotherReceiver的onReceive()方法中调用了abortBroadcast()方法,表示将这条广播截断,后面的广播接收器将无法再接收到这条广播。现在重新运行程序,并点击一下按钮,然后会发现,只有AnotherReceiver中的Toast信息弹出,说明这条广播经过AnotherReceiver之后确实是终止传递了。
关于本地广播
使用本地广播,自己在之前用过,参考这篇文章
前面学到的的广播都属于系统全局广播,即发出的广播可被其他应用程序接收到,且我们也可接收到其他任何应用程序发送的广播。为了能够简单地解决全局广播可能带来的安全性问题,Android引入了一套本地广播机制,使用这个机制发出的广播只能够在应用程序的内部进行传递,并且广播接收器也只能接收本应用程序发出的广播。
实现本地广播的发送和接收也很简单,主要使用了一个LocalBroadcastManager来对广播进行管理,并提供了相应的发送广播和注册广播接收器的方法。
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("firstcode.zs.com.fc_5.LOCAL_BROADCAST");
localBroadcastManager.sendBroadcast(intent); // 发送本地广播
}
});
intentFilter = new IntentFilter();
intentFilter.addAction("firstcode.zs.com.fc_5.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();
}
}
}
关于不要在onreceive中添加过多的逻辑或超时操作:
广播接收器不允许开启线程。当onreceive方法运行了较长时间没有结束时,程序就会报错。
关于本地广播无法通过静态注册方式来接收
静态注册主要是为了让程序在未启动的情况下也能收到广播,而发送本地广播是我们的程序肯定已经启动了,完全不需要静态注册。
FC系列文章,均参考郭神的《第一行代码》,所以这里的文章均为转载