四大组件:BroadCastReceiver广播

2024-01-28 21:38

本文主要是介绍四大组件:BroadCastReceiver广播,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

简介

BroadCastReceiver:广播接收者,可以接受手机电量变化、短信、电话、app的安装与卸载等都可以接受到这些广播(这些事系统发出的广播),当然我们还可以自定义广播,这就我们自己写发送广播的代码。

分类:

有序广播和无序广播
有序广播:是可以拦截的,可以设置优先级(数值越大,越先接收广播)
无序广播:不可以被拦截,没有优先级。

有关方法:

sendBroadcast(intent);发送广播
sendOrderedBroadcast(Intent intent, String receiverPermission, BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, String initialData, Bundle initialExtras)发送有序广播
abortBroadcast();取消广播,只有有序广播才可以调用该方法,无序广播调用会报错BroadcastReceiver trying to return result during a non-ordered broadcast

这里写图片描述

如果是静态广播,那么不需要在onReceive(...)中判断action,如果是动态注册,需要判断action

静态广播接收者BroadCastReceiver

注册广播接收者有2种方法,代码中注册(动态注册)和AndroidManifest.xml中注册(静态注册),下面的案例没说明动态注册的都是静态注册。

系统发出的广播,我们只做接收。常见的如下:
- 打电话 Receiver
- SD卡状态 Receiver
- 来短信 Receiver
- app的安装与卸载 Receiver
- 开机启动 Receiver

打电话 Receiver

打电话,若是长途,则广播中给手机号添加ip:123456

这里写图片描述

    @Overridepublic void onReceive(Context context, Intent intent) {//获取保存的ipSharedPreferences sp = context.getSharedPreferences("config", context.MODE_PRIVATE);String ip = sp.getString("ip", "17951");//获取拨进来的号码String number = getResultData();//以0开头,则是长途,则在号码前加ipif (number.startsWith("0")) {setResultData(ip + number);}}
<!--在androidManifest中注册的广播是持久广播,app退出仍然有效。  -->
<!-- 声明receiver 添加action -->
<receiver android:name="com.cqc.ipnumber.OutGoingCallBroadCastReceiver" ><intent-filter><action android:name="android.intent.action.NEW_OUTGOING_CALL" /></intent-filter>
</receiver>
<!-- 添加外拨电话权限 -->
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS"/>

SD卡状态 Receiver

 根据action判断sd卡是挂载还是卸载。注意卸载sd卡的action是UNMOUNTED,不是REMOVE
@Override
public void onReceive(Context context, Intent intent) {String action = intent.getAction();if (Intent.ACTION_MEDIA_MOUNTED.equals(action)) {// 挂载Log.d(TAG, "sd卡挂载");} else if (Intent.ACTION_MEDIA_UNMOUNTED.equals(action)) {Log.d(TAG, "sd卡卸载");}
}
<!-- 声明receiver --><receiver android:name="com.cqc.sdstatelistener.SdStateReceiver" ><intent-filter><action android:name="android.intent.action.MEDIA_MOUNTED" /><action android:name="android.intent.action.MEDIA_UNMOUNTED" /><!-- sd卡状态比较特殊,除了设置action,还需要data --><data android:scheme="file" /></intent-filter></receiver>

来短信 Receiver

广播接收者:

    @Overridepublic void onReceive(Context context, Intent intent) {//转换成数组Object[] objects = (Object[]) intent.getExtras().get("pdus");//遍历数组,湖区sms对象for (Object object : objects) {SmsMessage sms = SmsMessage.createFromPdu((byte[]) object);//获取短信内容和发布者手机号String content = sms.getMessageBody();String originNumber= sms.getOriginatingAddress();Log.d(TAG, "content="+content+"____originNumber"+originNumber);}}
<receiver android:name="com.cac.smsreceiver.SmsReceiver" ><intent-filter><!-- 处于安全性考虑,android没有提示短信监听的action,但仍然可以使用 --><action android:name="android.provider.Telephony.SMS_RECEIVED" /></intent-filter></receiver>
 <!-- 短信监听的权限 --><uses-permission android:name="android.permission.RECEIVE_SMS" />

把androidManifest.xml的启动的actiivty的intent_filter注释掉,就没有界面了,但是海驿拿到短信, api4.0后,注释掉intent_filter,就拿不到短信了。

app的安装与卸载 Receiver

这里写图片描述

@Override
public void onReceive(Context context, Intent intent) {String action = intent.getAction();if (Intent.ACTION_PACKAGE_ADDED.equals(action)) {// 挂载Log.d(TAG, "安装");} else if (Intent.ACTION_PACKAGE_REMOVED.equals(action)) {Log.d(TAG, "卸载");}
}
<receiver android:name="com.cqc.installreceiver.InstallReceiver"><intent-filter ><action android:name="android.intent.action.PACKAGE_ADDED"/><action android:name="android.intent.action.PACKAGE_REMOVED"/><!-- 安装卸载还需要添加data --><data android:scheme="package"/></intent-filter>
</receiver>

开机启动 Receiver

    @Overridepublic void onReceive(Context context, Intent intent) {Log.d(TAG, "intent2");Intent intent2 = new Intent(context, MainActivity.class);intent2.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);context.startActivity(intent2);String action = intent.getAction();if (Intent.ACTION_BOOT_COMPLETED.equals(action)) {Log.d(TAG, "Intent.ACTION_BOOT_COMPLETED");}}
 <receiver android:name="com.cqc.bootreceiver.BootReceiver" ><intent-filter><action android:name="android.intent.action.BOOT_COMPLETED"/></intent-filter></receiver>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

自定义广播接收者

自定义广播需要设置action,可以获取intent中的数据。

基本使用

自定义广播,在Button的点击监听中发送广播,在receiver中根据action,从intent中取值。

这里写图片描述

发送广播:

Intent intent = new  Intent();
intent.setAction("MyReceiver");
intent.putExtra("name", "奥巴马");
sendBroadcast(intent);

MyReceiver :

public class MyReceiver extends BroadcastReceiver {private static final String TAG = "MyReceiver";@Overridepublic void onReceive(Context context, Intent intent) {Log.d(TAG, "MyReceiver--name="+intent.getStringExtra("name"));//取消广播abortBroadcast();}
}

在AndroidManifest.xml中配置receiver:

<receiver android:name="com.cqc.custombroadcast.MyReceiver"><intent-filter ><action android:name="MyReceiver"/></intent-filter>
</receiver>

自定义有序广播

demo:国家发布政令后,先到省政府,再到市政府,再到县政府…,这里只设置这3级,有先后顺序。点击Button发送广播,一次向下传递。

点击Button发送广播:

 btn.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {//发送自定义广播Intent intent = new Intent();intent.setAction("customOrderReceiver");intent.putExtra("commond", "全国各级部门应该加强安全防范措施");
//              sendBroadcast(intent);//这是无序广播/*** 这是有序广播,参数分别是:* Intent intent:intent对象* String receiverPermission: 接收者权限* BroadcastReceiver resultReceiver:最后一个接收者,不为null,则最后的receiver会接收2次。* Handler scheduler, null* int initialCode  状态码* String initialData,  传递的数据,intent.putExtra(...)* Bundle initialExtras:null*/sendOrderedBroadcast(intent, null, new CountyReceiver(), null, 1, null, null);}});

省级先接到通知

public class ProviceReceiver extends BroadcastReceiver {@Overridepublic void onReceive(Context context, Intent intent) {Log.d("tag", "省级部门接到中央命令+content="+intent.getStringExtra("commond"));}
}

然后是市级接到通知

public class CityReceiver extends BroadcastReceiver {@Overridepublic void onReceive(Context context, Intent intent) {Log.d("tag", "市级部门接到中央命令+content="+intent.getStringExtra("commond"));}
}

最后是县级接到通知

public class CountyReceiver extends BroadcastReceiver {@Overridepublic void onReceive(Context context, Intent intent) {Log.d("tag", "县级部门接到中央命令+content="+intent.getStringExtra("commond"));}
}

注意:

1 上面的先后级别是根据广播接收者的priority(优先级)决定的。是在配置receiver时设置的。

 <receiver android:name="com.cqc.customorderreceiver.ProviceReceiver" ><intent-filter android:priority="3" ><action android:name="customOrderReceiver" /></intent-filter></receiver><receiver android:name="com.cqc.customorderreceiver.CityReceiver" ><intent-filter android:priority="2" ><action android:name="customOrderReceiver" /></intent-filter></receiver><receiver android:name="com.cqc.customorderreceiver.CountyReceiver" ><intent-filter android:priority="1" ><action android:name="customOrderReceiver" /></intent-filter></receiver>

2 调用方法sendOrderedBroadcast(…)发送有序广播的时候若指定了最后接收者( resultReceiver),那么 resultReceiver会收到2次广播。
这里写图片描述

动态注册广播接收者

与静态相比区别是:

代码上:

1 不需要再AndroidManifest.xml中注册
2 调用registerReceiver(receiver, filter)注册接收者

理解上:

静态注册的广播接收者:当app关闭的时候也是有效的,也可以接受到服务器发出的广播。
动态注册的广播接收者:当app关闭的时候,不会接受到广播。因为我们是在onCreate()中注册的,而不是在AndroidManifest.xml中注册。

下面的是锁屏和开锁的的广播接收者,当我们打开这个app的时候,按住手机电源键锁屏和接收会打印出log,但是当我们关闭app的时候,再按住手机电源键锁屏和接收则不会打印出log

这里写图片描述

Demo1:

public class MainActivity extends Activity {private MyBroadcastReceiver receiver;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);receiver = new MyBroadcastReceiver();IntentFilter filter = new IntentFilter();filter.addAction("android.intent.action.SCREEN_ON");//添加actionfilter.addAction("android.intent.action.SCREEN_OFF");registerReceiver(receiver, filter);//注册广播接收者}@Overrideprotected void onDestroy() {unregisterReceiver(receiver);//取消广播接收者super.onDestroy();}//创建广播接收者类public class MyBroadcastReceiver extends BroadcastReceiver{@Overridepublic void onReceive(Context context, Intent intent) {String action = intent.getAction();if ("android.intent.action.SCREEN_OFF".equals(action)) {System.out.println("锁屏");} else if("android.intent.action.SCREEN_ON".equals(action)){System.out.println("解锁");}           }}    
}

代码:https://git.oschina.net/beifang2008/DongTaiBroadCastReceiver

Demo2:

public class MainActivity extends Activity {private MyBroadcastReceiver receiver;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);Button btn = (Button) findViewById(R.id.btn);btn.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {Intent intent = new Intent("auto_finish");sendBroadcast(intent);              }});receiver = new MyBroadcastReceiver();IntentFilter filter = new IntentFilter();filter.addAction("finish");// 添加actionregisterReceiver(receiver, filter);// 注册广播接收者   }@Overrideprotected void onDestroy() {unregisterReceiver(receiver);// 取消广播接收者super.onDestroy();}// 创建广播接收者类public class MyBroadcastReceiver extends BroadcastReceiver {@Overridepublic void onReceive(Context context, Intent intent) {String action = intent.getAction();if ("finish".equals(action)) {finish();}}}
}

sendBroadcast(intent)与sendStickyBroadcast(intent)的区别?

区别主要是在动态注册广播中才有,在静态注册中是一样的。
sendBroadcast(intent):当发送广播在注册广播前时,接收者是接收不到广播的。
sendStickyBroadcast(intent):当发送广播在注册广播前时,接收者是可以接收到广播的。sendStickyBroadcast发出的最后一个Intent会被保留,下次当Recevier处于活跃的 时候,又会接受到它。

Demo:https://git.oschina.net/beifang2008/DongTaiBroadCastReceiver2

LocalBroadcastManager

Android高效安全的本地广播LocalBroadcast完全解析
LocalBroadcastManager只可以动态注册广播。

获取LocalBroadcastManager对象,单利模式

LocalBroadcastManager broadcastManager = LocalBroadcastManager.getInstance(this);

设置InentFilter,intentFilter和intent都必须设置action

IntentFilter filter = new IntentFilter();
filter.addAction(localAction);

注册

broadcastManager.registerReceiver(receiver, filter);

发送Broadcast

Intent intent = new Intent(localAction);
broadcastManager.sendBroadcast(intent);

取消注册

broadcastManager.unregisterReceiver(receiver);

android.support.v4.content.LocalBroadcastManager工具类,可以实现在自己的进程内进行局部广播发送与注册,使用它比直接通过sendBroadcast(Intent)发送系统全局广播有以下几个好处

  • 因广播数据在本应用范围内传播,你不用担心隐私数据泄露的问题。
  • 不用担心别的应用伪造广播,造成安全隐患。
  • 相比在系统内发送全局广播,它更高效。

这篇关于四大组件:BroadCastReceiver广播的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/654842

相关文章

Vue中组件之间传值的六种方式(完整版)

《Vue中组件之间传值的六种方式(完整版)》组件是vue.js最强大的功能之一,而组件实例的作用域是相互独立的,这就意味着不同组件之间的数据无法相互引用,针对不同的使用场景,如何选择行之有效的通信方式... 目录前言方法一、props/$emit1.父组件向子组件传值2.子组件向父组件传值(通过事件形式)方

Spring组件初始化扩展点BeanPostProcessor的作用详解

《Spring组件初始化扩展点BeanPostProcessor的作用详解》本文通过实战案例和常见应用场景详细介绍了BeanPostProcessor的使用,并强调了其在Spring扩展中的重要性,感... 目录一、概述二、BeanPostProcessor的作用三、核心方法解析1、postProcessB

kotlin中的行为组件及高级用法

《kotlin中的行为组件及高级用法》Jetpack中的四大行为组件:WorkManager、DataBinding、Coroutines和Lifecycle,分别解决了后台任务调度、数据驱动UI、异... 目录WorkManager工作原理最佳实践Data Binding工作原理进阶技巧Coroutine

Vue项目的甘特图组件之dhtmlx-gantt使用教程和实现效果展示(推荐)

《Vue项目的甘特图组件之dhtmlx-gantt使用教程和实现效果展示(推荐)》文章介绍了如何使用dhtmlx-gantt组件来实现公司的甘特图需求,并提供了一个简单的Vue组件示例,文章还分享了一... 目录一、首先 npm 安装插件二、创建一个vue组件三、业务页面内 引用自定义组件:四、dhtmlx

Vue ElementUI中Upload组件批量上传的实现代码

《VueElementUI中Upload组件批量上传的实现代码》ElementUI中Upload组件批量上传通过获取upload组件的DOM、文件、上传地址和数据,封装uploadFiles方法,使... ElementUI中Upload组件如何批量上传首先就是upload组件 <el-upl

Vue3中的动态组件详解

《Vue3中的动态组件详解》本文介绍了Vue3中的动态组件,通过`component:is=动态组件名或组件对象/component`来实现根据条件动态渲染不同的组件,此外,还提到了使用`markRa... 目录vue3动态组件动态组件的基本使用第一种写法第二种写法性能优化解决方法总结Vue3动态组件动态

四种Flutter子页面向父组件传递数据的方法介绍

《四种Flutter子页面向父组件传递数据的方法介绍》在Flutter中,如果父组件需要调用子组件的方法,可以通过常用的四种方式实现,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录方法 1:使用 GlobalKey 和 State 调用子组件方法方法 2:通过回调函数(Callb

Vue项目中Element UI组件未注册的问题原因及解决方法

《Vue项目中ElementUI组件未注册的问题原因及解决方法》在Vue项目中使用ElementUI组件库时,开发者可能会遇到一些常见问题,例如组件未正确注册导致的警告或错误,本文将详细探讨这些问题... 目录引言一、问题背景1.1 错误信息分析1.2 问题原因二、解决方法2.1 全局引入 Element

vue解决子组件样式覆盖问题scoped deep

《vue解决子组件样式覆盖问题scopeddeep》文章主要介绍了在Vue项目中处理全局样式和局部样式的方法,包括使用scoped属性和深度选择器(/deep/)来覆盖子组件的样式,作者建议所有组件... 目录前言scoped分析deep分析使用总结所有组件必须加scoped父组件覆盖子组件使用deep前言

基于Qt Qml实现时间轴组件

《基于QtQml实现时间轴组件》时间轴组件是现代用户界面中常见的元素,用于按时间顺序展示事件,本文主要为大家详细介绍了如何使用Qml实现一个简单的时间轴组件,需要的可以参考下... 目录写在前面效果图组件概述实现细节1. 组件结构2. 属性定义3. 数据模型4. 事件项的添加和排序5. 事件项的渲染如何使用