安卓开发文档翻译:BroadcastReceiver,BroadcastReceiver
|
↳ |
android.content.BroadcastReceiver |
这是一个基类,继承这个基类的那些代码将能够接收到由sendBroadcast()发送出来的意图。
如果 妳不需要向其它应用程序发送广播的话,那么,可考虑将这个类与 LocalBroadcastManager 配套使用 , 而不是使用下文将要说到的那些更通用的工具。 这会具有 好得多的性能(因为 不需要进行进程间通信 ) ,并且 , 妳也不需要考虑安全相关的因素:担心其它 的应用程序接收到妳的广播或者伪造妳的广播并且发送出来。
妳可以使用 Context.registerReceiver() 来动态地将这个类的某个实例注册到广播系统中,或者, 在 AndroidManifest.xml 文件中使用 <receiver> 标记来静态地注册一个广播接收器。
注意 : 如果 妳是在 Activity.onResume() 方法中注册的广播接收器,那么,妳应当在 Activity.onPause() 方法中解除注册。 ( 这样,在被暂停时,妳就不会接收到广播意图,同时也能省去系统中不必要的开销 ) 。 不要在 Activity.onSaveInstanceState() 方法中解除注册,因为 ,当用户按后退键时,这个方法不会被调用。
主要有两种可被接收的广播:
•. 普通广播 (使用 Context.sendBroadcast 来发送 ) 是完全异步的。 该广播的所有接收器是按照一个不确定的顺序来运行的,一般来说是同时运行的。 这样更有效率,但同时也意味着,接收 器不能使用此文中提到的结果访问及终止广播接口。
•. 有序广播 (使用 Context.sendOrderedBroadcast 来发送 ) 同一时刻只会被传递给一个接收器。 每个接收器按顺序运行,在运行过程中,它可以向下一个接收器传递一个结果信息,或者也可以完全终止掉该广播,使得其它接收器无法接收到该广播。 可使用对应的意图过滤器的 android:priority 属性来控制各个接收器运行的顺序;具有相同优先 级的接收器会按照随机顺序来运行。
即使是对于普通广播,在某些情况下,系统也可能会将该广播按照每次一个接收器的方式来传递。尤其是,对于那些可能需要创建进程的接收器,每次只会被执行一个,以免系统因为大量新进程而超载。但是,在这种情况下,仍然是“无序”广播的语义起作用的:这些接收器仍然无法返回结果,也无法终止广播。
注意 ,尽管我们使用了 Intent (意图)类来发送及接收广播,但是, 这里使用的意图广播机制与那些在 Context.startActivity() 中用来启动活动(Activities)的意图对象是完全区分开来的。BroadcastReceiver 是无法看到或捕捉到用于startActivity()的意图的;同样的,当妳广播一个意图时,妳永远不会找到或启动一个活动(Activity)。 这两个操作在语义上是有狠大不同的:使用意图 来 启动 一个活动,这是一个前台操作,它会改变用户正与之交互的东西;使用意图来发送一个广播,这是一个后台操作,用户通常不会注意到有什么不同。
BroadcastReceiver 类 ( 当它作为一个组件从清单文件的 <receiver> 标记中启动时 ) 是 应用程序的整个生命 周期 中的一个重要组成部分。
本文将讲述以下主题:
欲了解如何使用这个类来接收及解析意图,则阅读 意图及意图过滤器 开发指南。
与 Context 编程接口配套使用的那些接收器,天生就是一种跨进程通信工具,所以,妳必须仔细考虑,其它的应用程序是否有可能干扰妳对这些接收器的使用过程。 要考虑以下问题:
•.意图(Intent)的命名空间是全局的。要确保,意图的动作名字及其它字符串都是处于妳所拥有的某个命名空间中的,否则的话,妳可能偶然与其它应用程序发生冲突。
•. 当妳使用了 registerReceiver(BroadcastReceiver, IntentFilter) 之后, 任意 一个 应用程序 都能够向被注册的那个接收器发送广播。妳可以使用下文将要说明的权限来控制谁可以向该接收器发送广播。
•. 当妳在妳的应用程序的清单文件中注册一个接收器并且指定了它的意图过滤器的时候,无论妳指定了什么过滤器,其它的任意应用程序都可以向该接收器发送广播。要想阻止其它应用程序向该接收器发送广播的话,则使用 android:exported="false" 属性让它变成对于其它应用程序不可用的。
•. 当妳使用 sendBroadcast(Intent) 或相关的方法时,一般情况下任意的其它应用程序都可以接收到这些广播。妳可以使用下文将要说明的权限来控制哪些应用程序可以接收到这些广播。或者,从 ICE_CREAM_SANDWICH 开始,妳可以使用 Intent.setPackage 来将该广播限制在单个应用程序的范围内。
当妳使用 LocalBroadcastManager 时,以上问题都不存在,因为所广播的意图不会超出当前进程的范围之外。
一个广播的发送者和接收者都可以强制给它加上某些访问权限。
要想在发送广播时强制加上一个权限,则给 sendBroadcast(Intent, String) 或 sendOrderedBroadcast(Intent, String, BroadcastReceiver, android.os.Handler, int, String, Bundle) 方法传递一个非空的(non-null) permission (权限)参数。只有那些拥有 这个权限的接收器(在它们的 AndroidManifest.xml 文件中通过 <uses-permission> 标记来请求获取该权限)才能够接收到这个广播。
要想在接收时强制加上权限控制,则,在注册接收器时提供一个非空的权限参数值——或者 在调用 registerReceiver(BroadcastReceiver, IntentFilter, String, android.os.Handler) 时提供,或者在 AndroidManifest.xml 文件的静态 <receiver> 标记中提供。只有那些拥有 了这个权限(在它们的 AndroidManifest.xml 文件中使用 <uses-permission> 标记来请求这个权限)的广播发送者才能够向该接收器发送意图广播。
参考 安全 性和权限 文档, 以了解更多关于权限和安全性的普遍信息。
BroadcastReceiver对象只有 在调用 onReceive(Context, Intent) 的期间才是有效的。 一旦妳的代码从这个函数中退出了,系统就认为该对象应当被终结,因而不再是活跃的。
这就限制了妳能够在 onReceive(Context, Intent) 中做的事情的范围:任何需要异步操作 的事情都无法进行,因为 妳需要从该函数中退出再处理异步操作,但是,到那个时候,这个BroadcastReceiver 对象就不再是活跃状态了,因而,系统可以在异步操作完成之前杀死它所在的进程。
尤其 地,妳 不能 在 BroadcastReceiver 的代码中显示对话框或者绑定到某个服务。对于前者 , 妳应当使用 NotificationManager 接口。对于后者 ,妳可以使用 Context.startService() 来向该服务发送一条命令。
当前正在执行某个BroadcastReceiver ( 即为,当前正在运行它的 onReceive(Context, Intent) 方法中的代码 )的进程, 被认为是一个前台进程,因而 会由系统保持它的运行,除非遇到严重的内存压力。
一旦妳的代码从onReceive()中退出了,这个BroadcastReceiver就不再处于活跃状态了,而用于容纳它的那个进程呢,其重要程度将与当前运行于其中的那些程序组件相同。这一点非常重要,因为,如果该进程中仅仅运行着该BroadcastReceiver的话(对于那些用户从未启动或最近未启动的程序来说,这是一种常见情况),则,从onReceive()中退出之后,系统就会认为这个进程是空白的,因而会积极地杀死该进程,以便回收资源,用于更重要的进程。
这就意味着,对于需要较长时间来运行的操作, 妳通常要将一个服务( Service )和一个BroadcastReceiver 配套使用, 以确保该进程在妳的整个操作过程中保持活跃状态。
自此版本开始引入 应用编程接口级别1
设置 一个标志位,表明该接收器应当终止当前这个广播; 只对那些通过 Context.sendOrderedBroadcast 发送的广播有效。 这会阻止余下的任何广播接收器接收到该广播。 它仍然会调用在 Context.sendOrderedBroadcast 中明确指定的那个BroadcastReceiver 的 onReceive(Context, Intent) 方法。 这个方法对于无序的广播无效,例如那些通过 Context.sendBroadcast 发送的广播。
自此版本开始引入 应用编程接口级别1
当该BroadcastReceiver 正接收到一个意图广播时,会调用此方法。 在这个执行过程中,妳可以使用BroadcastReceiver 的其它方法来查看/修改当前的那些结果值。 这个方法会在该进程的主线程中执行,除非 妳使用 registerReceiver(BroadcastReceiver, IntentFilter, String, android.os.Handler) 来明确要求将它放在别的线程中执行。 当它在主线程中执行时,妳不应当在其中执行长时间的操作(系统 会有10秒的超时时间,过了该时间,便认为该接收器已经阻塞,于是有可能杀死它 )。 妳不能在onReceive()代码中启动一个弹出式对话框。
如果 这个 BroadcastReceiver 是通过一个<receiver>标记来启动的,那么, 当从本方法中退出之后,该对象便不再处于活跃状态。 这意味着, 妳不应当进行任何会向妳异步返回结果的操作——尤其 地,在与服务进行交互时,妳应当使用 startService(Intent) 而不是 bindService(Intent, ServiceConnection, int) 。如果 妳想与一个已经处于运行状态的服务进行交互的话, 妳可以使用 peekService(Context, Intent) 。
在 registerReceiver(BroadcastReceiver, IntentFilter) 和应用程序的清单文件中使用的那些意图过滤器 并不 确保是排他性的。它们只是作为建议 被提供给操作系统,以告知如果找到适当的接收者。 发送者仍然可以强制将广播发送给特定的接收者,而在这个过程中无视过滤器规则。出于 这个原因, onReceive() 代码 中应当 只对已知的动作作出响应,而忽略掉它们可能收到的任何未预期的意图。
|
context |
该接收器所运行于其中的上下文(Context)。 |
|
intent |
当前接收到的意图(Intent)。 |
未知美人
Your opinionsHxLauncher: Launch Android applications by voice commands