Batas Eksekusi Latar Belakang

Setiap kali aplikasi berjalan di latar belakang, aplikasi akan menggunakan beberapa resource perangkat yang terbatas, seperti RAM. Hal ini dapat mengakibatkan pengalaman pengguna yang terganggu, terutama jika pengguna menggunakan aplikasi yang membutuhkan banyak resource, seperti bermain game atau menonton video. Untuk meningkatkan pengalaman pengguna, Android 8.0 (API level 26) memberlakukan batasan pada tindakan yang dapat dilakukan aplikasi saat berjalan di latar belakang. Dokumen ini menjelaskan perubahan pada sistem operasi, dan cara mengupdate aplikasi agar berfungsi dengan baik dalam batasan baru.

Ringkasan

Banyak aplikasi dan layanan Android yang bisa dijalankan secara bersamaan. Misalnya, pengguna dapat bermain game di satu jendela sambil menjelajahi web di jendela lain, dan menggunakan aplikasi ketiga untuk memutar musik. Makin banyak aplikasi yang berjalan sekaligus, makin banyak beban yang ditempatkan pada sistem. Jika aplikasi atau layanan tambahan berjalan di latar belakang, hal ini akan menempatkan beban tambahan pada sistem, yang dapat menyebabkan pengalaman pengguna yang buruk; misalnya, aplikasi musik mungkin tiba-tiba dinonaktifkan.

Untuk mengurangi kemungkinan masalah ini, Android 8.0 menerapkan batasan pada hal yang dapat dilakukan aplikasi saat pengguna tidak berinteraksi langsung dengannya. Aplikasi dibatasi dengan dua cara:

  • Batasan Layanan Latar Belakang: Saat aplikasi tidak ada aktivitas, ada batasan penggunaan layanan latar belakangnya. Hal ini tidak berlaku untuk layanan latar depan, yang lebih terlihat oleh pengguna.

  • Batasan Siaran: Dengan pengecualian terbatas, aplikasi tidak dapat menggunakan manifesnya untuk mendaftar ke siaran implisit. Mereka masih dapat mendaftar untuk siaran ini saat runtime, dan mereka dapat menggunakan manifes untuk mendaftar ke siaran vulgar dan siaran yang ditargetkan secara khusus untuk aplikasi mereka.

Pada umumnya, aplikasi dapat mengatasi batasan ini dengan menggunakan tugas JobScheduler. Pendekatan ini memungkinkan aplikasi mengatur untuk melakukan pekerjaan saat aplikasi tidak berjalan secara aktif, tetapi tetap memberi sistem kelonggaran untuk menjadwalkan tugas ini dengan cara yang tidak memengaruhi pengalaman pengguna. Android 8.0 menawarkan beberapa peningkatan pada JobScheduler yang mempermudah penggantian layanan dan penerima siaran dengan tugas terjadwal; untuk informasi selengkapnya, lihat Peningkatan JobScheduler.

Batasan Layanan Latar Belakang

Layanan yang berjalan di latar belakang dapat menggunakan resource perangkat, yang berpotensi menghasilkan pengalaman pengguna yang lebih buruk. Untuk mengurangi masalah ini, sistem menerapkan sejumlah batasan pada layanan.

Sistem akan membedakan antara aplikasi latar depan dan latar belakang. (Definisi latar belakang untuk tujuan pembatasan layanan berbeda dengan definisi yang digunakan oleh pengelolaan memori; aplikasi mungkin berada di latar belakang sehubungan dengan pengelolaan memori, tetapi berada di latar depan sehubungan dengan kemampuannya untuk meluncurkan layanan.) Aplikasi dianggap berada di latar depan jika salah satu dari pernyataan berikut terpenuhi:

  • Aplikasi memiliki aktivitas yang terlihat, baik yang telah dimulai maupun yang dihentikan sementara.
  • Aplikasi memiliki layanan latar depan.
  • Aplikasi latar depan lainnya terhubung ke aplikasi tersebut, baik melalui pengikatan ke salah satu layanannya maupun melalui penggunaan salah satu penyedia kontennya. Misalnya, aplikasi berada di latar depan jika aplikasi lain terikat ke:
    • IME
    • Layanan wallpaper
    • Pemroses notifikasi
    • Layanan suara atau teks

Jika tidak ada satu pun dari kondisi tersebut yang benar, aplikasi akan dianggap berada di latar belakang.

Saat berada di latar depan, aplikasi dapat membuat dan menjalankan layanan latar depan dan latar belakang dengan bebas. Saat aplikasi beralih ke latar belakang, aplikasi memiliki periode beberapa menit saat aplikasi masih diizinkan untuk membuat dan menggunakan layanan. Di akhir periode tersebut, aplikasi dianggap tidak ada aktivitas. Pada saat ini, sistem akan menghentikan layanan latar belakang aplikasi, seolah-olah aplikasi telah memanggil metode Service.stopSelf() layanan.

Dalam keadaan tertentu, aplikasi latar belakang ditempatkan di daftar yang diizinkan sementara selama beberapa menit. Saat berada dalam daftar yang diizinkan, aplikasi dapat meluncurkan layanan tanpa batasan, dan layanan latar belakangnya diizinkan untuk berjalan. Aplikasi ditempatkan di daftar yang diizinkan saat menangani tugas yang terlihat oleh pengguna, seperti:

Dalam banyak kasus, aplikasi Anda dapat mengganti layanan latar belakang dengan tugas JobScheduler. Misalnya, CoolPhotoApp perlu memeriksa apakah pengguna telah menerima foto yang dibagikan dari teman, meskipun aplikasi tidak berjalan di latar depan. Sebelumnya, aplikasi menggunakan layanan latar belakang yang diperiksa dengan penyimpanan cloud aplikasi. Untuk bermigrasi ke Android 8.0 (API level 26), developer mengganti layanan latar belakang dengan tugas terjadwal, yang diluncurkan secara berkala, membuat kueri server, lalu berhenti.

Sebelum Android 8.0, cara biasa untuk membuat layanan latar depan adalah membuat layanan latar belakang, lalu mempromosikan layanan tersebut ke latar depan. Dengan Android 8.0, ada komplikasi; sistem tidak mengizinkan aplikasi latar belakang membuat layanan latar belakang. Oleh karena itu, Android 8.0 memperkenalkan metode baru startForegroundService() untuk memulai layanan baru di latar depan. Setelah sistem membuat layanan, aplikasi memiliki waktu lima detik untuk memanggil metode [startForeground()](/reference/android/app/Service#startForeground(int, android.app.Notification) layanan untuk menampilkan notifikasi layanan baru yang terlihat pengguna. Jika aplikasi tidak memanggil startForeground() dalam batas waktu, sistem akan menghentikan layanan dan mendeklarasikan aplikasi sebagai ANR.

Batasan Siaran

Jika aplikasi mendaftar untuk menerima siaran, penerima aplikasi akan menggunakan resource setiap kali siaran dikirim. Hal ini dapat menyebabkan masalah jika terlalu banyak aplikasi mendaftar untuk menerima siaran berdasarkan peristiwa sistem; peristiwa sistem yang memicu siaran dapat menyebabkan semua aplikasi tersebut menggunakan resource secara berturut-turut dengan cepat, sehingga mengganggu pengalaman pengguna. Untuk mengurangi masalah ini, Android 7.0 (API level 24) menempatkan batasan pada siaran, seperti yang dijelaskan dalam Pengoptimalan Latar Belakang. Android 8.0 (API level 26) membuat pembatasan-pembatasan ini lebih ketat.

  • Aplikasi yang menargetkan Android 8.0 atau yang lebih tinggi tidak dapat lagi mendaftarkan penerima siaran untuk siaran implisit dalam manifesnya, kecuali jika siaran dibatasi untuk aplikasi tersebut secara khusus. Siaran implisit adalah siaran yang tidak menargetkan komponen tertentu dalam aplikasi. Misalnya, ACTION_PACKAGE_REPLACED dikirim ke semua pemroses terdaftar di semua aplikasi, yang memberi tahu mereka bahwa beberapa paket di perangkat telah diganti. Karena siaran bersifat implisit, siaran tidak akan dikirim ke penerima yang terdaftar dalam manifes di aplikasi yang menargetkan Android 8.0 atau yang lebih tinggi. ACTION_MY_PACKAGE_REPLACED juga merupakan siaran implisit, tetapi karena hanya dikirim ke aplikasi yang paketnya diganti, siaran ini akan dikirim ke penerima yang terdaftar dalam manifes.
  • Aplikasi tetap bisa mendaftar untuk mendapatkan siaran eksplisit dalam manifesnya.
  • Aplikasi dapat menggunakan Context.registerReceiver() saat runtime untuk mendaftarkan penerima untuk siaran apa pun, baik implisit maupun eksplisit.
  • Siaran yang memerlukan izin tanda tangan dikecualikan dari pembatasan ini, karena siaran ini hanya dikirim ke aplikasi yang ditandatangani dengan sertifikat yang sama, bukan ke semua aplikasi di perangkat.

Dalam banyak kasus, aplikasi yang sebelumnya terdaftar untuk siaran implisit dapat mendapatkan fungsi serupa menggunakan tugas JobScheduler. Misalnya, aplikasi foto sosial mungkin perlu melakukan pembersihan pada datanya dari waktu ke waktu, dan lebih memilih untuk melakukannya saat perangkat terhubung ke pengisi daya. Sebelumnya, aplikasi mendaftarkan penerima untuk ACTION_POWER_CONNECTED dalam manifesnya; saat aplikasi menerima siaran tersebut, aplikasi akan memeriksa apakah pembersihan diperlukan. Untuk bermigrasi ke Android 8.0 atau yang lebih tinggi, aplikasi akan menghapus penerima tersebut dari manifesnya. Sebagai gantinya, aplikasi menjadwalkan tugas pembersihan yang berjalan saat perangkat tidak ada aktivitas dan sedang mengisi daya.

Panduan Migrasi

Secara default, perubahan ini hanya memengaruhi aplikasi yang menargetkan Android 8.0 (API level 26) atau yang lebih tinggi. Namun, pengguna dapat mengaktifkan batasan ini untuk aplikasi apa pun dari layar Setelan, meskipun aplikasi menargetkan API level yang lebih rendah dari 26. Anda mungkin perlu mengupdate aplikasi untuk mematuhi batasan baru.

Periksa untuk mengetahui cara aplikasi Anda menggunakan layanan. Jika aplikasi Anda mengandalkan layanan yang berjalan di latar belakang saat aplikasi tidak ada aktivitas, Anda harus menggantinya. Solusi yang memungkinkan antara lain:

  • Jika aplikasi Anda perlu membuat layanan latar depan saat aplikasi berada di latar belakang, gunakan metode startForegroundService(), bukan startService().
  • Jika layanan terlihat oleh pengguna, maka jadikan layanan latar depan. Misalnya, layanan yang memutar audio harus selalu berupa layanan latar depan. Buat layanan menggunakan metode startForegroundService(), bukan startService().
  • Temukan cara untuk menduplikasi fungsi layanan dengan tugas terjadwal. Jika layanan tidak melakukan sesuatu yang langsung terlihat oleh pengguna, Anda umumnya dapat menggunakan tugas terjadwal.
  • Gunakan FCM untuk membangunkan aplikasi secara selektif saat peristiwa jaringan terjadi, bukan melakukan polling di latar belakang.
  • Tangguhkan pekerjaan latar belakang hingga aplikasi berada di latar depan dengan sendirinya.

Tinjau penerima siaran yang ditentukan dalam manifes aplikasi Anda. Jika manifes mendeklarasikan penerima untuk siaran implisit yang terpengaruh, Anda harus menggantinya. Solusi yang memungkinkan antara lain:

  • Buat penerima saat runtime dengan memanggil Context.registerReceiver(), bukan mendeklarasikan penerima dalam manifes.
  • Gunakan tugas terjadwal untuk memeriksa kondisi yang akan memicu siaran implisit.