Android四大组件 BroadcastReceiver

广播2种注册方式:静态注册和动态注册

  • 静态注册:在AndroidManifest.xml文件中进行注册,当App退出后,Receiver仍然可以接收到广播并且进行相应的处理。

API 级别 26 或更高级别的平台版本为目标,则不能使用清单为隐式广播(没有明确针对您的应用的广播)声明接收器,但一些不受此限制的隐式广播除外。在大多数情况下,您可以使用调度作业来代替。

    
        
            
            
        
    
    
    private const val TAG = "MyBroadcastReceiver"

    class MyBroadcastReceiver : BroadcastReceiver() {

        override fun onReceive(context: Context, intent: Intent) {
            StringBuilder().apply {
                append("Action: ${intent.action}\n")
                append("URI: ${intent.toUri(Intent.URI_INTENT_SCHEME)}\n")
                toString().also { log ->
                    Log.d(TAG, log)
                    Toast.makeText(context, log, Toast.LENGTH_LONG).show()
                }
            }
        }
    }
  • 动态注册:在代码中动态注册,当App退出后,也就没办法再接受广播了
    val br: BroadcastReceiver = MyBroadcastReceiver()
    val filter = IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION).apply {
        addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED)
    }
    registerReceiver(br, filter)
//要注册本地广播,请调用 `LocalBroadcastManager.registerReceiver(BroadcastReceiver, IntentFilter)`

停止接收广播,请调用 unregisterReceiver(android.content.BroadcastReceiver)。当您不再需要接收器或上下文不再有效时,请务必注销接收器。

发送广播三种方式

  • sendOrderedBroadcast(Intent, String) 方法一次向一个接收器发送广播。当接收器逐个顺序执行时,接收器可以向下传递结果,也可以完全中止广播,使其不再传递给其他接收器。接收器的运行顺序可以通过匹配的 intent-filter 的 android:priority 属性来控制;具有相同优先级的接收器将按随机顺序运行。
  • sendBroadcast(Intent) 方法会按随机的顺序向所有接收器发送广播。这称为常规广播。这种方法效率更高,但也意味着接收器无法从其他接收器读取结果,无法传递从广播中收到的数据,也无法中止广播。
  • LocalBroadcastManager.sendBroadcast 方法会将广播发送给与发送器位于同一应用中的接收器。如果您不需要跨应用发送广播,请使用本地广播。这种实现方法的效率更高(无需进行进程间通信),而且您无需担心其他应用在收发您的广播时带来的任何安全问题。

发送广播限制及API更改

  • 系统广播更改
随着 Android 平台的发展,它会不定期地更改系统广播的行为方式。如果您的应用以 Android 7.0(API 级别 24)或更高版本为目标平台,或者安装在搭载 Android 7.0 或更高版本的设备上,请注意以下更改。

#### Android 9

从 Android 9(API 级别 28)开始,[`NETWORK_STATE_CHANGED_ACTION`](https://developer.android.com/reference/android/net/wifi/WifiManager?hl=zh-cn#NETWORK_STATE_CHANGED_ACTION) 广播不再接收有关用户位置或个人身份数据的信息。

此外,如果您的应用安装在搭载 Android 9 或更高版本的设备上,则通过 WLAN 接收的系统广播不包含 SSID、BSSID、连接信息或扫描结果。要获取这些信息,请调用 [`getConnectionInfo()`](https://developer.android.com/reference/android/net/wifi/WifiManager?hl=zh-cn#getConnectionInfo())。

#### Android 8

从 Android 8.0(API 级别 26)开始,系统对清单声明的接收器施加了额外的限制。

如果您的应用以 Android 8.0 或更高版本为目标平台,那么对于大多数隐式广播(没有明确针对您的应用的广播),您不能使用清单来声明接收器。当用户正在活跃地使用您的应用时,您仍可使用[上下文注册的接收器](https://developer.android.com/guide/components/broadcasts?hl=zh-cn#context-registered-recievers)。

#### Android 7

Android 7.0(API 级别 24)及更高版本不发送以下系统广播:

*   `[ACTION_NEW_PICTURE](https://developer.android.com/reference/android/hardware/Camera?hl=zh-cn#ACTION_NEW_PICTURE)`
*   `[ACTION_NEW_VIDEO](https://developer.android.com/reference/android/hardware/Camera?hl=zh-cn#ACTION_NEW_VIDEO)`

此外,以 Android 7.0 及更高版本为目标平台的应用必须使用 `[registerReceiver(BroadcastReceiver, IntentFilter)](https://developer.android.com/reference/android/content/Context?hl=zh-cn#registerReceiver(android.content.BroadcastReceiver,%20android.content.IntentFilter))` 注册 `[CONNECTIVITY_ACTION](https://developer.android.com/reference/android/net/ConnectivityManager?hl=zh-cn#CONNECTIVITY_ACTION)` 广播。无法在清单中声明接收器。

  • 通过权限限制广播
    带权限的发送,当您调用 sendBroadcast(Intent, String) 或 sendOrderedBroadcast(Intent, String, BroadcastReceiver, Handler, int, String, Bundle) 时,可以指定权限参数。接收器若要接收此广播,则必须通过其清单中的 标记请求该权限(如果存在危险,则会被授予该权限)。
发送:
    sendBroadcast(Intent("com.example.NOTIFY"), Manifest.permission.SEND_SMS)

接收权限:

带权限接收,如果您在注册广播接收器时指定了权限参数(通过 registerReceiver(BroadcastReceiver, IntentFilter, String, Handler) 或清单中的 ,则广播方必须通过其清单中的 标记请求该权限(如果存在危险,则会被授予该权限),才能向该接收器发送 Intent。

接收:
var filter = IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED)
registerReceiver(receiver, filter, Manifest.permission.SEND_SMS, null )

发送:
    

广播最佳做法建议

  • 优先只用应用内广播
  • 优先使用动态注册广播
  • 广播命名带包名防止同名广播
  • onReceive()主线程执行,不要在主线程执行耗时任务
  • 广播可作为跨应用和普通用户流之外的消息传递系统。但是,您必须小心,不要滥用在后台响应广播和运行作业的机会,因为这会导致系统变慢。

你可能感兴趣的:(Android四大组件 BroadcastReceiver)