# Android 14 AlarmManager SCHEDULE_EXACT_ALARM 權限閃退 > [name=Daniel Huang][time=Wed, Mar 27, 2024 11:53 AM][color=#d4e057] :::warning 同步發表在 [Code with DH](https://dh46tw.github.io/posts/2024/android-alarm-manager-schedule-exact-alarm/?utm_source=hackmd&utm_medium=cpc&utm_campaign=hackmd_public) ::: ## 一、問題描述 Android 14 的使用者反映應用程式閃退,經查測後發現是設定指定時間提醒功能時出現閃退。 ```! Fatal Exception: java.lang.SecurityException: Caller com.tms.qpass needs to hold android.permission.SCHEDULE_EXACT_ALARM or android.permission.USE_EXACT_ALARM to set exact alarms. ``` 從錯誤訊息可以清楚看到,問題發生當下是拋出 `SecurityException` 。 ## 二、錯誤原因說明 其實從錯誤訊息中就可略知一二,一切都跟 `SCHEDULE_EXACT_ALARM` 還有 `USE_EXACT_ALARM` 有關。 > [!Note] 如果是日曆或鬧鐘應用程式,應該要宣告的是 [USE_EXACT_ALARM](https://developer.android.com/reference/android/Manifest.permission#USE_EXACT_ALARM) 精確鬧鐘權限。 > > USE_EXACT_ALARM 是一項即將推出的新權限,作用是針對以 Android 13 (API 級別 33) 以上版本為目標的應用程式,授予[精確鬧鐘功能](https://developer.android.com/about/versions/13/features#use-exact-alarm-permission)的存取權。 > > USE_EXACT_ALARM 是一項受限制權限,只有當應用程式的核心功能支援精確鬧鐘需求,應用程式才能宣告這項權限。要求這項受限制權限的應用程式必須接受審查,若是應用程式不符合使用限制條件,就禁止在 Google Play 發布 > 核心功能: > - 應用程式是鬧鐘或計時器應用程式。 > - 應用程式是會顯示活動通知的日曆應用程式。 > 上述以外的用途,則應評估能否選擇使用 SCHEDULE_EXACT_ALARM 做為替代方案。 > > 以上整理自 [Google Play Policy](https://support.google.com/googleplay/android-developer/answer/9888170?hl=zh-Hant)。 ### SCHEDULE_EXACT_ALARM 權限 > [!Tip] 適用的精準鬧鐘 API > > 1. `setExact()` > 2. `setExactAndAllowWhileIdle()` > 3. `setAlarmClock()` #### Android 12 以前 可直接使用 API。 #### Android 12 後 從 Android 12 開始,所有 Target SDK 為 Android 12 的 App ,如果要使用 `AlarmManager` 的精準鬧鐘 API,都必須要在 `AndroidManifest.xml` 中宣告`SCHEDULE_EXACT_ALARM` 權限。 因為此權限系統預設允許,所以不用特別引導使用者開啟設定。 #### Android 14 後 在以下幾種情況時,`SCHEDULE_EXACT_ALARM` 權限預設關閉。 1. App Target SDK 為 Android 13 或以上。 1. 包含使用者使用備份軟體將 App 還原到較新版本的裝置上。 2. 原本就有安裝且允許權限,然後系統自動更新到新系統者不在此限。 2. 在 `AndroidManifest.xml` 中有宣告 `SCHEDULE_EXACT_ALARM`。 3. App 不在豁免條件或預先允許的情境內。 4. 非日曆或鬧鐘應用程式。 ## 三、最佳實踐 #### 1. 在 `AndroidManifest.xml` 宣告使用的權限 ```xml <uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" /> ``` #### 2. 設定 Alarm 前動態檢查,否則會出 `SecurityExeption` 使用 `AlarmManager.canScheduleExactAlarm()` 檢查是否取得權限。 ```kotlin /** * [ALARMMANAGER] Android 12 以上 精確鬧鐘權限 * * @return */ private fun isSetExactAlarmAllowed(): Boolean = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { val alarmManager = requireContext().getSystemService(Context.ALARM_SERVICE) as AlarmManager alarmManager.canScheduleExactAlarms() } else { true } ``` #### 3. 若無法取得權限,可以跟使用者說明後,使用 `Intent` 帶往系統設定。 ```kotlin if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) return val intent = Intent(Settings.ACTION_REQUEST_SCHEDULE_EXACT_ALARM) intent.data = Uri.parse("package:${context?.packageName}") startActivity(intent) ``` #### 4. 官方建議在 `onResume()` 再次檢查是否有取得權限。 ```kotlin override fun onResume() { if (alarmManager.canScheduleExactAlarms()) { // Set exact alarms. alarmManager.setExact(...) } else { // Permission not yet approved. Display user notice and revert to a fallback approach. alarmManager.setWindow(...) } } ``` > [!warning] 監聽權限允許結果 > > 當 `SCHEDULE_EXACT_ALARMS` 的權限允許時,系統會發送帶有 [`ACTION_SCHEDULE_EXACT_ALARM_PERMISSION_STATE_CHANGED`](https://developer.android.com/reference/android/app/AlarmManager#ACTION_SCHEDULE_EXACT_ALARM_PERMISSION_STATE_CHANGED)的 Broadcast,App 可以實作 `BroadcastReceiver`來監聽此事件。 > 在監聽事件的回呼中,官方也建議再用 `canSetExactAlarm()` 檢查是否真的有拿到權限。 > > 我個人的作法,會另外將是否曾請求過權限記錄在本地端,避免因為單一功能重複向使用者請求權限。 ## 四、參考資料 - [Android Doc: AlarmManager.setExactAndAllowWhileIdle](https://developer.android.com/reference/android/app/AlarmManager#setExactAndAllowWhileIdle(int,%20long,%20android.app.PendingIntent)) - 基本上跟 `setExact()` 一樣的方法,可以設定指定時間執行的鬧鐘。差別在於當系統處於低電量模式時,鬧鐘仍會執行。 - [SCHEDULE_EXACT_ALARM](https://developer.android.com/reference/android/Manifest.permission#SCHEDULE_EXACT_ALARM) - 權限文件 - [Android 14 Behaviour changes--Schedule exact alarms are denied by default](https://developer.android.com/about/versions/14/changes/schedule-exact-alarms#migration) - 基本上可以單看這篇就好,把整個權限的前因後果,以及最佳實踐寫得很清楚。 - [App Targets Android 12 Behaviour changes--Exact Alarm Permission](https://developer.android.com/about/versions/12/behavior-changes-12#exact-alarm-permission - [Medium--Android 14 Behavior Changes:精確鬧鐘行為變更](https://carterchen247.medium.com/android-14-behavior-changes-%E7%B2%BE%E7%A2%BA%E9%AC%A7%E9%90%98%E8%A1%8C%E7%82%BA%E8%AE%8A%E6%9B%B4-87b432f979e0) - 中文版的說明,寫得很清楚,文末也有提供一個開源的 Library 可以使用。
×
Sign in
Email
Password
Forgot password
or
By clicking below, you agree to our
terms of service
.
Sign in via Facebook
Sign in via Twitter
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
New to HackMD?
Sign up