Android12版本鬧鐘服務崩潰問題

原文地址: Android12版本鬧鐘服務崩潰問題 - Stars-One的雜貨小窩

公司項目app線上出現的崩潰記錄問題,崩潰日誌如下所示:

Caused by java.lang.SecurityException: Caller com.health.trackeranz needs to hold android.permission.SCHEDULE_EXACT_ALARM or android.permission.USE_EXACT_ALARM to set exact alarms.

一看到是安全異常,估計就是高版本android系統加的限制了,原因就是沒正確適配新權限導致的崩潰問題

先貼下已解決的代碼:

//在第二天的0:00清理髮出清理數據的廣播
val calendar: Calendar = Calendar.getInstance()
calendar.set(Calendar.HOUR_OF_DAY, 0)
calendar.set(Calendar.MINUTE, 0)
calendar.set(Calendar.SECOND, 0)
calendar.add(Calendar.DAY_OF_MONTH, 1)

//測試用的數據,鬧鐘定爲60s後
//val calendar: Calendar = Calendar.getInstance()
//calendar.add(Calendar.SECOND, 60)

val alarmManager = application.getSystemService<AlarmManager>()

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S && alarmManager?.canScheduleExactAlarms()==false) {
	alarmManager.setExactAndAllowWhileIdle(
		AlarmManager.RTC_WAKEUP,
		calendar.getTimeInMillis(),
		pendingIntent
	)
} else {
	alarmManager?.setExact(
		AlarmManager.RTC_WAKEUP,
		calendar.getTimeInMillis(),
		pendingIntent
	)
}
LogUtils.d("鬧鐘已啓動,預定觸發時間:" + TimeUtils.date2String(calendar.time))

這裏代碼注意alarmManager?.canScheduleExactAlarms()==false這個判斷,之前沒有添加次判斷,於是就有了上文提及的崩潰問題

復現的話很容易,去設置頁面裏,把應用的鬧鐘服務關閉就會出現了,如下圖所示

原因

首先,瞭解下alarmManager設置定時的3個方法:

  • setExactAndAllowWhileIdle(long triggerAtMillis, PendingIntent operation):這個方法用於設置精確的鬧鐘,即你可以指定鬧鐘觸發的特定時間。它會在設備進入低功耗模式時仍然觸發鬧鐘。但是,如果你的應用程序在後臺運行並且設備處於省電模式,則可能不會觸發鬧鐘。
  • setExact(long triggerAtMillis, PendingIntent operation):這個方法也用於設置精確的鬧鐘,與 setExactAndAllowWhileIdle 方法類似,允許你指定特定的觸發時間。但是,它不會在設備處於低功耗模式時觸發鬧鐘。如果你的應用程序在後臺運行並且設備處於省電模式,則鬧鐘可能會被延遲執行。
  • setAndAllowWhileIdle(int type, long triggerAtMillis, PendingIntent operation):這個方法允許你設置具有彈性的觸發時間的鬧鐘,以適應設備的省電模式。它提供了三種可能的觸發類型:ELAPSED_REALTIME_WAKEUPRTC_WAKEUPRTC。它會在設備處於低功耗模式時仍然觸發鬧鐘。

需要注意的是,如果 targetSdkVersion >= 33,且在 Android14 設備上沒有顯式申請該權限,調用上面的3個方法,則會拋出一個 SecurityException 異常

不過Android13新增android.permission.USE_EXACT_ALARM,用了模擬機的Android13版本測試,如果不寫android.permission.USE_EXACT_ALARM還是會出現上面的錯誤

所以最終做法,就是2個權限android.permission.SCHEDULE_EXACT_ALARMandroid.permission.USE_EXACT_ALARM都申請纔不會有問題,這裏推薦權限申請框架可以使用getActivity/XXPermissions: Android 權限請求框架,已適配 Android 14這個開源庫

應該是setExact方法的限制稍微鬆一些吧,上面的方法可以使用,不過實際沒有太高精度要求,只使用setExact應該也能達到效果

像上述的app,只是在第二日凌晨進行通知欄的數據更新(類似每日提醒那種感覺)

至於保活方面,高版本的Android限制太多,產品也沒有其他要求,就先這樣,只要app後臺沒被殺死,每日通知還是有的

不過看了其他文章,說到:

日曆或鬧鐘應用需要在應用停止運行時發送日曆提醒、喚醒鬧鐘或提醒。這些應用可以請求 USE_EXACT_ALARM 常規權限。系統將在安裝時授予 USE_EXACT_ALARM 權限,擁有此權限的應用將能夠像具有 SCHEDULE_EXACT_ALARM 權限的應用一樣設置精確鬧鐘。

參考

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章