原文:http://aoandroid.com/node/1414

最近,Android官方开发员博客(Developers Blog)登载了Google巴西分布的一名工程师(
Belo Horizonte )的文章,介绍了正确使用Broadcast的概念和实例分析。该文章在概念上纠正了很多开发人员对Broadcast处理中存在的严重问题,并指出这反映了开发文档存在缺陷,没有解释清楚。

Broadcast是Android的一个很有用的概念。当系统产生某些事件的时候,apps可以对某些事件(ACTION)注册(register)后,通过BroadcastReceiver捕捉到这些Broadcasts,从而获得一些很重要的系统信息。电池状态就是一个例子,比如,ACTION_BATTERY_LOW。

Belo注意到有些开发人员没有使用正确方法调用BroadcastReveiver。比较有代表性的概念混淆是

Not ordered 相对于 Ordered Broadcasts

在Not-ordered模式,系统的Broadcasts是同时发布出来,所有receiver都可以得到该事件信息,互相并不影响。即,一个receiver不能影响其它receivers是否能获得该事件信息。上面电池的 ACTION_BATTERY_LOW 就是属于not-ordered事件。

在ordered模式
,broadcasts是通过优先设置传达给不同receivers的,优先度在AndroidManifest文件中通过android:priority的intent-filter设置控制的。某个receiver可以通过BroadcastReceiver取消broadcast,取消后,比它优先度底的receivers将不再能得到该broadcast。一个典型的例子是,ACTION_NEW_OUTGOING_CALL。
 
每当用户拨打电话的时候,系统会发布(broadcast)这个 ACTION_NEW_OUTGOING_CALL 的事件。由于这是个ordered broadcast,app的不同receiver可以对它进行必要的控制。Belo给出一段暗含问题的代码
(注意,CallReceiver 必须首先在AndroidManifest里面关联ACTION_NEW_OUTGOING_CALL)

public class CallReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { // Original phone number is in the EXTRA_PHONE_NUMBER Intent extra. String phoneNumber = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER); if (shouldCancel(phoneNumber)) { // Cancel our call. setResultData(null); } else { // Use rewritten number as the result data. setResultData(reformatNumber(phoneNumber)); } }

这段代码试图在获得
ACTION_NEW_OUTGOING_CALL后根据条件,或者拒绝拨打电话,或者让用户修改电话号码。

但是,只有在没有其它具备更高优先度的Receiver的时候,这段代码才会如预期的正确执行。如果有一个更高优先的receiver也关联了ACTION_NEW_OUTGOING_CALL,并且先于这段代码执行了,那么,有可能他们会用一样的原始号码,而没有正确的使用修改后的号码。

正确的做法应该是如下列代码那样:

public class CallReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { // Try to read the phone number from previous receivers. String phoneNumber = getResultData(); if (phoneNumber == null) { // We could not find any previous data. Use the original phone number in this case. phoneNumber = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER); } if (shouldCancel(phoneNumber)) { // Cancel our call. setResultData(null); } else { // Use rewritten number as the result data. setResultData(reformatNumber(phoneNumber)); } }

这段代码事先判断了是否有另外receiver可能已经生成了一个拨号号码,没有的话,才调用intent extra的
EXTRA_PHONE_NUMBER。

这个问题有多严重?

Belo声称,很多apps被发现,使用priority 0的NEW_OUTGOING_CALL的receivers,所有这些receivers都如上述第一个代码例子那样忽略了可能的高优先receivers已经先期执行,并同样关联了NEW_OUTGOING_CALL。当然,你也可以把所有关联了NEW_OUTGOING_CALL的receivers都设在priority 0上,但是这又违反了Android拨打电话的代码处理原则,如果不能访问这个链接,可以参考SDK带的文档。

该处理原则是:

‘为了保持一致性,任何意在阻止向外拨打电话的receiver必须设0优先 (priority 0),以确保该receiver获得最后输入的电话号码。任何意在修改拨打号码的receiver应该设正数优先度,即大于零的正数。负数优先度是给系统保留的,任何apps用负数优先度可能引发问题’

Belo的结论是,很多应用软件存在这个问题,呼吁大家抓紧检查,即时解决这类问题,确保Android应用软件的整体质量。

正确处理Ordered Broadcasts相关推荐

  1. 有序广播Ordered broadcasts的使用

    给多个接受者发送广播 logcat中显示: MainActivity.java中注册button,添加过滤器. 发送信息用putExtra. 定义广播声明一个类Broadcast1.java,Broa ...

  2. 为什么说“仁者不忧”?

    子曰:"知者不惑,仁者不忧,勇者不惧." 智(知:通"智")者不惑,好理解,智者从不停止学习,不断更新自己的认知,对世界有一个清醒的认识:勇者不惧,好理解,勇者 ...

  3. Android10.0 四大组件与进程启动间关系

    原文地址:https://skytoby.github.io/2019/Android%E5%9B%9B%E5%A4%A7%E7%BB%84%E4%BB%B6%E4%B8%8E%E8%BF%9B%E7 ...

  4. Android日志[进阶篇]五-阅读错误报告

    Android日志[进阶篇]一-使用 Logcat 写入和查看日志 Android日志[进阶篇]二-分析堆栈轨迹(调试和外部堆栈) Android日志[进阶篇]三-Logcat命令行工具 Androi ...

  5. android学习笔记1

    adb 常用命令 adb device  adb kill-server adb start-server adb install adb uninstall adb pull  adb push  ...

  6. Android - Broadcast

    10s执行不完就ANR异常. 一.概念 Broadcast运行在主线程,使用了观察者模式,基于消息的发布/订阅事件模型,将发送者和接收者解耦使得方便集成更易扩展. 全局广播 APP ↔ 系统 像电量低 ...

  7. Android开发关键知识点讲解

    有下载:http://download.csdn.net/detail/zl594389970/6281471 Android应用程序架构 src/  java原代码存放目录 gen/ 自动生成目录 ...

  8. Android Activity的启动流程分析:以Launcher启动一个Activity为例,分析应用进程的创建、Activity的启动,以及他们和AMS之间的交互

    文章目录 一. Step1 - Step 11:Launcher通过Binder进程间通信机制通知ActivityManagerService,它要启动一个Activity: Step 1. Laun ...

  9. Instrumentation框架分析及其使用

    本文旨在从Android系统源码出发,简单梳理Instrumentation框架的行为及逻辑结构,供有兴趣的同学一起学习 从am instrument谈起 am instrument命令的执行 我们知 ...

最新文章

  1. @service注解_Spring 中 @Component、@Service 等注解如何被解析的
  2. 查找、下载基因序列的方法
  3. UNIX系统编程(一)
  4. MySQL exists后面的子查询使用
  5. 禁用Zuul的过滤器
  6. 树的同构(c语言静态链表实现)
  7. 《走遍中国》珍藏版(六)
  8. 抽象工厂模式 -- 大话设计模式
  9. sql server 内存_SQL Server内存性能指标–第3部分– SQL Server Buffer Manager指标和内存计数器
  10. 解决IE9下JQuery的ajax失效的问题
  11. 分布式为什么使用python
  12. C语言入门了解篇—C语言编译流程
  13. 我的世界php motd,ColorMOTD 彩色字体插件 | 我的世界 | MC世界侠
  14. PHP7函数大全(4553个函数)
  15. OCR开源代码库介绍
  16. 计算机主机接口有哪些,主机接口有哪些
  17. CapstoneCS5263|DP转HDMI 4K60HZ方案|替代PS176芯片
  18. 张飞硬件90天学习笔记——第01天个人记录,完整请看我的个人简介/主页
  19. 登陆器生成登陆器不显示服务器列表,GeeM2单机登录器读取不到列表怎么办?
  20. 超文本传输协议 - 白话篇

热门文章

  1. 如何免费开通微信公众号留言功能(上)
  2. 2022-2027年中国农村网络零售行业市场深度分析及投资战略规划报告
  3. 声卡是组成多媒体电脑必不可少的
  4. 03 # 网页元素的属性
  5. 2005年乔布斯stanford演讲全文
  6. str[]与*str的区别
  7. 用户行为分析面面观(之一)-----用户行为研究体系 + 特征1:差异性
  8. 计算机编程语言排行榜—TIOBE世界编程语言排行榜(2020年11月份最新版)
  9. ubuntu卡在Started gnome...上的问题
  10. 文本溢出及其在angular中失效的bug