BroadcastReceiver巩固学习

第一篇文。

一、官方文档翻译

原文链接(请科学上网 _ )

BroadcastReceiver是一个用于接收从sendBroadcast()发出的intent意图的基础类。

如果你不需要通过应用发送广播,那么请考虑使用LocalBroadcastManager来代替下面将介绍的更加通用的方法与此类结合使用。这将会使你的代码更加高效(没有跨进程交流的需求)并且让你无需考虑有关其他应用能够接收和发送你的广播所产生的安全问题。

你可以通过 [Context.registerReceiver()](https://developer.android.com/reference/android/content/Context.html#registerReceiver(android.content.BroadcastReceiver, android.content.IntentFilter))动态注册BroadcastReceiver或者在AndroidManifest.xml中通过 [<receiver>]
(https://developer.android.com/reference/android/R.styleable.html#AndroidManifestReceiver)标签静态注册。

注意:如果你在 Activity.onResume()中注册广播接收器,那就应该在Activity.onPause()中去解除注册。(不要在“paused”之后再去接收intent意图,这将减少不必要的系统开销)。不要在 Activity.onSaveInstanceState()中解除BroadcastResceiver的注册,因为当用户会退到历史栈(作者注:即activity的pop操作,例:a->b,b->a(由b返回a)此处的b->a即为pop操作)时,不会执行该方法。

以下是两个主要的能够被接收的广播类型:

  • ** 普通广播 (由 Context.sendBroadcast发出)异步发出。所有广播接收器都没有被定义接收广播的顺序,一般在同一时间接收广播。这样做更加高效,但是这也意味着广播接收者无法接收广播(作者注:被其它接收器)的处理结果或者阻断广播的传递。

  • ** 有序广播 (由 [Context.sendOrderedBroadcast](https://developer.android.com/reference/android/content/Context.html#sendOrderedBroadcast(android.content.Intent, java.lang.String))发出)每次只发送给一个广播接收器。当每个广播接收器依次执行时,它可以向下一个广播接收器传播(作者注:由该前一个广播接收器修改的)结果,或者它甚至可以阻断该广播,另该广播不能被下一个广播接收器接收到。有序广播的传播顺序由意图过滤器的 android:priority属性控制(作者注:例<intent-filter android:priority="100">);定义了同一优先级的广播接收器接收顺序随机。

即使是普通广播,系统在某些情况下也只会没辞职将它发送给一个广播接收器,尤其是对于那些可能创建新进程的接收者,为了防止创建新进程造成的系统过载,每次只有一个接收器可以运行。但是,在这种情况下,由于无序语法的定义:这些广播接收器依然不能返回它们的结果或者阻断广播的传播。

请注意,尽管这里的Intent意图类用于发送或者接收广播,但是它与在Context.startActivity()中使用的郁郁开启Activity的Intent的原理是完全不同的。广播接收器是没有办法查看或者捕捉用于startActivity()的Intent的。同理,当你广播一个意图,你也不会找到或者打开Activity。这两种操作的语义是不同的:开启Activity的Intent是修改用户实时交互界面的前台操作;发送广播的Intent是用户通常不会注意到的后台操作。

广播接收者类(由manifest中的 <receiver>标签注册的)是应用生命全周期的重要部分。

这里的主题:

  1. 安全
  2. 广播接收者生命周期
  3. 进程生命周期

开发人员导读

要了解有关如何接收或解析intents,请阅读 Intents and Intent Filters 开发人员导读。

安全

Context接口结合和使用的广播接收器从本质上来说是一个跨应用的设备,所以你必须得防止其他应用滥用你的接收器功能。以下是要考虑的几点:

  • Intent类的命名空间是全局的。请保证给Intent添加的action的名字以及其他字符串是被定义在你的私人命名空间的,否则你将可能不小心与其他应用产生冲突。
  • 当你使用 [registerReceiver(BroadcastReceiver, IntentFilter)](https://developer.android.com/reference/android/content/Context.html#registerReceiver(android.content.BroadcastReceiver, android.content.IntentFilter))注册广播接收器时,其他应用也可以给它发送广播。你可以通过以下描述的权限来控制谁可以给它发送广播。
  • 当你在应用的清单文件中注册广播接收器,并且为它添加了 intent-filters* (作者注:意图过滤器) *,任何其他应用还是都可以忽视过滤器给它发送广播。为了阻止其它应用发送,可以使用android:exported="false"属性使它变的不可达。
  • 当你使用sendBroadcast(Intent)或相关方法时,通常其他应用也可以接收这些广播。你可以通过以下描述的权限控制它。或者,在 ICE_CREAM_SANDWICH*(作者注:Android 4.0.) *下,你可以通过Intent.setPackage安全的限制广播仅发送给一个应用。

在使用LocalBroadcastManager时,所有这些问题都不会出现,被发送的intents不会被发送到当前应用外。

访问权限可以在广播发送者或者接收者中设置。

在发送时设置访问权限,你需要提供一个非空的权限给[sendBroadcast(Intent, String)](https://developer.android.com/reference/android/content/Context.html#sendBroadcast(android.content.Intent, java.lang.String))
或 [sendOrderedBroadcast(Intent, String, BroadcastReceiver, android.os.Handler, int, String, Bundle)](https://developer.android.com/reference/android/content/Context.html#sendOrderedBroadcast(android.content.Intent, java.lang.String, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle))* (作者注:关于自定义权限参考) *。只有当广播接收器具有这个权限(通过 <uses-permission>
标签在AndroidManifest.xml中申明)才可以接收相应广播。

在接收设置权限,你需要在注册接收器是提供一个非空的权限,无论是通过 [registerReceiver(BroadcastReceiver, IntentFilter, String, android.os.Handler)](https://developer.android.com/reference/android/content/Context.html#registerReceiver(android.content.BroadcastReceiver, android.content.IntentFilter, java.lang.String, android.os.Handler))注册还是通过<receiver>
标签在AndroidManifest.xml静态注册。只有当广播具有这些权限(通过 <uses-permission>标签在AndroidManifest.xml中声明)才可以发送给接收者。

更多有关权限和安全的信息请参考 Security and Permissions 文档。

广播接收者生命周期

广播接收器对象仅当调用 [onReceive(Context, Intent)](https://developer.android.com/reference/android/content/BroadcastReceiver.html#onReceive(android.content.Context, android.content.Intent))时有效。一旦这个方法return了,系统就认为这个对象应该被结束掉并且不再有效。

这对于在[onReceive(Context, Intent)](https://developer.android.com/reference/android/content/BroadcastReceiver.html#onReceive(android.content.Context, android.content.Intent))中的具体实现就是十分重要的一点:涉及到要求异步操作的代码不应该在此处编写,因为为了处理异步操作,你需要获取异步操作的结果,但是在那时广播接收器可能已经不再有效,并且系统可以在异步操作结束前杀死该进程。

特别是你不应该在广播接收器中显示对话框或绑定服务。对于前者,你应该 NotificationManagerAPI来代替使用。对于后者,你应该使用Context.startService()来发送命令给服务。

进程生命周期

一个正在运行广播接收器的进程(意思是,正在执行[onReceive(Context, Intent)](https://developer.android.com/reference/android/content/BroadcastReceiver.html#onReceive(android.content.Context, android.content.Intent))方法)被认为是前台进程,除非是在极端内存压力的情况下,否则该进程将被系统保持运行状态。

一旦从onReceive()返回了,那么广播接收器不再有效,它的宿主进程的级别将降为与其它应用程序组件相同。这十分重要,因为一旦该进程仅仅运行了一个广播接收器(这是一种情况:一个用户从来没有交互过的应用),然后在onReceive()方法返回时,系统将该进程视为空进程并且为了给其他更重要的进程提供更多资源将该进程杀死。

这意味着对于耗时操作,你应该使用 Service结合广播接收器使用,来保证宿主进程在你的操作全程保持有效。

*(作者注:第一次翻译,有错误的话希望多多提点,多包容咯) *

<br /><br />

二、总结

(一)静态注册和动态注册的特点

  1. 静态注册:无论宿主应用程序是否处于活动状态,都会进行广播监听,比如某个程序时监听内存的使用情况的,当在手机上安装好后,不管该应用程序是处于什么状态,都会执行改监听方法中的内容。
  2. 动态注册:在代码中进行注册后,当应用程序关闭后,就不再进行监听。
    参考链接

(二)动态注册与解除注册的时机

动态注册的[Context.registerReceiver()](https://developer.android.com/reference/android/content/Context.html#registerReceiver(android.content.BroadcastReceiver, android.content.IntentFilter))最好是在onCreate()中执行,解除注册的unregisterReceiver(BroadcastReceiver receiver)在onDestroy()中执行。
原因:android 中的注销、内存回收、View视图的回收,最好都在onDestroy中进行,在onStop、onPause中有的情况下会有异常。

(三)关于广播的自定义权限的使用

参考

(四)广播的生命周期

** 广播接收者被认为仅当它执行这个方法时是活跃的。当onReceive()返回后,它是不活跃的。**
有一个活跃的广播接收者的进程是受保护的,不会被杀死。但是当别的进程需要被占用的内存时,系统可以在任何时候杀死仅有不活跃组件的进程。
这带来一个问题,当一个广播消息的响应费时的,应该在独立的线程中做这些事,远离用户界面其它组件运行的主线程。如果onReceive()衍生线程然后返回,整个进程,包括新的线程,被判定为不活跃的(除非进程中的其它应用程序组件是活跃的),将使它处于被杀的危机。解决这个问题的方法是onReceive()
启动一个服务,让服务做这个工作
,因此系统知道进程中有活跃的工作在做。(进程升级为服务进程,Android进程回收优先级参考

(五)广播的应用

  1. 自定义广播接收器子类,实现onReceive()方法
  2. 注册广播:静态注册或动态注册
  3. 若为动态注册,则需要解除注册
    实例参考跳转
    <br />

***感谢各位前辈的分享精神 ***

参考链接汇总:
BroadcastReceiver官方文档
BroadcastReceiver自定义权限定义及使用
Android进程回收优先级
BroadcastReceiver应用实例

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容

  • 本文转载自http://www.cnblogs.com/lwbqqyumidi/p/4168017.html 1....
    Ernest_Chang阅读 701评论 0 3
  • 广播接收器 是Android的四大组件之一,可见广播在Android中的重要性; 1. 什么是广播? 广播(Bro...
    Lost_Robot阅读 1,929评论 2 10
  • 前言:本文所写的是博主的个人见解,如有错误或者不恰当之处,欢迎私信博主,加以改正! 原文链接,demo链接 广播简...
    PassersHowe阅读 3,436评论 0 9
  • 现实中的广播:电台为了传达一些消息而发送广播,通过广播携带要传达的消息,群众只要买一个收音机,就可以收到广播了。 ...
    stevewang阅读 4,227评论 0 8
  • 1.Android广播机制概述 Android广播分为两个方面:广播发送者和广播接收者,通常情况下,Broadca...
    IT小魔女的故事阅读 548评论 0 2