Alarm kur

Alarmlar (AlarmManager sınıfına dayalı), uygulamanızın kullanım ömrü dışında zamana dayalı işlemler gerçekleştirmenizi sağlar. Örneğin, hava durumu tahminini indirmek için günde bir kez hizmet başlatmak gibi uzun süreli bir işlemi başlatmak için alarm kullanabilirsiniz.

Alarmlar şu özelliklere sahiptir:

  • Bu sayede, Intent'leri belirli zamanlarda ve/veya aralıklarla tetikleyebilirsiniz.

  • Diğer işlemleri gerçekleştirmek için işleri veya WorkRequest'leri planlamak üzere bunları yayın alıcılarıyla birlikte kullanabilirsiniz.

  • Uygulamanızın dışında çalıştıkları için uygulamanız çalışmıyorken ve hatta cihaz uyku modundayken bile etkinlikleri veya işlemleri tetiklemek için bunları kullanabilirsiniz.

  • Uygulamanızın kaynak gereksinimlerini en aza indirmenize yardımcı olur. Zamanlayıcılara veya sürekli çalışan hizmetlere ihtiyaç duymadan işlemleri planlayabilirsiniz.

Tam olmayan alarm kurma

Bir uygulama kesin olmayan bir alarm ayarladığında sistem, alarmı gelecekte bir noktada yayınlar. Tam olmayan alarmlar, alarmın zamanlamasıyla ilgili bazı garantiler sunarken Doze gibi pil tasarrufu kısıtlamalarına uyar.

Geliştiriciler, tam olmayan alarm yayınlama zamanlamasını özelleştirmek için aşağıdaki API garantilerinden yararlanabilir.

Belirli bir süre sonra alarm verme

Uygulamanız set(), setInexactRepeating() veya setAndAllowWhileIdle() yöntemini çağırırsa alarm, sağlanan tetikleme zamanından önce asla çalmaz.

Android 12 (API düzeyi 31) ve sonraki sürümlerde sistem, pil tasarrufu veya Doze gibi pil tasarrufu kısıtlamaları geçerli olmadığı sürece alarmı, sağlanan tetikleme zamanından sonraki bir saat içinde çağırır.

Belirli bir zaman aralığında alarm verme

Uygulamanız setWindow() yöntemini çağırırsa alarm, sağlanan tetikleme zamanından önce asla çalmaz. Pil tasarrufu kısıtlamaları geçerli değilse alarm, belirtilen tetikleme zamanından başlayarak belirtilen zaman aralığında yayınlanır.

Uygulamanız Android 12 veya sonraki sürümleri hedefliyorsa sistem, zaman aralıklı kesin olmayan bir alarmın çağrılmasını en az 10 dakika geciktirebilir. Bu nedenle, 600000 altındaki windowLengthMillis parametre değerleri genellikle 600000 değerine kırpılır. Sistem, özellikle alarmın yakın gelecekte tetiklenmesi planlanıyorsa daha küçük pencerelere uyum sağlayabilir.

Yaklaşık olarak düzenli aralıklarla yinelenen bir alarm verme

Uygulamanız setInexactRepeating() yöntemini çağırırsa sistem birden fazla alarmı çağırır:

  1. İlk alarm, belirtilen tetikleme zamanından başlayarak belirtilen zaman aralığında çalar.
  2. Sonraki alarmlar genellikle belirtilen zaman aralığı geçtikten sonra çalar. Alarmın art arda iki çağrısı arasındaki süre değişiklik gösterebilir.

Kesin zamanlı alarm kurma

Sistem, gelecekte tam olarak belirlenen bir zamanda kesin zamanlı alarm çağırır.

Çoğu uygulama, çeşitli yaygın kullanım alanlarını tamamlamak için kesin olmayan alarmlar kullanarak görevleri ve etkinlikleri planlayabilir. Uygulamanızın temel işlevi, tam olarak zamanlanmış bir alarma bağlıysa (ör. çalar saat uygulaması veya takvim uygulaması) kesin zamanlı alarm kullanabilirsiniz.

Kesin zamanlı alarm gerektirmeyebilecek kullanım alanları

Aşağıdaki listede, kesin zamanlı alarm gerektirmeyebilecek yaygın iş akışları gösterilmektedir:

Uygulamanızın kullanım ömrü boyunca zamanlama işlemlerini planlama
Handler sınıfı, uygulamanız çalışırken her n saniyede bir işlem yapmak gibi zamanlama işlemlerini yönetmek için kullanılabilecek birkaç iyi yöntem içerir: postAtTime() ve postDelayed(). Bu API'lerin gerçek zamanı değil, sistemin çalışma süresini temel aldığını unutmayın.
Uygulamanızı güncelleme ve günlükleri yükleme gibi planlanmış arka plan çalışmaları
WorkManager, zamana duyarlı periyodik işleri planlamanın bir yolunu sunar. İş için ayrıntılı çalışma süresi tanımlamak üzere bir tekrar aralığı ve flexInterval (en az 15 dakika) belirtebilirsiniz.
Belirli bir süreden sonra gerçekleşmesi gereken, kullanıcı tarafından belirtilen işlem (sistem boşta olsa bile)
Tam olmayan alarm kullanın. Özellikle setAndAllowWhileIdle() yöntemini çağırın.
Belirli bir sürenin ardından gerçekleşmesi gereken, kullanıcı tarafından belirtilen işlem
Tam olmayan alarm kullanın. Özellikle set() yöntemini çağırın.
Belirli bir zaman aralığında gerçekleşebilecek, kullanıcı tarafından belirtilen işlem
Tam olmayan alarm kullanın. Özellikle setWindow() yöntemini çağırın. Uygulamanız Android 12 veya sonraki sürümleri hedefliyorsa izin verilen en küçük pencere uzunluğunun 10 dakika olduğunu unutmayın.

Kesin zamanlı alarm ayarlama yöntemleri

Uygulamanız, aşağıdaki yöntemlerden birini kullanarak kesin zamanlı alarmlar ayarlayabilir. Bu yöntemler, listenin alt kısmına yakın olanlar daha fazla zamana duyarlı görevlere hizmet edecek ancak daha fazla sistem kaynağı gerektirecek şekilde sıralanır.

setExact()

Diğer pil tasarrufu önlemleri geçerli olmadığı sürece gelecekte neredeyse kesin bir zamanda alarmı çağırın.

Uygulamanızın işi kullanıcı için zamana duyarlı değilse kesin zamanlı alarmlar ayarlamak için bu yöntemi kullanın.

setExactAndAllowWhileIdle()

Pil tasarrufu önlemleri geçerli olsa bile gelecekte neredeyse tam bir zamanda alarmı etkinleştirin.

setAlarmClock()

Gelecekte belirli bir zamanda alarmı etkinleştirme Bu alarmlar kullanıcılar tarafından kolayca görülebildiğinden sistem, alarmların yayınlanma zamanını hiçbir zaman ayarlamaz. Sistem, bu alarmları en kritik alarmlar olarak tanımlar ve alarmları iletmek için gerekirse düşük güç modlarından çıkar.

Sistem kaynağı tüketimi

Sistem, uygulamanızın ayarladığı kesin zamanlı alarmları tetiklediğinde cihaz, özellikle güç tasarrufu modundaysa pil ömrü gibi çok fazla kaynak tüketir. Ayrıca sistem, kaynakları daha verimli kullanmak için bu istekleri kolayca gruplandıramaz.

Mümkün olduğunda kesin olmayan alarm oluşturmanız önemle tavsiye edilir. Daha uzun süreli işler gerçekleştirmek için alarmınızın BroadcastReceiver yönteminden WorkManager veya JobScheduler kullanarak planlama yapın. Cihaz Doze modundayken işlem yapmak için setAndAllowWhileIdle() kullanarak tam olmayan bir alarm oluşturun ve alarmdan bir iş başlatın.

Uygun kesin zamanlı alarm iznini beyan etme

Uygulamanız Android 12 veya sonraki sürümleri hedefliyorsa "Alarmlar ve hatırlatıcılar" özel uygulama erişimini edinmeniz gerekir. Bunu yapmak için aşağıdaki kod snippet'inde gösterildiği gibi uygulamanızın manifest dosyasında SCHEDULE_EXACT_ALARM iznini beyan edin:

<manifest ...>
    <uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM"/>
    <application ...>
        ...
    </application>
</manifest>

Uygulamanız Android 13 (API düzeyi 33) veya sonraki sürümleri hedefliyorsa SCHEDULE_EXACT_ALARM veya USE_EXACT_ALARM iznini beyan edebilirsiniz.

<manifest ...>
    <uses-permission android:name="android.permission.USE_EXACT_ALARM"/>
    <application ...>
        ...
    </application>
</manifest>

Hem SCHEDULE_EXACT_ALARM hem de USE_EXACT_ALARM izinleri aynı özellikleri işaret etse de farklı şekilde verilir ve farklı kullanım alanlarını destekler. Uygulamanız, yalnızca kullanıcılara yönelik bir işlevi tam olarak zamanlanmış işlemler gerektiriyorsa kesin zamanlı alarmlar kullanmalı ve SCHEDULE_EXACT_ALARM ya da USE_EXACT_ALARM iznini beyan etmelidir.

USE_EXACT_ALARM

SCHEDULE_EXACT_ALARM

  • Kullanıcı tarafından izin verildi
  • Daha geniş kullanım alanı yelpazesi
  • Uygulamalar, iznin iptal edilmediğini doğrulamalıdır.

SCHEDULE_EXACT_ALARM izni, Android 13 (API düzeyi 33) ve sonraki sürümleri hedefleyen uygulamaların yeni yüklemelerine önceden verilmez. Kullanıcı, yedekleme ve geri yükleme işlemiyle uygulama verilerini Android 14 çalıştıran bir cihaza aktarırsa yeni cihazda SCHEDULE_EXACT_ALARM izni reddedilir. Ancak mevcut bir uygulamada bu izin zaten varsa cihaz Android 14'e yükseltildiğinde izin önceden verilmiş olur.

Not: Kesin zamanlı alarm, setExact API'si gibi bir OnAlarmListener nesnesi kullanılarak ayarlanırsa SCHEDULE_EXACT_ALARM izni gerekmez.

SCHEDULE_EXACT_ALARM izni kullanılıyor

USE_EXACT_ALARM izninin aksine SCHEDULE_EXACT_ALARM izninin kullanıcı tarafından verilmesi gerekir. Hem kullanıcı hem de sistem SCHEDULE_EXACT_ALARM iznini iptal edebilir.

Uygulamanıza izin verilip verilmediğini kontrol etmek için kesin zamanlı alarm ayarlamayı denemeden önce canScheduleExactAlarms() öğesini çağırın. Uygulamanızın SCHEDULE_EXACT_ALARM izni iptal edildiğinde uygulamanız durdurulur ve gelecekteki tüm kesin zamanlı alarmlar iptal edilir. Bu, canScheduleExactAlarms() tarafından döndürülen değerin uygulamanızın tüm yaşam döngüsü boyunca geçerli kalacağı anlamına da gelir.

Uygulamanıza SCHEDULE_EXACT_ALARMS izni verildiğinde sistem, uygulamaya ACTION_SCHEDULE_EXACT_ALARM_PERMISSION_STATE_CHANGED yayınını gönderir. Uygulamanız, aşağıdakileri yapan bir yayın alıcısı uygulamalıdır:

  1. Uygulamanızın özel uygulama erişimine sahip olduğunu onaylar. Bunun için canScheduleExactAlarms() numaralı telefonu arayın. Bu kontrol, kullanıcının uygulamanıza izin verdikten hemen sonra izni iptal etmesi durumunda uygulamanızı korur.
  2. Uygulamanızın ihtiyaç duyduğu kesin zamanlı alarmları mevcut durumuna göre yeniden planlar. Bu mantık, uygulamanız ACTION_BOOT_COMPLETED yayını aldığında yaptığı işleme benzer olmalıdır.

Kullanıcılardan SCHEDULE_EXACT_ALARM izni vermelerini isteyin

Bu seçeneğin adı &quot;Alarm ve hatırlatıcı ayarlamasına izin ver&quot;dir.
Şekil 1. Kullanıcıların uygulamanızın kesin zamanlı alarmlar ayarlamasına izin verebileceği, sistem ayarlarındaki "Alarmlar ve hatırlatıcılar" özel uygulama erişimi sayfası.

Gerekirse kullanıcıları sistem ayarlarındaki Alarmlar ve hatırlatıcılar ekranına yönlendirebilirsiniz (Şekil 1'de gösterildiği gibi). Bunun için aşağıdaki adımları uygulayın:

  1. Uygulamanızın kullanıcı arayüzünde, uygulamanızın neden kesin zamanlı alarmlar planlaması gerektiğini kullanıcıya açıklayın.
  2. ACTION_REQUEST_SCHEDULE_EXACT_ALARM intent işlemini içeren bir intent çağırın.

Tekrarlanan alarm kurma

Yinelenen alarmlar, sistemin uygulamanızı yinelenen bir programa göre bilgilendirmesine olanak tanır.

Kötü tasarlanmış bir alarm, pilin tükenmesine neden olabilir ve sunuculara önemli bir yük bindirebilir. Bu nedenle, Android 4.4 (API düzeyi 19) ve sonraki sürümlerde tüm yinelenen alarmlar kesin olmayan alarmlardır.

Tekrarlanan bir alarm aşağıdaki özelliklere sahiptir:

  • Alarm türü. Daha fazla bilgi için Alarm türü seçme bölümüne bakın.

  • Tetikleme zamanı Belirttiğiniz tetikleme zamanı geçmişteyse alarm hemen tetiklenir.

  • Alarmın aralığı. Örneğin, günde bir kez, saatte bir veya 5 dakikada bir.

  • Alarm tetiklendiğinde etkinleşen, beklemede olan intent. Aynı beklemede olan intent'i kullanan ikinci bir alarm ayarladığınızda bu alarm, orijinal alarmın yerini alır.

Bir PendingIntent() iptal etmek için FLAG_NO_CREATE öğesini PendingIntent.getService() öğesine ileterek intent'in bir örneğini (varsa) alın, ardından bu intent'i AlarmManager.cancel() öğesine iletin.

Kotlin

val alarmManager =
    context.getSystemService(Context.ALARM_SERVICE) as? AlarmManager
val pendingIntent =
    PendingIntent.getService(context, requestId, intent,
                                PendingIntent.FLAG_NO_CREATE)
if (pendingIntent != null && alarmManager != null) {
  alarmManager.cancel(pendingIntent)
}

Java

AlarmManager alarmManager =
    (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
PendingIntent pendingIntent =
    PendingIntent.getService(context, requestId, intent,
                                PendingIntent.FLAG_NO_CREATE);
if (pendingIntent != null && alarmManager != null) {
  alarmManager.cancel(pendingIntent);
}

Alarm türü seçin

Tekrarlanan alarm kullanırken ilk dikkat edilmesi gereken noktalardan biri, alarmın türüdür.

Alarmlar için iki genel saat türü vardır: "geçen gerçek zaman" ve "gerçek zamanlı saat" (RTC). Geçen gerçek zaman, referans olarak "sistem başlatıldıktan sonra geçen süreyi" kullanır. Gerçek zamanlı saat ise UTC (duvar saati) saatini kullanır. Bu, geçen gerçek zamanın, saat diliminden veya yerel ayardan etkilenmediği için zamanın geçişine göre alarm ayarlamaya (örneğin, her 30 saniyede bir çalan alarm) uygun olduğu anlamına gelir. Gerçek zamanlı saat türü, mevcut yerel ayara bağlı alarmlar için daha uygundur.

Her iki türün de ekran kapalıysa cihazın CPU'sunu uyandırmayı belirten bir"uyandırma" sürümü vardır. Bu, alarmın planlanan zamanda çalmasını sağlar. Uygulamanızda zamana bağlı bir durum varsa bu özellikten yararlanabilirsiniz. Örneğin, belirli bir işlemi gerçekleştirmek için sınırlı bir zaman aralığı varsa. Alarm türünüzün uyandırma sürümünü kullanmıyorsanız cihazınız bir sonraki uyanışında tüm yinelenen alarmlar çalar.

Alarmınızın belirli bir aralıkta (örneğin, yarım saatte bir) tetiklenmesi gerekiyorsa geçen gerçek zaman türlerinden birini kullanın. Genel olarak bu, daha iyi bir seçimdir.

Alarmınızın günün belirli bir saatinde çalması gerekiyorsa saate dayalı gerçek zamanlı saat türlerinden birini seçin. Ancak bu yaklaşımın bazı dezavantajları olabilir. Uygulama diğer yerel ayarlara iyi çevrilmeyebilir ve kullanıcı cihazın saat ayarını değiştirirse uygulamanızda beklenmedik davranışlara neden olabilir. Gerçek zamanlı saat alarmı türünün kullanılması, yukarıda açıklandığı gibi iyi ölçeklenmez. Mümkünse "geçen gerçek zaman" alarmı kullanmanızı öneririz.

Türlerin listesi aşağıda verilmiştir:

  • ELAPSED_REALTIME: Beklemede olan intent'i, cihazın başlatılmasından bu yana geçen süreye göre tetikler ancak cihazı uyandırmaz. Geçen süre, cihazın uyku modunda olduğu zamanları da içerir.

  • ELAPSED_REALTIME_WAKEUP: Cihazın başlatılmasından itibaren belirtilen süre geçtikten sonra cihazı uyandırır ve beklemede olan intent'i tetikler.

  • RTC: Beklemede olan intent'i belirtilen zamanda tetikler ancak cihazı uyandırmaz.

  • RTC_WAKEUP: Beklemede olan intent'i belirtilen zamanda tetiklemek için cihazı uyandırır.

Geçen gerçek zamanlı alarmlara örnekler

ELAPSED_REALTIME_WAKEUP kullanımına dair bazı örnekler:

Alarmı 30 dakika sonra ve ondan sonra her 30 dakikada bir çalacak şekilde ayarlamak için cihazı uyandırın:

Kotlin

// Hopefully your alarm will have a lower frequency than this!
alarmMgr?.setInexactRepeating(
        AlarmManager.ELAPSED_REALTIME_WAKEUP,
        SystemClock.elapsedRealtime() + AlarmManager.INTERVAL_HALF_HOUR,
        AlarmManager.INTERVAL_HALF_HOUR,
        alarmIntent
)

Java

// Hopefully your alarm will have a lower frequency than this!
alarmMgr.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
        SystemClock.elapsedRealtime() + AlarmManager.INTERVAL_HALF_HOUR,
        AlarmManager.INTERVAL_HALF_HOUR, alarmIntent);

Bir dakika içinde tek seferlik (tekrarlanmayan) bir alarmı tetiklemek için cihazı uyandırın:

Kotlin

private var alarmMgr: AlarmManager? = null
private lateinit var alarmIntent: PendingIntent
...
alarmMgr = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
alarmIntent = Intent(context, AlarmReceiver::class.java).let { intent ->
    PendingIntent.getBroadcast(context, 0, intent, 0)
}

alarmMgr?.set(
        AlarmManager.ELAPSED_REALTIME_WAKEUP,
        SystemClock.elapsedRealtime() + 60 * 1000,
        alarmIntent
)

Java

private AlarmManager alarmMgr;
private PendingIntent alarmIntent;
...
alarmMgr = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(context, AlarmReceiver.class);
alarmIntent = PendingIntent.getBroadcast(context, 0, intent, 0);

alarmMgr.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
        SystemClock.elapsedRealtime() +
        60 * 1000, alarmIntent);

Gerçek zamanlı saat alarmlarına örnekler

RTC_WAKEUP kullanımına dair bazı örnekleri aşağıda bulabilirsiniz.

Alarmı yaklaşık 14:00'te çalmak için cihazı uyandırın ve her gün aynı saatte bir kez tekrarlayın:

Kotlin

// Set the alarm to start at approximately 2:00 p.m.
val calendar: Calendar = Calendar.getInstance().apply {
    timeInMillis = System.currentTimeMillis()
    set(Calendar.HOUR_OF_DAY, 14)
}

// With setInexactRepeating(), you have to use one of the AlarmManager interval
// constants--in this case, AlarmManager.INTERVAL_DAY.
alarmMgr?.setInexactRepeating(
        AlarmManager.RTC_WAKEUP,
        calendar.timeInMillis,
        AlarmManager.INTERVAL_DAY,
        alarmIntent
)

Java

// Set the alarm to start at approximately 2:00 p.m.
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.HOUR_OF_DAY, 14);

// With setInexactRepeating(), you have to use one of the AlarmManager interval
// constants--in this case, AlarmManager.INTERVAL_DAY.
alarmMgr.setInexactRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
        AlarmManager.INTERVAL_DAY, alarmIntent);

Alarmı tam olarak 08:30'da ve sonrasında her 20 dakikada bir çalmak için cihazı uyandırın:

Kotlin

private var alarmMgr: AlarmManager? = null
private lateinit var alarmIntent: PendingIntent
...
alarmMgr = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
alarmIntent = Intent(context, AlarmReceiver::class.java).let { intent ->
    PendingIntent.getBroadcast(context, 0, intent, 0)
}

// Set the alarm to start at 8:30 a.m.
val calendar: Calendar = Calendar.getInstance().apply {
    timeInMillis = System.currentTimeMillis()
    set(Calendar.HOUR_OF_DAY, 8)
    set(Calendar.MINUTE, 30)
}

// setRepeating() lets you specify a precise custom interval--in this case,
// 20 minutes.
alarmMgr?.setRepeating(
        AlarmManager.RTC_WAKEUP,
        calendar.timeInMillis,
        1000 * 60 * 20,
        alarmIntent
)

Java

private AlarmManager alarmMgr;
private PendingIntent alarmIntent;
...
alarmMgr = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(context, AlarmReceiver.class);
alarmIntent = PendingIntent.getBroadcast(context, 0, intent, 0);

// Set the alarm to start at 8:30 a.m.
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.HOUR_OF_DAY, 8);
calendar.set(Calendar.MINUTE, 30);

// setRepeating() lets you specify a precise custom interval--in this case,
// 20 minutes.
alarmMgr.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
        1000 * 60 * 20, alarmIntent);

Alarmınızın ne kadar hassas olması gerektiğine karar verin

Daha önce de belirtildiği gibi, alarm türünü seçmek genellikle alarm oluşturmanın ilk adımıdır. Bir diğer fark ise alarmınızın ne kadar hassas olması gerektiğidir. Çoğu uygulama için setInexactRepeating() doğru seçimdir. Bu yöntemi kullandığınızda Android, birden fazla yaklaşık tekrarlanan alarmı senkronize eder ve aynı anda tetikler. Bu sayede pil daha az tüketilir.

Mümkünse kesin zamanlı alarmlar kullanmaktan kaçının. Ancak katı zaman şartları olan nadir uygulamalar için setRepeating() yöntemini çağırarak kesin zamanlı alarm ayarlayabilirsiniz.

setInexactRepeating() ile setRepeating()'te olduğu gibi özel bir aralık belirleyemezsiniz. INTERVAL_FIFTEEN_MINUTES, INTERVAL_DAY gibi aralık sabitlerinden birini kullanmanız gerekir. Tam listeyi AlarmManager sayfasında bulabilirsiniz.

Alarmı iptal etme

Uygulamanıza bağlı olarak alarmı iptal etme özelliğini eklemek isteyebilirsiniz. Bir alarmı iptal etmek için Alarm Yöneticisi'nde cancel() yöntemini çağırın ve artık tetiklemek istemediğiniz PendingIntent öğesini iletin. Örneğin:

Kotlin

// If the alarm has been set, cancel it.
alarmMgr?.cancel(alarmIntent)

Java

// If the alarm has been set, cancel it.
if (alarmMgr!= null) {
    alarmMgr.cancel(alarmIntent);
}

Cihaz yeniden başlatıldığında alarm başlatma

Varsayılan olarak, cihaz kapandığında tüm alarmlar iptal edilir. Bunu önlemek için uygulamanızı, kullanıcı cihazı yeniden başlattığında yinelenen alarmı otomatik olarak yeniden başlatacak şekilde tasarlayabilirsiniz. Bu sayede AlarmManager, kullanıcının alarmı manuel olarak yeniden başlatmasına gerek kalmadan görevini yapmaya devam eder.

İlgili adımlar aşağıdadır:

  1. Uygulamanızın manifest dosyasında RECEIVE_BOOT_COMPLETED iznini ayarlayın. Bu sayede uygulamanız, sistem başlatma işlemini tamamladıktan sonra yayınlanan ACTION_BOOT_COMPLETED öğesini alabilir (Bu, yalnızca uygulama kullanıcı tarafından en az bir kez başlatılmışsa çalışır):

    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
  2. Yayını almak için bir BroadcastReceiver uygulayın:

    Kotlin

    class SampleBootReceiver : BroadcastReceiver() {
    
        override fun onReceive(context: Context, intent: Intent) {
            if (intent.action == "android.intent.action.BOOT_COMPLETED") {
                // Set the alarm here.
            }
        }
    }

    Java

    public class SampleBootReceiver extends BroadcastReceiver {
    
        @Override
        public void onReceive(Context context, Intent intent) {
            if (intent.getAction().equals("android.intent.action.BOOT_COMPLETED")) {
                // Set the alarm here.
            }
        }
    }
  3. Alıcıyı, ACTION_BOOT_COMPLETED işlemini filtreleyen bir intent filtresiyle uygulamanızın manifest dosyasına ekleyin:

    <receiver android:name=".SampleBootReceiver"
            android:enabled="false">
        <intent-filter>
            <action android:name="android.intent.action.BOOT_COMPLETED"></action>
        </intent-filter>
    </receiver>

    Manifest dosyasında, başlatma alıcısının android:enabled="false" olarak ayarlandığına dikkat edin. Bu, uygulama açıkça etkinleştirmediği sürece alıcının çağrılmayacağı anlamına gelir. Bu sayede, başlatma alıcısının gereksiz yere çağrılması önlenir. Bir alıcıyı (örneğin, kullanıcı alarm kurarsa) aşağıdaki şekilde etkinleştirebilirsiniz:

    Kotlin

    val receiver = ComponentName(context, SampleBootReceiver::class.java)
    
    context.packageManager.setComponentEnabledSetting(
            receiver,
            PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
            PackageManager.DONT_KILL_APP
    )

    Java

    ComponentName receiver = new ComponentName(context, SampleBootReceiver.class);
    PackageManager pm = context.getPackageManager();
    
    pm.setComponentEnabledSetting(receiver,
            PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
            PackageManager.DONT_KILL_APP);

    Alıcıyı bu şekilde etkinleştirdiğinizde, kullanıcı cihazı yeniden başlatsa bile etkin kalır. Başka bir deyişle, alıcıyı programatik olarak etkinleştirmek, yeniden başlatma işlemlerinde bile manifest ayarını geçersiz kılar. Alıcı, uygulamanız tarafından devre dışı bırakılana kadar etkin kalır. Bir alıcıyı (ör. kullanıcı bir alarmı iptal ederse) aşağıdaki gibi devre dışı bırakabilirsiniz:

    Kotlin

    val receiver = ComponentName(context, SampleBootReceiver::class.java)
    
    context.packageManager.setComponentEnabledSetting(
            receiver,
            PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
            PackageManager.DONT_KILL_APP
    )

    Java

    ComponentName receiver = new ComponentName(context, SampleBootReceiver.class);
    PackageManager pm = context.getPackageManager();
    
    pm.setComponentEnabledSetting(receiver,
            PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
            PackageManager.DONT_KILL_APP);

Cihaz Doze modundayken alarmları çağırma

Android 6.0 (API düzeyi 23) çalıştıran cihazlar, cihazın pil ömrünü uzatmaya yardımcı olan Doze modunu destekler. Cihaz Doze modundayken alarmlar çalmaz. Planlanan alarmlar, cihaz Doze modundan çıkana kadar ertelenir. Cihaz boştayken bile iş tamamlamanız gerekiyorsa kullanabileceğiniz birkaç seçenek vardır:

  • Kesin zamanlı alarm kurun.

  • Arka planda çalışma gerçekleştirmek için tasarlanmış WorkManager API'yi kullanın. Sistemin, işinizi hızlandırması gerektiğini belirtebilirsiniz. Böylece işiniz mümkün olan en kısa sürede tamamlanır. Daha fazla bilgi için WorkManager ile görevleri planlama başlıklı makaleyi inceleyin.

En iyi uygulamalar

Tekrarlanan alarmınızı tasarlarken yaptığınız her seçim, uygulamanızın sistem kaynaklarını nasıl kullandığı (veya kötüye kullandığı) konusunda sonuçlar doğurabilir. Örneğin, bir sunucuyla senkronize olan popüler bir uygulama düşünün. Senkronizasyon işlemi saat bazlıysa ve uygulamanın her örneği saat 23:00'te senkronize ediliyorsa sunucudaki yük, yüksek gecikmeye ve hatta "hizmet reddine" neden olabilir. Alarmları kullanırken aşağıdaki en iyi uygulamalardan yararlanın:

  • Tekrarlanan bir alarm sonucunda tetiklenen ağ isteklerine rastgelelik (titreşim) ekleyin:

    • Alarm tetiklendiğinde yerel işleri yapma "Yerel çalışma", sunucuya erişmeyen veya sunucudan veri gerektirmeyen her şey anlamına gelir.

    • Aynı zamanda, ağ isteklerini içeren alarmı rastgele bir zaman diliminde tetiklenecek şekilde planlayın.

  • Alarm sıklığını minimumda tutun.

  • Cihazı gereksiz yere uyandırmayın (Bu davranış, Alarm türü seçme bölümünde açıklandığı gibi alarm türüne göre belirlenir).

  • Alarmınızın tetiklenme zamanını gerektiğinden daha hassas ayarlamayın.

    setRepeating() yerine setInexactRepeating() kullanın. setInexactRepeating() kullandığınızda Android, birden fazla uygulamadaki yinelenen alarmları senkronize eder ve aynı anda tetikler. Bu, sistemin cihazı uyandırması gereken toplam sayıyı azaltır ve böylece pil tüketimini azaltır. Android 4.4 (API düzeyi 19) itibarıyla tüm yinelenen alarmlar kesin olmayan alarm olarak ayarlanır. setInexactRepeating(), setRepeating()'a göre daha iyi bir yöntem olsa da bir uygulamanın her örneği sunucuya aynı anda erişirse sunucuyu yine de zorlayabilir. Bu nedenle, ağ istekleri için alarmlarınıza daha önce de bahsettiğimiz gibi biraz rastgelelik ekleyin.

  • Mümkünse alarmınızı saate göre ayarlamayın.

    Kesin bir tetikleme zamanına dayalı yinelenen alarmlar iyi ölçeklenmez. Mümkünse ELAPSED_REALTIME kullanın. Farklı alarm türleri aşağıdaki bölümde daha ayrıntılı olarak açıklanmıştır.