Pembatasan sistem pada tugas latar belakang

Proses latar belakang dapat menggunakan banyak memori dan daya baterai. Misalnya, siaran implisit dapat memulai banyak proses latar belakang yang telah mendaftar untuk memantau siaran tersebut, meskipun proses itu mungkin tidak begitu berguna. Hal ini dapat berdampak besar pada performa perangkat dan pengalaman pengguna.

Untuk menghindari batasan sistem, pastikan Anda menggunakan API yang tepat untuk tugas latar belakang. Dokumentasi Ringkasan tugas latar belakang membantu Anda memilih API yang tepat untuk kebutuhan Anda.

Larangan yang diinisialisasi pengguna

Jika aplikasi menunjukkan beberapa perilaku buruk yang dijelaskan dalam Android vitals, sistem akan meminta pengguna untuk membatasi akses aplikasi tersebut ke resource sistem.

Jika sistem mendeteksi bahwa aplikasi menggunakan terlalu banyak resource, pengguna akan diberi tahu dan diberi opsi untuk membatasi tindakan aplikasi. Perilaku yang dapat memicu pemberitahuan ini meliputi:

  1. Penguncian layar saat aktif yang berlebihan: 1 penguncian layar saat aktif parsial ditahan selama satu jam saat layar nonaktif
  2. Layanan latar belakang yang berlebihan: Jika aplikasi menargetkan level API di bawah 26 dan memiliki layanan latar belakang yang berlebihan

Pembatasan pasti yang diberlakukan ditentukan oleh produsen perangkat. Misalnya, pada build AOSP, aplikasi yang dibatasi tidak dapat menjalankan tugas, memicu alarm, atau menggunakan jaringan, kecuali jika aplikasi tersebut berada di latar depan.

Pembatasan untuk menerima siaran aktivitas jaringan

Aplikasi tidak menerima siaran CONNECTIVITY_ACTION jika sudah mendaftar untuk menerima siaran tersebut dalam manifesnya. Semua proses yang bergantung pada siaran ini tidak akan dimulai. Hal ini dapat menimbulkan masalah pada aplikasi yang ingin memproses perubahan jaringan atau menjalankan aktivitas jaringan massal saat perangkat tersambung ke jaringan tidak berbayar. Beberapa solusi untuk mengatasi pembatasan ini sudah disediakan dalam framework Android, tetapi pemilihan solusi yang tepat bergantung pada apa yang Anda ingin aplikasi capai.

Menjadwalkan pekerjaan pada koneksi tidak berbayar

Saat membuat WorkRequest, tambahkan NetworkType.UNMETERED Constraint.

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

    workManager.enqueue(workRequest)
}

Saat kondisi tugas terpenuhi, aplikasi Anda akan menerima callback untuk menjalankan metode doWork() dalam class Worker yang ditetapkan.

Memantau konektivitas jaringan selagi aplikasi berjalan

Aplikasi yang sedang berjalan masih dapat memproses CONNECTIVITY_CHANGE dengan BroadcastReceiver yang terdaftar. Namun, ConnectivityManager API menyediakan metode yang lebih andal untuk meminta callback hanya jika kondisi jaringan tertentu terpenuhi.

Objek NetworkRequest mendefinisikan parameter callback jaringan dari segi NetworkCapabilities. Anda membuat objek NetworkRequest dengan class NetworkRequest.Builder. registerNetworkCallback kemudian meneruskan objek NetworkRequest ke sistem. Saat kondisi jaringan terpenuhi, aplikasi akan menerima callback untuk menjalankan metode onAvailable() yang ditentukan di class ConnectivityManager.NetworkCallback.

Aplikasi akan terus menerima callback hingga aplikasi keluar atau memanggil unregisterNetworkCallback().

Pembatasan penerimaan gambar dan siaran video

Aplikasi tidak dapat mengirim atau menerima siaran ACTION_NEW_PICTURE atau ACTION_NEW_VIDEO. Pembatasan ini membantu mengurangi dampak performa dan pengalaman pengguna saat beberapa aplikasi harus aktif untuk memproses gambar atau video baru.

Menentukan otoritas konten yang memicu pekerjaan

WorkerParameters memungkinkan aplikasi Anda menerima informasi berguna tentang URI dan otoritas konten yang memicu tugas:

List<Uri> getTriggeredContentUris()

Menampilkan daftar URI yang memicu tugas. Array ini akan kosong jika tidak ada URI yang memicu tugas tersebut (misalnya, tugas terpicu karena batas waktu atau alasan lain), atau jumlah URI yang berubah lebih dari 50.

List<String> getTriggeredContentAuthorities()

Menampilkan daftar string otoritas konten yang memicu pekerjaan. Jika daftar yang ditampilkan tidak kosong, gunakan getTriggeredContentUris() untuk mengambil detail URI mana yang telah berubah.

Kode contoh berikut mengganti metode CoroutineWorker.doWork() dan mencatat URI dan otoritas konten yang memicu tugas:

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()
    }
}

Menguji aplikasi dalam batasan sistem

Mengoptimalkan aplikasi agar berjalan di perangkat bermemori rendah, atau dalam kondisi memori rendah, dapat meningkatkan performa dan pengalaman pengguna. Menghapus dependensi pada layanan latar belakang dan penerima siaran implisit yang terdaftar di manifes dapat membuat aplikasi Anda berjalan lebih baik di perangkat tersebut. Sebaiknya Anda mengoptimalkan aplikasi agar berjalan tanpa menggunakan proses latar belakang ini sepenuhnya.

Beberapa perintah Android Debug Bridge (ADB) tambahan dapat membantu Anda menguji perilaku aplikasi dengan proses latar belakang yang dinonaktifkan:

  • Untuk menyimulasikan kondisi saat siaran implisit dan layanan latar belakang tidak tersedia, masukkan perintah berikut:

    $ adb shell cmd appops set <package_name> RUN_IN_BACKGROUND ignore

  • Untuk mengaktifkan kembali siaran implisit dan layanan latar belakang, masukkan perintah berikut:

    $ adb shell cmd appops set <package_name> RUN_IN_BACKGROUND allow

Mengoptimalkan aplikasi Anda lebih jauh

Untuk mengetahui cara lain yang baik dalam mengoptimalkan perilaku tugas latar belakang, lihat dokumentasi Mengoptimalkan penggunaan baterai untuk API penjadwalan tugas.