BroadcastReceiver
作为 Android 的四大组件之一 BroadcastReceiver 有着非常广泛的使用。要想使用 BroadcastReceiver 搜先高搞明白 Broadcast 目前来看, Broadcast 也就是所谓的广播,主要分为两种:普通广播 和 有序广播。故名思意,Broadcast 就是用于发出消息,而 BroadcastReceiver 则是用来接收消息。
普通广播
就是能让所有的 BroadcastReceiver 都接收到消息,这样咋一看非常方便,但实际上有个很严重的缺陷,就是信息不能被一层层的广播,按照优先级(-1000 - 1000)次序接收,包装、在传递。
有序广播
有序广播,顾名思义,与普通广播相比,就是增添了有序性。也就是它能够一层层的包装并向下传播。所以它也就克服了 普通广播 致命的缺点。
广播发送
方法一:Context.sendBroadcast
这就是普通广播的发送方法,也就是让所有接收器都收到广播
方法二:Context.sendOrderedBroadcast
- 这个方法发送的是有序广播,系统会根据声明的优先级,按顺序逐个执行 BroadcastReceiver ,前面的接收者有权终止广播(调用 BroadcastReceiver.abortBroadcast()),注意:广播被前面的接收者终止,后面的接收者就再也无法获取到广播。
- 对于有序广播,前面的接收者可以将处理结果通过setResultExtras(Bundle)方法存放进结果对象,然后传给下一个接收者,通过代码:Bundle bundle =getResultExtras(true))可以获取上一个接收者存入在结果对象中的数据。
- 系统收到短信,发出的广播属于有序广播。如果想阻止用户收到短信,可以通过设置优先级,让你们自定义的接收者先获取到广播,然后终止广播,这样用户就接收不到短信了。
生命周期:
广播的生命周期非常短暂,如果一个广播处理完 onReceive 方法,那么系统将认定此广播对象,不再是一个活动的对象。这时候它就会 finish 掉它。
拓展:同时还有一个注意点,我们知道,既然 BroadcastReceiver 生命,周期这么短暂,就不应该用它来做一些耗时操作( 更 普通的 Service 一样 ),就是说不要在里边定义线程,用 sleep 方法等。
BroadcastReceiver 步骤:
1,自定义一个类继承 BroadcastReceiver
2,重写 onReceive 方法
3,在 manifest.xml 中注册 ( 但不注册好像也没事。。。主要是为了安全 )
MyBroadcastReceiver
public class MyBroadcastReceiver extends BroadcastReceiver {
private int progressStatus = 0;
private final String EXTRA_ID = "status";
private ProgressDialog progressDialog;
MyBroadcastReceiver(){
}
public MyBroadcastReceiver(ProgressDialog progressDialog){
this.progressDialog = progressDialog;
}
// 回调判断意图 更新进度条
@Override
public void onReceive(Context context, Intent intent) {
// 。。。
}
}
重写 onReceive
我在这里模拟了一个进度条,接收到信息后 更新 进度条信息,进度条在广播注册时被传入
// 回调判断意图 更新进度条
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction() != null){
switch (intent.getAction()){
case IntentManager.ACTION_TYPE_SERVICE:
progressDialog.setMessage("线程状态:" + intent.getStringExtra(IntentManager.INTENT_STATUS_SERVICE));
if (intent.getStringExtra(IntentManager.INTENT_STATUS_SERVICE).equals("服务已结束运行")){
progressDialog.dismiss();// 从源码看出调用后 在调用了 dismiss()
}
break;
case IntentManager.ACTION_TYPE_THREAD:
progressStatus = intent.getIntExtra(IntentManager.INTENT_PROGRESS_SERVICE, 0);
progressDialog.setMessage("线程状态:" + intent.getStringExtra(IntentManager.INTENT_STATUS_SERVICE));
progressDialog.setProgress(progressStatus);
break;
}
progressStatus = intent.getIntExtra(EXTRA_ID, 0);
}else {
// ...
}
}
在 manifest.xml 中注册
<application
android:name=".App"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
。
。
。
<receiver android:name=".broadcast.MyBroadcastReceiver">
<!--这里自定义一个广播动作-->
<intent-filter>
<action android:name="android.intent.action.ACTION_POWER_CONNECTED" />
<action android:name="test"/>
</intent-filter>
</receiver>
</application>
并在 Mainfest.xml 中添加权限
<uses-permission android:name="android.permission.INTERNET" /> <!-- 广播权限 -->
上面完成了广播基本功能的实现,现在我们在活动里来实现具体的
注册广播:
注册很简单
- 定义 LocalBroadcastManager 类对象
- 实例化一个 MyBroadcastReceiver 对象,并将需要更新的控件传入
- 实例化 intentFilter 对象,并给他添加 action
- 调用 registerReceiver 进行注册
private fun iniBroadCast() {
val manager = LocalBroadcastManager.getInstance(this)
val broadcastReceiver = MyBroadcastReceiver(progressDialog)// 在这之前 progressDialog 要先被实例化出来
val intentFilter = IntentFilter()
intentFilter.addAction(IntentManager.ACTION_TYPE_SERVICE)
intentFilter.addAction(IntentManager.ACTION_TYPE_THREAD)
manager.registerReceiver(broadcastReceiver, intentFilter)
val intent = Intent(this, MyIntentService::class.java)
startService(intent)
}
发送广播
- 建立一个 Intent 添加 Action
- 用 putExtra 传入信息
- 调用 sendBroadcast 发送
manager = LocalBroadcastManager.getInstance(this);
private void sendIfoToBroadCast(String serviceStatus){
Intent intent1 = new Intent(IntentManager.ACTION_TYPE_SERVICE);
intent1.putExtra(IntentManager.INTENT_STATUS_SERVICE, serviceStatus);
manager.sendBroadcast(intent1);
}
private void sendIfoToBroadCast(String serviceStatus, int progressStatus){
Intent intent = new Intent(IntentManager.ACTION_TYPE_THREAD);
intent.putExtra(IntentManager.INTENT_STATUS_SERVICE, serviceStatus);
intent.putExtra(IntentManager.INTENT_PROGRESS_SERVICE, progressStatus);
manager.sendBroadcast(intent);
}
这里有个注意点 -> https://blog.csdn.net/qq_43377749/article/details/90738979
静态注册与动态注册
静态注册:
MyBroadcastReceiver myBroadcastReceiver=new MyBroadcastReceiver();
IntentFilter intentFilter=new IntentFilter();
intentFilter.addAction("com.example.dimple.MY_BROADCAST");
registerReceiver(myBroadcastReceiver,intentFilter);
在用完后 记得及时接触注册
@Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(myBroadcastReceiver);
}
- 静态注册是常驻型,也就是说当应用程序关闭后,如果有信息广播来,程序也会被系统调用自动运行。
动态注册:
public class MyReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context,"开机启动!",Toast.LENGTH_LONG).show();
}
}
添加权限:
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"></uses-permission>
在 Mainfest 中注册
<application
android:name=".App"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
。
。
。
<receiver android:name=".broadcast.MyBroadcastReceiver">
<!--这里自定义一个广播动作-->
<intent-filter>
<action android:name="android.intent.action.ACTION_POWER_CONNECTED" />
<action android:name="test"/>
</intent-filter>
</receiver>
</application>
- 动态注册广播不是常驻型广播,也就是说广播跟随activity的生命周期。注意: 在activity结束前,移除广播接收器。
文中代码 Demo 已打包到 github 点击跳转->
点击跳转 https://github.com/FishInWater-1999/android_four_major_components
如果觉得我归纳的还行,不妨点个赞呦~么么哒~~