ANR की गड़बड़ियों का पता लगाना और उन्हें ठीक करना

जब किसी Android ऐप्लिकेशन का यूज़र इंटरफ़ेस (यूआई) थ्रेड बहुत देर तक ब्लॉक रहता है, तो सिस्टम "ऐप्लिकेशन काम नहीं कर रहा है" (एएनआर) गड़बड़ी भेजता है. इस पेज पर, अलग-अलग तरह के एएनआर के बारे में बताया गया है. साथ ही, यह भी बताया गया है कि इनकी पहचान कैसे की जाती है और इन्हें ठीक करने के सुझाव क्या हैं. टाइम आउट होने की डिफ़ॉल्ट समयावधि की सभी रेंज, AOSP और Pixel डिवाइसों के लिए हैं. ओईएम के हिसाब से, ये समयावधियां अलग-अलग हो सकती हैं.

ध्यान रखें कि ANR की वजह का पता लगाते समय, सिस्टम और ऐप्लिकेशन से जुड़ी समस्याओं के बीच अंतर करना फ़ायदेमंद होता है.

सिस्टम की स्थिति खराब होने पर, इन समस्याओं की वजह से एएनआर हो सकते हैं:

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

अगर आपके पास यह सुविधा उपलब्ध है, तो सिस्टम और ऐप्लिकेशन से जुड़ी समस्याओं के बीच अंतर करने का सबसे अच्छा तरीका Perfetto ट्रेस का इस्तेमाल करना है:

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

इनपुट डिस्पैच टाइम आउट

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

डिफ़ॉल्ट टाइम आउट अवधि: 5 सेकंड.

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

इनपुट डिस्पैच एएनआर से बचने के लिए, यहां दिए गए सबसे सही तरीके अपनाएं:

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

आम वजहें

यहां इनपुट डिस्पैच एएनआर की कुछ आम वजहें और उन्हें ठीक करने के सुझाव दिए गए हैं.

वजह क्या होगा सुझाए गए सुधार
धीमा बाइंडर कॉल मुख्य थ्रेड, सिंक्रोनस बाइंडर कॉल करता है. अगर आपके पास एपीआई का मालिकाना हक है, तो कॉल को मुख्य थ्रेड से हटा दें या कॉल को ऑप्टिमाइज़ करने की कोशिश करें.
लगातार कई बाइंडर कॉल मुख्य थ्रेड, एक के बाद एक कई सिंक्रोनस बाइंडर कॉल करता है. टाइट लूप में बाइंडर कॉल न करें.
ब्लॉकिंग I/O मुख्य थ्रेड, डेटाबेस या नेटवर्क ऐक्सेस जैसे I/O कॉल को ब्लॉक करता है. सभी ब्लॉकिंग IO को मुख्य थ्रेड से हटा दें.
लॉक का विवाद मुख्य थ्रेड को ब्लॉक किया गया है और यह लॉक हासिल करने का इंतज़ार कर रही है. मुख्य थ्रेड और अन्य थ्रेड के बीच लॉक कंटेंशन को कम करें. दूसरी थ्रेड में धीमे कोड को ऑप्टिमाइज़ करें.
रेंडर होने में बहुत ज़्यादा समय लेने वाला फ़्रेम एक ही फ़्रेम में बहुत ज़्यादा रेंडरिंग की जा रही है. इससे गंभीर जंक हो रहा है. फ़्रेम को रेंडर करने में कम समय लगता है. n2 एल्गोरिदम का इस्तेमाल न करें. स्क्रोल या पेजिंग जैसी चीज़ों के लिए, असरदार कॉम्पोनेंट का इस्तेमाल करें. उदाहरण के लिए, Jetpack Paging library.
किसी अन्य कॉम्पोनेंट ने ब्लॉक किया कोई दूसरा कॉम्पोनेंट, जैसे कि ब्रॉडकास्ट रिसीवर चल रहा है और मुख्य थ्रेड को ब्लॉक कर रहा है. यूज़र इंटरफ़ेस (यूआई) से जुड़े काम को जितना हो सके उतना मुख्य थ्रेड से अलग रखें. ब्रॉडकास्ट रिसीवर को किसी अन्य थ्रेड पर चलाएं.
GPU हैंग होने की समस्या जीपीयू हैंग, सिस्टम या हार्डवेयर से जुड़ी समस्या है. इसकी वजह से, रेंडरिंग ब्लॉक हो जाती है. इसलिए, इनपुट डिस्पैच एएनआर की समस्या होती है. माफ़ करें, आम तौर पर ऐप्लिकेशन में कोई सुधार नहीं किया जाता है. अगर संभव हो, तो समस्या हल करने के लिए हार्डवेयर टीम से संपर्क करें.

डीबग करने का तरीका

Google Play Console या Firebase Crashlytics में एएनआर क्लस्टर के सिग्नेचर को देखकर, डीबग करना शुरू करें. इस क्लस्टर में आम तौर पर, ऐसे टॉप फ़्रेम शामिल होते हैं जिनकी वजह से ANR की समस्या हुई है.

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

पहली इमेज. इनपुट डिसपैच से जुड़ी एएनआर की गड़बड़ी को डीबग करने का तरीका.

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

दूसरी इमेज. Play की ज़रूरी जानकारी में एएनआर का पता लगाने की सुविधा.

कोई फ़ोकस की गई विंडो नहीं है

टच जैसे इवेंट, हिट टेस्टिंग के आधार पर सीधे तौर पर काम की विंडो पर भेजे जाते हैं. हालांकि, कुंजियों जैसे इवेंट के लिए टारगेट की ज़रूरत होती है. इस टारगेट को फ़ोकस की गई विंडो कहा जाता है. हर डिसप्ले पर सिर्फ़ एक फ़ोकस की गई विंडो होती है. आम तौर पर, यह वह विंडो होती है जिससे उपयोगकर्ता फ़िलहाल इंटरैक्ट कर रहा होता है. अगर फ़ोकस की गई विंडो नहीं मिलती है, तो इनपुट से no-focused-window ANR की समस्या होती है. फ़ोकस न की गई विंडो में होने वाली एएनआर, इनपुट डिस्पैच एएनआर का एक टाइप है.

डिफ़ॉल्ट टाइम आउट अवधि: 5 सेकंड.

आम वजहें

आम तौर पर, नो-फ़ोकस्ड-विंडो वाले एएनआर, इनमें से किसी एक वजह से होते हैं:

  • ऐप्लिकेशन बहुत ज़्यादा काम कर रहा है और पहला फ़्रेम बनाने में बहुत समय ले रहा है.
  • मुख्य विंडो पर फ़ोकस नहीं किया जा सकता. अगर किसी विंडो को FLAG_NOT_FOCUSABLE के तौर पर फ़्लैग किया गया है, तो उपयोगकर्ता उस पर बटन या कीबोर्ड इवेंट नहीं भेज सकता.

Kotlin

override fun onCreate(savedInstanceState: Bundle) {
  super.onCreate(savedInstanceState)
  setContentView(R.layout.activity_main)
  window.addFlags(WindowManager.LayoutParams.FLAG_FLAG_NOT_FOCUSABLE)
}

Java

@Override
protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  getWindow().addFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE);
}

ब्रॉडकास्ट रिसीवर का टाइम आउट

ब्रॉडकास्ट रिसीवर में एएनआर की समस्या तब होती है, जब ब्रॉडकास्ट रिसीवर किसी ब्रॉडकास्ट को समय पर हैंडल नहीं करता. सिंक्रोनस रिसीवर या goAsync() को कॉल नहीं करने वाले रिसीवर के लिए, टाइम आउट का मतलब है कि onReceive() समय पर पूरा नहीं हुआ. एसिंक्रोनस रिसीवर या goAsync() को कॉल करने वाले रिसीवर के लिए, टाइम आउट का मतलब है कि PendingResult.finish() को समय पर कॉल नहीं किया गया.

ब्रॉडकास्ट रिसीवर के एएनआर अक्सर इन थ्रेड में होते हैं:

  • अगर ऐप्लिकेशन के शुरू होने में ज़्यादा समय लग रहा है, तो मुख्य थ्रेड.
  • अगर समस्या onReceive() कोड के धीमे चलने की वजह से है, तो ब्रॉडकास्ट रिसीवर चलाने वाला थ्रेड.
  • अगर समस्या ब्रॉडकास्ट कोड goAsync() के धीरे काम करने की है, तो ब्रॉडकास्ट वर्कर थ्रेड.

ब्रॉडकास्ट रिसीवर के एएनआर से बचने के लिए, यहां दिए गए सबसे सही तरीके अपनाएं:

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

टाइम आउट की अवधि

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

इंटेंट टाइप Android 13 और इससे पहले के वर्शन Android 14 और उसके बाद के वर्शन

फ़ोरग्राउंड में प्राथमिकता के साथ चलाने का अनुरोध

(FLAG_RECEIVER_FOREGROUND सेट करें)

10 सेकंड

10 से 20 सेकंड, यह इस बात पर निर्भर करता है कि प्रोसेस में सीपीयू का इस्तेमाल कम हो रहा है या नहीं

बैकग्राउंड में काम करने वाले इंटेंट को प्राथमिकता देना

(FLAG_RECEIVER_FOREGROUND सेट नहीं है)

60 सेकंड

60 से 120 सेकंड, इस बात पर निर्भर करता है कि प्रोसेस सीपीयू-स्टार्व्ड है या नहीं

FLAG_RECEIVER_FOREGROUND फ़्लैग सेट है या नहीं, यह जानने के लिए एएनआर के विषय में "flg=" खोजें और देखें कि 0x10000000 मौजूद है या नहीं. अगर यह बिट सेट है, तो इसका मतलब है कि इंटेंट में FLAG_RECEIVER_FOREGROUND सेट है. इसलिए, टाइम आउट कम है.

कम समय (10 से 20 सेकंड) के ब्रॉडकास्ट टाइमआउट के साथ एएनआर के विषय का उदाहरण:

Broadcast of Intent { act=android.inent.action.SCREEN_ON flg=0x50200010 }

ब्रॉडकास्ट टाइमआउट (60 से 120 सेकंड) के साथ एएनआर के विषय का उदाहरण:

Broadcast of Intent { act=android.intent.action.TIME_SET flg=0x25200010 }

ब्रॉडकास्ट के समय को कैसे मापा जाता है

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

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

तीसरी इमेज. ब्रॉडकास्ट रिसीवर के एएनआर की टाइमलाइन.

एएनआर टाइमआउट मेज़रमेंट तब खत्म होता है, जब रिसीवर ब्रॉडकास्ट को प्रोसेस कर लेता है. यह कब खत्म होता है, यह इस बात पर निर्भर करता है कि रिसीवर सिंक्रोनस है या असिंक्रोनस.

  • सिंक्रोनस रिसीवर के लिए, onReceive() के वापस आने पर मेज़रमेंट रुक जाता है.
  • एसिंक्रोनस रिसीवर के लिए, PendingResult.finish() को कॉल करने पर मेज़रमेंट बंद हो जाता है.
चौथी इमेज. सिंक्रोनस और एसिंक्रोनस रिसीवर के लिए, एएनआर टाइम आउट मेज़रमेंट एंडपॉइंट.

आम वजहें

यहां ब्रॉडकास्ट रिसीवर एएनआर की कुछ सामान्य वजहें और उन्हें ठीक करने के सुझाव दिए गए हैं.

वजह ऑफ़र इस पर लागू होता है समस्या क्या थी सुझाया गया हल
ऐप्लिकेशन शुरू होने की रफ़्तार कम है सभी पाने वाले ऐप्लिकेशन को कोल्ड स्टार्ट होने में बहुत ज़्यादा समय लगा. ऐप्लिकेशन के शुरू होने की रफ़्तार को ऑप्टिमाइज़ करें.
onReceive() शेड्यूल नहीं किया गया सभी पाने वाले ब्रॉडकास्ट रिसीवर थ्रेड, दूसरे काम में व्यस्त थी. इसलिए, वह onReceive() तरीके को शुरू नहीं कर सकी. रिसीवर थ्रेड पर लंबे समय तक चलने वाले टास्क न करें. इसके अलावा, रिसीवर को किसी खास थ्रेड पर ले जाएं.
onReceive() ठीक से काम नहीं कर रहा है सभी रिसीवर, लेकिन मुख्य रूप से सिंक्रोनस रिसीवर onReceive() तरीका शुरू किया गया था, लेकिन इसे ब्लॉक कर दिया गया था या यह धीमा था. इसलिए, यह समय पर पूरा नहीं हो सका. धीमे रिसीवर कोड को ऑप्टिमाइज़ करें.
एसिंक्रोनस रिसीवर टास्क शेड्यूल नहीं किए गए goAsync() receivers onReceive() तरीके ने ब्लॉक किए गए वर्कर थ्रेड पूल पर काम करने की कोशिश की. इसलिए, काम कभी शुरू नहीं हुआ. धीमे या ब्लॉक करने वाले कॉल को ऑप्टिमाइज़ करें या ब्रॉडकास्ट वर्कर के लिए अलग-अलग थ्रेड का इस्तेमाल करें. ऐसा अन्य लंबे समय तक चलने वाले टास्क के लिए भी किया जा सकता है.
कर्मचारी धीरे काम कर रहे हैं या काम नहीं कर रहे हैं goAsync() रिसीवर ब्रॉडकास्ट को प्रोसेस करते समय, वर्कर थ्रेड पूल में कोई ऑपरेशन ब्लॉक हो गया था या वह धीरे-धीरे हो रहा था. इसलिए, PendingResult.finish को समय पर कॉल नहीं किया गया. धीमे async रिसीवर कोड को ऑप्टिमाइज़ करें.
PendingResult.finish को कॉल करना भूल गया goAsync() रिसीवर कोड पाथ में finish() को कॉल करने का तरीका मौजूद नहीं है. पक्का करें कि finish() को हमेशा कॉल किया जाए.

डीबग करने का तरीका

क्लस्टर सिग्नेचर और एएनआर रिपोर्ट के आधार पर, उस थ्रेड का पता लगाया जा सकता है जिस पर रिसीवर चलता है. इसके बाद, उस कोड का पता लगाया जा सकता है जो मौजूद नहीं है या धीरे चल रहा है.

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

पांचवीं इमेज. ब्रॉडकास्ट रिसीवर में होने वाली ANR को डीबग करने का तरीका.

रिसीवर कोड ढूंढना

Google Play Console, ANR सिग्नेचर में रिसीवर क्लास और ब्रॉडकास्ट इंटेंट दिखाता है. इन बातों पर ध्यान दें:

  • cmp=<receiver class>
  • act=<broadcast_intent>

यहां ब्रॉडकास्ट रिसीवर के एएनआर सिग्नेचर का एक उदाहरण दिया गया है:

com.example.app.MyClass.myMethod
Broadcast of Intent { act=android.accounts.LOGIN_ACCOUNTS_CHANGED
cmp=com.example.app/com.example.app.MyAccountReceiver }

onReceive() तरीके को चलाने वाला थ्रेड ढूंढना

अगर कस्टम हैंडलर के बारे में बताने के लिए Context.registerReceiver का इस्तेमाल किया जा रहा है, तो यह हैंडलर को चलाने वाला थ्रेड होता है. अगर ऐसा नहीं है, तो यह मुख्य थ्रेड है.

उदाहरण: एसिंक रिसीवर टास्क शेड्यूल नहीं किए गए हैं

इस सेक्शन में, ब्रॉडकास्ट रिसीवर की एएनआर गड़बड़ी को डीबग करने का तरीका बताया गया है.

मान लें कि एएनआर का सिग्नेचर ऐसा दिखता है:

com.example.app.MyClass.myMethod
Broadcast of Intent {
act=android.accounts.LOG_ACCOUNTS_CHANGED cmp=com.example.app/com.example.app.MyReceiver }

हस्ताक्षर के आधार पर, ऐसा लगता है कि ब्रॉडकास्ट इंटेंट android.accounts.LOG_ACCOUNTS_CHANGED है और रिसीवर क्लास com.example.app.MyReceiver है.

Receiver कोड से, यह पता लगाया जा सकता है कि इस ब्रॉडकास्ट को प्रोसेस करने का मुख्य काम, थ्रेड पूल "BG Thread [0,1,2,3]" करता है. स्टैक डंप देखने पर पता चलता है कि सभी चार बैकग्राउंड (बीजी) थ्रेड का पैटर्न एक जैसा है: ये एक ब्लॉकिंग कॉल, getDataSync को चलाते हैं. सभी बीजी थ्रेड व्यस्त होने की वजह से, ब्रॉडकास्ट को समय पर प्रोसेस नहीं किया जा सका. इस वजह से, एएनआर की गड़बड़ी हुई.

BG Thread #0 (tid=26) Waiting

at jdk.internal.misc.Unsafe.park(Native method:0)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:211)
at com.google.common.util.concurrent.AbstractFuture.get(AbstractFuture:563)
at com.google.common.util.concurrent.ForwardingFuture.get(ForwardingFuture:68)
at com.example.app.getDataSync(<MyClass>:152)

...

at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:644)
at com.google.android.libraries.concurrent.AndroidExecutorsModule.lambda$withStrictMode$5(AndroidExecutorsModule:451)
at com.google.android.libraries.concurrent.AndroidExecutorsModule$$ExternalSyntheticLambda8.run(AndroidExecutorsModule:1)
at java.lang.Thread.run(Thread.java:1012)
at com.google.android.libraries.concurrent.ManagedPriorityThread.run(ManagedPriorityThread:34)

There are several approaches to fix the issue:

  • Find out why getDataSync is slow and optimize.
  • Don't run getDataSync on all four BG threads.
  • More generally, ensure that the BG thread pool isn't saturated with long-running operations.
  • Use a dedicated thread pool for goAsync worker tasks.
  • Use an unbounded thread pool instead of the bounded BG thread pool

Example: slow app startup

A slow app startup can cause several types of ANRs, especially broadcast receiver and execute service ANRs. The cause of an ANR is likely slow app startup if you see ActivityThread.handleBindApplication in the main thread stacks.

Execute service timeout

An execute service ANR happens when the app's main thread doesn't start a service in time. Specifically, a service doesn't finish executing onCreate() and onStartCommand() or onBind() within the timeout period.

Default timeout period: 20 seconds for foreground service; 200 seconds for background service. The ANR timeout period includes the app cold start, if necessary, and calls to onCreate(), onBind(), or onStartCommand().

To avoid execute service ANRs, follow these general best practices:

  • Make sure that app startup is fast, since it's counted in the ANR timeout if the app is started to run the service component.
  • Make sure that the service's onCreate(), onStartCommand(), and onBind() methods are fast.
  • Avoid running any slow or blocking operations on the main thread from other components; these operations can prevent a service from starting quickly.

Common causes

The following table lists common causes of execute service ANRs and suggested fixes.

Cause What Suggested fix
Slow app startup The app takes too long to perform a cold start. Optimize slow app start.
Slow onCreate(), onStartCommand(), or onBind() The service component's onCreate(), onStartCommand(), or onBind() method takes too long to execute on the main thread. Optimize slow code. Move slow operations off the critical path where possible.
Not scheduled (main thread blocked before onStart()) The app's main thread is blocked by another component before the service can be started. Move other component's work off the main thread. Optimize other component's blocking code.

How to debug

From the cluster signature and ANR report in Google Play Console or Firebase Crashlytics, you can often determine the cause of the ANR based on what the main thread is doing.

The following flow chart describes how to debug an execute service ANR.

Figure 6. How to debug an execute service ANR.

If you've determined that the execute service ANR is actionable, follow these steps to help resolve the issue:

  1. Find the service component class in the ANR signature. In Google Play Console, the service component class is shown in the ANR signature. In the following example ANR details, it's com.example.app/MyService.

    com.google.common.util.concurrent.Uninterruptibles.awaitUninterruptibly
    Executing service com.example.app/com.example.app.MyService
    
  2. Determine whether the slow or block operation is part of app startup, the service component, or elsewhere by checking for the following important function call(s) in the main threads.

    Function call(s) in main thread stacks What it means
    android.app.ActivityThread.handleBindApplication App was starting up, so the ANR was caused by slow app start.

    <ServiceClass>.onCreate()

    [...]

    android.app.ActivityThread.handleCreateService

    Service was being created, so the ANR was likely caused by slow onCreate() code.

    <ServiceClass>.onBind()

    [...]

    android.app.ActivityThread.handleBindService

    Service was being bound, so the ANR was likely caused by slow onBind() code.

    <ServiceClass>.onStartCommand()

    [...]

    android.app.ActivityThread.handleServiceArgs

    Service was being started, so the ANR was likely caused by slow onStartCommand() code.

    For example, if the onStartCommand() method in the MyService class is slow, the main threads will look like this:

    at com.example.app.MyService.onStartCommand(FooService.java:25)
    at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:4820)
    at android.app.ActivityThread.-$$Nest$mhandleServiceArgs(unavailable:0)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2289)
    at android.os.Handler.dispatchMessage(Handler.java:106)
    at android.os.Looper.loopOnce(Looper.java:205)
    at android.os.Looper.loop(Looper.java:294)
    at android.app.ActivityThread.main(ActivityThread.java:8176)
    at java.lang.reflect.Method.invoke(Native method:0)
    

    अगर आपको कोई भी ज़रूरी फ़ंक्शन कॉल नहीं दिखता है, तो इसकी कुछ और वजहें हो सकती हैं:

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

  4. सेवाओं के बारे में ज़्यादा जानने के लिए, ये पेज देखें:

    कॉन्टेंट उपलब्ध कराने वाली कंपनी जवाब नहीं दे रही है

    कॉन्टेंट उपलब्ध कराने वाली रिमोट सेवा के लिए एएनआर तब होता है, जब वह किसी क्वेरी का जवाब देने में टाइम आउट की अवधि से ज़्यादा समय लेती है और उसे बंद कर दिया जाता है.

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

    कॉन्टेंट उपलब्ध कराने वाली कंपनी के एएनआर से बचने के लिए, इन सबसे सही तरीकों को अपनाएं:

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

    आम वजहें

    नीचे दी गई टेबल में, कॉन्टेंट उपलब्ध कराने वाले ऐप्लिकेशन में होने वाली एएनआर की सामान्य वजहें और उन्हें ठीक करने के सुझाव दिए गए हैं.

    वजह क्या होगा सिग्नल सुझाया गया हल
    कॉन्टेंट देने वाले ऐप्लिकेशन की क्वेरी के जवाब में समय लग रहा है कॉन्टेंट उपलब्ध कराने वाली कंपनी, अनुरोध को पूरा करने में बहुत ज़्यादा समय लेती है या उसे ब्लॉक कर दिया गया है. android.content.ContentProvider$Transport.query फ़्रेम, बाइंडर थ्रेड में है. कॉन्टेंट देने वाले ऐप्लिकेशन की क्वेरी को ऑप्टिमाइज़ करें. पता लगाएं कि बाइंडर थ्रेड को कौनसी प्रोसेस ब्लॉक कर रही है.
    ऐप्लिकेशन शुरू होने की रफ़्तार कम है कॉन्टेंट उपलब्ध कराने वाले का ऐप्लिकेशन, शुरू होने में बहुत ज़्यादा समय लेता है. ActivityThread.handleBindApplication फ़्रेम, मुख्य थ्रेड में है. ऐप्लिकेशन के स्टार्टअप को ऑप्टिमाइज़ करें.
    Binder थ्रेड का इस्तेमाल नहीं किया जा सकता—सभी Binder थ्रेड व्यस्त हैं सभी बाइंडर थ्रेड, अन्य सिंक्रोनस अनुरोधों को पूरा करने में व्यस्त हैं. इसलिए, कॉन्टेंट उपलब्ध कराने वाली कंपनी के बाइंडर कॉल को नहीं चलाया जा सकता. ऐप्लिकेशन शुरू नहीं हो रहा है, सभी बाइंडर थ्रेड व्यस्त हैं, और कॉन्टेंट प्रोवाइडर काम नहीं कर रहा है. बाइंडर थ्रेड पर लोड कम करें. इसका मतलब है कि सिंक्रोनस आउटगोइंग बाइंडर कॉल कम करें या इनकमिंग कॉल हैंडल करते समय कम काम करें.

    डीबग करने का तरीका

    Google Play Console या Firebase Crashlytics में क्लस्टर सिग्नेचर और एएनआर रिपोर्ट का इस्तेमाल करके, कॉन्टेंट प्रोवाइडर के एएनआर से जुड़ी गड़बड़ी को ठीक करने के लिए, देखें कि मुख्य थ्रेड और बाइंडर थ्रेड क्या कर रहे हैं.

    यहां दिए गए फ़्लो चार्ट में, कॉन्टेंट प्रोवाइडर के एएनआर को डीबग करने का तरीका बताया गया है:

    इमेज 7. कॉन्टेंट प्रोवाइडर के एएनआर को डीबग करने का तरीका.

    नीचे दिया गया कोड स्निपेट दिखाता है कि कॉन्टेंट उपलब्ध कराने वाली कंपनी की क्वेरी के धीमे होने की वजह से, बाइंडर थ्रेड कैसा दिखता है. इस मामले में, कॉन्टेंट उपलब्ध कराने वाली कंपनी की क्वेरी, डेटाबेस खोलने के दौरान लॉक होने का इंतज़ार कर रही है.

    binder:11300_2 (tid=13) Blocked
    
    Waiting for osm (0x01ab5df9) held by at com.google.common.base.Suppliers$NonSerializableMemoizingSupplier.get(Suppliers:182)
    at com.example.app.MyClass.blockingGetOpenDatabase(FooClass:171)
    [...]
    at com.example.app.MyContentProvider.query(MyContentProvider.java:915)
    at android.content.ContentProvider$Transport.query(ContentProvider.java:292)
    at android.content.ContentProviderNative.onTransact(ContentProviderNative.java:107)
    at android.os.Binder.execTransactInternal(Binder.java:1339)
    at android.os.Binder.execTransact(Binder.java:1275)
    

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

    main (tid=1) Blocked
    
    [...]
    at dagger.internal.DoubleCheck.get(DoubleCheck:51)
    - locked 0x0e33cd2c (a qsn)at dagger.internal.SetFactory.get(SetFactory:126)
    at com.myapp.Bar_Factory.get(Bar_Factory:38)
    [...]
    at com.example.app.MyApplication.onCreate(DocsApplication:203)
    at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1316)
    at android.app.ActivityThread.handleBindApplication(ActivityThread.java:6991)
    at android.app.ActivityThread.-$$Nest$mhandleBindApplication(unavailable:0)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2235)
    at android.os.Handler.dispatchMessage(Handler.java:106)
    at android.os.Looper.loopOnce(Looper.java:205)
    at android.os.Looper.loop(Looper.java:294)
    at android.app.ActivityThread.main(ActivityThread.java:8170)
    at java.lang.reflect.Method.invoke(Native method:0)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:552)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:971)
    

    जॉब के जवाब मिलने में देरी होना

    जब कोई ऐप्लिकेशन JobService.onStartJob() या JobService.onStopJob() को जवाब देने में बहुत ज़्यादा समय लेता है या JobService.setNotification() का इस्तेमाल करके सूचना देने में बहुत ज़्यादा समय लेता है, तब जॉब के जवाब देने में ज़्यादा समय लगने की वजह से एएनआर की समस्या होती है. इससे पता चलता है कि ऐप्लिकेशन की मुख्य थ्रेड, किसी और काम में व्यस्त है.

    अगर समस्या JobService.onStartJob() या JobService.onStopJob() से जुड़ी है, तो देखें कि मुख्य थ्रेड पर क्या हो रहा है. अगर JobService.setNotification() से जुड़ी कोई समस्या है, तो जल्द से जल्द कॉल करें. सूचना देने से पहले, ज़्यादा काम न करें.

    थ्रेडिंग से जुड़े उल्लंघन की जानकारी देखना

    Compose को आज़माएं
    Android के लिए, Jetpack Compose को यूज़र इंटरफ़ेस (यूआई) टूलकिट के तौर पर इस्तेमाल करने का सुझाव दिया जाता है.

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

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

    थ्रेडिंग से जुड़े इस उल्लंघन की वजह से, ANR स्टैक ट्रेस की गड़बड़ी होती है.इसमें मुख्य थ्रेड कुछ समय से इस्तेमाल नहीं हो रहा होता है. उदाहरण के लिए, "nativePollOnce" या "main thread idle" में कैप्चर किया गया.

    सिंक बैरियर लीक

    व्यू को अमान्य किया जा सकता है. ऐसा सीधे तौर पर View.invalidate या View.requestLayout को कॉल करके किया जा सकता है. इसके अलावा, व्यू की स्थिति में बदलाव करके भी ऐसा किया जा सकता है. उदाहरण के लिए, TextView.setText और View.setVisibility को कॉल करके. जब किसी व्यू को अमान्य किया जाता है, तो ViewRootImpl मेज़रमेंट, लेआउट, और ड्रॉइंग करने के लिए ट्रैवर्सल शेड्यूल करता है, ताकि यूज़र इंटरफ़ेस (यूआई) की स्थिति को अपडेट किया जा सके.

    1. ट्रैवर्सल शेड्यूल करना: ViewRootImpl, यूआई थ्रेड के MessageQueue में सिंक्रनाइज़ेशन बैरियर पोस्ट करके, ट्रैवर्सल को शेड्यूल करता है. ट्रैवर्सल, लेआउट और ड्रॉइंग पास होता है. यह बैरियर, मैसेज को प्रोसेस करने की सामान्य प्रक्रिया को रोकता है, ताकि यूज़र इंटरफ़ेस (यूआई) लेआउट को प्राथमिकता दी जा सके.
    2. रेस कंडीशन: जब कई थ्रेड एक साथ किसी व्यू को अमान्य करने की कोशिश करती हैं, तो वे इस ट्रैवर्सल को शेड्यूल करने के लिए रेस करती हैं. दोनों थ्रेड, सिंक्रनाइज़ेशन बैरियर को सही तरीके से डाल सकती हैं. हालांकि, फ़्रेमवर्क सिर्फ़ एक थ्रेड के लिए टोकन सेव करता है.
    3. यूज़र इंटरफ़ेस (यूआई) फ़्रीज़ होना: जब ट्रैवर्सल लागू होता है, तो यह सिर्फ़ सेव की गई एक बैरियर को हटाता है. सेकंडरी, "लीक" बैरियर, कतार में हमेशा के लिए बने रहते हैं. इससे यूज़र इंटरफ़ेस (यूआई) थ्रेड, किसी भी सिंक्रोनस मैसेज को प्रोसेस नहीं कर पाती.

    इस वजह से, यूज़र इंटरफ़ेस (यूआई) फ़्रीज़ हो जाता है. लीक हुए बैरियर के बाद, MessageQueue किसी भी सिंक्रोनस मैसेज को प्रोसेस नहीं कर सकता. इसलिए, मुख्य थ्रेड निष्क्रिय हो जाती है. आम तौर पर, यह समस्या स्टैक ट्रेस में nativePollOnce के साथ ANR के तौर पर दिखती है.

    व्यू थ्रेडिंग के उल्लंघन से बचने के लिए, इन सबसे सही तरीकों को अपनाएं:

    • सिर्फ़ उन थ्रेड पर View ऑब्जेक्ट के साथ इंटरैक्ट करें जहां आपने व्यू हैरारकी बनाई है. इनमें width या height जैसी प्रॉपर्टी पढ़ना या TextView's text जैसी प्रॉपर्टी सेट करना शामिल है. यह थ्रेड, मुख्य या यूज़र इंटरफ़ेस (यूआई) थ्रेड होती है.
    • अगर आपको यह पक्का नहीं है कि व्यू ऐक्सेस करते समय, यूज़र इंटरफ़ेस (यूआई) थ्रेड पर काम किया जा रहा है, तो मान लें कि ऐसा करना सुरक्षित नहीं है. उदाहरण के लिए, अगर बैकग्राउंड में काम करने के लिए Coroutines का इस्तेमाल किया जा रहा है, तो आपको View ऑब्जेक्ट में बदलाव करने से पहले, मुख्य डिसपैचर पर स्विच करना होगा.

    lifecycleOwner.lifecycleScope.launch(Dispatchers.IO) {
        val data = myRepository.getData()
        withContext(Dispatchers.Main) { // Switch context to Main
            myTextView.text = data.title
        }
    }

    सबसे सही तरीकों का पालन करने के लिए, Android अन्य थ्रेड से यूज़र इंटरफ़ेस (यूआई) थ्रेड को ऐक्सेस करने के कई तरीके उपलब्ध कराता है:

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

    डीबग करने का तरीका

    Android 17 में नए टूल जोड़े गए हैं. इनकी मदद से, डेवलपमेंट के दौरान व्यू थ्रेडिंग से जुड़े उल्लंघनों की पहचान की जा सकती है, उन्हें ट्रैक किया जा सकता है, और ठीक किया जा सकता है.

    1. कंपैटिबिलिटी फ़्रेमवर्क टूल

    कंपैटिबिलिटी फ़्रेमवर्क टूल की मदद से, ऐप्लिकेशन डेवलपर डेवलपर के लिए सेटिंग और टूल या ADB का इस्तेमाल करके, व्यवहार में होने वाले बदलावों को अलग-अलग तौर पर चालू और बंद कर सकते हैं. थ्रेडिंग के उल्लंघन के व्यवहार में हुए बदलावों को टॉगल करके देखने के लिए, यह तरीका अपनाएं:

    1. Android 17 या इसके बाद के वर्शन पर काम करने वाले डिवाइस पर, अपने ऐप्लिकेशन का डीबग किया जा सकने वाला वर्शन इंस्टॉल करें.
    2. अपने डिवाइस में सेटिंग ऐप्लिकेशन खोलें और सिस्टम > ऐडवांस > डेवलपर के लिए सेटिंग और टूल > ऐप्लिकेशन के साथ काम करने से जुड़ी सेटिंग में बदलाव पर जाएं.
    3. सूची में से अपना ऐप्लिकेशन चुनें.
    4. बदलावों की सूची में, ENFORCE_THREAD_CHECKS_ON_VIEW_ROOT_IMPL_APIS स्विच ढूंढें और उसे टॉगल करके चालू करें.

    ADB का इस्तेमाल करके, फ़्लैग को चालू या बंद भी किया जा सकता है:

    $ adb shell am compat enable ENFORCE_THREAD_CHECKS_ON_VIEW_ROOT_IMPL_APIS <your.package.name>
    $ adb shell am compat disable ENFORCE_THREAD_CHECKS_ON_VIEW_ROOT_IMPL_APIS <your.package.name>
    

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

    2. CalledFromWrongThreadListener API

    थ्रेड को गलत तरीके से ऐक्सेस करने का पता लगाने के लिए, ग्लोबल View#registerCalledFromWrongThreadListener एपीआई को भी लागू किया जा सकता है.

    • टेलीमेट्री और ट्रैकिंग: यह लिसनर, आपके ऐप्लिकेशन को कॉलबैक पाने की अनुमति देता है. ऐसा तब होता है, जब किसी गलत थ्रेड से View API को शुरू किया जाता है. इससे टेलीमेट्री को लॉग करना और गड़बड़ियों को ट्रैक करना आसान हो जाता है.
    • इनलाइन एक्ज़ीक्यूशन: लिसनर को इनलाइन कहा जाता है. इससे आपको उल्लंघन होने के समय, स्टैक ट्रेस को कैप्चर करने और उसकी जांच करने की अनुमति मिलती है.
    android {
       //...
       compileSdk = 37
    }
    

    val listener = object : View.CalledFromWrongThreadListener {
        override fun onCalledFromWrongThread() {
            // Handle the issue, e.g. crash if this is a dev build, or log an event
            // e.g. Log.d(TAG, "CalledFromWrongThread: ${Exception().stackTraceToString()}")
            // Unregister the listener to avoid redundant notifications for the same issue
            View.unregisterCalledFromWrongThreadListener(this)
        }
    }
    View.registerCalledFromWrongThreadListener(listener)

    nativePollOnce

    अगर आपको एएनआर स्टैक में "nativePollOnce" या "message queue idle" फ़्रेम दिखता है, तो इसका मतलब है कि जिस थ्रेड के जवाब न देने की आशंका है वह असल में कुछ नहीं कर रही थी. साथ ही, वह लूपर मैसेज का इंतज़ार कर रही थी. Google Play Console में, ANR की जानकारी इस तरह दिखती है:

    Native method - android.os.MessageQueue.nativePollOnce
    Executing service com.example.app/com.example.app.MyService
    

    उदाहरण के लिए, अगर मुख्य थ्रेड कुछ समय से इस्तेमाल में नहीं है, तो स्टैक इस तरह दिखते हैं:

    "main" tid=1 NativeMain threadIdle
    
    #00  pc 0x00000000000d8b38  /apex/com.android.runtime/lib64/bionic/libc.so (__epoll_pwait+8)
    #01  pc 0x0000000000019d88  /system/lib64/libutils.so (android::Looper::pollInner(int)+184)
    #02  pc 0x0000000000019c68  /system/lib64/libutils.so (android::Looper::pollOnce(int, int*, int*, void**)+112)
    #03  pc 0x000000000011409c  /system/lib64/libandroid_runtime.so (android::android_os_MessageQueue_nativePollOnce(_JNIEnv*, _jobject*, long, int)+44)
    at android.os.MessageQueue.nativePollOnce (Native method)
    at android.os.MessageQueue.next (MessageQueue.java:339)  at android.os.Looper.loop (Looper.java:208)
    at android.app.ActivityThread.main (ActivityThread.java:8192)
    at java.lang.reflect.Method.invoke (Native method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:626)
    at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:1015)
    

    थ्रेड के जवाब न देने की कई वजहें हो सकती हैं:

    • सिस्टम से जुड़ी समस्या. सिस्टम पर ज़्यादा लोड होने या सिस्टम सर्वर में किसी समस्या की वजह से, प्रोसेस को शेड्यूल नहीं किया गया.
    • लेट स्टैक डंप. एएनआर ट्रिगर होने और स्टैक डंप होने के बीच के छोटे समय में थ्रेड वापस आ गई. Android 13 पर चलने वाले Pixel डिवाइसों में, लेटेंसी करीब 100 मि॰से॰ होती है. हालांकि, यह एक सेकंड से ज़्यादा भी हो सकती है. Android 14 पर काम करने वाले Pixel डिवाइसों में, इंतज़ार का समय आम तौर पर 10 मि॰से॰ से कम होता है.
    • थ्रेड को गलत एट्रिब्यूट करना. एएनआर सिग्नेचर बनाने के लिए इस्तेमाल किया गया थ्रेड, वह थ्रेड नहीं था जिसकी वजह से एएनआर हुआ.
    • थ्रेडिंग के उल्लंघन की जानकारी देखें पर क्लिक करें. अगर आपका ऐप्लिकेशन बैकग्राउंड थ्रेड पर किसी व्यू में बदलाव करता है, तो इससे व्यू के इंटरनल में रेस कंडीशन ट्रिगर हो सकती है. इससे यूज़र इंटरफ़ेस (यूआई) थ्रेड के टास्क नहीं चल पाते

    "nativePollOnce" एएनआर के ट्रिगर, एएनआर के टाइप के हिसाब से अलग-अलग होते हैं. इसलिए, एएनआर की किसी खास कैटगरी की जांच करने से, आपके ऐप्लिकेशन में समस्या को हल करने के लिए ज़रूरी चरणों की पहचान करने में मदद मिल सकती है.

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

    NativePollOnce ANR का विश्लेषण करने के लिए, यहां सुझाए गए तरीके दिए गए हैं.

    1. प्रोसेसर पर बहुत ज़्यादा लोड है: डिवाइस के सभी संसाधनों पर पड़ने वाले दबाव का आकलन करें. जैसे, पूरे सिस्टम के सीपीयू, मेमोरी या I/O पर बहुत ज़्यादा लोड पड़ना. यह समस्या की मुख्य वजह हो सकती है.
    2. थ्रेड का गलत एट्रिब्यूशन: डेडलॉक के लिए, वर्कर और बाइंडर थ्रेड की जांच करें. साथ ही, मुख्य थ्रेड पर असर डालने वाले लॉक कंटेंशन या एसिंक्रोनस कॉम्पोनेंट (जैसे, goAsync()) को प्रोसेस करने वाली हैंगिंग बैकग्राउंड थ्रेड की जांच करें.
    3. थ्रेडिंग से जुड़ी उल्लंघनों की जांच करना: बैकग्राउंड थ्रेड को स्कैन करके, यूज़र इंटरफ़ेस (यूआई) के व्यू में किए गए गैर-कानूनी बदलावों का पता लगाना. इससे MessageQueue में सिंक बैरियर अनाथ हो सकता है और सभी सिंक्रोनस मैसेज हमेशा के लिए ब्लॉक हो सकते हैं.

    कोई स्टैक फ़्रेम नहीं है

    कुछ एएनआर रिपोर्ट में, एएनआर वाले स्टैक शामिल नहीं होते. इसका मतलब है कि एएनआर रिपोर्ट जनरेट करते समय, स्टैक डंपिंग की प्रोसेस पूरी नहीं हुई. स्टैक फ़्रेम मौजूद न होने की कुछ संभावित वजहें यहां दी गई हैं:

    • स्टैक लेने में बहुत समय लगता है और टाइम आउट हो जाता है.
    • स्टैक लिए जाने से पहले ही प्रोसेस बंद हो गई या उसे बंद कर दिया गया.
    [...]
    
    --- CriticalEventLog ---
    capacity: 20
    timestamp_ms: 1666030897753
    window_ms: 300000
    
    libdebuggerd_client: failed to read status response from tombstoned: timeout reached?
    
    ----- Waiting Channels: pid 7068 at 2022-10-18 02:21:37.<US_SOCIAL_SECURITY_NUMBER>+0800 -----
    
    [...]
    

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

    पहले से मालूम समस्याएं

    ANR ट्रिगर होने से पहले ब्रॉडकास्ट हैंडलिंग को पूरा करने के लिए, अपने ऐप्लिकेशन की प्रोसेस में टाइमर रखने से शायद ठीक से काम न हो. इसकी वजह यह है कि सिस्टम, ANR को एसिंक्रोनस तरीके से मॉनिटर करता है.