zoukankan      html  css  js  c++  java
  • Android BroadcastReceiver(一)

    Android BroadcastReceiver


    介绍: broadcastReceiver是android的四大组件之一,大部分的广播是系统发出来的。例如,屏幕关闭,电池电量不足等等。应用同样可以创建广播,例如:当下载完成的时候,要让其他的应用知道这个情况,需要用到broadcastreceiver,receiver没有界面,它可能会创建一个status bar notification通知用户。broadcastreceiver 只是会做一些非常小的工作,例如,它可以出发一个service工作。


    基类的代码会收到sendBroadcast()发送过来的Intents.

    如果不需要在应用之间发送广播,可以考虑使用LocalBroadcastManager代替下面介绍的方式。这种方式会有更好的性能,并且不用考虑不同应用之间的安全问题,因为其他的应用有可能可以接收这个广播。

    可以用Context.registerReceiver()动态注册receiver或者是在AndroidManifest.xml 文件里通过<receiver>元素静态注册receiver。

    注意:    如果在Activity.onResume() 里面注册一个receiver,那么必须在Activity.onPause() 方法里面注销这个receiver。不要在Activity.onSaveInstanceState() 方法里面注销receiver,因为当用户回到历史堆栈中不会调用它。

    这里有两种主要的广播可以收到:

    • 正常的 broadcasts ( Context.sendBroadcast发送的) 都是异步的. 所有的receiver都是没有顺序的,通常在同一时间。这种方式效率更好,这意味着receiver不能使用结果或者终止API。
    • 有序的 broadcasts (Context.sendOrderedBroadcast 发送的) 是同时发送给一个receiver。因为每一个receiver按照顺序执行,那么就可以传递结果到下一个receiver,或者它可以完全终止广播,已达到不传递给下一个receiver。有序的receiver运行的时与android:priority 有关系,这个属性可以控制它执行顺序;如果receiver拥有同样的priority,那么它们的执行顺序是任意的。

    即使在正常的广播中,系统在有些情况下会把广播同时发给一个receiver。在特殊条件下,可能需要创建一个进程来处理receiver,在某一时间点只有一个receiver会运行,为了避免超负荷工作是系统可能创建新的进程。在这种情况下,然而,这些receiver还是不能够返回结果和终止他们的广播。

    需要注意,即使Intent类被用来发送和接收广播,Intent 广播与启动activity的机制是完全不同的。BroadcastReceiver 不能处理startActivity()方法发送出来的Intent,没有这种机制;同样的,当广播一个Intent,同样不能找到或者启动一个activity。这两种操作在语义上是完全不同的:通过Intent启动一个activity是一个前台操作,这是随着用户的操作而发生的改变;广播一个Intent是一种后台操作,用户是不能意识到的.

    下面有三个主题的内容:

    1. Security
    2. Receiver Lifecycle
    3. Process Lifecycle

    Security

    receiver通常是应用之间通信的一个工具,因此必须考虑其他的应用可能如何滥用它们。需要考虑的问题有:

    • Intent的命名空间是全局的。要保证定义的action名字和其他的字符串都是属于自己的应用,要不然会无意识的与系统其他的冲突。

    • 如果是用 registerReceiver(BroadcastReceiver, IntentFilter)注册Receiver, 任何应用都有可能发送广播到那个receiver。可以通过定义permissions控制谁能发送广播给它。

    • 在manifest里面定义receiver,并且定义了intent-filters, 任何应用都可以忽略指定的过滤条件并发送广播给它。为了防止其他的应用发送广播给它,在在manifest里面定义android:exported="false",这样其他的应用就不能发送广播到这个receiver了。

    • sendBroadcast(Intent)   或者相关的方法,正常情况,其他的应用可以收到这个广播。需要通过定义permission控制可以接受这个广播的receiver。或者是,从 ICE_CREAM_SANDWICH 开始,可以同通过设置Intent.setPackage 来指定receiver

    用 LocalBroadcastManager 就不会有这个些问题,从广播发出后,都不会出当前进程。

    receiver和broadcast都可以设置访问权限。

    为了在发送的时候执行permission,必须提供一个非空的permission参数给 sendBroadcast(Intent, String) 或者 sendOrderedBroadcast(Intent, String, BroadcastReceiver, android.os.Handler, int, String, Bundle). 仅仅定义这个permission的receiver可以接收广播( AndroidManifest.xml 里面定义<uses-permission>)。

    当收到执行权限时,在注册receiver的时候需要提供一个非空的permission参数--要么当调用registerReceiver(BroadcastReceiver, IntentFilter, String, android.os.Handler) 或者是在AndroidManifest.xml 文件里面定义一个静态的<receiver>. 只有授予了指定permission的广播才能够发送到receiver中。

    Receiver Lifecycle

    BroadcastReceiver 对象只有在调用onReceive(Context, Intent)方法是才有效. 一旦从这个方法里面返回,系统会认为这个对象已经完成并且不在处于活动状态。

    这里是当实现 onReceive(Context, Intent) 时需要注意: 任何需要异步的操作是不可行的,因为需要从方法里面返回,但是方法又要处理异步的操作,这样就可以行了,这种情况下,系统会在异步操作完成之前可能会杀死BroadcastReceiver的进程。

    特殊情况下,在BroadcastReceiver里面可能不会显示一个dialog或者绑定一个service。对于前者,用NotificationManager API代替,对后者,可以用 Context.startService() 发送命令给service。

    Process Lifecycle

    当前正在运行的BroadcastReceiver(运行在onReceive(Context, Intent)方法上)进程需要被认为是前台进程,并且会一直运行除非是系统的内存处于极限情况下(系统会回收内存)。

    一旦从onReceive()返回,BroadcastReceiver不再是活动状态的,它运行的进程与其他运行的在它里面的应用组件一样重要,这是非常特殊并且非常重要的,因为那个进程只是为BroadcastReceiver服务,然后receiver从onReceive()里面返回,系统会认为这个进程是空的并且会尽快杀死它回收资源。

    这就意味着,如果是一个长时间运行的操作,最好是用service和BroadcastReceiver 结合使用,为了保持进程在整个操作中持久运行。

  • 相关阅读:
    【leetcode】1365. How Many Numbers Are Smaller Than the Current Number
    【leetcode】1363. Largest Multiple of Three
    【leetcode】1362. Closest Divisors
    【leetcode】1361. Validate Binary Tree Nodes
    【leetcode】1360. Number of Days Between Two Dates
    【leetcode】1359. Count All Valid Pickup and Delivery Options
    【leetcode】1357. Apply Discount Every n Orders
    【leetcode】1356. Sort Integers by The Number of 1 Bits
    ISE应用入门的一些问题
    DDR的型号问题
  • 原文地址:https://www.cnblogs.com/java20130722/p/3207268.html
Copyright © 2011-2022 走看看