जब किसी Android ऐप्लिकेशन का यूज़र इंटरफ़ेस (यूआई) थ्रेड बहुत देर तक ब्लॉक रहता है, तब "ऐप्लिकेशन काम नहीं कर रहा" (एएनआर) गड़बड़ी ट्रिगर होती है. अगर ऐप्लिकेशन फ़ोरग्राउंड में है, तो सिस्टम उपयोगकर्ता को एक डायलॉग दिखाता है. यह डायलॉग पहली इमेज में दिखाया गया है. 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 और इसके बाद के वर्शन को टारगेट करने वाले ऐप्लिकेशन के लिए, एएनआर की सूचना दी जाती है और ऐप्लिकेशन को इसकी जानकारी दी जाती है.
अगर आपके ऐप्लिकेशन में एएनआर की समस्याएं आ रही हैं, तो इस दस्तावेज़ में दिए गए दिशा-निर्देशों का इस्तेमाल करके, समस्या का पता लगाया जा सकता है और उसे ठीक किया जा सकता है.
ANR की गड़बड़ियों का पता लगाना
एएनआर की समस्या का पता लगाते समय, इन सामान्य पैटर्न पर ध्यान दें:
- ऐप्लिकेशन, मुख्य थ्रेड पर I/O से जुड़ी कार्रवाइयां धीरे-धीरे कर रहा है.
- ऐप्लिकेशन, मुख्य थ्रेड पर लंबी कैलकुलेशन कर रहा है.
- मुख्य थ्रेड, किसी दूसरी प्रोसेस को सिंक्रोनस बाइंडर कॉल कर रहा है. साथ ही, वह प्रोसेस जवाब देने में ज़्यादा समय ले रही है.
- मुख्य थ्रेड को ब्लॉक किया गया है. यह किसी दूसरे थ्रेड पर हो रहे लंबे ऑपरेशन के लिए, सिंक्रनाइज़ किए गए ब्लॉक का इंतज़ार कर रही है.
- मुख्य थ्रेड, आपकी प्रोसेस या बाइंडर कॉल के ज़रिए किसी दूसरी थ्रेड के साथ डेडलॉक में है. मुख्य थ्रेड, लंबे समय तक चलने वाली किसी प्रोसेस के पूरा होने का इंतज़ार नहीं कर रही है, बल्कि डेडलॉक की स्थिति में है.
यहां दी गई तकनीकों से, आपको एएनआर की वजह का पता लगाने में मदद मिल सकती है.
HealthStats
HealthStats, ऐप्लिकेशन की परफ़ॉर्मेंस के बारे में मेट्रिक उपलब्ध कराता है. इसके लिए, यह उपयोगकर्ता और सिस्टम के कुल समय, सीपीयू के इस्तेमाल का समय, नेटवर्क, रेडियो के आंकड़े, स्क्रीन चालू/बंद होने का समय, और वेक अप अलार्म कैप्चर करता है. इससे आपको सीपीयू के कुल इस्तेमाल और बैटरी खत्म होने की दर को मेज़र करने में मदद मिल सकती है.
डीबग
Debug की मदद से, डेवलपमेंट के दौरान Android ऐप्लिकेशन की जांच की जा सकती है. इसमें ऐप्लिकेशन में जंक और लैग की पहचान करने के लिए, ट्रेसिंग और ऐलोकेशन की संख्या शामिल है.
Debug का इस्तेमाल करके, रनटाइम और नेटिव मेमोरी काउंटर के साथ-साथ मेमोरी मेट्रिक भी पाई जा सकती हैं. इनसे आपको किसी प्रोसेस के मेमोरी फ़ुटप्रिंट की पहचान करने में मदद मिल सकती है.
ApplicationExitInfo
ApplicationExitInfo Android 11 (एपीआई लेवल 30) या इसके बाद के वर्शन पर उपलब्ध है. इससे ऐप्लिकेशन बंद होने की वजह के बारे में जानकारी मिलती है. इसमें एएनआर, कम मेमोरी, ऐप्लिकेशन क्रैश, सीपीयू का ज़्यादा इस्तेमाल, उपयोगकर्ता के काम में रुकावटें, सिस्टम में रुकावटें, और रनटाइम की अनुमतियों में बदलाव शामिल हैं.
स्ट्रिक्ट मोड
StrictMode का इस्तेमाल करके, ऐप्लिकेशन डेवलप करते समय मुख्य थ्रेड पर होने वाली अनचाही I/O कार्रवाइयों का पता लगाया जा सकता है. StrictMode का इस्तेमाल ऐप्लिकेशन या गतिविधि के लेवल पर किया जा सकता है.
बैकग्राउंड में होने वाले एएनआर के डायलॉग बॉक्स चालू करें
Android, ब्रॉडकास्ट मैसेज को प्रोसेस करने में ज़्यादा समय लेने वाले ऐप्लिकेशन के लिए, एएनआर डायलॉग दिखाता है. हालांकि, ऐसा सिर्फ़ तब होता है, जब डिवाइस के डेवलपर विकल्प में सभी एएनआर दिखाएं विकल्प चालू हो. इस वजह से, बैकग्राउंड में होने वाले एएनआर के डायलॉग, उपयोगकर्ता को हमेशा नहीं दिखते. भले ही, ऐप्लिकेशन को परफ़ॉर्मेंस से जुड़ी समस्याएं आ रही हों.
रीकंपोज़िशन से जुड़ी समस्याएं
रीकंपोज़िशन की समस्याओं का पता लगाने के लिए, Android Studio के प्रोफ़ाइलर और लेआउट इंस्पेक्टर का इस्तेमाल करें. ज़्यादा जानकारी के लिए, Jetpack Compose की परफ़ॉर्मेंस देखें.
ट्रेस फ़ाइल को पुल करना
जब Android में ANR की समस्या होती है, तब वह ट्रेस की जानकारी सेव करता है. ओएस के पुराने वर्शन में, डिवाइस पर सिर्फ़ एक /data/anr/traces.txt फ़ाइल होती है. OS के नए वर्शन में, /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 coroutines, स्कोप, और डिस्पैचर का इस्तेमाल करके) पर ट्रांसफ़र करना चाहिए. अगर टास्क को पूरा होने में ज़्यादा से ज़्यादा कुछ सेकंड लगते हैं, तो किसी भी तरह के स्टेट होल्डर या WorkManager पर ट्रांसफ़र करना चाहिए. ऐसा उन टास्क के लिए किया जाना चाहिए जिन्हें पूरा होने में कुछ सेकंड से ज़्यादा समय लगता है.
GameActivity
GameActivity लाइब्रेरी की मदद से, C या C++ में लिखे गए गेम और ऐप्लिकेशन के केस स्टडी में एएनआर की संख्या कम हुई है. अगर मौजूदा नेटिव ऐक्टिविटी को GameActivity से बदल दिया जाता है, तो यूज़र इंटरफ़ेस (यूआई) थ्रेड को ब्लॉक होने से रोका जा सकता है. साथ ही, कुछ एएनआर को होने से रोका जा सकता है.
ANR के बारे में ज़्यादा जानने के लिए, अपने ऐप्लिकेशन को रिस्पॉन्सिव बनाए रखें लेख पढ़ें. थ्रेड के बारे में ज़्यादा जानकारी के लिए, थ्रेडिंग की मदद से बेहतर परफ़ॉर्मेंस लेख पढ़ें.
अन्य संसाधन
कॉन्टेंट देखना
आपके लिए सुझाव
- ध्यान दें: JavaScript बंद होने पर लिंक का टेक्स्ट दिखता है
- बहुत बार स्क्रीन चालू होना