一、問題描述
Android 14 的使用者反映應用程式閃退,經查測後發現是設定指定時間提醒功能時出現閃退。
|
|
從錯誤訊息可以清楚看到,問題發生當下是拋出 SecurityException
。
二、錯誤原因說明
其實從錯誤訊息中就可略知一二,一切都跟 SCHEDULE_EXACT_ALARM
還有 USE_EXACT_ALARM
有關。
✍ 如果是日曆或鬧鐘應用程式,應該要宣告的是 USE_EXACT_ALARM 精確鬧鐘權限。
USE_EXACT_ALARM 是一項即將推出的新權限,作用是針對以 Android 13 (API 級別 33) 以上版本為目標的應用程式,授予精確鬧鐘功能的存取權。
USE_EXACT_ALARM 是一項受限制權限,只有當應用程式的核心功能支援精確鬧鐘需求,應用程式才能宣告這項權限。要求這項受限制權限的應用程式必須接受審查,若是應用程式不符合使用限制條件,就禁止在 Google Play 發布 核心功能: - 應用程式是鬧鐘或計時器應用程式。 - 應用程式是會顯示活動通知的日曆應用程式。 上述以外的用途,則應評估能否選擇使用 SCHEDULE_EXACT_ALARM 做為替代方案。
以上整理自 Google Play Policy。
SCHEDULE_EXACT_ALARM 權限
💡 適用的精準鬧鐘 API
setExact()
setExactAndAllowWhileIdle()
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
權限預設關閉。
- App Target SDK 為 Android 13 或以上。
- 包含使用者使用備份軟體將 App 還原到較新版本的裝置上。
- 原本就有安裝且允許權限,然後系統自動更新到新系統者不在此限。
- 在
AndroidManifest.xml
中有宣告SCHEDULE_EXACT_ALARM
。 - App 不在豁免條件或預先允許的情境內。
- 非日曆或鬧鐘應用程式。
三、最佳實踐
1. 在 AndroidManifest.xml
宣告使用的權限
|
|
2. 設定 Alarm 前動態檢查,否則會出 SecurityExeption
使用 AlarmManager.canScheduleExactAlarm()
檢查是否取得權限。
|
|
3. 若無法取得權限,可以跟使用者說明後,使用 Intent
帶往系統設定。
|
|
4. 官方建議在 onResume()
再次檢查是否有取得權限。
|
|
🚨 監聽權限允許結果
當
SCHEDULE_EXACT_ALARMS
的權限允許時,系統會發送帶有ACTION_SCHEDULE_EXACT_ALARM_PERMISSION_STATE_CHANGED
的 Broadcast,App 可以實作BroadcastReceiver
來監聽此事件。 在監聽事件的回呼中,官方也建議再用canSetExactAlarm()
檢查是否真的有拿到權限。我個人的作法,會另外將是否曾請求過權限記錄在本地端,避免因為單一功能重複向使用者請求權限。
四、參考資料
- Android Doc: AlarmManager.setExactAndAllowWhileIdle
- 基本上跟
setExact()
一樣的方法,可以設定指定時間執行的鬧鐘。差別在於當系統處於低電量模式時,鬧鐘仍會執行。
- 基本上跟
- SCHEDULE_EXACT_ALARM
- 權限文件
- Android 14 Behaviour changes–Schedule exact alarms are denied by default
- 基本上可以單看這篇就好,把整個權限的前因後果,以及最佳實踐寫得很清楚。
- App Targets Android 12 Behaviour changes–Exact Alarm Permission
- Medium–Android 14 Behavior Changes:精確鬧鐘行為變更
- 中文版的說明,寫得很清楚,文末也有提供一個開源的 Library 可以使用。