文章目录
一、BroadcastReceiver是什么?
BroadcastReceiver:广播接收者。我们常说听广播,那么什么是收听广播呢?打开收音机,调频就可以收到对应的广播节目了。其实在Android开发中也有类似的概念,所以就称之为广播了。
广播包括发广播和广播接收者,这就类似于广播发射塔和收音机。因些在Android开发中,我们主要研究的就是发广播和接收广播。
二、广播的注册方式
1、静态注册
例子:监听开机广播
在AndroidManifext.xml中注册广播并添加权限
<receiver
android:name=".BootCompleteReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
public class BootCompleteReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "开机完成!", Toast.LENGTH_SHORT).show();
}
}
例子:监听应用的安装与卸载
<receiver
android:name=".AppStateChangeReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.PACKAGE_ADDED" />
<action android:name="android.intent.action.PACKAGE_REMOVED" />
<data android:scheme="package" />
</intent-filter>
</receiver>
public class AppStateChangeReceiver extends BroadcastReceiver {
private final String TAG = "AppStateChangeReceiver";
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
Log.d(TAG, "action:");
if (action.equals(Intent.ACTION_PACKAGE_ADDED)) {
Log.d(TAG, "安装了应用!");
} else if (action.equals(Intent.ACTION_PACKAGE_REMOVED)) {
Log.d(TAG, "卸载了应用!");
}
}
}
应用场景:Launcher监听应用的安装与卸载;大型公司为了收集用户使用习惯或是用于分析未来市场。
注意事项:Android8.0以后需要动态注册监听。详见:监听App安装、卸载的系统广播
2、动态注册
例子:监听电量、充电变化的广播
public class MainActivity extends AppCompatActivity {
private BatteryReceiver mBatteryReceiver;
private final String TAG = "MainActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
IntentFilter intentFilter = new IntentFilter();
//监听电量变化 设置action
intentFilter.addAction(Intent.ACTION_BATTERY_CHANGED);
intentFilter.addAction(Intent.ACTION_POWER_CONNECTED);
intentFilter.addAction(Intent.ACTION_POWER_DISCONNECTED);
mBatteryReceiver = new BatteryReceiver();
//注册广播
this.registerReceiver(mBatteryReceiver, intentFilter);
}
//创建广播
public class BatteryReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
Log.d(TAG, "action: " + action);
switch (action) {
case Intent.ACTION_BATTERY_CHANGED:
//获取当前电量
int batteryLevel = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0);
Toast.makeText(MainActivity.this, "电量: " + batteryLevel, Toast.LENGTH_SHORT).show();
break;
case Intent.ACTION_POWER_CONNECTED:
Toast.makeText(MainActivity.this, "USB线已连接", Toast.LENGTH_SHORT).show();
break;
case Intent.ACTION_POWER_DISCONNECTED:
Toast.makeText(MainActivity.this, "USB线已断开", Toast.LENGTH_SHORT).show();
break;
}
}
}
@Override
protected void onDestroy() {
Log.d(TAG, "onDestroy");
super.onDestroy();
//取消广播注册 否则造成内存泄露
if (mBatteryReceiver != null) {
this.unregisterReceiver(mBatteryReceiver);
}
}
}
在AndroidManifest.xml添加权限
<uses-permission android:name="android.permission.BATTERY_STATS"/>
3、两种方式的区别
1、静态注册可以长期监听,即使应用没有起来也可以监听,所以耗资源;
2、静态注册的广播优先级高于动态注册的广播;
3、动态注册的优点就是省资源,需要的时候才监听,不需要的时候需要取消注册。
不可以静态注册的广播
android.intent.action.SCREEN_ON
android.intent.action.SCREEN_OFF
android.intent.action.BATTERY_CHANGED
android.intent.action.CONFIGURATION_CHANGED
android.intent.action.TIME_TICK
为什么不能静态注册?
如果不是必须一直监听着的广播,一直监听的话会消耗资源,所以静态注册会提高系统的效率。而动态注册的话需要释放资源取消注册,否则会报错的。这样子有利于提高系统的速度。
三、发送广播
例子:自定义一个广播
public class SendBroadCastActivity extends AppCompatActivity {
private EditText mEtSendContent;
private Button mBtSend;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_send_broad_cast);
initView();
initListener();
}
private void initView() {
mEtSendContent = findViewById(R.id.et_sendContent);
mBtSend = findViewById(R.id.bt_send);
}
private void initListener() {
mBtSend.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent();
intent.setAction(Constants.ACTION_SEND_MESSAGE);
String content = mEtSendContent.getText().toString();
intent.putExtra(Constants.CONTENT, content);
intent.setComponent(new ComponentName("com.wj.broadcastdemo","com.wj.broadcastdemo.MessageReceiver"));
//发送广播
sendBroadcast(intent);
}
});
}
}
public class Constants {
public static final String ACTION_SEND_MESSAGE = "com.wj.broadcastdemo.SEND_MESSAGE";
public static final String CONTENT = "content";
}
public class MessageReceiver extends BroadcastReceiver {
private final String TAG = "MessageReceiver";
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
Log.d(TAG, "action: " + action);
String content = intent.getStringExtra(Constants.CONTENT);
Log.d(TAG, "content: " + content);
Toast.makeText(context, "收到了一条广播: " + content, Toast.LENGTH_SHORT).show();
}
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="20dp"
tools:context=".SendBroadCastActivity">
<EditText
android:id="@+id/et_sendContent"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="请输入要发送的广播内容" />
<Button
android:id="@+id/bt_send"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="发送广播" />
</LinearLayout>
打印Log
2022-12-10 18:39:51.094 5275-5275 MessageReceiver com.wj.broadcastdemo D action: com.wj.broadcastdemo.SEND_MESSAGE
2022-12-10 18:39:51.094 5275-5275 MessageReceiver com.wj.broadcastdemo D content: 放假回家过年了
四、广播的类型
1、有序广播
注意事项:Android8.0以后发送有序广播需要动态注册 详见:解决安卓8.0版本之后有序广播的接收问题
public class SendOrderedBroadCastActivity extends AppCompatActivity {
private Button mBtSend;
private HighLevelReceiver mHighLevelReceiver;
private DefaultLevelReceiver mDefaultLevelReceiver;
private LowLevelReceiver mLowLevelReceiver;
private final String TAG = "SendOrderedBroadCast";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_send_ordered_broad_cast);
initView();
initListener();
handleSendOrderBroadcast();
}
private void handleSendOrderBroadcast() {
Log.d(TAG, "handleSendOrderBroadcast");
IntentFilter filter1 = new IntentFilter();
filter1.addAction(Constants.ACTION_SEND_ORDERED);
filter1.setPriority(1000);
mHighLevelReceiver = new HighLevelReceiver();
this.registerReceiver(mHighLevelReceiver, filter1);
IntentFilter filter2 = new IntentFilter();
filter2.addAction(Constants.ACTION_SEND_ORDERED);
filter2.setPriority(0);
mDefaultLevelReceiver = new DefaultLevelReceiver();
this.registerReceiver(mDefaultLevelReceiver, filter2);
IntentFilter filter3 = new IntentFilter();
filter3.addAction(Constants.ACTION_SEND_ORDERED);
filter3.setPriority(-1000);
mLowLevelReceiver = new LowLevelReceiver();
this.registerReceiver(mLowLevelReceiver, filter3);
}
private void initView() {
mBtSend = findViewById(R.id.bt_send);
}
private void initListener() {
mBtSend.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent();
intent.setAction(Constants.ACTION_SEND_ORDERED);
//发送一个有序广播
//sendOrderedBroadcast(Intent intent, //发送广播的意图对象(可以携带数据)
// String receiverPermission, //接收权限(如果为空,则不需要权限)
// BroadcastReceiver resultReceiver, //广播接收者对象(自己创建的最终的广播接收者,可以无须在清单文件中配置,也会接收到广播 )
// Handler scheduler, //若传null,则默认是在主线程中
// int initialCode, //初始化的一个值。可默认:Activity.RESULT_OK
// String initialData, //可发送的初始化数据(相当于一条广播数据)。可为null
// Bundle initialExtras) //可绑定数据传递(Intent对象也可以,所以可为null)
sendOrderedBroadcast(intent, null, null, null, Activity.RESULT_OK, "国家发放补贴1000", null);
}
});
}
@Override
protected void onDestroy() {
super.onDestroy();
if (mHighLevelReceiver != null) {
this.unregisterReceiver(mHighLevelReceiver);
}
if (mDefaultLevelReceiver != null) {
this.unregisterReceiver(mDefaultLevelReceiver);
}
if (mLowLevelReceiver != null) {
this.unregisterReceiver(mLowLevelReceiver);
}
}
}
public class HighLevelReceiver extends BroadcastReceiver {
private final String TAG = "HighLevelReceiver";
@Override
public void onReceive(Context context, Intent intent) {
//终止往下传达
//abortBroadcast();
Log.d(TAG, "HighLevelReceiver action: " + intent.getAction());
String resultData = getResultData();
setResultData("国家发放补贴800");
Toast.makeText(context, "省接收:" + resultData, Toast.LENGTH_SHORT).show();
}
}
public class DefaultLevelReceiver extends BroadcastReceiver {
private final String TAG = "DefaultLevelReceiver";
@Override
public void onReceive(Context context, Intent intent) {
Log.d(TAG, "DefaultLevelReceiver action: " + intent.getAction());
String resultData = getResultData();
setResultData("国家发放补贴600");
Toast.makeText(context, "市接收:" + resultData, Toast.LENGTH_SHORT).show();
}
}
public class LowLevelReceiver extends BroadcastReceiver {
private final String TAG = "LowLevelReceiver";
@Override
public void onReceive(Context context, Intent intent) {
Log.d(TAG, "LowLevelReceiver action: " + intent.getAction());
String resultData = getResultData();
Toast.makeText(context, "县接收:" + resultData, Toast.LENGTH_SHORT).show();
}
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="20dp"
tools:context=".SendBroadCastActivity">
<Button
android:id="@+id/bt_send"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="发送一条有序广播" />
</LinearLayout>
打印Log
2022-12-10 21:15:36.264 21188-21188 HighLevelReceiver com.wj.broadcastdemo D HighLevelReceiver action: com.wj.broadcastdemo.SEND_ORDERED
2022-12-10 21:15:36.300 21188-21188 DefaultLevelReceiver com.wj.broadcastdemo D DefaultLevelReceiver action: com.wj.broadcastdemo.SEND_ORDERED
2022-12-10 21:15:36.343 21188-21188 LowLevelReceiver com.wj.broadcastdemo D LowLevelReceiver action: com.wj.broadcastdemo.SEND_ORDERED
2、无序广播
之前的例子都是无序广播。
3、广播的权限
谁可以接受我的广播
在发送的AndroidManifest.xml中定义权限
<permission android:name="com.wj.broadcastdemo.ORDER_PERMISSION" />
sendOrderedBroadcast(intent, Manifest.permission.ORDER_PERMISSION, null, null, Activity.RESULT_OK, null, null);
在接收的AndroidManifest.xml中申明权限
<uses-permission android:name="com.wj.broadcastdemo.ORDER_PERMISSION"/>
谁有权限给我发广播
同理需要在节点添加permission属性。