참고 : 여기에 대한 다양한 솔루션을 시도했습니다 (예 : here ). 찾은 솔루션이 아래에서 작성한 테스트를 사용하여 작동하는지 확인하지 않고 닫지 마십시오.
배경
앱에는 사용자가 미리 알림을 특정 시간에 예약하도록 요구해야 하므로이 시간에 앱이 트리거 될 때 백그라운드에서 작은 작업 (일부 DB 쿼리 작업)을 수행하고 알림에 대한 간단한 알림.
과거에는 간단한 코드를 사용하여 상대적으로 특정 시간에 예약 할 항목을 설정했습니다.
val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
val pendingIntent = PendingIntent.getBroadcast(context, requestId, Intent(context, AlarmReceiver::class.java), PendingIntent.FLAG_UPDATE_CURRENT)
when {
VERSION.SDK_INT >= VERSION_CODES.KITKAT -> alarmManager.setExact(AlarmManager.RTC_WAKEUP, timeToTrigger, pendingIntent)
else -> alarmManager.set(AlarmManager.RTC_WAKEUP, timeToTrigger, pendingIntent)
}
class AlarmReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
Log.d("AppLog", "AlarmReceiver onReceive")
//do something in the real app
}
}
용법:
val timeToTrigger = System.currentTimeMillis() + java.util.concurrent.TimeUnit.MINUTES.toMillis(1)
setAlarm(this, timeToTrigger, 1)
문제
이제 새로운 Android 버전 및 Android 10의 Pixel 4에서 에뮬레이터 에서이 코드를 테스트했으며 트리거 한 것처럼 보이지 않거나 제공 한 이후로 오랜 시간 후에 트리거 될 수 있습니다. 일부 OEM 이 최근 작업에서 앱을 제거하기 위해 추가 한 끔찍한 동작 을 잘 알고 있지만 에뮬레이터와 Pixel 4 장치 (스톡)에 있습니다.
알람 설정 에 대한 문서를 읽었 으므로 앱이 너무 자주 발생하지 않도록 앱에 제한되어 있지만 특정 시간에 알람을 설정하는 방법은 설명하지 않으며 설명하지 않습니다. 어떻게 온 구글의 시계 응용 프로그램이 그 일을 성공합니다.
그뿐만 아니라 내가 이해 한 바에 따르면, 특히 장치의 저전력 상태에 대해 제한 사항을 적용해야한다고 말하지만 제 경우에는 장치와 에뮬레이터 모두 에서이 상태가 없었습니다. 지금부터 약 1 분 안에 알람이 트리거되도록 설정했습니다.
많은 알람 시계 앱이 더 이상 작동하지 않는 것을 확인하면 문서에 누락 된 것이 있다고 생각합니다. 이러한 앱의 예로는 Google 에서 구입 했지만 새로운 제한 사항을 처리하기 위해 새로운 업데이트를받지 못한 인기있는 Timely 앱이 있으며, 이제 사용자 는 다시 원합니다. . 그러나 일부 인기있는 애플 리케이션과 같은, 잘 작동을 이것 .
내가 시도한 것
실제로 알람이 작동하는지 테스트하기 위해 처음으로 앱을 설치 한 후 장치가 PC에 연결되어있는 동안 (로그를 보려면) 알람을 트리거하려고 할 때 이러한 테스트를 수행합니다.
- 앱이 포 그라운드에 있고 사용자에게 표시 될 때 테스트합니다. -1-2 분 걸렸습니다.
- 앱이 백그라운드로 전송 된시기 테스트 (예 : 홈 버튼 사용)-약 1 분 소요
- 앱의 작업이 최근 작업에서 제거 된시기를 테스트합니다. -20 분 이상 기다렸는데 로그에 기록하면서 알람이 트리거되는 것을 보지 못했습니다.
- # 3처럼 화면을 끕니다. 아마 더 나쁠 것입니다 ...
나는 다음 것들을 사용하려고했지만 모두 작동하지 않습니다.
alarmManager.setAlarmClock(AlarmManager.AlarmClockInfo(timeToTrigger, pendingIntent), pendingIntent)
alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, timeToTrigger, pendingIntent)
AlarmManagerCompat.setExactAndAllowWhileIdle(alarmManager, AlarmManager.RTC_WAKEUP, timeToTrigger, pendingIntent)
위와 함께 다음과의 조합 :
if (VERSION.SDK_INT >= VERSION_CODES.KITKAT) alarmManager.setWindow(AlarmManager.RTC_WAKEUP, 0, 60 * 1000L, pendingIntent)
BroadcastReceiver 대신 서비스를 사용하려고했습니다. 다른 프로세스에서도 시도했습니다.
배터리 최적화에서 앱을 무시하려고 시도했지만 (도움이되지 않음) 다른 앱은 필요하지 않으므로 사용하지 않아야합니다.
이것을 사용하여 시도 :
if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP)
alarmManager.setAlarmClock(AlarmManager.AlarmClockInfo(timeToTrigger, pendingIntent), pendingIntent)
AlarmManagerCompat.setExactAndAllowWhileIdle(alarmManager, AlarmManager.RTC_WAKEUP, timeToTrigger, pendingIntent)
- onTaskRemoved 트리거가있는 서비스를 시도 하여 알람을 다시 예약했지만 도움이되지 않았습니다 (서비스는 정상적으로 작동했습니다).
Google 시계 앱의 경우 트리거되기 전에 알림을 표시하는 것을 제외하고는 배터리 최적화 설정 화면의 "최적화되지 않은"섹션에도 표시되지 않습니다.
이것이 버그처럼 보이는 것을 보았으므로 문제를 보여주는 샘플 프로젝트 및 비디오를 포함하여 여기 에 대해보고 했습니다.
여러 버전의 에뮬레이터를 확인 했는데이 동작은 API 27 (Android 8.1-Oreo)에서 시작된 것으로 보입니다. 상대 워드 프로세서에서 , 나는 알람 관리기가 언급되고, 대신에, 그것은 다양한 배경의 작품에 대해 기록 된 표시되지 않습니다.
질문
요즘 비교적 정확한 시간에 트리거되도록 무언가를 어떻게 설정합니까?
위의 솔루션이 더 이상 작동하지 않습니까? 아무것도 빠졌습니까? 허가? 어쩌면 작업자를 대신 사용해야합니까? 그러나 그것이 제 시간에 전혀 트리거되지 않을 수도 있다는 것을 의미하지 않습니까?
Google "시계"앱은이 모든 것을 어떻게 극복하고 1 분 전에 트리거 된 경우에도 항상 정확한 시간에 트리거합니까? 시스템 앱이기 때문입니까? 앱이 내장되어 있지 않은 기기에 사용자 앱으로 설치되면 어떻게 되나요?
시스템 응용 프로그램이기 때문에 2 분 안에 두 번 경보를 트리거 할 수있는 다른 응용 프로그램을 찾았습니다. 여기 에서는 전경 서비스를 사용할 수 있다고 생각합니다.
편집 : 여기에 아이디어를 시도하기 위해 작은 Github 저장소를 만들었습니다 .
편집 : 마침내 공개 소스 이며이 문제가없는 샘플 을 발견했습니다 . 슬프게도 매우 복잡하며 여전히 최신 작업에서 앱을 제거한 후에도 알람이 예약 된 상태를 유지할 수 있도록 다른 점과 POC에 추가 해야하는 최소 코드는 무엇인지 파악하려고합니다.