探秘安卓广播:揭秘Android广播机制的神奇之处

news2024/12/23 0:37:04

壹 广播机制

  • Android中的广播(Broadcast)机制用于进程/线程间通信,该机制使用了观察者模式。
  • 观察者模式是一种软件设计模式,该模式是基于消息的发布/订阅事件模型,该模型中的消息发布者是广播机制中的广播发送者,消息订阅者是广播机制中的广播接收者,广播机制的具体实现流程,如下图所示。
    在这里插入图片描述
  1. 广播接收者通过Binder机制在AMS(Activity Manager Service)中进行注册
  2. 广播发送者通过Binder机制向AMS发送广播。
  3. AMS查找符合相应条件(IntentFilter/Permission)的广播接收者(BroadcastReceiver),将广播发送到相应的消息循环队列中。
  4. 执行消息循环时获取到此广播,会回调广播接收者(BroadcastReceiver)中的onReceive()方法并在该方法中进行相关处理。
  • Android系统中内置了很多广播,例如手机开机完成、电池电量不足时都会发送一条广播。为了监听来自系统或者应用程序的广播事件,Android系统提供了BroadcastReceiver(广播接收者)组件。
    在这里插入图片描述
  • 广播接收者的创建,具体如下:在应用程序的包中创建一个类继承BroadcastReceiver并重写onReceive()方法来实现的。
public class MyReceiver extends BroadcastReceiver {
    public MyReceiver() {
    }
    //在该方法中实现广播接收者的相关操作
    @Override
     public void onReceive (Context context, Intent intent) {
          throw new UnsupportedOperationException("Not yet implemented");
     }
}

1.1 动态注册

  • 创建完广播接收者之后还需要对广播接收者进行注册才可以接收广播[一般在MainActivity中注册]
  • 动态注册广播,动态注册的广播接收者是否被注销依赖于注册广播的组件,当组件销毁时,广播接收者也随之被注销。
protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState); 
       //实例化广播接收者
       MyReceiver receiver = new MyReceiver();
       //实例化过滤器并设置要过滤的广播
       String action = "android.provider.Telephony.SMS_RECEIVED";
       IntentFilter intentFilter = new IntentFilter();
       intentFilter.addAction(action);
       registerReceiver(receiver,intentfilter);//注册广播
}
protected void onDestroy() {
       super.onDestroy();
       //当Activity销毁时,取消注册
       unregisterReceiver(receiver);
}

1.2 静态注册

  • 静态注册广播,在小于Android8.0的设备上,只要设备处于开启状态,广播接收者就能接收到广播。
<?xml version="1.0" encoding="utf-8"?>
<manifest ……….  >
     <application ……… > 
         <receiver
                 android:name=".MyReceiver"
                 android:enabled="true"
                 android:exported="true" >
         </receiver> 
    </application>
 </manifest>

1.3 自定义广播

  • 当系统提供的广播不能满足实际需求时,可以自定义广播,同时需要编写对应的广播接收者。
    在这里插入图片描述
  • 当自定义广播发送消息时,会储存到公共消息区中,而公共消息区中如果存在对应的广播接收者,就会及时的接收这条信息。

贰 广播的类型

Android系统提供了两种广播类型,有序广播和无序广播,开发者可根据需求为程序设置不同的广播类型。

  1. 无序广播:无序广播是完全异步执行,发送广播时所有监听这个广播的广播接收者都会接收到此消息,但接收的顺序不确定。
    在这里插入图片描述
  2. 有序广播:按照接收者的优先级接收,只有一个广播接收者能接收消息,在此广播接收者中逻辑执行完毕后,才会继续传递。
    在这里插入图片描述
  3. 局部广播
  • 使用LocalBroadcastManager.sendBroadcast方法在同sender同一个app内部发送广播。 如果你不需要在不同的app之间发送广播,使用局部广播。这种广播的实现更加高效,不需要进程间通信,也不需要担心安全限制。

叁 优先级

  • 数值越大,优先级越高。如果两个广播接收者的优先级相同,则先注册的广播接收者优先级高。
//动态注册MyReceiver广播
MyReceiver  one = new MyReceiver ();
IntentFilter filter = new IntentFilter();
filter.setPriority(1000); 
filter.addAction("Intercept_Stitch");
registerReceiver(one,filter);

肆 有序广播

有序广播,它的广播方法有两个:

  1. 第一个方法的形式为:

    sendOrderedBroadcast(Intent, String)
    
    • 第二个参数可以省略,如果省略,表示广播接收者无需某种权限即可接收,如果不省略,则广播接收者必须具有第二个参数所指定的权限方可接收该广播。第一个参数值intent中包含广播接收者的意图过滤器中对应的action。
  2. 第二个方法的形式为:

    public abstract void sendOrderedBroadcast (Intent intent, String receiverPermission, BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, String initialData, Bundle initialExtras)
    
    • 该方法的前两个参数同上个方法,第三个参数表示最后一个必须接收到广播的接收者,第四个参数用于指定调度第三个接收者的线程,如果为null,表示所在上下文的主线程;
      initialCode 结果码的初始值,通常为Activity.RESULT_OK.
      initialData 结果数据的初始值,通常为null.
      initialExtras 附加结果的初始值,通常为null.

4.1 中断广播

  • 广播接收者如果希望中断广播,可以调用abortBroadcast ()来标记所接收的有序广播不再传递下去,如果sendOrderedBroadcast中指定了最后接收者的话,该广播还会再传递给该最后接收者。
  • 如果想取消中断广播,执行clearAbortBroadcast ()

4.2 获取结果状态和数据

通过调用getResultCode (),可以获取上一个接收者传递过来的结果码;
通过调用getResultData (),可以获取上一个接收者传递过来的结果数据,通常为null
通过调用getResultExtras (boolean makeMap),可以获取到上一个接收者传递过来的附加数据,参数如果为true,表示如果没有传递来的附加数据,会自动创建一个空的Map,参数如果为false,表示如果没有传递过来的附加数据,只返回null,不会创建新的Map

4.3 设置结果状态和数据

通过调用setResult (int code, String data, Bundle extras),改变有序广播中的结果码、结果数据和附加结果;
通过调用setResultCode (int code)设置结果码,该参数通常为RESULT_CANCELEDRESULT_OK
通过调用setResultData (String data),改变广播的结果数据;
通过调用setResultExtras (Bundle extras)会取代广播中原有的附加数据

4.4 判断是否为有序广播

调用isOrderedBroadcast ()判断收到的广播是否是顺序广播

伍 通过权限来限制广播

  • 使用权限可以限制广播发送到某些app集合,既可以限制发送者也可以限制接收者。

5.1 发送添加权限

  • 当调用sendBroadcast(Intent, String)或者sendOrderedBroadcast(Intent, String, BroadcastReceiver, Handler, int, String, Bundle)的时候,可以指定一个权限参数。只有在manifest中已经获得该权限的接收者可以接收到该广播。
  • 例如:
    sendBroadcast(new Intent("com.example.NOTIFY"),Manifest.permission.SEND_SMS);
    
  • 为了接收该广播,接收者必须需要获取权限:
    //指定一个存在的系统权限,也可以使用<permission>自定义一个权限
    <uses-permission android:name="android.permission.SEND_SMS"/>
    
  • 注意:当app在安装到系统里的时候,自定义权限会被注册。自定义权限必须在app安装以后才能使用。

5.2 接收添加权限

  • 当注册一个广播接收器的时候,你指定了一个权限参数,( 或者使用registerReceiver(BroadcastReceiver, IntentFilter, String, Handler) 或者在 manifest的<receiver> 标签中),那么只有那些在manifest中使用<uses-permission> 来获取该权限的广播者采用向接收者发送广播意图。
  • 假设广播接收者manifest定义如下:
    <receiver android:name=".MyBroadcastReceiver"
              android:permission="android.permission.SEND_SMS">
        <intent-filter>
            <action android:name="android.intent.action.AIRPLANE_MODE"/>
        </intent-filter>
    </receiver>
    
  • 或者在MainActivity中注册广播接收者:
    IntentFilter filter = new IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED);
    registerReceiver(receiver, filter, Manifest.permission.SEND_SMS, null );
    
  • 为了向接收器发送广播,发送app必须如下获取权限:
    <uses-permission android:name="android.permission.SEND_SMS"/>
    

陆 重要题目

  1. 简述广播机制的实现过程
    在这里插入图片描述
    1. 广播接收者通过Binder机制在AMS(Activity Manager Service)中进行注册
    2. 广播发送者通过Binder机制向AMS发送广播。
    3. AMS查找符合相应条件(IntentFilter/Permission)的广播接收者(BroadcastReceiver),将广播发送到相应的消息循环队列中。
    4. 执行消息循环时获取到此广播,会回调广播接收者(BroadcastReceiver)中的onReceive()方法并在该方法中进行相关处理。
  2. 简述有序广播和无须广播的区别
    1. 发送广播时,使用的方法不同。有序广播使用sendOrderedBroadcast()发送广播,而无序广播使用sendBroadcast()方法发送广播。
    2. 广播接收者执行的顺序。
      • 有序广播的接收者是顺序执行的。有序广播按照广播接收者声明的优先级别被依次接收。当在高级别的广播接收者逻辑执行完毕之后,广播才会继续传递。当优先级相同时,先注册的广播接受者优先执行。
      • 无序广播是完全异步执行的。当发送无序广播时,所有监听这个广播的广播接收者都会接收到此广播消息,但接收和执行的顺序不确定。
    3. 拦截广播:有序广播的接收者可拦截广播。如果优先级较高的广播接收者将广播终止,那么广播将不再向后传递。而无序广播则不能被拦截。
    4. 效率:有序广播的效率比无序广播低。

  1. abortBroadcast:通过该方法可以终止有序广播
  2. 在清单文件中注册了NEW_OUTGOING_CALL,代码中获取到广播事件的方法是( ).
    A、getAction()
    B、getActionCall()
    C、getMethod()
    D、getOutCall()
  • 解析:
    • 在代码中获取广播事件的方法是使用广播接收器(BroadcastReceiver)来处理广播事件。当接收到广播事件时,广播接收器的onReceive()方法会被调用,并且可以通过Intent参数来获取广播事件的相关信息。在处理NEW_OUTGOING_CALL广播事件时,可以通过Intent的getAction()方法来获取广播事件的动作(Action)。例如:
    //通过intent.getAction()方法获取广播事件的动作,并将其与"android.intent.action.NEW_OUTGOING_CALL"进行比较,
    //以判断是否接收到了NEW_OUTGOING_CALL广播事件
    public class MyBroadcastReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if (action.equals("android.intent.action.NEW_OUTGOING_CALL")) {
                // 处理NEW_OUTGOING_CALL广播事件
            }
        }
    }
    
  1. 关于短信拦截的广播事件说法正确的是( ).
    A、监听用户的短信到来的广播事件在高版本ADT里该事件找不到了
    B、需要注册 权限
    C、在国内国外注册这样的广播事件方式不一样
    D、以上说法都正确
  2. 常驻型广播是当应用程序关闭后,如果接收到其他应用程序发出的广播,那么该程序会自动重新启动。
  3. 在清单文件中,注册广播时使用的节点是( C)。
    A、<Activity>
    B、<Broadcast>
    C、<receiver>
    D、<broadcastreceiver>
    • 在清单文件中注册广播时使用的节点是<receiver><receiver>节点用于声明一个广播接收器(BroadcastReceiver),用于接收和处理广播事件。在<receiver>节点中,可以指定广播接收器的类名、优先级、过滤器等属性。
  4. 对于一些特殊的广播事件,比如屏幕锁屏和解锁,对于这样的广播事件,需要采用动态代码的方式进行注册,在清单文件注册不生效
  5. 注册外拨电话的广播事件对应的action是android_intent.action.NEW_OUTGOING_CALL
  6. 下面关于静态注册广播接收者中Exported属性的描述,正确的是()。
    A、广播接收者是否可以由系统实例化
    B、是否接收当前程序之外的广播
    C、创建广播接收者名称
    D、以上说法都不对
  7. 代码注册广播需要调用( registerReceiver() )方法,解除广播需要调用( unrigisterReceiver() )方法
  8. 注册广播有两种方式,常驻型广播与( 非常驻型广播
    - 注册广播有两种方式,常驻型广播与非常驻型广播。
    1. 常驻型广播(Sticky Broadcast):常驻型广播是指在广播发送后,即使没有注册的广播接收器,后续注册的广播接收器也能接收到该广播。常驻型广播可以通过sendStickyBroadcast(Intent intent)方法发送。这种广播适用于需要在广播发送后,后续注册的广播接收器也能接收到广播事件的场景。
    2. 非常驻型广播(Normal Broadcast):非常驻型广播是指在广播发送后,只有已经注册的广播接收器能接收到该广播。非常驻型广播通过sendBroadcast(Intent intent)方法发送。这种广播适用于只希望已经注册的广播接收器能接收到广播事件的场景。
  • 需要注意的是,常驻型广播可能会增加系统负担,因为即使没有注册的广播接收器,系统仍然会将广播事件保存在内存中,直到有广播接收器注册为止。因此,应谨慎使用常驻型广播,避免对系统性能产生不必要的影响。
  1. 手机重启对应的广播事件是( android.intent.action.BOOT_COMPLETED
  2. 广播是一种运用在应用程序之间( 传递消息 )的机制
  3. 注册系统短信到来的广播事件需要加入的权限是( android.permission.RECEIVE_SMS

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/687147.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ajax原理是什么?如何实现?

一、是什么 AJAX全称(Async Javascript and XML) 即异步的JavaScript 和XML&#xff0c;是一种创建交互式网页应用的网页开发技术&#xff0c;可以在不重新加载整个网页的情况下&#xff0c;与服务器交换数据&#xff0c;并且更新部分网页 Ajax的原理简单来说通过XmlHttpReq…

算法——查找表

查找&#xff0c;根据一个值查找另一个值&#xff0c;value值可以是容器&#xff0c;结构&#xff0c;这样可查找的元素就更多&#xff1b; 哈希冲突&#xff1a; 主关键字&#xff1a;可以唯一的标识一个记录的关键字&#xff0c;如准考证号&#xff1b; 此关键词&#xff…

RFID微图柜的操作流程以及功能介绍

微型图书馆智能书柜是一种基于 RFID 技术的图书自助借阅延伸服务的终端设备&#xff0c;可实现 24 小时无人看守的共享的智能化设备&#xff0c;可自助借还书、自动数据记录分析、自助提醒等一体化管理服务功能。 智能书柜的操作流程 借书&#xff1a;在操作页面上选择“借书…

【好书精读】网络是怎样连接的 —— 信号在网线和集线器中传输

&#xff08; 该图由我使用 AI 绘制 &#xff09; 目录 每个包都是独立传输的 防止网线中的信号衰减很重要 “双绞”是为了抑制噪声 集线器将信号发往所有线路 每个包都是独立传输的 从计算机发送出来的网络包会通过集线器 、 路由器等设备被转发 &#xff0c; 最 终到达…

解决 CentOS/Alma 安装 libpcap-devel 报错:No match for argument: libpcap-devel

环境&#xff1a;Alma 8.5、Centos 7.x 解决方案 Linux 安装软件的时候&#xff0c;需要 libpcap-devel 这个组件&#xff0c;执行命令&#xff1a;yum install libpcap-devel &#xff0c;然后报错如下&#xff1a; Last metadata expiration check: 0:05:24 ago on Mon 12…

5.3 Linux目录配置

5.3.1 Linux目录配置的依据--FHS 根据FHS的标准文件指出&#xff0c;他们的主要目的是希望让使用者可以了解到已安装软件通常放置于那个目录下&#xff0c; 所以他们希望独立的软件开发商、操作系统制作者、以及想要维护系统的使用者&#xff0c;都能够遵循FHS的标准。 也就是…

ECS 简略版说明五:Baking and entity scenes

目录 Baking and entity scenes Creating and editing sub scenes Accessing data in a baker Loading and unloading entity scenes Baking and entity scenes Baking 是一个把 sub scenes 转变成 entity scenes 的过程&#xff0c;使用 bakers和 baking systems: A sub …

数据中心供配电监控系统解决方案介绍 安科瑞 许敏

摘 要&#xff1a;供配电系统始终是数据中心比较重要的内容&#xff0c;在供配电系统能够得到平稳安全的运行的时候&#xff0c;才能够促使数据中心的相关设备具有比较可靠的动力源泉。在新型数据中心不断发展的过程中&#xff0c;其功率密度也相对比较大&#xff0c;对供电的要…

销售人员如何通过CRM系统提升业绩

面对日趋激烈的竞争&#xff0c;销售人员的压力也日益剧增。尤其伴随流量红利的消失&#xff0c;越来越多的企业开始借助数字化工具赋能销售人员&#xff0c;希望通过工具的加持&#xff0c;实现销售人才和销售工具的“人器合一”&#xff0c;最终助力企业业绩的增长。 在市场有…

专访虎牙直播毛茂德 | 看互联网老兵如何用技术驱动效能提升?

引言 作为一位经历了互联网、移动互联网阶段的老兵&#xff0c;毛茂德老师一路走来&#xff0c;始终保持自己的技术初心&#xff0c;不断探索未知领域的宽度&#xff0c;进入虎牙直播后&#xff0c;他积极推动虎牙拥抱云原生&#xff0c;进行业务创新&#xff0c;同时他也发挥技…

1. MongoDB快速实战与基本原理

分布式缓存技术Redis 1. MongoDB介绍1.1 什么是MongoDB1.2 MongoDB vs 关系型数据库1.3 MongoDB的技术优势1.4 MongoDB的应用场景 2. 2.MongoDB快速开始2.1 linux安装MorgoDB 本文是按照自己的理解进行笔记总结&#xff0c;如有不正确的地方&#xff0c;还望大佬多多指点纠正&a…

基于SpringBoot+mybatis+layui就业管理系统设计和实现

基于SpringBootmybatislayui就业管理系统设计和实现 博主介绍&#xff1a;5年java开发经验&#xff0c;专注Java开发、定制、远程、指导等,csdn特邀作者、专注于Java技术领域 作者主页 超级帅帅吴 Java项目精品实战案例《500套》 欢迎点赞 收藏 ⭐留言 文末获取源码联系方式 文…

【STL】容器适配器

放在专栏【C知识总结】&#xff0c;会持续更新&#xff0c;期待支持 1、什么是适配器&#xff1f; 我们生活中就存在大量的适配器&#xff0c;最常见的莫过于我们常见的电源适配器&#xff0c;它的作用就是将交流电源转化为直流电源进行输出&#xff0c;可以说电源适配器在电流…

618复盘:爆款存当下,蓝海寄未来

价格&#xff0c;贵必赔。优惠&#xff0c;直接减。 号称史上最内卷的一届618在一家又一家号称史上最大补贴的狂欢下&#xff0c;落幕得悄无声息&#xff0c;各大平台默契地都没有公布具体GMV。 这样的结局似乎已有预见。此前有媒体援引浙江大学经济学院教授叶建亮的说法&…

从小白到大神之路之学习运维第47天---第三阶段----Iptables、路由表的配置、Linux下创建虚拟IP

第三阶段基础 时 间&#xff1a;2023年6月26日 参加人&#xff1a;全班人员 内 容&#xff1a; Iptables、路由表的配置、Linux下创建虚拟IP 目录 Iptables 1. 查看 iptables 设置&#xff1a; 2. 开启全部流量&#xff1a; 3. 关闭全部流量&#xff1a; 4. 允许某…

【Jmeter教程】_事务控制器

目录 一、添加事务控制器 二、事务控制器参数说明 三、运用事务控制器 统计性能测试结果一定会关注TPS&#xff0c;TPS表示每秒处理事务数&#xff0c;JMeter默认每个事务对应一个请求。我们可以用逻辑控制器中的事务控制器将多个请求统计为一个事务。 一、添加事务控制器 …

分享 5 个你可能不知道的前端小技巧

大家都知道&#xff0c;如今前端开发是一个充满活力的领域&#xff0c;每天都会涌现出新的技术和最佳实践。 作为前端开发人员&#xff0c;如果你真的想创建引人入胜、直观且响应迅速的用户界面&#xff0c;就必须时刻跟进最新的趋势和技术。 作为前端开发人员&#xff0c;我们…

不止10倍提速!PCIe EtherCAT实时运动控制卡XPCIE1032H 等您评测!

在高速高精运动控制领域&#xff0c;数据交互的快慢对产线的生产效率起着重要作用。提升数据交互速度能够实时地接收和处理大量的传感器监控运行数据、运动指令和反馈信息&#xff0c;从而实现更精确的运动控制、速度调整和轨迹规划&#xff0c;进而提高系统的响应时间和稳定性…

LDR6023C 专门为USB-C接口无线领夹式麦克风方案打造

推出领夹式无线麦克风方案&#xff0c;专门为USB-C接口手机打造&#xff0c;兼容性非常的游戏&#xff0c;可让手机同时一边充电一边传输数据。 随着直播平台的兴起&#xff0c;网络直播越来越火&#xff0c; 领夹式直播麦克风得到广泛应用&#xff0c; 现在手机&#xff0c;电…

海睿思分享 | 浅谈企业数据质量问题

一、数据质量问题场景 在日常工作中&#xff0c;业务领导经常通过BI系统来了解各项业务的业绩情况。倘若某天&#xff0c;他打开某张核心报表&#xff0c;发现当日某个区域的数据一直是空白的。BI开发人员经过几个小时的排查分析&#xff0c;发现是当日该区域的销售数据存在产…