Arka plan görevleriyle ilgili sistem kısıtlamaları

Arka plan işlemleri, bellek ve pil kullanımını artırabilir. Örneğin, dolaylı bir yayın, bu yayını dinlemek için kaydolan birçok arka plan işlemini başlatabilir. Bu işlemler çok fazla iş yapmasa bile bu durum geçerlidir. Bu durum, hem cihaz performansını hem de kullanıcı deneyimini önemli ölçüde etkileyebilir.

Sistem kısıtlamalarından kaçınmak için arka plan göreviniz için doğru API'yi kullandığınızdan emin olun. Arka plan görevlerine genel bakış dokümanı, ihtiyaçlarınıza uygun API'yi seçmenize yardımcı olur.

Kullanıcı tarafından başlatılan kısıtlamalar

Bir uygulama, Android vitals'da açıklanan kötü davranışlardan bazılarını sergiliyorsa sistem, kullanıcıdan bu uygulamanın sistem kaynaklarına erişimini kısıtlamasını ister.

Sistem, bir uygulamanın aşırı kaynak tükettiğini fark ederse kullanıcıyı bilgilendirir ve uygulamanın işlemlerini kısıtlama seçeneği sunar. Bildirimi tetikleyebilecek davranışlar şunlardır:

  1. Aşırı sayıda uyanık kalma kilidi: Ekran kapalıyken bir saat boyunca tutulan 1 kısmi uyanık kalma kilidi
  2. Aşırı düzeyde arka plan hizmetleri: Uygulama, 26'dan düşük hedef API düzeylerini hedefliyorsa ve aşırı düzeyde arka plan hizmetleri varsa

Uygulanan kısıtlamalar cihaz üreticisi tarafından belirlenir. Örneğin, AOSP derlemelerinde kısıtlanmış uygulamalar, ön planda olmadıkları sürece işleri çalıştıramaz, alarmları tetikleyemez veya ağı kullanamaz.

Ağ etkinliği yayınlarını alma kısıtlamaları

Uygulamalar, manifest dosyalarında CONNECTIVITY_ACTION yayınlarını almak için kaydolursa bu yayınları almaz ve bu yayına bağlı işlemler başlatılmaz. Bu durum, cihaz tarifesiz bir ağa bağlandığında ağ değişikliklerini dinlemek veya toplu ağ etkinlikleri gerçekleştirmek isteyen uygulamalar için sorun oluşturabilir. Android çerçevesinde bu kısıtlamayı aşmak için çeşitli çözümler zaten mevcuttur ancak doğru olanı seçmek, uygulamanızın ne yapmasını istediğinize bağlıdır.

Ölçümsüz bağlantılarda çalışma planlama

WorkRequest oluştururken NetworkType.UNMETERED Constraint ekleyin.

fun scheduleWork(context: Context) {
    val workManager = WorkManager.getInstance(context)
    val workRequest = OneTimeWorkRequestBuilder<MyWorker>()
        .setConstraints(
            Constraints.Builder()
                .setRequiredNetworkType(NetworkType.UNMETERED)
                .build()
        )
        .build()

    workManager.enqueue(workRequest)
}

İşinizle ilgili koşullar karşılandığında uygulamanız, belirtilen Worker sınıfında doWork() yöntemini çalıştırmak için bir geri çağırma alır.

Uygulama çalışırken ağ bağlantısını izleme

Çalışan uygulamalar, kayıtlı bir BroadcastReceiver ile CONNECTIVITY_CHANGE dinlemeye devam edebilir. Ancak ConnectivityManager API'si, yalnızca belirli ağ koşulları karşılandığında geri çağırma isteğinde bulunmak için daha sağlam bir yöntem sunar.

NetworkRequest nesneleri, ağ geri çağırma parametrelerini NetworkCapabilities açısından tanımlar. NetworkRequest.Builder sınıfıyla NetworkRequest nesneleri oluşturursunuz. registerNetworkCallback daha sonra NetworkRequest nesnesini sisteme iletir. Ağ koşulları karşılandığında uygulama, ConnectivityManager.NetworkCallback sınıfında tanımlanan onAvailable() yöntemini yürütmek için bir geri çağırma alır.

Uygulama, çıkış yapana veya unregisterNetworkCallback() işlevini çağırana kadar geri çağırma almaya devam eder.

Resim ve video yayınları alma kısıtlamaları

Uygulamalar ACTION_NEW_PICTURE veya ACTION_NEW_VIDEO yayınları gönderemez ya da alamaz. Bu kısıtlama, yeni bir resim veya videoyu işlemek için birkaç uygulamanın uyanması gerektiğinde performans ve kullanıcı deneyimi üzerindeki etkileri azaltmaya yardımcı olur.

Çalışmayı hangi içerik yetkililerinin tetiklediğini belirleme

WorkerParameters, uygulamanızın hangi içerik yetkililerinin ve URI'ların çalışmayı tetiklediğiyle ilgili faydalı bilgiler almasına olanak tanır:

List<Uri> getTriggeredContentUris()

Çalışmayı tetikleyen URI'lerin listesini döndürür. İşi tetikleyen URI yoksa (örneğin, iş bir son tarih veya başka bir nedenle tetiklendiyse) ya da değiştirilen URI'lerin sayısı 50'den fazlaysa bu alan boş olur.

List<String> getTriggeredContentAuthorities()

Çalışmayı tetikleyen içerik yetkililerinin dize listesini döndürür. Döndürülen liste boş değilse hangi URI'lerin değiştiğiyle ilgili ayrıntıları almak için getTriggeredContentUris() yöntemini kullanın.

Aşağıdaki örnek kod, CoroutineWorker.doWork() yöntemini geçersiz kılar ve işi tetikleyen içerik yetkililerini ve URI'leri kaydeder:

class MyWorker(
    appContext: Context,
    private val params: WorkerParameters
) : CoroutineWorker(appContext, params) {
    override suspend fun doWork(): Result {
        StringBuilder().apply {
            append("Media content has changed:\n")
            params.triggeredContentAuthorities
                .takeIf { it.isNotEmpty() }
                ?.let { authorities ->
                    append("Authorities: ${authorities.joinToString(", ")}\n")
                    append(params.triggeredContentUris.joinToString("\n"))
                } ?: append("(No content)")
            Log.i(TAG, toString())
        }
        return Result.success()
    }
}

Uygulamayı sistem kısıtlamaları altında test etme

Uygulamalarınızı düşük bellekli cihazlarda veya düşük bellek koşullarında çalışacak şekilde optimize etmek, performansı ve kullanıcı deneyimini iyileştirebilir. Arka plan hizmetlerine ve manifestte kayıtlı dolaylı yayın alıcılarına olan bağımlılıkları kaldırmak, uygulamanızın bu tür cihazlarda daha iyi çalışmasına yardımcı olabilir. Uygulamanızı, bu arka plan işlemlerini tamamen kullanmadan çalışacak şekilde optimize etmeniz önerilir.

Bazı ek Android Debug Bridge (ADB) komutları, bu arka plan işlemleri devre dışıyken uygulama davranışını test etmenize yardımcı olabilir:

  • Dolaylı yayınların ve arka plan hizmetlerinin kullanılamadığı koşulları simüle etmek için aşağıdaki komutu girin:

    $ adb shell cmd appops set <package_name> RUN_IN_BACKGROUND ignore

  • Dolaylı yayınları ve arka plan hizmetlerini yeniden etkinleştirmek için aşağıdaki komutu girin:

    $ adb shell cmd appops set <package_name> RUN_IN_BACKGROUND allow

Uygulamanızı daha da optimize etme

Arka plan görevlerinizin davranışını optimize etmenin diğer iyi yolları için Görev planlama API'leri için pil kullanımını optimize etme dokümanlarına bakın.