当前位置 博文首页 > 庆述倾述:广播接收器BroadCastReceiver
每个应用都可以注册广播接收器(BroadCastReceiver
)来接受系统和其他应用发来的广播,也可以发送广播给其他应用。
广播大致有四种类型:
AndroidManifest.xml
配置文件中注册的广播接收器的intent-filter
中android:priority
属性来设置优先级。取值范围-1000~1000
,数值越大级别越高。且静态注册优于动态注册,先注册的优于后注册的广播。Android
系统中使用了很多广播,比如低电量、开机启动、锁屏、SD
卡挂载、打电话等。BroadCastReceiver
的注册方式有两种,静态和动态。
public class TestActivity extends AppCompatActivity {
private String TAG = "TestActivity";
private MyBroadCastReceiver myBroadCastReceiver;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test);
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("android.intent.action.TIME_TICK");
myBroadCastReceiver = new MyBroadCastReceiver();
registerReceiver(myBroadCastReceiver, intentFilter);
}
@Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(myBroadCastReceiver);
}
static class MyBroadCastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "Time Changed", Toast.LENGTH_LONG).show();
}
}
}
通过使用IntentFilter
对象来添加相应的action
,从而让广播接收器知道自己监听的是什么广播。
对应的系统支持的广播行为在Android SDK/platforms/version/data/broadcast_actions.txt
文件中。比如:
动态广播存在一个确定就是,需要程序启动才可以接收广播,因为注册是在onCreate
中完成的。理论上使用静态广播可以让程序在未启动的情况下也可以接收到广播,但是这样大家都使用静态广播,那么就会导致任何应用都可以频繁的从后台被唤醒,严重影响了手机电量和性能。
因此每个版本的系统都在削弱静态广播注册功能。
在Android8.0
之后,所有隐式广播都不允许使用静态注册的方式来接收了。大多数系统广播都属于隐式广播。还有少数特殊的广播仍然允许使用静态注册的方式来接收。见:隐式广播例外情况
使用快捷方式创建一个静态广播很容易。
它会自动在配置文件中注册:
<receiver
android:name=".receiver.MyReceiver"
android:enabled="true"
android:exported="true">
</receiver>
我们为之添加系统启动广播过滤器:
// 权限
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
// 注册
<receiver
android:name=".receiver.MyReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>
对应的java
文件添加Toast
:
public class MyReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
// TODO: This method is called when the BroadcastReceiver is receiving
Toast.makeText(context, "Boot Complete", Toast.LENGTH_LONG).show();
}
}
在启动类中加入动态权限申请:
public class TestActivity extends AppCompatActivity {
private String TAG = "TestActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test);
//权限检查
if (ContextCompat.checkSelfPermission(TestActivity.this,
Manifest.permission.RECEIVE_BOOT_COMPLETED) != PackageManager.PERMISSION_GRANTED) {
//申请权限
ActivityCompat.requestPermissions(TestActivity.this,
new String[]{Manifest.permission.RECEIVE_BOOT_COMPLETED}, 1);
}
}
}
实现接收自定义广播,我们只需要在action
中指定一个自定义的字符串即可。如:
<receiver
android:name=".receiver.MyReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="com.weizu.broadcast.test"/>
</intent-filter>
</receiver>
然后:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test);
Button button = findViewById(R.id.id_button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.d("TAG", "onClick: ");
Intent intent = new Intent();
intent.setAction("com.weizu.broadcast.test");
// 指定发给哪个程序,让隐式广播变为显式广播,才可以被接收到
intent.setPackage(getPackageName());
sendBroadcast(intent);
}
});
}
注意,这里必须调用:intent.setPackage(getPackageName());
方法。因为默认自定义广播是隐式广播,我们需要使用setPackage()
方法来指定这个广播是发送给哪个应用程序,从而让它变成显式广播。否则,静态注册的BroadCastReceiver
无法收到这个广播
有序广播可以被拦截,同步执行,有优先级顺序。
只需要使用:
sendOrderedBroadcast(intent, null);
可以在intent-filter
中设置优先级:
<receiver
android:name=".receiver.MyReceiver"
android:enabled="true"
android:exported="true">
<intent-filter android:priority="100">
<action android:name="com.weizu.broadcast.test"/>
</intent-filter>
</receiver>
如果需要某个广播接收器拦截这个广播,可以在onReceive
方法中拦截:
public class MyReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "Boot Complete", Toast.LENGTH_LONG).show();
abortBroadcast(); // 拦截
}
}
主要使用LocalBroadcastManager
来对广播进行管理,需要注意的是,这里的广播接收器的注册不能使用静态注册,而需要使用LocalBroadcastManager
对象的registerReceiver(myReceiver, intentFilter);
方法进行注册。且注册这里为动态注册。
public class TestActivity extends AppCompatActivity {
LocalBroadcastManager localBroadCastManager;
MyReceiver myReceiver;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test);
localBroadCastManager = LocalBroadcastManager.getInstance(TestActivity.this);
Button button = findViewById(R.id.id_button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent();
intent.setAction("com.weizu.broadcast.test");
localBroadCastManager.sendBroadcast(intent);
}
});
IntentFilter intentFilter