ANR

जब किसी Android ऐप्लिकेशन का यूज़र इंटरफ़ेस (यूआई) थ्रेड बहुत देर तक ब्लॉक रहता है, तब "ऐप्लिकेशन काम नहीं कर रहा है" (एएनआर) गड़बड़ी ट्रिगर होती है. अगर ऐप्लिकेशन फ़ोरग्राउंड में है, तो सिस्टम उपयोगकर्ता को एक डायलॉग दिखाता है. जैसा कि पहली इमेज में दिखाया गया है. ANR डायलॉग से, उपयोगकर्ता को ऐप्लिकेशन को बंद करने का विकल्प मिलता है.

उपयोगकर्ता को दिखाया गया ANR डायलॉग.
पहली इमेज. उपयोगकर्ता को दिखाया गया ANR डायलॉग

ANR एक समस्या है, क्योंकि ऐप्लिकेशन की मुख्य थ्रेड, यूज़र इंटरफ़ेस (यूआई) को अपडेट करने के लिए ज़िम्मेदार होती है. यह उपयोगकर्ता के इनपुट इवेंट को प्रोसेस नहीं कर सकती या ड्रा नहीं कर सकती. इससे उपयोगकर्ता को परेशानी होती है. ऐप्लिकेशन के मुख्य थ्रेड के बारे में ज़्यादा जानने के लिए, प्रोसेस और थ्रेड की खास जानकारी देखें.

इनमें से कोई भी स्थिति होने पर, आपके ऐप्लिकेशन के लिए एएनआर ट्रिगर होता है:

  • इनपुट डिस्पैच करने में समय लग गया: अगर आपका ऐप्लिकेशन, इनपुट इवेंट (जैसे कि बटन दबाना या स्क्रीन को छूना) का जवाब पांच सेकंड के अंदर नहीं देता है.
  • सेवा को पूरा करने में समस्या: अगर आपके ऐप्लिकेशन की ओर से बताई गई कोई सेवा, कुछ सेकंड में Service.onCreate और Service.onStartCommand/Service.onBind को पूरा नहीं कर पाती है.
  • Service.startForeground को कॉल नहीं किया गया: अगर आपका ऐप्लिकेशन, फ़ोरग्राउंड में नई सेवा शुरू करने के लिए Context.startForegroundService का इस्तेमाल करता है, लेकिन सेवा पांच सेकंड के अंदर startForeground को कॉल नहीं करती है.
  • ब्रॉडकास्ट ऑफ़ इंटेंट: अगर BroadcastReceiver को तय समय में पूरा नहीं किया गया है. अगर ऐप्लिकेशन में फ़ोरग्राउंड में कोई गतिविधि हो रही है, तो यह टाइम आउट पांच सेकंड का होता है.
  • JobScheduler इंटरैक्शन: अगर JobService कुछ सेकंड में JobService.onStartJob या JobService.onStopJob से वापस नहीं आता है या अगर उपयोगकर्ता की ओर से शुरू किया गया कोई जॉब शुरू होता है और आपका ऐप्लिकेशन, JobService.onStartJob को कॉल करने के कुछ सेकंड बाद JobService.setNotification को कॉल नहीं करता है. Android 13 और इससे पहले के वर्शन को टारगेट करने वाले ऐप्लिकेशन के लिए, एएनआर की सूचना नहीं दी जाती है और न ही ऐप्लिकेशन को इसकी जानकारी दी जाती है. Android 14 और इसके बाद के वर्शन को टारगेट करने वाले ऐप्लिकेशन के लिए, एएनआर की सूचना दी जाती है और ऐप्लिकेशन को इसकी जानकारी दी जाती है.

अगर आपके ऐप्लिकेशन में एएनआर की समस्याएं आ रही हैं, तो इस दस्तावेज़ में दिए गए दिशा-निर्देशों का इस्तेमाल करके, समस्या का पता लगाया जा सकता है और उसे ठीक किया जा सकता है.

समस्या का पता लगाना

अगर आपने पहले ही अपना ऐप्लिकेशन पब्लिश कर दिया है, तो Android की ज़रूरी जानकारी का इस्तेमाल करके, अपने ऐप्लिकेशन के लिए एएनआर की जानकारी देखी जा सकती है. फ़ील्ड में एएनआर का पता लगाने के लिए, अन्य टूल का इस्तेमाल किया जा सकता है. हालांकि, ध्यान दें कि Android की ज़रूरी जानकारी के उलट, तीसरे पक्ष के टूल, Android 10 और इससे पुराने वर्शन पर एएनआर की रिपोर्ट नहीं कर सकते.

Android की ज़रूरी जानकारी

'Android की ज़रूरी जानकारी' की मदद से, अपने ऐप्लिकेशन के एएनआर रेट को मॉनिटर किया जा सकता है और उसे बेहतर बनाया जा सकता है. Android vitals, एएनआर रेट को कई तरह से मेज़र करता है:

  • एएनआर रेट: हर दिन के ऐसे सक्रिय उपयोगकर्ताओं का प्रतिशत जिन्होंने किसी भी तरह की एएनआर की गड़बड़ी का सामना किया.
  • यूज़र-पर्सीव्ड ANR रेट: हर दिन के ऐसे सक्रिय उपयोगकर्ताओं का प्रतिशत जिन्होंने कम से कम एक बार यूज़र-पर्सीव्ड ANR का सामना किया. फ़िलहाल, सिर्फ़ Input dispatching timed out टाइप के एएनआर को यूज़र-पर्सीव्ड माना जाता है.
  • मल्टिपल ANR रेट: हर दिन के ऐसे सक्रिय उपयोगकर्ताओं का प्रतिशत जिन्होंने कम से कम दो बार ANR की गड़बड़ी का सामना किया.

हर दिन का सक्रिय उपयोगकर्ता, ऐसा यूनीक उपयोगकर्ता होता है जो एक दिन में एक ही डिवाइस पर आपके ऐप्लिकेशन का इस्तेमाल करता है. ऐसा हो सकता है कि वह एक से ज़्यादा सेशन में ऐप्लिकेशन का इस्तेमाल करे. अगर कोई उपयोगकर्ता आपके ऐप्लिकेशन का इस्तेमाल एक दिन में एक से ज़्यादा डिवाइसों पर करता है, तो उस दिन सक्रिय उपयोगकर्ता की गिनती इस्तेमाल किए गए डिवाइस के अनुसार की जाएगी.

यूज़र-पर्सीव्ड एएनआर रेट, ऐप्लिकेशन के लिए सबसे ज़रूरी जानकारी की तरह होता है. इसका मतलब है कि इसका असर इस बात पर भी पड़ता है कि Google Play पर आपके ऐप्लिकेशन को लोग आसानी से खोज पा रहे हैं या नहीं. यूज़र-पर्सीव्ड एएनआर रेट बहुत मायने रखता है, क्योंकि इसमें एएनआर वाली उन गड़बड़ियों को शामिल किया जाता है जिनका सामना उपयोगकर्ता को आपका ऐप्लिकेशन इस्तेमाल करते समय अक्सर करना पड़ता है. साथ ही, इनकी वजह से ऐप्लिकेशन में सबसे ज़्यादा क्रैश और फ़्रीज़ होने जैसी समस्याएं भी आती हैं.

Play ने इस मेट्रिक के लिए, ऐप्लिकेशन की खराब परफ़ॉर्मेंस के दो थ्रेशोल्ड तय किए हैं:

  • सभी डिवाइस मॉडल पर ऐप्लिकेशन की खराब परफ़ॉर्मेंस की थ्रेशोल्ड वैल्यू: हर दिन के सक्रिय उपयोगकर्ताओं में से कम से कम 0.47% लोगों को सभी डिवाइस मॉडल पर यूज़र-पर्सीव्ड एएनआर का सामना करना पड़ता है.
  • किसी खास डिवाइस मॉडल पर ऐप्लिकेशन की खराब परफ़ॉर्मेंस की थ्रेशोल्ड वैल्यू: हर दिन आपका ऐप्लिकेशन इस्तेमाल करने वाले लोगों में से कम से कम 8% लोगों को किसी एक डिवाइस मॉडल पर, यूज़र-पर्सीव्ड एएनआर वाली गड़बड़ियों का सामना करना पड़ता है.

अगर आपके ऐप्लिकेशन की खराब परफ़ॉर्मेंस का थ्रेशोल्ड, तय किए गए थ्रेशोल्ड से ज़्यादा है, तो उसे सभी डिवाइसों पर खोजे जाने की संभावना कम हो सकती है. अगर आपके ऐप्लिकेशन की खराब परफ़ॉर्मेंस का थ्रेशोल्ड, कुछ डिवाइसों पर हर डिवाइस के लिए तय किए गए थ्रेशोल्ड से ज़्यादा है, तो उन डिवाइसों पर आपके ऐप्लिकेशन को खोजे जाने की संभावना कम हो सकती है. साथ ही, आपके स्टोर पेज पर चेतावनी दिख सकती है.

अगर आपके ऐप्लिकेशन में एएनआर की समस्या बहुत ज़्यादा हो रही है, तो Android की ज़रूरी जानकारी आपको Play Console के ज़रिए इसकी सूचना दे सकती है.

Google Play, Android की ज़रूरी जानकारी का डेटा कैसे इकट्ठा करता है, इस बारे में जानने के लिए Play Console का दस्तावेज़ देखें.

ANR की गड़बड़ियों का पता लगाना

एएनआर की समस्या का पता लगाते समय, इन सामान्य पैटर्न पर ध्यान दें:

  • ऐप्लिकेशन, मुख्य थ्रेड पर I/O से जुड़ी कार्रवाइयां धीरे-धीरे कर रहा है.
  • ऐप्लिकेशन, मुख्य थ्रेड पर लंबी कैलकुलेशन कर रहा है.
  • मुख्य थ्रेड, किसी दूसरी प्रोसेस को सिंक्रोनस बाइंडर कॉल कर रही है. साथ ही, वह प्रोसेस जवाब देने में ज़्यादा समय ले रही है.
  • मुख्य थ्रेड को ब्लॉक किया गया है. यह किसी दूसरे थ्रेड पर हो रहे लंबे ऑपरेशन के लिए, सिंक्रनाइज़ किए गए ब्लॉक का इंतज़ार कर रही है.
  • मुख्य थ्रेड, आपकी प्रोसेस या बाइंडर कॉल के ज़रिए किसी दूसरी थ्रेड के साथ डेडलॉक में है. मुख्य थ्रेड सिर्फ़ लंबे समय तक चलने वाले ऑपरेशन के पूरा होने का इंतज़ार नहीं कर रही है, बल्कि डेडलॉक की स्थिति में है.

नीचे दी गई तकनीकों से, एएनआर की वजह का पता लगाया जा सकता है.

HealthStats

HealthStats, ऐप्लिकेशन की परफ़ॉर्मेंस के बारे में मेट्रिक उपलब्ध कराता है. इसके लिए, यह उपयोगकर्ता और सिस्टम के कुल समय, सीपीयू के इस्तेमाल का समय, नेटवर्क, रेडियो के आंकड़े, स्क्रीन चालू/बंद होने का समय, और वेक अप अलार्म कैप्चर करता है. इससे आपको सीपीयू के कुल इस्तेमाल और बैटरी की खपत को मेज़र करने में मदद मिल सकती है.

डीबग

Debug की मदद से, डेवलपमेंट के दौरान Android ऐप्लिकेशन की जांच की जा सकती है. इसमें ऐप्लिकेशन में जंक और लैग की पहचान करने के लिए, ट्रेसिंग और ऐलोकेशन की संख्या शामिल है. रंटाइम और नेटिव मेमोरी काउंटर पाने के लिए, Debug का इस्तेमाल किया जा सकता है. साथ ही, मेमोरी से जुड़ी मेट्रिक भी देखी जा सकती हैं. इनसे आपको किसी प्रोसेस के मेमोरी फ़ुटप्रिंट की पहचान करने में मदद मिल सकती है.

ApplicationExitInfo

ApplicationExitInfo Android 11 (एपीआई लेवल 30) या इसके बाद के वर्शन पर उपलब्ध है. इससे ऐप्लिकेशन बंद होने की वजह के बारे में जानकारी मिलती है. इसमें एएनआर, कम मेमोरी, ऐप्लिकेशन क्रैश, बहुत ज़्यादा सीपीयू इस्तेमाल होना, उपयोगकर्ता के काम में रुकावटें, सिस्टम में रुकावटें, और रनटाइम की अनुमतियों में बदलाव शामिल हैं.

स्ट्रिक्ट मोड

StrictMode का इस्तेमाल करने से, आपको ऐप्लिकेशन डेवलप करते समय मुख्य थ्रेड पर होने वाली I/O कार्रवाइयों के बारे में पता चलता है. StrictMode का इस्तेमाल ऐप्लिकेशन या गतिविधि के लेवल पर किया जा सकता है.

बैकग्राउंड में होने वाले एएनआर के डायलॉग बॉक्स चालू करें

Android, ब्रॉडकास्ट मैसेज को प्रोसेस करने में ज़्यादा समय लेने वाले ऐप्लिकेशन के लिए एएनआर डायलॉग दिखाता है. हालांकि, ऐसा सिर्फ़ तब होता है, जब डिवाइस के डेवलपर विकल्प में सभी एएनआर दिखाएं विकल्प चालू हो. इस वजह से, बैकग्राउंड में होने वाले एएनआर के डायलॉग, उपयोगकर्ता को हमेशा नहीं दिखते. भले ही, ऐप्लिकेशन को परफ़ॉर्मेंस से जुड़ी समस्याएं आ रही हों.

रीकंपोज़िशन से जुड़ी समस्याएं

रीकंपोज़िशन की समस्याओं का पता लगाने के लिए, Android Studio Profiler और Layout Inspector का इस्तेमाल करें. ज़्यादा जानकारी के लिए, Jetpack Compose की परफ़ॉर्मेंस देखें.

ट्रेस फ़ाइल को पुल करना

जब Android में ANR की समस्या होती है, तब वह ट्रेस की जानकारी सेव करता है. ओएस के पुराने वर्शन में, डिवाइस पर सिर्फ़ एक /data/anr/traces.txt फ़ाइल होती है. ओएस के नए वर्शन में, /data/anr/anr_* की कई फ़ाइलें होती हैं. रूट के तौर पर Android डीबग ब्रिज (adb) का इस्तेमाल करके, किसी डिवाइस या एम्युलेटर से एएनआर ट्रेस ऐक्सेस किए जा सकते हैं:

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

किसी फ़िज़िकल डिवाइस से गड़बड़ी की रिपोर्ट कैप्चर की जा सकती है. इसके लिए, डिवाइस पर मौजूद डेवलपर विकल्प में जाकर, गड़बड़ी की रिपोर्ट पाएं विकल्प का इस्तेमाल करें. इसके अलावा, डेवलपमेंट मशीन पर adb bugreport कमांड का इस्तेमाल करके भी गड़बड़ी की रिपोर्ट कैप्चर की जा सकती है. ज़्यादा जानकारी के लिए, बग रिपोर्ट कैप्चर करना और उन्हें पढ़ना लेख पढ़ें.

समस्याएं ठीक करना

समस्या का पता लगाने के बाद, इस सेक्शन में दी गई सलाह का इस्तेमाल करके, आम तौर पर होने वाली समस्याओं को ठीक किया जा सकता है.

मुख्य थ्रेड पर कोड धीरे-धीरे चल रहा है

अपने कोड में उन जगहों का पता लगाएं जहां ऐप्लिकेशन का मुख्य थ्रेड, पांच सेकंड से ज़्यादा समय तक व्यस्त रहता है. अपने ऐप्लिकेशन में, इस्तेमाल के संदिग्ध उदाहरणों को ढूंढें और एएनआर को फिर से जनरेट करने की कोशिश करें.

एक सामान्य समस्या यह है कि कंपोज़ेबल में लंबे समय तक चलने वाला टास्क सीधे तौर पर मौजूद हो:

@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

मुख्य थ्रेड पर I/O कार्रवाइयां करने की वजह से, मुख्य थ्रेड पर कार्रवाइयां धीमी हो जाती हैं. इससे ANR की गड़बड़ियां हो सकती हैं. Compose में, डेवलपर अक्सर शुरुआती स्थिति का पता लगाने की कोशिश करते समय, गलती से डिस्क रीड (जैसे कि SharedPreferences या डेटाबेस कॉल) को ट्रिगर कर देते हैं.

ज़्यादा समय तक चलने वाली I/O कार्रवाइयों को यूज़र इंटरफ़ेस (यूआई) लेयर से अलग तरीके से पूरा करें. ViewModel में withContext(Dispatchers.IO) का इस्तेमाल करें. इसके अलावा, डेटा लेयर पर Repository का इस्तेमाल करना ज़्यादा बेहतर होता है.

डेडलॉक

डेडलॉक तब होता है, जब कोई थ्रेड इंतज़ार की स्थिति में आ जाती है. ऐसा इसलिए होता है, क्योंकि ज़रूरी संसाधन किसी दूसरी थ्रेड के पास होता है. यह थ्रेड भी उस संसाधन का इंतज़ार कर रही होती है जो पहली थ्रेड के पास होता है. अगर ऐप्लिकेशन का मुख्य थ्रेड इस स्थिति में है, तो ANR की गड़बड़ियां हो सकती हैं.

डेडलॉक, कंप्यूटर साइंस में एक जानी-मानी समस्या है. डेडलॉक से बचने के लिए, डेडलॉक रोकने वाले एल्गोरिदम का इस्तेमाल किया जा सकता है.

ज़्यादा जानकारी के लिए, Wikipedia पर डेडलॉक और डेडलॉक रोकने वाले एल्गोरिदम लेख पढ़ें.

Kotlin और Compose का इस्तेमाल करते समय, प्रिमिटिव लॉक को नॉन-ब्लॉकिंग कोरूटीन म्यूटेक्स (Mutex.withLock) से बदला जा सकता है. इससे थ्रेड को ब्लॉक होने से रोका जा सकता है. इसके लिए, यूज़र इंटरफ़ेस (यूआई) थ्रेड को फ़्रीज़ करने के बजाय, एक्ज़ीक्यूशन कॉन्टेक्स्ट को सस्पेंड किया जाता है. उदाहरण के लिए:

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

ब्रॉडकास्ट रिसीवर को सूचना मिलने में समय लग रहा है

ऐप्लिकेशन, ब्रॉडकास्ट रिसीवर की मदद से ब्रॉडकास्ट मैसेज का जवाब दे सकते हैं. जैसे, फ़्लाइट मोड को चालू या बंद करना या कनेक्टिविटी की स्थिति में बदलाव करना. जब कोई ऐप्लिकेशन ब्रॉडकास्ट मैसेज को प्रोसेस करने में बहुत ज़्यादा समय लेता है, तब एएनआर की समस्या होती है.

एएनआर इन मामलों में होता है:

  • ब्रॉडकास्ट रिसीवर ने onReceive तरीके को तय समय में पूरा नहीं किया है.
  • ब्रॉडकास्ट रिसीवर, goAsync को कॉल करता है और PendingResult ऑब्जेक्ट पर finish को कॉल नहीं कर पाता.

आपके ऐप्लिकेशन को BroadcastReceiver के onReceive तरीके में सिर्फ़ छोटी कार्रवाइयां करनी चाहिए. हालांकि, अगर ब्रॉडकास्ट मैसेज की वजह से आपके ऐप्लिकेशन को ज़्यादा जटिल प्रोसेसिंग की ज़रूरत है, तो आपको टास्क को ViewModel (Kotlin कोरूटीन, स्कोप, और डिस्पैचर का इस्तेमाल करके) पर ट्रांसफ़र करना चाहिए. अगर टास्क को पूरा होने में कुछ सेकंड लगते हैं, तो किसी भी तरह के स्टेट होल्डर पर ट्रांसफ़र करें. अगर टास्क को पूरा होने में कुछ सेकंड से ज़्यादा समय लगता है, तो WorkManager पर ट्रांसफ़र करें.

GameActivity

GameActivity लाइब्रेरी की मदद से, C या C++ में लिखे गए गेम और ऐप्लिकेशन की केस स्टडी में एएनआर की संख्या कम हुई है. अगर मौजूदा नेटिव ऐक्टिविटी को GameActivity से बदल दिया जाता है, तो यूज़र इंटरफ़ेस (यूआई) थ्रेड को ब्लॉक होने से रोका जा सकता है. साथ ही, कुछ एएनआर को होने से रोका जा सकता है.

ANR के बारे में ज़्यादा जानने के लिए, अपने ऐप्लिकेशन को रिस्पॉन्सिव बनाए रखें लेख पढ़ें. थ्रेड के बारे में ज़्यादा जानकारी के लिए, थ्रेडिंग की मदद से बेहतर परफ़ॉर्मेंस लेख पढ़ें.

अन्य संसाधन

कॉन्टेंट देखना