ANR

Saat UI thread aplikasi Android diblokir terlalu lama, error "Aplikasi Tidak Merespons" (ANR) akan dipicu. Jika aplikasi digunakan di latar depan, sistem menampilkan dialog kepada pengguna, seperti ditunjukkan di gambar 1. Dialog ANR memberikan kesempatan kepada pengguna untuk memaksa menghentikan aplikasi.

Dialog ANR yang ditampilkan kepada pengguna.
Gambar 1. Dialog ANR yang ditampilkan kepada pengguna

ANR adalah masalah yang muncul karena thread utama aplikasi, yang bertanggung jawab untuk mengupdate UI, tidak dapat memproses peristiwa input pengguna atau melakukan draw, sehingga dapat membuat pengguna kebingungan. Untuk mengetahui informasi selengkapnya tentang thread utama aplikasi, lihat Ringkasan proses dan thread.

ANR dipicu untuk aplikasi jika salah satu kondisi berikut terjadi:

  • Waktu pengiriman input habis: Jika aplikasi Anda tidak merespons peristiwa input (seperti penekanan tombol atau sentuhan layar) dalam 5 detik.
  • Mengeksekusi layanan: Jika layanan yang dideklarasikan oleh aplikasi Anda tidak dapat menyelesaikan eksekusi Service.onCreate dan Service.onStartCommand/Service.onBind dalam beberapa detik.
  • Service.startForeground tidak dipanggil: Jika aplikasi Anda menggunakan Context.startForegroundService untuk memulai layanan baru di latar depan tetapi layanan tidak memanggil startForeground dalam 5 detik.
  • Broadcast intent: Jika BroadcastReceiver belum selesai dieksekusi dalam jangka waktu yang ditentukan. Jika aplikasi memiliki aktivitas di latar depan, waktu tunggu ini adalah 5 detik.
  • Interaksi JobScheduler: Jika JobService tidak ditampilkan dari JobService.onStartJob atau JobService.onStopJob dalam beberapa detik, atau jika tugas yang dimulai pengguna dimulai dan aplikasi Anda tidak memanggil JobService.setNotification dalam beberapa detik setelah JobService.onStartJob dipanggil. Untuk aplikasi yang menargetkan Android 13 dan yang lebih lama, ANR bersifat implisit dan tidak dilaporkan ke aplikasi. Untuk aplikasi yang menargetkan Android 14 dan yang lebih baru, ANR bersifat eksplisit dan dilaporkan ke aplikasi.

Jika aplikasi mengalami ANR, Anda dapat menggunakan panduan dalam dokumen ini untuk mendiagnosis dan memperbaiki masalahnya.

Mendeteksi masalah

Jika sudah memublikasikan aplikasi, Anda dapat menggunakan Android vitals untuk melihat informasi tentang ANR untuk aplikasi Anda. Anda dapat menggunakan alat lain untuk mendeteksi ANR di kolom, tetapi perhatikan bahwa alat pihak ketiga tidak dapat melaporkan ANR di Android 10 dan yang lebih lama, tidak seperti Android vitals.

Android vitals

Android vitals dapat membantu Anda memantau dan meningkatkan rasio ANR aplikasi. Android vitals mengukur beberapa rasio ANR:

  • Rasio ANR: Persentase pengguna aktif harian Anda yang mengalami semua jenis ANR.
  • Rasio ANR yang dirasakan pengguna: Persentase pengguna aktif harian Anda yang mengalami setidaknya satu ANR yang dirasakan pengguna. Saat ini, hanya ANR jenis Input dispatching timed out yang dianggap dirasakan pengguna.
  • Rasio multi-ANR: Persentase pengguna aktif harian yang mengalami setidaknya dua ANR.

Pengguna aktif harian adalah pengguna unik yang menggunakan aplikasi Anda pada satu hari di satu perangkat, kemungkinan melalui beberapa sesi. Jika pengguna menggunakan aplikasi Anda di lebih dari satu perangkat dalam satu hari, setiap perangkat akan berkontribusi pada jumlah pengguna aktif untuk hari tersebut.

Rasio ANR yang dirasakan pengguna merupakan data vital inti, yang berarti rasio ini memengaruhi visibilitas aplikasi Anda di Google Play. Rasio ini penting karena ANR yang dihitung selalu terjadi saat pengguna berinteraksi dengan aplikasi, sehingga paling banyak menyebabkan gangguan.

Play telah menentukan dua batas perilaku buruk pada metrik ini:

  • Batas perilaku buruk keseluruhan: Setidaknya 0,47% pengguna aktif harian mengalami ANR yang dirasakan pengguna di semua model perangkat.
  • Batas perilaku buruk per perangkat: Setidaknya 8% pengguna aktif harian mengalami ANR yang dirasakan pengguna, untuk satu model perangkat.

Jika aplikasi Anda melebihi batas perilaku buruk secara keseluruhan, mungkin aplikasi tersebut akan sulit ditemukan di semua perangkat. Jika aplikasi Anda melebihi batas perilaku buruk per perangkat di beberapa perangkat, mungkin aplikasi tersebut akan kurang visibel di perangkat tersebut, dan peringatan mungkin ditampilkan di listingan Google Play Store Anda.

Android vitals dapat memperingatkan Anda melalui Konsol Play saat aplikasi Anda menampilkan ANR berlebihan.

Untuk mengetahui informasi tentang cara Google Play mengumpulkan data Android vitals, lihat dokumentasi Konsol Play.

Mendiagnosis ANR

Ada beberapa pola umum yang perlu diperhatikan saat mendiagnosis ANR:

  • Aplikasi melakukan operasi lambat yang melibatkan I/O di thread utama.
  • Aplikasi melakukan perhitungan yang lama di thread utama.
  • Thread utama melakukan panggilan pengikat sinkron ke proses lain, dan proses lain tersebut memerlukan waktu yang lama untuk kembali.
  • Thread utama diblokir menunggu blok yang disinkronkan untuk operasi panjang yang terjadi di thread lain.
  • Thread utama mengalami deadlock dengan thread lain, baik dalam proses Anda atau melalui panggilan binder. Thread utama tidak hanya menunggu operasi yang panjang selesai, tetapi dalam situasi deadlock.

Teknik berikut dapat membantu Anda menentukan penyebab ANR.

HealthStats

HealthStats memberikan metrik tentang kesehatan aplikasi dengan mencatat total waktu pengguna dan sistem, waktu CPU, jaringan, statistik radio, waktu aktif/nonaktif layar, dan alarm bangun. Hal ini dapat membantu Anda mengukur penggunaan CPU dan konsumsi baterai secara keseluruhan.

Debug

Debug membantu Anda memeriksa aplikasi Android selama pengembangan, termasuk jumlah rekaman aktivitas dan alokasi untuk mengidentifikasi jank dan jeda dalam aplikasi. Anda juga dapat menggunakan Debug untuk mendapatkan penghitung memori native dan runtime, serta metrik memori yang dapat membantu Anda mengidentifikasi jejak memori proses tertentu.

ApplicationExitInfo

ApplicationExitInfo tersedia di Android 11 (level API 30) atau yang lebih tinggi, dan memberikan informasi tentang alasan keluar dari aplikasi. Hal ini mencakup ANR, memori rendah, error aplikasi, penggunaan CPU yang berlebihan, gangguan pengguna, gangguan sistem, dan perubahan izin runtime.

Mode ketat

Menggunakan StrictMode membantu Anda menemukan operasi I/O yang tidak disengaja di thread utama saat Anda mengembangkan aplikasi. Anda dapat menggunakan StrictMode di tingkat aplikasi atau aktivitas.

Mengaktifkan dialog ANR latar belakang

Android menampilkan dialog ANR untuk aplikasi yang memerlukan waktu terlalu lama untuk memproses pesan siaran hanya jika Tampilkan semua ANR diaktifkan di Opsi developer pada perangkat. Karena alasan ini, dialog ANR latar belakang tidak selalu ditampilkan kepada pengguna, bahkan saat aplikasi mengalami masalah performa.

Bottleneck rekomposisi

Gunakan Android Studio Profiler dan Layout Inspector untuk melacak bottleneck rekomposisi. Untuk mengetahui informasi selengkapnya, lihat Performa Jetpack Compose.

Mengambil file rekaman aktivitas

Android menyimpan informasi rekaman aktivitas saat mengalami ANR. Di OS versi lama , ada satu file /data/anr/traces.txt di perangkat. Di OS versi baru, ada beberapa file /data/anr/anr_*. Anda dapat mengakses rekaman aktivitas ANR dari perangkat atau emulator dengan menggunakan Android Debug Bridge (adb) sebagai root:

adb root
adb shell ls /data/anr
adb pull /data/anr/<filename>

Anda dapat mengambil laporan bug dari perangkat fisik dengan menggunakan opsi developer Ambil laporan bug di perangkat atau perintah adb bugreport di mesin pengembangan. Untuk mengetahui informasi selengkapnya, lihat Merekam dan membaca laporan bug.

Memperbaiki masalah

Setelah mengidentifikasi masalah, Anda dapat menggunakan tips di bagian ini untuk memperbaiki masalah yang umum ditemukan.

Kode lambat di thread utama

Identifikasi tempat di kode tempat thread utama aplikasi sibuk selama lebih dari 5 detik. Cari kasus penggunaan yang mencurigakan di aplikasi dan coba reproduksi ANR.

Masalah umum adalah tugas yang berjalan lama secara langsung dalam composable:

@Composable
fun BadList(rawStrings: List<String>) {
    // Math or sorting inside the composable runs on EVERY recomposition pass!
    val heavilyProcessedList = rawStrings
        .filter { it.isNotBlank() }
        .map { it.uppercase().reversed() }
        .map { it.computationallyHeavyFunction() }
.sortedBy { it.length }
    LazyColumn { items(sortedList) { Text(it) } }
}

// Modern Compose-first fix
@Composable
fun GoodList(viewModel: MyViewModel = viewModel()) {
    val uiState by viewModel.uiState.collectAsStateWithLifecycle()

    // UI simply renders state; no heavy processing allowed here
    LazyColumn { items(uiState.sortedData) { Text(it) } }
}

I/O di thread utama

Mengeksekusi operasi I/O di thread utama adalah penyebab umum operasi yang lambat di thread utama, yang dapat menyebabkan ANR. Di Compose, developer sering kali secara tidak sengaja memicu pembacaan disk (seperti SharedPreferences atau panggilan database) saat mencoba mendapatkan status awal.

Jalankan operasi I/O yang berjalan lama di luar lapisan UI. Gunakan withContext(Dispatchers.IO) dalam ViewModel atau, lebih baik lagi, gunakan Repository di lapisan data.

Deadlock

Deadlock terjadi saat thread memasuki status menunggu karena resource yang diperlukan ditahan oleh thread lain, yang juga menunggu resource yang ditahan oleh thread pertama. Jika thread utama aplikasi mengalami situasi ini, ANR mungkin terjadi.

Deadlock adalah fenomena yang dipelajari dengan baik dalam ilmu komputer, dan terdapat algoritma pencegahan deadlock yang dapat Anda gunakan untuk menghindari deadlock.

Untuk mengetahui informasi selengkapnya, lihat Deadlock dan Algoritma pencegahan deadlock di Wikipedia.

Saat menggunakan Kotlin dan Compose, Anda dapat mengganti kunci primitif dengan Mutex coroutine non-blocking (Mutex.withLock) untuk mencegah pemblokiran thread dengan menangguhkan konteks eksekusi, bukan membekukan thread UI. Contoh:

import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock

// Modern non-blocking concurrency state architecture
class SecureDataRepository {
    private val mutex = Mutex()

    suspend fun safeUIAccess() {
        // If locked, the main thread suspends seamlessly, preventing an ANR
        mutex.withLock {
            performSafeOperation()
        }
    }
}

Penerima siaran lambat

Aplikasi dapat merespons pesan siaran, seperti mengaktifkan atau menonaktifkan mode pesawat atau perubahan status konektivitas, melalui penerima siaran. ANR terjadi saat aplikasi memerlukan waktu yang terlalu lama untuk memproses pesan siaran.

ANR terjadi dalam kasus-kasus berikut:

  • Penerima siaran belum selesai mengeksekusi metode onReceive-nya dalam waktu yang cukup lama.
  • Penerima siaran memanggil goAsync dan gagal memanggil finish pada objek PendingResult.

Aplikasi Anda hanya dapat menjalankan operasi pendek dalam metode onReceive dari BroadcastReceiver. Namun, jika aplikasi Anda memerlukan pemrosesan yang lebih kompleks karena pesan siaran, Anda harus mengalihkan tugas ke ViewModel (memanfaatkan kecanggihan coroutine, cakupan, dan dispatcher Kotlin) jika tugas diperkirakan akan memakan waktu paling lama beberapa detik, jenis penampung status apa pun, atau ke WorkManager untuk tugas yang diperkirakan akan memakan waktu lebih dari beberapa detik.

GameActivity

Library GameActivity telah mengurangi ANR dalam studi kasus game dan aplikasi yang ditulis dalam C atau C++. Jika Anda mengganti aktivitas native yang ada dengan GameActivity, Anda dapat mengurangi pemblokiran UI thread dan mencegah terjadinya beberapa ANR.

Untuk mengetahui informasi selengkapnya tentang ANR, lihat Menjaga aplikasi Anda tetap responsif. Untuk mengetahui informasi selengkapnya tentang thread, lihat Performa yang lebih baik melalui threading.

Referensi lainnya

Melihat konten