Not: Burada StackOverflow üzerinde yazılmış çeşitli çözümler denedim (örnek burada). Lütfen aşağıda yazdığım testi kullanarak bulduğunuz çözümün işe yarayıp yaramadığını kontrol etmeden bunu kapatmayın.
Arka fon
Uygulamada, kullanıcının belirli bir zamanda programlanacak bir hatırlatıcı ayarlaması gerektiği için bir gereksinim vardır, bu nedenle uygulama bu zamanda tetiklendiğinde, arka planda küçük bir şey yapar (sadece bazı DB sorgu işlemi) ve hatırlatma hakkında anlatmak için basit bir bildirim.
Geçmişte, nispeten belirli bir zamanda programlanacak bir şeyi ayarlamak için basit bir kod kullandım:
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
}
}
Kullanımı:
val timeToTrigger = System.currentTimeMillis() + java.util.concurrent.TimeUnit.MINUTES.toMillis(1)
setAlarm(this, timeToTrigger, 1)
Sorun
Şimdi bu kodu yeni Android sürümlerindeki emülatörlerde ve Android 10 ile Pixel 4'te test ettim ve tetiklemiyor gibi görünüyor, ya da sağladığımdan bu yana çok uzun bir süre sonra tetikleniyor. Ben çok iyi biliyorum korkunç davranışları o bazı OEM son görevleri uygulamaları kaldırmayı eklendi, ama bu her iki öykünücülerinde ve Piksel 4 cihazı (stok).
Bir alarm ayarlama hakkında dokümanlar üzerinde okudum, uygulamalar için kısıtlandığını, böylece çok sık meydana gelmeyeceğini, ancak bu, belirli bir zamanda bir alarmın nasıl ayarlanacağını açıklamıyor ve açıklamıyor Google'ın Saat uygulaması nasıl olur? bunu başarabilir.
Sadece bu değil, aynı zamanda anladığım kadarıyla, kısıtlamalar özellikle cihazın düşük güç durumu için uygulanmalıdır, ancak benim durumumda, hem cihazda hem de emülatörlerde bu duruma sahip değildim. Alarmları bir dakika içinde tetiklenecek şekilde ayarladım.
Birçok çalar saat uygulamasının eskisi gibi artık çalışmadığını görünce, dokümanlarda eksik olan bir şey olduğunu düşünüyorum. Bu tür uygulamalara örnek olarak, Google tarafından satın alınan ancak yeni kısıtlamalarla başa çıkacak yeni güncellemeler bulunmayan popüler Timely uygulaması veriliyor ve şimdi kullanıcılar geri istiyor. . Ancak, bazı popüler uygulamalar bunun gibi iyi çalışır .
Ne denedim
Gerçekten alarmın çalıştığını test etmek için, uygulamayı ilk kez yükledikten sonra, cihaz PC'ye bağlıyken (günlükleri görmek için) alarmı bir dakika sonra tetiklemeye çalışırken bu testleri gerçekleştiriyorum:
- Uygulamanın kullanıcı tarafından görülebildiği ön planda olup olmadığını test edin. - 1-2 dakika sürdü.
- Uygulamanın arka plana ne zaman gönderildiğini test edin (örneğin ana sayfa düğmesini kullanarak) - yaklaşık 1 dakika sürdü
- Uygulamanın görevinin son görevlerden ne zaman kaldırıldığını test edin. - 20 dakikadan fazla bekledim ve alarmın tetiklendiğini, günlüklere yazdığını görmedim.
- # 3 gibi, ama aynı zamanda ekranı kapatın. Muhtemelen daha kötü olurdu ...
Sonraki şeyleri kullanmaya çalıştım, hepsi işe yaramıyor:
alarmManager.setAlarmClock(AlarmManager.AlarmClockInfo(timeToTrigger, pendingIntent), pendingIntent)
alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, timeToTrigger, pendingIntent)
AlarmManagerCompat.setExactAndAllowWhileIdle(alarmManager, AlarmManager.RTC_WAKEUP, timeToTrigger, pendingIntent)
yukarıdakilerin herhangi birinin kombinasyonu:
if (VERSION.SDK_INT >= VERSION_CODES.KITKAT) alarmManager.setWindow(AlarmManager.RTC_WAKEUP, 0, 60 * 1000L, pendingIntent)
BroadcastReceiver yerine bir hizmet kullanmayı denedi. Ayrıca farklı bir süreç üzerinde çalıştı.
Uygulamayı pil optimizasyonundan yok saymaya çalıştım (yardım etmedi), ancak diğer uygulamalar buna ihtiyaç duymadığından da kullanmamalıyım.
Bunu kullanarak denedim:
if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP)
alarmManager.setAlarmClock(AlarmManager.AlarmClockInfo(timeToTrigger, pendingIntent), pendingIntent)
AlarmManagerCompat.setExactAndAllowWhileIdle(alarmManager, AlarmManager.RTC_WAKEUP, timeToTrigger, pendingIntent)
- Alarmı yeniden programlamak için onTaskRemoved tetikleyicisine sahip bir hizmete sahip olmayı denedim , ancak bu da yardımcı olmadı (hizmet olsa da iyi çalıştı).
Google'ın Saat uygulamasına gelince, tetiklenmeden önce bir bildirim göstermesi dışında özel bir şey görmedim ve ayrıca pil optimizasyon ayarları ekranının "optimize edilmedi" bölümünde de görmüyorum.
Bunun bir hata gibi göründüğünü görünce , sorunu göstermek için örnek bir proje ve video da dahil olmak üzere burada bunu rapor ettim .
Emülatörün birden fazla sürümünü kontrol ettim ve bu davranış API 27'den (Android 8.1 - Oreo) başladı gibi görünüyor. Dokümanlara baktığımda , AlarmManager'ın bahsedildiğini görmüyorum, ancak bunun yerine çeşitli arka plan çalışmaları hakkında yazılmıştır.
Sorular
Bugünlerde göreceli olarak tam bir zamanda tetiklenecek bir şeyi nasıl ayarlayabiliriz?
Nasıl oluyor da yukarıdaki çözümler artık işe yaramıyor? Bir şey mi kaçırıyorum? İzin? Belki bunun yerine bir İşçi kullanmam gerekiyor? Ama o zaman hiç tetiklenmeyebileceği anlamına gelmez mi?
Google "Clock" uygulaması tüm bunların üstesinden nasıl gelir ve yalnızca bir dakika önce tetiklenmiş olsa bile her zaman tam zamanında tetiklenir? Sadece bir sistem uygulaması olduğu için mi? Yerleşik olmayan bir cihaza kullanıcı uygulaması olarak yüklenirse ne olur?
Bunun bir sistem uygulaması olduğu için söylüyorsanız, burada 2 dakika içinde iki kez bir alarmı tetikleyebilecek başka bir uygulama buldum , ancak bazen bir ön plan hizmeti kullanabileceğini düşünüyorum.
EDIT: Burada fikirleri denemek için küçük bir Github deposu yaptı .
EDIT: sonunda hem açık kaynaklı hem de bu sorunu olmayan bir örnek bulundu . Ne yazık ki çok karmaşık ve hala bu kadar farklı kılan (ve benim POC için eklemem gereken en az kod nedir) anlamaya çalışıyorum, son görevleri app kaldırdıktan sonra alarmları planlı kalmasını sağlar