Hey, why can't Oreo receive the broadcast?

This article has been simultaneously sent to the WeChat public account: Yuan Shi Xoong

I'm busy~ I've been very busy recently.

I am busy, and the articles of the SystemUI series are advancing as slow as a snail~

This article takes a break and records the broadcast restrictions on Android 8.0.

Recently, in the system project based on Android 8.1, the static registration broadcast is used to monitor the broadcast. But no matter whether I install the Apk or push it to the corresponding system/priv-app/ directory, I cannot receive this broadcast. Mentality, DUANG, exploded.

Later, with a flash of inspiration, I picked out the broadcast restrictions of Android 7.0 in the corner of memory, and quickly Googled it. It turned out to be the case, suddenly realized: After Android 8.0, when App targetSDK >= 26, almost all static registration monitoring of implicit broadcasts is prohibited. I record it here to prevent me from forgetting it later.

This article mainly describes the following content, please pick up the small bench, bring snacks, and come to watch:

  • Android radio science
  • Background restrictions of Android 8.0
  • List of specific broadcast restrictions and corresponding amnesties
  • Adaptation/Solution

Popular science broadcast knowledge

Come on, let’s start with popular science, broadcast two monitoring/receiving registration methods and two types, take a small notebook and write it down, remember!

How to register :

  • Static registration: Also known as manifest registration, is the broadcast registered in AndroidManifest.xml. Such broadcast receivers can receive corresponding broadcasts when the application has not yet started .
  • Dynamic registration: Also known as runtime registration, that is, in the Service or Activity component, the broadcast receiver is registered through Context.registerReceiver(). Such broadcast receivers are registered via code after the application has been launched.

Two types :

  • Explicit Broadcast: The Intent sent is a broadcast that displays the Intent. It is implemented by specifying the name of the Intent component. It is generally used to call the following method under the premise of knowing the name of the target component. The intent is clear, specifying which component to activate, typically implemented within the same application.

    Intent.setComponent()
    Intent.setClassName()
    Intent.setClass()
    new Intent(A.this,B.class)
  • Implicit Broadcast: Implemented by Intent Filter, it is generally used without specifying the name of the target component. The Android system will find the most appropriate component to handle the intent based on the action, category, and data (URI and data type) set in the implicit intent. Generally used between different applications.

Background execution limit of Android 8.0

Note that it is for applications with targetSDK >= 26, that is to say, if the targetSDK is less than 26, it will not be affected for the time being

In Oreo, in order to further improve the user experience and further save power consumption, further restrictions are imposed on the operations that an application can perform when it is running in the background.

  • Background service limit : When idle, limit the background service of the app. For example: receive the boot broadcast through static registration (assuming your device is not customized and can receive ~), and start a Service in the onReceive method, on API 26, it is not allowed and an error will be reported. Of course, for foreground services, this limitation does not exist. The official statement is: foreground services are more likely to attract users' attention.

  • Broadcast restrictions : With limited exceptions, applications cannot use manifest registration ( static registration ) to receive implicit broadcasts .

    • But for these implicit broadcasts, they can be registered by means of runtime registration ( dynamic registration ).
    • For explicit broadcasts , you can still listen through manifest registration (static registration)

One more thing to say here, the lag of Android phones is largely due to the abuse of applications and the selfish use of various means (permission abuse, broadcast registration, resident background services, etc.) to keep alive or do some PY things. Google apparently realized this early on, and since Android 6.0 has gradually introduced various restrictions, such as runtime permissions and Doze.

List of specific broadcast restrictions and corresponding amnesties

If an application registers a broadcast receiver, then every time a broadcast is sent, the application's broadcast receiver will consume resources such as RAM, CPU, etc. If there are many applications that register broadcast receivers for system event broadcasts, this…., it will be very stuck!

So starting from Android 7.0 (API level 24), there are some restrictions on broadcasting:

  • For API24 and above applications, statically registered broadcast receivers cannot monitor network changes: android.net.conn.CONNECTIVITY_CHANGE
  • On Android 7.0 devices, App cannot send or receive ACTION_NEW_PICTURE and ACTION_NEW_VIDEO broadcasts.

However, on Android 8.0, the restrictions are further enhanced. Except for the following implicit broadcasts , all other implicit broadcasts cannot be monitored by registering in AndroidManifest.xml. Refer to the official website .

// Android 8.0 上不限制的隐式广播
/**
开机广播
 Intent.ACTION_LOCKED_BOOT_COMPLETED
 Intent.ACTION_BOOT_COMPLETED
*/
"保留原因:这些广播只在首次启动时发送一次,并且许多应用都需要接收此广播以便进行作业、闹铃等事项的安排。"

/**
增删用户
Intent.ACTION_USER_INITIALIZE
"android.intent.action.USER_ADDED"
"android.intent.action.USER_REMOVED"
*/
"保留原因:这些广播只有拥有特定系统权限的app才能监听,因此大多数正常应用都无法接收它们。"

/**
时区、ALARM变化
"android.intent.action.TIME_SET"
Intent.ACTION_TIMEZONE_CHANGED
AlarmManager.ACTION_NEXT_ALARM_CLOCK_CHANGED
*/
"保留原因:时钟应用可能需要接收这些广播,以便在时间或时区变化时更新闹铃"

/**
语言区域变化
Intent.ACTION_LOCALE_CHANGED
*/
"保留原因:只在语言区域发生变化时发送,并不频繁。 应用可能需要在语言区域发生变化时更新其数据。"

/**
Usb相关
UsbManager.ACTION_USB_ACCESSORY_ATTACHED
UsbManager.ACTION_USB_ACCESSORY_DETACHED
UsbManager.ACTION_USB_DEVICE_ATTACHED
UsbManager.ACTION_USB_DEVICE_DETACHED
*/
"保留原因:如果应用需要了解这些 USB 相关事件的信息,目前尚未找到能够替代注册广播的可行方案"

/**
蓝牙状态相关
BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED
BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED
BluetoothDevice.ACTION_ACL_CONNECTED
BluetoothDevice.ACTION_ACL_DISCONNECTED
*/
"保留原因:应用接收这些蓝牙事件的广播时不太可能会影响用户体验"

/**
Telephony相关
CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED
TelephonyIntents.ACTION_*_SUBSCRIPTION_CHANGED
TelephonyIntents.SECRET_CODE_ACTION
TelephonyManager.ACTION_PHONE_STATE_CHANGED
TelecomManager.ACTION_PHONE_ACCOUNT_REGISTERED
TelecomManager.ACTION_PHONE_ACCOUNT_UNREGISTERED
*/
"保留原因:设备制造商 (OEM) 电话应用可能需要接收这些广播"

/**
账号相关
AccountManager.LOGIN_ACCOUNTS_CHANGED_ACTION
*/
"保留原因:一些应用需要了解登录帐号的变化,以便为新帐号和变化的帐号设置计划操作"

/**
应用数据清除
Intent.ACTION_PACKAGE_DATA_CLEARED
*/
"保留原因:只在用户显式地从 Settings 清除其数据时发送,因此广播接收器不太可能严重影响用户体验"

/**
软件包被移除
Intent.ACTION_PACKAGE_FULLY_REMOVED
*/
"保留原因:一些应用可能需要在另一软件包被移除时更新其存储的数据;对于这些应用,尚未找到能够替代注册此广播的可行方案"

/**
外拨电话
Intent.ACTION_NEW_OUTGOING_CALL
*/
"保留原因:执行操作来响应用户打电话行为的应用需要接收此广播"

/**
当设备所有者被设置、改变或清除时发出
DevicePolicyManager.ACTION_DEVICE_OWNER_CHANGED
*/
"保留原因:此广播发送得不是很频繁;一些应用需要接收它,以便知晓设备的安全状态发生了变化"

/**
日历相关
CalendarContract.ACTION_EVENT_REMINDER
*/
"保留原因:由日历provider发送,用于向日历应用发布事件提醒。因为日历provider不清楚日历应用是什么,所以此广播必须是隐式广播。"

/**
安装或移除存储相关广播
Intent.ACTION_MEDIA_MOUNTED
Intent.ACTION_MEDIA_CHECKING
Intent.ACTION_MEDIA_EJECT
Intent.ACTION_MEDIA_UNMOUNTED
Intent.ACTION_MEDIA_UNMOUNTABLE
Intent.ACTION_MEDIA_REMOVED
Intent.ACTION_MEDIA_BAD_REMOVAL
*/
"保留原因:这些广播是作为用户与设备进行物理交互的结果:安装或移除存储卷或当启动初始化时(当可用卷被装载)的一部分发送的,因此它们不是很常见,并且通常是在用户的掌控下"

/**
短信、WAP PUSH相关
Telephony.Sms.Intents.SMS_RECEIVED_ACTION
Telephony.Sms.Intents.WAP_PUSH_RECEIVED_ACTION

注意:需要申请以下权限才可以接收
"android.permission.RECEIVE_SMS"
"android.permission.RECEIVE_WAP_PUSH"
*/
"保留原因:SMS短信应用需要接收这些广播"

Phew, finally finished, above. It can be said that the writing is more complete than the official website~

It is recommended to collect a wave to prevent future use.

Solution

According to the official recommendation, for implicit broadcasts, the following methods are used to replace them.

  • Dynamically Context.registerReceiver()register instead of declaring the receiver in the manifest.
  • Use JobScheduler .

I choose the way of dynamic registration to deal with this problem.

Alright, that's all for the chatter about Oreo's broadcast restrictions.

Recently inspired by a small partner, I got a sentence: hardworking people often have good luck and opportunities!

mutual encouragement!

Finally, welcome to pay attention to the WeChat public account: Xoong is
happy to share high-quality dry goods on Android
Scan the code to follow

Reference link

[1] Android Oreo background execution limit https://developer.android.com/about/versions/oreo/background#broadcasts

[2] Android Oreo Implicit Broadcast Exceptions https://developer.android.com/guide/components/broadcast-exceptions

[3] Features and differences between explicit and implicit intents in Android https://blog.csdn.net/u014177843/article/details/50596863

[4] Android O Behavior Changes – Implicit Broadcast Restrictions https://blog.csdn.net/hqocshheqing/article/details/76850164

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325774348&siteId=291194637