Ön plan hizmetlerini kullanıcı tarafından başlatılan veri aktarımı işlerine taşıma

Android 14, uygulamaların ön plan hizmetlerini ne zaman kullanmasına izin verileceği konusunda katı kurallar uygular.

Ayrıca Android 14'te, bir işin kullanıcı tarafından başlatılan veri aktarımı işi olması gerektiğini belirten yeni bir API'yi kullanıma sunuyoruz. Bu API, kullanıcı tarafından başlatılan uzun süreli veri aktarımı (ör. uzaktaki bir sunucudan dosya indirme) gerektiren kullanım alanları için faydalıdır. Bu tür görevler kullanıcı tarafından başlatılan bir veri aktarımı işi kullanmalıdır.

Kullanıcı tarafından başlatılan veri aktarımı işleri kullanıcı tarafından başlatılır. Bu işler bildirim gerektirir, hemen başlar ve sistem koşulları izin verdiği ölçüde uzun bir süre boyunca çalıştırılabilir. Kullanıcı tarafından başlatılan birden fazla veri aktarımı işini eşzamanlı olarak çalıştırabilirsiniz.

Kullanıcı tarafından başlatılan işler, uygulama kullanıcı tarafından görünürken (veya izin verilen koşullardan birinde) planlanmalıdır. Kullanıcı tarafından başlatılan işler, tüm kısıtlamalar karşılandıktan sonra sistem durumu kısıtlamalarına tabi olarak işletim sistemi tarafından yürütülebilir. Sistem, işin ne kadar süre boyunca yürütüleceğini belirlemek için sağlanan tahmini yük boyutunu da kullanabilir.

Kullanıcı tarafından başlatılan veri aktarımı işleri için izin

Kullanıcı tarafından başlatılan veri aktarımı işlerinin çalışması için yeni bir izin gerekir: RUN_USER_INITIATED_JOBS. Sistem bu izni otomatik olarak verir. Uygulama manifestinizde izni beyan etmezseniz sistem bir SecurityException atar.

Kullanıcı tarafından başlatılan veri aktarımı işlerini planlama işlemi

Kullanıcı tarafından başlatılan bir işi çalıştırmak için aşağıdakileri yapın:

  1. JobScheduler ile ilk kez API bildiriyorsanız manifest dosyanızdaki JobService özelliğini ve ilişkili izinleri beyan edin. Ayrıca, veri aktarımınız için somut bir JobService alt sınıfı tanımlayın:

    <service android:name="com.example.app.CustomTransferService"
            android:permission="android.permission.BIND_JOB_SERVICE"
            android:exported="false">
            ...
    </service>
    
    class CustomTransferService : JobService() {
      ...
    }
    
  2. Manifest'inizde RUN_USER_INITIATED_JOBS iznini bildirin:

    <manifest ...>
        <uses-permission android:name="android.permission.RUN_USER_INITIATED_JOBS" />
        <application ...>
            ...
        </application>
    </manifest>
    
  3. JobInfo nesnesi oluştururken yeni setUserInitiated() yöntemini çağırın. İşinizi oluştururken setEstimatedNetworkBytes() yöntemini çağırarak bir yük boyutu tahmini sunmanız da önerilir:

    val networkRequestBuilder = NetworkRequest.Builder()
            .addCapability(NET_CAPABILITY_INTERNET)
            .addCapability(NET_CAPABILITY_NOT_METERED)
            // Add or remove capabilities based on your requirements
            .build()
    
    val jobInfo = JobInfo.Builder()
            // ...
            .setUserInitiated(true)
            .setRequiredNetwork(networkRequestBuilder.build())
            .setEstimatedNetworkBytes(1024 * 1024 * 1024)
            // ...
            .build()
    
  4. Uygulama görünür durumdayken veya izin verilen koşullar listesindeyken işi aktarım başlamadan önce planlayın:

    val jobScheduler: JobScheduler =
        context.getSystemService(Context.JOB_SCHEDULER_SERVICE) as JobScheduler
    jobScheduler.schedule(jobInfo)
    
  5. İş yürütülürken JobService nesnesinde setNotification() yöntemini çağırdığınızdan emin olun. Bu değer, kullanıcının hem Görev Yöneticisi'nde hem de durum çubuğu bildirim alanında işin çalışmakta olduğunu bilmesini sağlamak için kullanılır:

    class CustomTransferService : JobService() {
      override fun onStartJob(params: JobParameters?): Boolean {
          val notification = Notification.Builder(applicationContext, NOTIFICATION_CHANNEL_ID)
                  .setContentTitle("My user-initiated data transfer job")
                  .setSmallIcon(android.R.mipmap.myicon)
                  .setContentText("Job is running")
                  .build()
    
          setNotification(params, notification.id, notification,
                  JobService.JOB_END_NOTIFICATION_POLICY_DETACH)
          // Do the job execution.
      }
    }
    
  6. Kullanıcıyı işin durumu ve ilerlemesi hakkında bilgilendirmek için bildirimi düzenli olarak güncelleyin. Aktarım boyutunu işi planlamadan önce belirleyemiyorsanız veya tahmini aktarım boyutunu güncellemeniz gerekiyorsa aktarım boyutunu öğrenildikten sonra güncellemek için yeni API'yi (updateEstimatedNetworkBytes()) kullanın.

  7. Yürütme tamamlandığında, sisteme işin tamamlandığını veya işin yeniden planlanması gerektiğini bildirmek için jobFinished() yöntemini çağırın.

Kullanıcı tarafından başlatılan veri aktarımı işleri durdurulabilir

Hem kullanıcı hem de sistem, kullanıcı tarafından başlatılan aktarım işlerini durdurabilir.

Kullanıcı tarafından, Görev Yöneticisi'nden

Kullanıcı, Görev Yöneticisi'nde görünen, kullanıcı tarafından başlatılan bir veri aktarımı işini durdurabilir.

Kullanıcı Durdur'a bastığı anda sistem aşağıdakileri yapar:

  • Çalışan diğer tüm işler veya ön plan hizmetleri de dahil olmak üzere uygulamanızın sürecini hemen sonlandırır.
  • Çalışan hiçbir iş için onStopJob() işlevini çağırmaz.
  • Kullanıcının görebildiği işlerin yeniden planlanmasını önler.

Bu nedenlerle, işin sorunsuz bir şekilde durdurulmasına ve yeniden planlanmasına olanak tanımak için iş için gönderilen bildirimde kontroller sağlamanız önerilir.

Özel durumlarda, Görev Yöneticisi'nde işin yanında Durdur düğmesi görünmez veya iş, Görev Yöneticisi'nde hiç gösterilmez.

Sistem tarafından

Normal işlerin aksine, kullanıcı tarafından başlatılan veri aktarımı işleri Uygulama Bekleme Paketleri kotalarından etkilenmez. Ancak, aşağıdaki koşullardan herhangi biri meydana gelirse sistem işi yine de durdurur:

  • Geliştirici tarafından tanımlanan bir kısıtlama artık karşılanmıyor.
  • Sistem, işin veri aktarımı görevini tamamlamak için gerekenden daha uzun süre çalıştığını belirler.
  • Sistemin, sistem sağlığına öncelik vermesi ve artan termal durum nedeniyle işleri durdurması gerekir.
  • Cihaz belleği yetersiz olduğundan uygulama işlemi sonlandırıldı.

İş, sistem tarafından durdurulduğunda (düşük bellek kapasiteli durum tarafından değil) sistem onStopJob() çağrısı yapar ve sistem, optimum olduğunu düşündüğü bir zamanda işi yeniden dener. Uygulamanızın, onStopJob() çağrılmasa bile veri aktarımı durumunu koruyabildiğinden ve onStartJob() tekrar çağrıldığında uygulamanızın bu durumu geri yükleyebileceğinden emin olun.

Kullanıcı tarafından başlatılan veri aktarımı işlerini planlamak için izin verilen koşullar

Uygulamalar yalnızca görünür penceredeyse veya belirli koşullar karşılanıyorsa kullanıcı tarafından başlatılan veri aktarımı işi başlatabilir. Kullanıcı tarafından başlatılan veri aktarımı işinin ne zaman planlanabileceğini belirlemek için sistem, uygulamaların özel durumlarda arka planda işlem başlatmasına izin veren koşul listesinin aynısını uygular. Bu koşul listesi, arka planda başlatılan ön plan hizmeti kısıtlamalarına yönelik muafiyetler grubuyla aynı olmaz.

Önceki ifadenin istisnaları şunlardır:

  • Bir uygulama arka planda işlem başlatabiliyorsa kullanıcı tarafından başlatılan veri aktarımı işlerini arka planda da başlatabilir.
  • Bir uygulamanın Son Kullanılanlar ekranındaki mevcut bir görevin arka yığınında bir etkinliği varsa bu etkinlik tek başına kullanıcı tarafından başlatılan bir veri aktarım işinin çalıştırılmasına izin vermez.

İş, izin verilen koşullar listesinde yer almayan başka bir zamana planlandıysa iş başarısız olur ve RESULT_FAILURE hata kodu döndürür.

Kullanıcı tarafından başlatılan veri aktarımı işleri için izin verilen kısıtlamalar

Android, en uygun noktalarda çalışan işleri desteklemek için her iş türüne kısıtlama atama özelliği sunar. Bu kısıtlamalar Android 13'te zaten kullanılmaktadır.

Not: Aşağıdaki tabloda yalnızca her iş türü arasında farklılık gösteren kısıtlamalar karşılaştırılmaktadır. Tüm kısıtlamalar için JobScheduler geliştirici sayfasına veya iş kısıtlamalarına bakın.

Aşağıdaki tabloda, belirli bir iş kısıtlamasını destekleyen farklı iş türleri ve WorkManager'ın desteklediği iş kısıtlamaları gösterilmektedir. Tabloyu bir iş kısıtlama yönteminin adına göre filtrelemek için tablonun önündeki arama çubuğunu kullanın.

Kullanıcı tarafından başlatılan veri aktarımı işlerinde izin verilen kısıtlamalar şunlardır:

  • setBackoffCriteria(JobInfo.BACKOFF_POLICY_EXPONENTIAL)
  • setClipData()
  • setEstimatedNetworkBytes()
  • setMinimumNetworkChunkBytes()
  • setPersisted()
  • setNamespace()
  • setRequiredNetwork()
  • setRequiredNetworkType()
  • setRequiresBatteryNotLow()
  • setRequiresCharging()
  • setRequiresStorageNotLow()

Test etme

Aşağıdaki listede, uygulamanızın işlerini manuel olarak test etmeyle ilgili bazı adımlar gösterilmektedir:

  • İş kimliğini almak için, oluşturulan işin ardından tanımlanan değeri alın.
  • Bir işi hemen çalıştırmak veya durdurulan bir işi yeniden denemek için bir terminal penceresinde şu komutu çalıştırın:

    adb shell cmd jobscheduler run -f APP_PACKAGE_NAME JOB_ID
    
  • Sistemin bir işi zorla durdurmasını (sistem sağlığı veya kota dışı koşullar nedeniyle) simüle etmek için bir terminal penceresinde aşağıdaki komutu çalıştırın:

    adb shell cmd jobscheduler timeout TEST_APP_PACKAGE TEST_JOB_ID