Arka plan işlemleri bellek ve pili yoğun olarak kullanıyor olabilir. Örneğin, dolaylı bir yayın, dinlemek için kaydedilmiş birçok arka plan işlemini başlatabilir (bu işlemler pek işe yaramasa bile). Bu değişiklik hem cihaz performansını hem de kullanıcı deneyimini önemli ölçüde etkileyebilir.
Bu sorunu gidermek için Android 7.0 (API düzeyi 24) aşağıdaki kısıtlamaları uygular:
- Android 7.0 (API düzeyi 24) ve sonraki sürümleri hedefleyen uygulamalar, yayın alıcılarını manifest dosyalarında beyan ederlerse
CONNECTIVITY_ACTION
yayınları almazlar.BroadcastReceiver
cihazlarınıContext.registerReceiver()
ile kaydetmelerine rağmen bu uygulama hâlâ geçerli olan uygulamalarCONNECTIVITY_ACTION
yayını alır. - Uygulamalar
ACTION_NEW_PICTURE
veyaACTION_NEW_VIDEO
yayınlarını gönderemez veya alamaz. Bu optimizasyon, yalnızca Android 7.0 (API düzeyi 24) sürümünü hedefleyen uygulamaları değil, tüm uygulamaları etkiler.
Uygulamanız bu amaçlardan herhangi birini kullanıyorsa Android 7.0 veya sonraki sürümleri çalıştıran cihazları doğru şekilde hedefleyebilmek için bu bağımlılıkları en kısa sürede kaldırmalısınız. Android çerçevesi, bu dolaylı yayınlara duyulan ihtiyacı azaltmak için çeşitli çözümler sunar. Örneğin, JobScheduler
ve yeni WorkManager, sınırsız bir ağa bağlantı gibi belirtilen koşullar karşılandığında ağ işlemlerini planlamak için sağlam mekanizmalar sağlar. Artık içerik sağlayıcılardaki değişikliklere tepki vermek için JobScheduler
aracını da kullanabilirsiniz. JobInfo
nesneleri, JobScheduler
hizmetinin işlerinizi planlamak için kullandığı parametreleri içerir. İş koşulları karşılandığında sistem, bu işi uygulamanızın JobService
bölümünde çalıştırır.
Bu sayfada, uygulamanızı bu yeni kısıtlamalara uyarlamak için JobScheduler
gibi alternatif yöntemleri nasıl kullanacağınızı öğreneceksiniz.
Kullanıcı tarafından başlatılan kısıtlamalar
Kullanıcı, sistem ayarlarındaki Pil kullanımı sayfasında aşağıdaki seçeneklerden birini belirleyebilir:
- Kısıtlanmamış: Daha fazla pil harcayabilecek tüm arka plan çalışmalarına izin verilir.
- Optimize edilmiş (varsayılan): Kullanıcının uygulamayla nasıl etkileşimde bulunduğuna bağlı olarak bir uygulamanın arka plan çalışması gerçekleştirme becerisini optimize edin.
- Kısıtlanmış: Bir uygulamanın arka planda çalışmasını tamamen engeller. Uygulamalar beklendiği gibi çalışmayabilir.
Bir uygulama Android Vitals bölümünde açıklanan bazı kötü davranışlar sergiliyorsa sistem, kullanıcıdan ilgili uygulamanın sistem kaynaklarına erişimini kısıtlamasını isteyebilir.
Sistem bir uygulamanın çok fazla kaynak tükettiğini fark ederse kullanıcıyı bilgilendirir ve kullanıcıya uygulamanın işlemlerini kısıtlama seçeneği sunar. Bildirimi tetikleyebilecek davranışlar şunlardır:
- Aşırı sayıda uyanık kalma kilidi: Ekran kapalıyken bir saat süreyle 1 kısmi uyanık kalma kilidi tutulur
- Aşırı arka plan hizmetleri: Uygulama 26'dan düşük API düzeylerini hedefliyorsa ve aşırı arka plan hizmetleri içeriyorsa
Uygulanan tam kısıtlamalar cihaz üreticisi tarafından belirlenir. Örneğin, Android 9 (API düzeyi 28) veya sonraki sürümleri çalıştıran AOSP derlemelerinde, arka planda "kısıtlı" durumunda çalışan uygulamalar aşağıdaki sınırlamalara tabidir:
- Ön plan hizmetleri başlatılamıyor
- Mevcut ön plan hizmetleri ön plandan kaldırılır
- Alarmlar tetiklenmez
- İşler yürütülmez
Ayrıca, bir uygulama Android 13'ü (API düzeyi 33) veya sonraki sürümleri hedefliyorsa ve"kısıtlanmış" durumdaysa sistem, başka nedenlerle başlatılana kadar BOOT_COMPLETED
yayınını veya LOCKED_BOOT_COMPLETED
yayınını yayınlamaz.
Belirli kısıtlamalar, Güç yönetimi kısıtlamaları bölümünde listelenir.
Ağ etkinliği yayınları almayla ilgili kısıtlamalar
Android 7.0'ı (API düzeyi 24) hedefleyen uygulamalar, manifestlerinde almak için kaydolurlarsa CONNECTIVITY_ACTION
yayınları almazlar ve bu yayına bağlı işlemler başlamaz. Bu, cihaz sınırsız bir ağa bağlandığında ağ değişikliklerini dinlemek veya toplu ağ etkinlikleri gerçekleştirmek isteyen uygulamalar için bir sorun oluşturabilir. Bu kısıtlamayı aşmaya yönelik çeşitli çözümler Android çerçevesinde zaten mevcuttur ancak doğru olanı seçmek uygulamanızın ne başarmasını istediğinize bağlıdır.
Not: Context.registerReceiver()
uygulaması ile kaydolan bir BroadcastReceiver
, bu yayınları uygulama çalışırken almaya devam eder.
Sınırsız bağlantılarda ağ işleri planlama
JobInfo
nesnenizi oluşturmak için JobInfo.Builder
sınıfını kullanırken setRequiredNetworkType()
yöntemini uygulayın ve JobInfo.NETWORK_TYPE_UNMETERED
değerini bir iş parametresi olarak iletin. Aşağıdaki kod örneği, cihaz sınırsız bir ağa bağlanıp şarj olurken çalışacak şekilde bir plan yapar:
Kotlin
const val MY_BACKGROUND_JOB = 0 ... fun scheduleJob(context: Context) { val jobScheduler = context.getSystemService(Context.JOB_SCHEDULER_SERVICE) as JobScheduler val job = JobInfo.Builder( MY_BACKGROUND_JOB, ComponentName(context, MyJobService::class.java) ) .setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED) .setRequiresCharging(true) .build() jobScheduler.schedule(job) }
Java
public static final int MY_BACKGROUND_JOB = 0; ... public static void scheduleJob(Context context) { JobScheduler js = (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE); JobInfo job = new JobInfo.Builder( MY_BACKGROUND_JOB, new ComponentName(context, MyJobService.class)) .setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED) .setRequiresCharging(true) .build(); js.schedule(job); }
İşinizin koşulları karşılandığında uygulamanız, belirtilen JobService.class
içinde onStartJob()
yöntemini çalıştırmak için bir geri arama alır. JobScheduler
uygulamasının diğer örneklerini görmek için Job Scheduler örnek uygulamasına bakın.
JobPlanr'ın yeni bir alternatifi olan WorkManager, uygulama işleminin etkin olup olmamasına bakılmaksızın, tamamlanması gereken garantili görevleri arka planda planlamanıza olanak tanıyan bir API'dir. WorkManager, cihaz API düzeyi gibi faktörlere göre işi (doğrudan uygulama sürecinizdeki bir mesaj dizisinde veya JobPlanr, FirebaseJobDispatcher veya AlarmManager'ı kullanarak) çalıştırmak için uygun yöntemi seçer. Ayrıca WorkManager, Play hizmetlerini zorunlu kılmaz ve görevleri birbirine bağlama veya görevin durumunu kontrol etme gibi çeşitli gelişmiş özellikler sunar. Daha fazla bilgi edinmek için WorkManager konusuna bakın.
Uygulama çalışırken ağ bağlantısını izleyin
Çalışmakta olan uygulamalar, kayıtlı BroadcastReceiver
cihazıyla CONNECTIVITY_CHANGE
bilgisini dinlemeye devam edebilir. Ancak ConnectivityManager
API, yalnızca belirtilen ağ koşulları karşılandığında geri çağırma isteğinde bulunmak için daha güçlü bir yöntem sağlar.
NetworkRequest
nesneleri, ağ geri çağırma parametrelerini NetworkCapabilities
açısından tanımlar. NetworkRequest.Builder
sınıfıyla NetworkRequest
nesne 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 uygulamak için bir geri çağırma alır.
Uygulama, çıkış yapıncaya veya unregisterNetworkCallback()
işlevini çağırana kadar geri çağırma almaya devam eder.
Resim ve video yayını almayla ilgili kısıtlamalar
Android 7.0 (API düzeyi 24) sürümünde uygulamalar ACTION_NEW_PICTURE
veya ACTION_NEW_VIDEO
yayınları gönderip alamaz. Bu kısıtlama, yeni bir resim veya videonun işlenmesi için birkaç uygulamanın uyanması gerektiğinde performansın ve kullanıcı deneyiminin etkilerini azaltmaya yardımcı olur. Android 7.0 (API düzeyi 24), alternatif bir çözüm sağlamak için JobInfo
ve JobParameters
özelliklerini kapsar.
İçerik URI değişikliklerinde işleri tetikleme
Android 7.0 (API düzeyi 24), içerik URI değişikliklerindeki işleri tetiklemek için aşağıdaki yöntemleri kullanarak JobInfo
API'nin kapsamını genişletir:
-
JobInfo.TriggerContentUri()
- İçerik URI değişikliklerinde iş tetiklemek için gereken parametreleri içerir.
-
JobInfo.Builder.addTriggerContentUri()
-
JobInfo
öğesine birTriggerContentUri
nesnesi geçirir.ContentObserver
, kapsüllenmiş içerik URI'sını izler. Bir işle ilişkili birden fazlaTriggerContentUri
nesnesi varsa sistem, içerik URI'lerinden yalnızca birindeki değişikliği bildirse bile bir geri çağırma sağlar. -
Belirli bir URI'nin alt öğeleri değişirse işi tetiklemek için
TriggerContentUri.FLAG_NOTIFY_FOR_DESCENDANTS
işaretini ekleyin. Bu işaret,registerContentObserver()
parametresine iletilennotifyForDescendants
parametresine karşılık gelir.
Not: TriggerContentUri()
, setPeriodic()
veya setPersisted()
ile birlikte kullanılamaz. İçerik değişikliklerini devamlı olarak izlemek amacıyla, uygulamanın JobService
uygulaması en son geri çağırmanın işlenmesini tamamlamadan önce yeni bir JobInfo
programlayın.
Aşağıdaki örnek kod, sistem içerik URI'sinde (MEDIA_URI
) bir değişiklik bildirdiğinde tetiklenecek bir iş planlar:
Kotlin
const val MY_BACKGROUND_JOB = 0 ... fun scheduleJob(context: Context) { val jobScheduler = context.getSystemService(Context.JOB_SCHEDULER_SERVICE) as JobScheduler val job = JobInfo.Builder( MY_BACKGROUND_JOB, ComponentName(context, MediaContentJob::class.java) ) .addTriggerContentUri( JobInfo.TriggerContentUri( MediaStore.Images.Media.EXTERNAL_CONTENT_URI, JobInfo.TriggerContentUri.FLAG_NOTIFY_FOR_DESCENDANTS ) ) .build() jobScheduler.schedule(job) }
Java
public static final int MY_BACKGROUND_JOB = 0; ... public static void scheduleJob(Context context) { JobScheduler js = (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE); JobInfo.Builder builder = new JobInfo.Builder( MY_BACKGROUND_JOB, new ComponentName(context, MediaContentJob.class)); builder.addTriggerContentUri( new JobInfo.TriggerContentUri(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, JobInfo.TriggerContentUri.FLAG_NOTIFY_FOR_DESCENDANTS)); js.schedule(builder.build()); }
Sistem belirtilen içerik URI'larındaki bir değişikliği bildirdiğinde, uygulamanız bir geri çağırma alır ve MediaContentJob.class
içindeki onStartJob()
yöntemine bir JobParameters
nesnesi iletilir.
İşi hangi içerik yetkililerinin tetiklediğini belirleme
Ayrıca Android 7.0 (API düzeyi 24), uygulamanızın işi hangi içerik yetkilileri ve URI'ler tetiklediği hakkında faydalı bilgiler almasına izin vermek için JobParameters
kapsamını genişletir:
-
Uri[] getTriggeredContentUris()
-
İşi tetikleyen bir URI dizisini döndürür. İşi tetikleyen herhangi bir URI yoksa (ör. iş, son tarih nedeniyle veya başka bir nedenle tetiklendiyse) ya da değiştirilen URI sayısı 50'den fazlaysa bu değer
null
olur. -
String[] getTriggeredContentAuthorities()
-
İşi tetikleyen içerik yetkililerinden oluşan bir dize dizisini döndürür.
Döndürülen dizi
null
değilse hangi URI'lerin değiştiğine dair ayrıntıları almak içingetTriggeredContentUris()
kullanın.
Aşağıdaki örnek kod, JobService.onStartJob()
yöntemini geçersiz kılar ve işi tetikleyen içerik yetkililerini ve URI'ları kaydeder:
Kotlin
override fun onStartJob(params: JobParameters): Boolean { StringBuilder().apply { append("Media content has changed:\n") params.triggeredContentAuthorities?.also { authorities -> append("Authorities: ${authorities.joinToString(", ")}\n") append(params.triggeredContentUris?.joinToString("\n")) } ?: append("(No content)") Log.i(TAG, toString()) } return true }
Java
@Override public boolean onStartJob(JobParameters params) { StringBuilder sb = new StringBuilder(); sb.append("Media content has changed:\n"); if (params.getTriggeredContentAuthorities() != null) { sb.append("Authorities: "); boolean first = true; for (String auth : params.getTriggeredContentAuthorities()) { if (first) { first = false; } else { sb.append(", "); } sb.append(auth); } if (params.getTriggeredContentUris() != null) { for (Uri uri : params.getTriggeredContentUris()) { sb.append("\n"); sb.append(uri); } } } else { sb.append("(No content)"); } Log.i(TAG, sb.toString()); return true; }
Uygulamanızı daha da optimize edin
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 manifeste 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. Android 7.0 (API düzeyi 24) bu sorunların bazılarını azaltmak için gerekli adımları atsa da, uygulamanızı bu arka plan işlemlerini hiç kullanmadan çalışacak şekilde optimize etmeniz önerilir.
Aşağıdaki Android Hata Ayıklama Köprüsü (ADB) komutları, 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
- Arka plan pil kullanımı için kullanıcının uygulamanızı "kısıtlı" duruma getirerek simülasyonunu yapabilirsiniz. Bu ayar, uygulamanızın arka planda çalışmasını engeller. Bunun için bir terminal penceresinde aşağıdaki komutu çalıştırın:
-
$ adb shell cmd appops set <PACKAGE_NAME> RUN_ANY_IN_BACKGROUND deny