যখন কোনো অ্যান্ড্রয়েড অ্যাপের UI থ্রেড খুব বেশি সময় ধরে ব্লক হয়ে থাকে, তখন সিস্টেম একটি "অ্যাপ্লিকেশন সাড়া দিচ্ছে না" (ANR) ত্রুটি পাঠায়। এই পৃষ্ঠায় বিভিন্ন ধরণের ANR, সেগুলি কীভাবে নির্ণয় করতে হয় এবং সমাধানের জন্য কিছু পরামর্শ বর্ণনা করা হয়েছে। এখানে তালিকাভুক্ত সমস্ত ডিফল্ট টাইমআউট সময়সীমা AOSP এবং পিক্সেল ডিভাইসের জন্য প্রযোজ্য; এই সময়গুলো OEM ভেদে ভিন্ন হতে পারে।
মনে রাখবেন যে, ANR-এর কারণ নির্ণয় করার সময় সিস্টেম এবং অ্যাপ-সম্পর্কিত সমস্যার মধ্যে পার্থক্য করা সহায়ক হয়।
সিস্টেমটি খারাপ অবস্থায় থাকলে, নিম্নলিখিত সমস্যাগুলির কারণে ANR আসতে পারে:
- সিস্টেম সার্ভারের সাময়িক সমস্যার কারণে সাধারণত দ্রুতগতির বাইন্ডার কলগুলো ধীর হয়ে যায়।
- সিস্টেম সার্ভারের সমস্যা এবং ডিভাইসের অতিরিক্ত চাপের কারণে অ্যাপ থ্রেডগুলো শিডিউল করা যাচ্ছে না।
আপনার কাছে উপলব্ধ থাকলে, সিস্টেম এবং অ্যাপের সমস্যার মধ্যে পার্থক্য করার একটি ভালো উপায় হলো পারফেটটো ট্রেস ব্যবহার করা:
- অ্যাপটির প্রধান থ্রেডটি শিডিউল করা হয়েছে কিনা তা জানতে, Perfetto-এর থ্রেড স্টেট ট্র্যাকে দেখুন সেটি চলছে বা চালানোর যোগ্য কিনা।
- লক কনটেনশনের মতো সমস্যার জন্য
system_serverথ্রেডগুলো খতিয়ে দেখুন। - বাইন্ডার কল ধীরগতির হলে, কেন এমন হচ্ছে তা জানতে রিপ্লাই থ্রেডটি (যদি থাকে) দেখুন।
ইনপুট প্রেরণের সময়সীমা
ইনপুট ডিসপ্যাচ এএনআর (ANR) ঘটে যখন অ্যাপের প্রধান থ্রেড কোনো ইনপুট ইভেন্টে (যেমন সোয়াইপ বা কী প্রেস) সময়মতো সাড়া দেয় না। যেহেতু ইনপুট ডিসপ্যাচ টাইমআউটের সময় অ্যাপটি ফোরগ্রাউন্ডে থাকে, তাই এগুলো প্রায় সবসময়ই ব্যবহারকারীর কাছে দৃশ্যমান হয় এবং এর প্রতিকার করা অত্যন্ত গুরুত্বপূর্ণ।
ডিফল্ট টাইমআউট সময়কাল : ৫ সেকেন্ড।
ইনপুট ডিসপ্যাচ ANR সাধারণত প্রধান থ্রেডের সমস্যার কারণে ঘটে থাকে। যদি প্রধান থ্রেডটি একটি লক অর্জনের জন্য অপেক্ষা করতে গিয়ে ব্লক হয়ে যায়, তবে হোল্ডার থ্রেডটিও এর সাথে জড়িত থাকতে পারে।
ইনপুট ডিসপ্যাচ ANR এড়াতে, এই সর্বোত্তম অনুশীলনগুলি অনুসরণ করুন:
- প্রধান থ্রেডে ব্লকিং বা দীর্ঘ সময় ধরে চলা অপারেশন সম্পাদন করবেন না। প্রধান থ্রেডে অনিচ্ছাকৃত কার্যকলাপ ধরতে
StrictModeব্যবহার করার কথা বিবেচনা করুন। - প্রধান থ্রেড এবং অন্যান্য থ্রেডগুলির মধ্যে লক নিয়ে দ্বন্দ্ব হ্রাস করুন।
- প্রধান থ্রেডে UI-বহির্ভূত কাজ কমিয়ে আনুন, যেমন ব্রডকাস্ট পরিচালনা করা বা সার্ভিস চালানোর সময়।
সাধারণ কারণগুলি
ইনপুট ডিসপ্যাচ ANR-এর কিছু সাধারণ কারণ এবং প্রস্তাবিত সমাধান নিচে দেওয়া হলো।
| কারণ | কী ঘটে | প্রস্তাবিত সমাধান |
|---|---|---|
| ধীরগতির বাইন্ডার কল | প্রধান থ্রেড একটি দীর্ঘ সিঙ্ক্রোনাস বাইন্ডার কল করে। | আপনি যদি API-টির মালিক হন, তবে কলটি মেইন থ্রেড থেকে সরিয়ে নিন অথবা কলটিকে অপ্টিমাইজ করার চেষ্টা করুন। |
| পরপর অনেকগুলো বাইন্ডার কল | প্রধান থ্রেড পরপর অনেকগুলো সিঙ্ক্রোনাস বাইন্ডার কল করে। | টাইট লুপে বাইন্ডার কল করবেন না। |
| ব্লকিং I/O | প্রধান থ্রেড ব্লকিং আই/ও কল করে, যেমন ডাটাবেস বা নেটওয়ার্ক অ্যাক্সেস। | সমস্ত ব্লকিং IO প্রধান থ্রেড থেকে সরিয়ে দিন। |
| লক বিরোধ | প্রধান থ্রেডটি একটি লক অর্জনের জন্য অপেক্ষা করতে গিয়ে আটকে আছে। | প্রধান থ্রেড এবং অন্য থ্রেডের মধ্যে লক নিয়ে দ্বন্দ্ব হ্রাস করুন। অন্য থ্রেডের ধীরগতির কোড অপ্টিমাইজ করুন। |
| দামী ফ্রেম | একই ফ্রেমে অতিরিক্ত রেন্ডার করার ফলে মারাত্মক জ্যাঙ্ক হচ্ছে। | ফ্রেম রেন্ডার করার কাজ কম করুন। n² অ্যালগরিদম ব্যবহার করবেন না। স্ক্রলিং বা পেজিং-এর মতো কাজের জন্য দক্ষ কম্পোনেন্ট ব্যবহার করুন—উদাহরণস্বরূপ, জেটপ্যাক পেজিং লাইব্রেরি । |
| অন্য উপাদান দ্বারা অবরুদ্ধ | ব্রডকাস্ট রিসিভারের মতো অন্য কোনো কম্পোনেন্ট চালু থাকায় প্রধান থ্রেডটি ব্লক হয়ে আছে। | যতটা সম্ভব, ইউজার ইন্টারফেস-বহির্ভূত কাজ মূল থ্রেড থেকে সরিয়ে নিন। ব্রডকাস্ট রিসিভারগুলো একটি ভিন্ন থ্রেডে চালান। |
| জিপিইউ হ্যাং | GPU হ্যাং হলো একটি সিস্টেম বা হার্ডওয়্যার সমস্যা, যার কারণে রেন্ডারিং আটকে যায় এবং ফলস্বরূপ একটি ইনপুট ডিসপ্যাচ ANR ঘটে। | দুর্ভাগ্যবশত, অ্যাপের দিক থেকে সাধারণত কোনো সমাধান থাকে না। সম্ভব হলে, সমস্যা সমাধানের জন্য হার্ডওয়্যার টিমের সাথে যোগাযোগ করুন। |
কিভাবে ডিবাগ করতে হয়
Google Play Console বা Firebase Crashlytics- এ ANR ক্লাস্টার সিগনেচার দেখে ডিবাগিং শুরু করুন। এই ক্লাস্টারে সাধারণত ANR-এর কারণ হিসেবে সন্দেহ করা শীর্ষ ফ্রেমগুলো থাকে।
নিম্নলিখিত ফ্লোচার্টটি দেখায় কিভাবে একটি ইনপুট টাইমআউট ডিসপ্যাচ ANR-এর কারণ নির্ণয় করতে হয়।

প্লে ভাইটালস এই সাধারণ ANR কারণগুলির কিছু সনাক্ত করতে এবং ডিবাগ করতে সাহায্য করতে পারে। উদাহরণস্বরূপ, যদি ভাইটালস সনাক্ত করে যে লক কনটেনশনের কারণে একটি ANR ঘটেছে, তবে এটি ANR ইনসাইটস বিভাগে সমস্যাটির সারসংক্ষেপ এবং প্রস্তাবিত সমাধান দিতে পারে।

কোন ফোকাস উইন্ডো নেই
টাচ-এর মতো ইভেন্টগুলো হিট টেস্টিং-এর উপর ভিত্তি করে সরাসরি প্রাসঙ্গিক উইন্ডোতে পাঠানো হলেও, কী-এর মতো ইভেন্টগুলোর একটি টার্গেট প্রয়োজন হয়। এই টার্গেটটিকে ফোকাসড উইন্ডো বলা হয়। প্রতি ডিসপ্লেতে কেবল একটিই ফোকাসড উইন্ডো থাকে, এবং এটি সাধারণত সেই উইন্ডোটিই হয় যার সাথে ব্যবহারকারী বর্তমানে ইন্টারঅ্যাক্ট করছেন। যদি কোনো ফোকাসড উইন্ডো খুঁজে না পাওয়া যায়, তাহলে ইনপুট একটি নো-ফোকাসড-উইন্ডো ANR তৈরি করে। একটি নো-ফোকাসড-উইন্ডো ANR হলো এক ধরনের ইনপুট ডিসপ্যাচ ANR।
ডিফল্ট টাইমআউট সময়কাল : ৫ সেকেন্ড।
সাধারণ কারণগুলি
নো-ফোকাসড-উইন্ডো এএনআর সাধারণত নিম্নলিখিত সমস্যাগুলির মধ্যে কোনো একটির কারণে ঘটে থাকে:
- অ্যাপটি অনেক বেশি কাজ করছে এবং প্রথম ফ্রেমটি আঁকতে অনেক বেশি সময় নিচ্ছে।
- প্রধান উইন্ডোটি ফোকাসযোগ্য নয়। যদি কোনো উইন্ডোকে
FLAG_NOT_FOCUSABLEহিসেবে চিহ্নিত করা হয়, তবে ব্যবহারকারী সেটিতে কী বা বাটন ইভেন্ট পাঠাতে পারবেন না।
কোটলিন
override fun onCreate(savedInstanceState: Bundle) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) window.addFlags(WindowManager.LayoutParams.FLAG_FLAG_NOT_FOCUSABLE) }
জাভা
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); getWindow().addFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE); }
সম্প্রচার রিসিভার টাইমআউট
যখন কোনো ব্রডকাস্ট রিসিভার সময়মতো একটি ব্রডকাস্ট পরিচালনা করতে পারে না, তখন একটি ব্রডকাস্ট রিসিভার ANR ঘটে। সিনক্রোনাস রিসিভারের ক্ষেত্রে, বা যে রিসিভারগুলো goAsync() কল করে না, একটি টাইমআউটের অর্থ হলো onReceive() সময়মতো সম্পন্ন হয়নি। অ্যাসিঙ্ক রিসিভারের ক্ষেত্রে, বা যে রিসিভারগুলো goAsync() কল করে, একটি টাইমআউটের অর্থ হলো PendingResult.finish() সময়মতো কল করা হয়নি।
ব্রডকাস্ট রিসিভার ANR প্রায়শই এই থ্রেডগুলিতে ঘটে থাকে:
- মূল থ্রেড, যদি সমস্যাটি অ্যাপ চালু হতে দেরি হওয়া হয়।
- থ্রেডটি ব্রডকাস্ট রিসিভার চালাচ্ছে, যদি সমস্যাটি
onReceive()কোডের ধীরগতির কারণে হয়। - যদি সমস্যাটি
goAsync()ব্রডকাস্ট কোডের ধীরগতির কারণে হয়, তবে ওয়ার্কার থ্রেডগুলো ব্রডকাস্ট করুন।
ব্রডকাস্ট রিসিভার ANR এড়াতে, এই সর্বোত্তম পদ্ধতিগুলো অনুসরণ করুন:
- অ্যাপটি যেন দ্রুত চালু হয় তা নিশ্চিত করুন, কারণ ব্রডকাস্টটি পরিচালনা করার জন্য অ্যাপটি চালু হলে তা ANR টাইমআউটের মধ্যে গণনা করা হয়।
- যদি
goAsync()ব্যবহার করা হয়, তাহলে নিশ্চিত করুন যেনPendingResult.finish()দ্রুত কল করা হয়। এটি সিনক্রোনাস ব্রডকাস্ট রিসিভারের মতোই একই ANR টাইমআউটের অধীন। - যদি
goAsync()ব্যবহার করা হয়, তাহলে নিশ্চিত করুন যে ওয়ার্কার থ্রেডগুলো অন্য কোনো দীর্ঘ-চলমান বা ব্লকিং অপারেশনের সাথে শেয়ার করা হচ্ছে না। - মেইন থ্রেডে চলমান UI কোডকে ব্লক করা এড়াতে, ব্রডকাস্ট রিসিভারগুলোকে একটি নন-মেইন থ্রেডে চালানোর জন্য
registerReceiver()ব্যবহার করার কথা বিবেচনা করুন।
টাইমআউট পিরিয়ড
ব্রডকাস্ট রিসিভ টাইমআউটের সময়কাল নির্ভর করে ফোরগ্রাউন্ড ইন্টেন্ট ফ্ল্যাগ সেট করা আছে কিনা এবং প্ল্যাটফর্ম ভার্সনের উপর।
| অভিপ্রায় প্রকার | অ্যান্ড্রয়েড ১৩ এবং তার নিচের সংস্করণ | অ্যান্ড্রয়েড ১৪ এবং উচ্চতর |
|---|---|---|
অগ্রভাগের অগ্রাধিকারের উদ্দেশ্য ( | ১০ সেকেন্ড | ১০-২০ সেকেন্ড, প্রসেসটি সিপিইউ-এর ওপর অতিরিক্ত চাপে আছে কিনা তার ওপর নির্ভর করে। |
পটভূমির অগ্রাধিকারের উদ্দেশ্য ( | ৬০ সেকেন্ড | ৬০-১২০ সেকেন্ড, প্রসেসটি সিপিইউ-এর ওপর অতিরিক্ত চাপ সৃষ্টি করছে কিনা তার ওপর নির্ভর করে। |
FLAG_RECEIVER_FOREGROUND ফ্ল্যাগটি সেট করা আছে কিনা তা জানতে, ANR সাবজেক্টে "flg=" খুঁজুন এবং 0x10000000 এর উপস্থিতি পরীক্ষা করুন। যদি এই বিটটি সেট করা থাকে, তাহলে ইন্টেন্টটিতে FLAG_RECEIVER_FOREGROUND সেট করা আছে এবং সেই কারণে টাইমআউট কম হয়।
স্বল্প সম্প্রচার সময়সীমা (১০-২০ সেকেন্ড) সহ ANR বিষয়ের উদাহরণ:
Broadcast of Intent { act=android.inent.action.SCREEN_ON flg=0x50200010 }
দীর্ঘ ব্রডকাস্ট টাইমআউট (৬০-১২০ সেকেন্ড) সহ ANR সাবজেক্টের উদাহরণ:
Broadcast of Intent { act=android.intent.action.TIME_SET flg=0x25200010 }
সম্প্রচারের সময় কীভাবে পরিমাপ করা হয়
system_server থেকে অ্যাপে ব্রডকাস্ট পাঠানো হলে ব্রডকাস্টের সময়কাল পরিমাপ শুরু হয় এবং অ্যাপটি ব্রডকাস্টটি প্রসেস করা শেষ করলে তা সমাপ্ত হয়। অ্যাপ প্রসেসটি যদি আগে থেকে চালু না থাকে, তবে ANR টাইমআউট সময়ের মধ্যে এটিকে একটি কোল্ড স্টার্টও করতে হয়। তাই, অ্যাপ চালু হতে দেরি হলে ব্রডকাস্ট রিসিভারে ANR হতে পারে।
নিম্নলিখিত চিত্রটি দেখায় যে কীভাবে ব্রডকাস্ট রিসিভারের ANR টাইমলাইন নির্দিষ্ট অ্যাপ প্রসেসগুলির সাথে সামঞ্জস্যপূর্ণ থাকে।

রিসিভার যখন ব্রডকাস্টটি প্রসেস করা শেষ করে, তখন ANR টাইমআউট পরিমাপ শেষ হয়; ঠিক কখন এটি ঘটে, তা নির্ভর করে রিসিভারটি সিনক্রোনাস নাকি অ্যাসিনক্রোনাস তার উপর।
- সিঙ্ক্রোনাস রিসিভারের ক্ষেত্রে,
onReceive()রিটার্ন করলে পরিমাপ বন্ধ হয়ে যায়। - অ্যাসিঙ্ক্রোনাস রিসিভারের ক্ষেত্রে,
PendingResult.finish()কল করা হলে পরিমাপ বন্ধ হয়ে যায়।

সাধারণ কারণগুলি
ব্রডকাস্ট রিসিভারে ANR হওয়ার কিছু সাধারণ কারণ এবং তার প্রস্তাবিত সমাধান নিচে দেওয়া হলো।
| কারণ | প্রযোজ্য | কী হলো | প্রস্তাবিত সমাধান |
|---|---|---|---|
| অ্যাপ চালু হতে ধীরগতি | সকল প্রাপক | অ্যাপটি কোল্ড স্টার্ট করতে অনেক বেশি সময় নিচ্ছিল। | অ্যাপ চালু হতে দেরি হলে তা অপ্টিমাইজ করুন। |
onReceive() নির্ধারিত নয় | সকল প্রাপক | ব্রডকাস্ট রিসিভার থ্রেডটি অন্য কাজে ব্যস্ত থাকায় onReceive() মেথডটি শুরু করতে পারেনি। | রিসিভার থ্রেডে দীর্ঘ সময় ধরে চলা কাজ সম্পাদন করবেন না (অথবা রিসিভারকে একটি ডেডিকেটেড থ্রেডে সরিয়ে নিন)। |
ধীর onReceive() | সমস্ত রিসিভার, তবে প্রধানত সিঙ্ক্রোনাস রিসিভারগুলো। | onReceive() মেথডটি শুরু হলেও ব্লক হয়ে যাওয়ায় বা ধীরগতির কারণে সময়মতো সম্পন্ন হয়নি। | ধীরগতির রিসিভার কোড অপ্টিমাইজ করুন। |
| অ্যাসিঙ্ক রিসিভার টাস্কগুলি নির্ধারিত নয় | goAsync() রিসিভার | onReceive() মেথডটি একটি ব্লকড ওয়ার্কার থ্রেড পুলে কাজ সম্পাদন করার চেষ্টা করেছিল, ফলে কাজটি কখনোই শুরু হয়নি। | ধীরগতির বা বাধা সৃষ্টিকারী কলগুলোকে অপ্টিমাইজ করুন, অথবা ব্রডকাস্ট ওয়ার্কার এবং অন্যান্য দীর্ঘস্থায়ী কাজের জন্য আলাদা থ্রেড ব্যবহার করুন। |
| কর্মীরা ধীর বা আটকে আছে | goAsync() রিসিভার | ব্রডকাস্টটি প্রসেস করার সময় ওয়ার্কার থ্রেড পুলের কোথাও একটি অপারেশন আটকে গিয়েছিল বা ধীরগতির ছিল। ফলে, PendingResult.finish সময়মতো কল করা হয়নি। | ধীরগতির async রিসিভার কোড অপ্টিমাইজ করুন। |
PendingResult.finish কল করতে ভুলে গেছি। | goAsync() রিসিভার | কোড পাথে finish() কলটি অনুপস্থিত। | নিশ্চিত করুন যেন সবসময় finish() কল করা হয়। |
কিভাবে ডিবাগ করতে হয়
ক্লাস্টার সিগনেচার এবং এএনআর রিপোর্টের উপর ভিত্তি করে, আপনি রিসিভারটি যে থ্রেডে চলে তা সনাক্ত করতে পারবেন এবং তারপরে যে নির্দিষ্ট কোডটি অনুপস্থিত বা ধীর গতিতে চলছে তাও খুঁজে বের করতে পারবেন।
নিম্নলিখিত ফ্লো চার্টটি দেখায় কিভাবে একটি ব্রডকাস্ট রিসিভার ANR-এর কারণ নির্ণয় করা যায়।

রিসিভার কোডটি খুঁজুন
গুগল প্লে কনসোল ANR সিগনেচারে রিসিভার ক্লাস এবং ব্রডকাস্ট ইন্টেন্ট দেখায়। নিম্নলিখিত বিষয়গুলো লক্ষ্য করুন:
-
cmp=<receiver class> -
act=<broadcast_intent>
এখানে একটি ব্রডকাস্ট রিসিভার ANR সিগনেচারের উদাহরণ দেওয়া হলো:
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 ব্যবহার করেন, তাহলে যে থ্রেডটি এই হ্যান্ডলারটি চালাচ্ছে সেটিই এটি। অন্যথায়, এটি মূল থ্রেড।
উদাহরণ: অ্যাসিঙ্ক রিসিভার টাস্ক শিডিউল করা হয়নি
এই অংশে একটি ব্রডকাস্ট রিসিভারের ANR ডিবাগ করার একটি উদাহরণ দেখানো হয়েছে।
ধরা যাক ANR সিগনেচারটি দেখতে নিম্নলিখিতের মতো:
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 ।
রিসিভার কোড থেকে, আপনি নির্ধারণ করতে পারেন যে "BG থ্রেড [0,1,2,3]" থ্রেড পুলটি এই ব্রডকাস্টটি প্রক্রিয়া করার প্রধান কাজটি করে। স্ট্যাক ডাম্পগুলি দেখলে, আপনি দেখতে পাবেন যে চারটি ব্যাকগ্রাউন্ড (BG) থ্রেডেরই একই প্যাটার্ন রয়েছে: তারা getDataSync একটি ব্লকিং কল চালায়। যেহেতু সমস্ত BG থ্রেড ব্যস্ত ছিল, ব্রডকাস্টটি সময়মতো প্রক্রিয়া করা যায়নি, যার ফলে একটি ANR ঘটে।
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
getDataSyncis slow and optimize. - Don't run
getDataSyncon 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
goAsyncworker 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(), andonBind()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.
If you've determined that the execute service ANR is actionable, follow these steps to help resolve the issue:
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.MyServiceDetermine 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.handleBindApplicationApp 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 theMyServiceclass 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-টিকে একটি ফলস পজিটিভ হিসেবে উপেক্ষা করতে পারেন।
- অন্য একটি অ্যাপ কম্পোনেন্ট, যেমন একটি ব্রডকাস্ট রিসিভার, চালু আছে। এক্ষেত্রে সম্ভবত মেইন থ্রেডটি এই কম্পোনেন্টে ব্লক হয়ে আছে, যা সার্ভিসটিকে চালু হতে বাধা দিচ্ছে।
যদি আপনি কোনো গুরুত্বপূর্ণ ফাংশন কল দেখতে পান এবং সাধারণভাবে ANR-টি কোথায় ঘটছে তা নির্ধারণ করতে পারেন, তবে ধীরগতির অপারেশনটি খুঁজে বের করতে মেইন থ্রেড স্ট্যাকের বাকি অংশগুলো পরীক্ষা করুন এবং সেটিকে অপ্টিমাইজ করুন বা ক্রিটিক্যাল পাথ থেকে সরিয়ে দিন।
পরিষেবা সম্পর্কে আরও তথ্যের জন্য, নিম্নলিখিত পৃষ্ঠাগুলি দেখুন:
কন্টেন্ট সরবরাহকারী সাড়া দিচ্ছে না
যখন কোনো রিমোট কন্টেন্ট প্রোভাইডার একটি কোয়েরির উত্তর দিতে টাইমআউট পিরিয়ডের চেয়ে বেশি সময় নেয় এবং কিলড হয়ে যায়, তখন একটি কন্টেন্ট প্রোভাইডার ANR ঘটে।
ডিফল্ট টাইমআউট পিরিয়ড : কন্টেন্ট প্রোভাইডার কর্তৃক ContentProviderClient.setDetectNotResponding ব্যবহার করে নির্দিষ্ট করা হয়। ANR টাইমআউট পিরিয়ডের মধ্যে একটি রিমোট কন্টেন্ট প্রোভাইডার কোয়েরি চলার মোট সময় অন্তর্ভুক্ত থাকে, যার মধ্যে রিমোট অ্যাপটি আগে থেকে চালু না থাকলে সেটিকে কোল্ড-স্টার্ট করার সময়ও থাকে।
কন্টেন্ট প্রোভাইডারের এএনআর এড়াতে এই সেরা পদ্ধতিগুলো অনুসরণ করুন:
- অ্যাপটি যেন দ্রুত চালু হয় তা নিশ্চিত করুন, কারণ কন্টেন্ট প্রোভাইডার চালানোর জন্য অ্যাপটি চালু করা হলে তা ANR টাইমআউটের মধ্যে গণনা করা হয়।
- নিশ্চিত করুন যে কন্টেন্ট প্রোভাইডার কোয়েরিগুলো দ্রুতগতিসম্পন্ন।
- একই সাথে অনেকগুলো ব্লকিং বাইন্ডার কল করবেন না, যা অ্যাপের সমস্ত বাইন্ডার থ্রেডকে ব্লক করে দিতে পারে।
সাধারণ কারণগুলি
নিচের সারণিতে কন্টেন্ট প্রোভাইডার ANR-এর সাধারণ কারণসমূহ এবং প্রস্তাবিত সমাধানসমূহ তালিকাভুক্ত করা হলো।
| কারণ | কী ঘটে | সংকেত | প্রস্তাবিত সমাধান |
|---|---|---|---|
| ধীরগতির কন্টেন্ট প্রোভাইডার কোয়েরি | কন্টেন্ট প্রোভাইডারটি কার্যকর হতে অনেক বেশি সময় নিচ্ছে অথবা এটি ব্লক হয়ে আছে। | android.content.ContentProvider$Transport.query ফ্রেমটি বাইন্ডার থ্রেডে রয়েছে। | কন্টেন্ট প্রোভাইডার কোয়েরি অপ্টিমাইজ করুন। বাইন্ডার থ্রেডটি কী কারণে ব্লক হচ্ছে তা খুঁজে বের করুন। |
| অ্যাপ চালু হতে ধীরগতি | কন্টেন্ট প্রোভাইডারের অ্যাপটি চালু হতে অনেক বেশি সময় নেয়। | ActivityThread.handleBindApplication ফ্রেমটি প্রধান থ্রেডে রয়েছে। | অ্যাপ চালু করার প্রক্রিয়া অপ্টিমাইজ করুন। |
| বাইন্ডারের সুতা শেষ—বাইন্ডারের সব সুতা ব্যস্ত। | সমস্ত বাইন্ডার থ্রেড অন্যান্য সিঙ্ক্রোনাস অনুরোধগুলি সম্পাদন করতে ব্যস্ত থাকায় কন্টেন্ট প্রোভাইডার বাইন্ডার কলটি চলতে পারছে না। | অ্যাপটি চালু হচ্ছে না, সমস্ত বাইন্ডার থ্রেড ব্যস্ত আছে এবং কন্টেন্ট প্রোভাইডারটি চলছে না। | বাইন্ডার থ্রেডগুলোর ওপর চাপ কমান। অর্থাৎ, কম সংখ্যক সিনক্রোনাস আউটগোয়িং বাইন্ডার কল করুন অথবা ইনকামিং কল হ্যান্ডেল করার সময় কম কাজ করুন। |
কিভাবে ডিবাগ করতে হয়
Google Play Console বা Firebase Crashlytics-এ থাকা ক্লাস্টার সিগনেচার এবং ANR রিপোর্ট ব্যবহার করে কোনো কন্টেন্ট প্রোভাইডারের ANR ডিবাগ করতে, মেইন থ্রেড এবং বাইন্ডার থ্রেড(গুলো) কী করছে তা দেখুন।
নিম্নলিখিত ফ্লো চার্টটি একটি কন্টেন্ট প্রোভাইডার ANR ডিবাগ করার পদ্ধতি বর্ণনা করে:

নিম্নলিখিত কোড স্নিপেটটি দেখায় যে একটি ধীরগতির কন্টেন্ট প্রোভাইডার কোয়েরির কারণে ব্লক হয়ে গেলে বাইন্ডার থ্রেডটি কেমন দেখায়। এক্ষেত্রে, কন্টেন্ট প্রোভাইডার কোয়েরিটি একটি ডেটাবেস খোলার সময় লকের জন্য অপেক্ষা করছে।
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() ব্যবহার করে নোটিফিকেশন দিতে অনেক বেশি সময় নেয়, তখন একটি স্লো জব রেসপন্স ANR ঘটে। এর থেকে বোঝা যায় যে, অ্যাপটির প্রধান থ্রেড অন্য কোনো কাজে আটকে আছে।
যদি JobService.onStartJob() বা JobService.onStopJob() নিয়ে কোনো সমস্যা হয়, তাহলে মেইন থ্রেডে কী ঘটছে তা পরীক্ষা করুন। যদি JobService.setNotification() নিয়ে কোনো সমস্যা হয়, তাহলে যত দ্রুত সম্ভব এটি কল করা নিশ্চিত করুন। নোটিফিকেশন দেওয়ার আগে বেশি কাজ করবেন না।
থ্রেডিং লঙ্ঘন দেখুন
আপনার অ্যাপ যদি ব্যাকগ্রাউন্ড থ্রেডে কোনো ভিউ পরিবর্তন করে, তাহলে তা ভিউ হায়ারার্কির অভ্যন্তরীণ অবস্থায় একটি রেস কন্ডিশন তৈরি করতে পারে। এই নিয়ম লঙ্ঘন মেইন (UI) থ্রেডকে যেকোনো সিনক্রোনাস মেসেজ এক্সিকিউট করা থেকে আটকে দিতে পারে, যার ফলে গুরুতর স্থিতিশীলতার সমস্যা দেখা দেয়:
- সাইলেন্ট ইউআই ফ্রিজ : অ্যাপের ইউআই ব্যবহারকারীর ইনপুটে সাড়া দেওয়া বন্ধ করে দেয়।
- ক্র্যাশ : অ্যাপটি
illegalStateExceptionএর কারণে ক্র্যাশ করতে পারে। - ANRs : সিস্টেমটি একটি ANR টাইমআউট ট্রিগার করতে পারে।
এই থ্রেডিং লঙ্ঘনটি ANR স্ট্যাক ট্রেসের অন্যতম মূল কারণ, যেখানে প্রধান থ্রেডকে নিষ্ক্রিয় বলে মনে হয় (যেমন "nativePollOnce" বা "main thread idle"-এ ধরা পড়ে)।
সিঙ্ক ব্যারিয়ার লিক
ভিউকে পরোক্ষভাবে তার অবস্থা পরিবর্তন করে (যেমন, TextView.setText বা View.setVisibility কল করে) অথবা সরাসরি View.invalidate বা View.requestLayout কল করে বাতিল করা যায়। যখন একটি ভিউ বাতিল করা হয়, তখন UI-এর অবস্থা আপডেট করার জন্য ViewRootImpl পরিমাপ, লেআউট এবং অঙ্কন সম্পাদন করতে একটি ট্রাভার্সাল নির্ধারণ করে।
- ট্র্যাভার্সাল শিডিউল করা :
ViewRootImplUI থ্রেডেরMessageQueueতে একটি সিনক্রোনাইজেশন ব্যারিয়ার পোস্ট করার মাধ্যমে একটি ট্র্যাভার্সাল—অর্থাৎ লেআউট এবং ড্রয়িং পাস—শিডিউল করে। এই ব্যারিয়ারটি সাধারণ মেসেজ প্রসেসিং থামিয়ে দেয়, যাতে UI লেআউট অগ্রাধিকার পেতে পারে। - রেস কন্ডিশন (Race Condition ): যখন একাধিক থ্রেড একই সাথে একটি ভিউকে বাতিল করার চেষ্টা করে, তখন তারা এই ট্রাভার্সালটি শিডিউল করার জন্য প্রতিযোগিতা করে। উভয় থ্রেডই সফলভাবে একটি সিনক্রোনাইজেশন ব্যারিয়ার যুক্ত করতে পারে, কিন্তু ফ্রেমওয়ার্ক তাদের মধ্যে কেবল একটির টোকেন সংরক্ষণ করে।
- UI ফ্রিজ : যখন ট্র্যাভার্সালটি সম্পাদিত হয়, তখন এটি শুধুমাত্র সংরক্ষিত একটিমাত্র ব্যারিয়ারটি সরিয়ে দেয়। দ্বিতীয়, অর্থাৎ 'লিক হওয়া' ব্যারিয়ারগুলো অনির্দিষ্টকালের জন্য কিউতে থেকে যায়, যা UI থ্রেডকে যেকোনো সিনক্রোনাস মেসেজ প্রসেস করা থেকে স্থায়ীভাবে ব্লক করে রাখে।
এর ফলে, UI ফ্রিজ হয়ে যায়। যেহেতু লিক হওয়া ব্যারিয়ারগুলোর কারণে MessageQueue কোনো সিনক্রোনাস মেসেজ প্রসেস করতে পারে না, তাই মেইন থ্রেড একটি নিষ্ক্রিয় অবস্থায় চলে যায়। এই সমস্যাটি সাধারণত স্ট্যাক ট্রেসে nativePollOnce সহ একটি ANR হিসেবে দেখা দেয়।
ভিউ থ্রেডিং লঙ্ঘন এড়াতে, এই সর্বোত্তম অনুশীলনগুলি অনুসরণ করুন:
-
Viewঅবজেক্টগুলোর সাথে—যার মধ্যেwidthবাheightএর মতো প্রোপার্টি পড়া কিংবাTextView's textমতো প্রোপার্টি সেট করাও অন্তর্ভুক্ত—শুধুমাত্র সেই থ্রেডেই ইন্টারঅ্যাক্ট করুন যেখানে আপনি ভিউ হায়ারার্কিটি তৈরি করেছেন। এটি প্রায় সবসময়ই মেইন বা UI থ্রেড হয়ে থাকে। - ভিউ অ্যাক্সেস করার সময় আপনি যে UI থ্রেডে চলছেন, তা যদি নিশ্চিত করতে না পারেন, তবে ধরে নিন যে তা করা অনিরাপদ। উদাহরণস্বরূপ, আপনি যদি ব্যাকগ্রাউন্ডের কাজের জন্য
Coroutinesব্যবহার করেন, তবেViewঅবজেক্টগুলো ম্যানিপুলেট করার আগে আপনাকে অবশ্যই মেইন ডিসপ্যাচারে সুইচ করতে হবে।
lifecycleOwner.lifecycleScope.launch(Dispatchers.IO) { val data = myRepository.getData() withContext(Dispatchers.Main) { // Switch context to Main myTextView.text = data.title } }
সর্বোত্তম অনুশীলন অনুসরণে আপনাকে সাহায্য করার জন্য, অ্যান্ড্রয়েড অন্যান্য থ্রেড থেকে UI থ্রেড অ্যাক্সেস করার বিভিন্ন উপায় প্রদান করে:
-
ContextCompat#getMainExecutor(android.content.Context) -
View.post(Runnable) -
Activity.runOnUiThread(Runnable)
জনপ্রিয় ইমেজ লোডার, রিঅ্যাক্টিভ এক্সটেনশন ফ্রেমওয়ার্ক, ইভেন্ট বাস লাইব্রেরি এবং অন্যান্য থ্রেডিং সলিউশনগুলো সাধারণত মেইন থ্রেডে নির্দিষ্ট ইভেন্ট পর্যবেক্ষণ করার উপায় দিয়ে থাকে। এটি সেইসব অবজারভার এবং ইভেন্ট লিসেনারদের জন্য উপযোগী, যাদের ভিউ-এর স্টেট গেট ও সেট করার প্রয়োজন হয়।
কিভাবে ডিবাগ করবেন
অ্যান্ড্রয়েড ১৭-এ নতুন কিছু টুল যুক্ত করা হয়েছে, যা আপনাকে ডেভেলপমেন্টের সময় ভিউ থ্রেডিং লঙ্ঘন শনাক্ত করতে, তার উৎস খুঁজে বের করতে এবং সমাধান করতে সাহায্য করবে।
১. সামঞ্জস্য কাঠামো সরঞ্জাম
কম্প্যাটিবিলিটি ফ্রেমওয়ার্ক টুলগুলো অ্যাপ ডেভেলপারদের ডেভেলপার অপশন বা ADB ব্যবহার করে স্বতন্ত্রভাবে আচরণগত পরিবর্তন চালু ও বন্ধ করার সুযোগ দেয়। আপনি নিম্নলিখিত ধাপগুলো অনুসরণ করে ভিউ থ্রেডিং ভায়োলেশন আচরণগত পরিবর্তনগুলো টগল করতে পারেন:
- অ্যান্ড্রয়েড ১৭ বা তার উচ্চতর সংস্করণে চালিত কোনো ডিভাইসে আপনার অ্যাপের একটি ডিবাগযোগ্য সংস্করণ ইনস্টল করুন।
- আপনার ডিভাইসের সেটিংস অ্যাপটি খুলুন এবং সিস্টেম > অ্যাডভান্সড > ডেভেলপার অপশন > অ্যাপ কম্প্যাটিবিলিটি চেঞ্জেস-এ যান।
- তালিকা থেকে আপনার অ্যাপটি বেছে নিন।
- পরিবর্তনসমূহের তালিকা থেকে
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>
এই ফ্ল্যাগটি সক্রিয় করলে, ভুল থ্রেড থেকে কোনো ভিউ এপিআই কল করা হলে অ্যাপটি একটি এক্সেপশন থ্রো করে ক্র্যাশ করে, যা আপনাকে ভিউ থ্রেডিং ভায়োলেশন সমস্যা ধরতে ও সমাধান করতে সাহায্য করে।
২. CalledFromWrongThreadListener API
প্রোগ্রাম্যাটিকভাবে অনুপযুক্ত থ্রেড অ্যাক্সেস শনাক্ত করতে আপনি গ্লোবাল View#registerCalledFromWrongThreadListener 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)
নেটিভপোলওয়ান্স
যদি আপনি ANR স্ট্যাকে 'nativePollOnce' বা 'message queue idle' ফ্রেমটি দেখতে পান, তবে এটি প্রায়শই নির্দেশ করে যে সন্দেহভাজন প্রতিক্রিয়াহীন থ্রেডটি আসলে নিষ্ক্রিয় ছিল এবং লুপার বার্তার জন্য অপেক্ষা করছিল। গুগল প্লে কনসোলে, 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)
সন্দেহভাজন অনুত্তরদায়ী থ্রেডটি নিষ্ক্রিয় থাকার বেশ কয়েকটি কারণ রয়েছে:
- সিস্টেম-ব্যাপী সমস্যা । সিস্টেমে অতিরিক্ত চাপ অথবা সিস্টেম সার্ভারের কোনো সমস্যার কারণে প্রসেসটি শিডিউল করা যায়নি।
- দেরিতে স্ট্যাক ডাম্প । ANR ট্রিগার হওয়া এবং স্ট্যাক ডাম্প হওয়ার মধ্যবর্তী স্বল্প সময়ে থ্রেডটি পুনরুদ্ধার হয়েছে। অ্যান্ড্রয়েড ১৩ চালিত পিক্সেল ফোনগুলিতে ল্যাটেন্সি প্রায় ১০০ মিলিসেকেন্ড, তবে তা ১ সেকেন্ড অতিক্রম করতে পারে। অ্যান্ড্রয়েড ১৪ চালিত পিক্সেল ফোনগুলিতে ল্যাটেন্সি সাধারণত ১০ মিলিসেকেন্ডের নিচে থাকে।
- থ্রেড শনাক্তকরণে ভুল। ANR সিগনেচার তৈরি করতে ব্যবহৃত থ্রেডটি সেই প্রকৃত অনুত্তেজিত থ্রেড ছিল না, যা ANR-এর কারণ হয়েছিল।
- ভিউ থ্রেডিং লঙ্ঘন । আপনার অ্যাপ যদি ব্যাকগ্রাউন্ড থ্রেডে কোনো ভিউ পরিবর্তন করে, তবে এটি ভিউ-এর অভ্যন্তরীণ কার্যপ্রণালীতে একটি রেস কন্ডিশন তৈরি করতে পারে, যা UI থ্রেডের কাজগুলোকে চলতে বাধা দেয়।
যেহেতু 'nativePollOnce' ANR-এর অন্তর্নিহিত কারণগুলো ANR-এর প্রকারভেদে ভিন্ন হয়, তাই নির্দিষ্ট ANR বিভাগটি নির্ণয় করা আপনার অ্যাপের মধ্যে সমস্যাটি সমাধানের জন্য কার্যকর পদক্ষেপ শনাক্ত করতে সাহায্য করতে পারে।
| বিভাগ | কারণ | প্রস্তাবিত সমাধান |
|---|---|---|
| ইনপুট প্রেরণের সময়সীমা | সিস্টেম-ব্যাপী সমস্যা দেরিতে স্ট্যাক ডাম্প | কোনো পদক্ষেপের প্রয়োজন নেই। |
| কোন ফোকাস উইন্ডো নেই | সিস্টেম-ব্যাপী সমস্যা দেরিতে স্ট্যাক ডাম্প থ্রেডিং লঙ্ঘন দেখুন | ভিউ থ্রেডিং লঙ্ঘনের জন্য কোডবেসটি পরীক্ষা করুন। |
| সম্প্রচার রিসিভার টাইমআউট | দেরিতে স্ট্যাক ডাম্প সিস্টেম-ব্যাপী সমস্যা থ্রেডের ভুল আরোপ থ্রেডিং লঙ্ঘন দেখুন | স্ট্যাক ডাম্পে প্রাসঙ্গিক থ্রেডগুলো পরীক্ষা করুন। ভিউ থ্রেডিং লঙ্ঘনের জন্য কোডবেসটি পরীক্ষা করুন। |
| সার্ভিস কার্যকর করার সময়সীমা অতিক্রান্ত | দেরিতে স্ট্যাক ডাম্প সিস্টেম-ব্যাপী সমস্যা থ্রেডিং লঙ্ঘন দেখুন | ভিউ থ্রেডিং লঙ্ঘনের জন্য কোডবেসটি পরীক্ষা করুন। |
| কন্টেন্ট সরবরাহকারী সাড়া দিচ্ছে না | দেরিতে স্ট্যাক ডাম্প সিস্টেম-ব্যাপী সমস্যা থ্রেডের ভুল আরোপ | স্ট্যাক ডাম্পে প্রাসঙ্গিক থ্রেডগুলো পরীক্ষা করুন। |
nativePollOnce ANR বিশ্লেষণ করার জন্য প্রস্তাবিত পদক্ষেপগুলো নিচে দেওয়া হলো।
- সিস্টেমে অতিরিক্ত চাপ: প্রতিক্রিয়াহীনতার প্রাথমিক কারণ হিসেবে সিস্টেম-ব্যাপী সিপিইউ, মেমরি বা আই/ও-এর ঘাটতির মতো ডিভাইসের সামগ্রিক রিসোর্স চাপের বিষয়টি মূল্যায়ন করুন।
- থ্রেডের ভুল শনাক্তকরণ: ডেডলক, প্রধান থ্রেডকে প্রভাবিত করছে এমন লক কনটেনশন অথবা অ্যাসিঙ্ক্রোনাস উপাদান (যেমন,
goAsync()) প্রসেস করার সময় আটকে থাকা ব্যাকগ্রাউন্ড থ্রেডের জন্য ওয়ার্কার এবং বাইন্ডার থ্রেডগুলো নিরীক্ষা করুন। - থ্রেডিং লঙ্ঘন দেখুন: UI ভিউ হায়ারার্কির অবৈধ পরিবর্তনের জন্য ব্যাকগ্রাউন্ড থ্রেডগুলি স্ক্যান করুন, যা MessageQueue-তে একটি সিঙ্ক ব্যারিয়ারকে অনাথ করে দিতে পারে এবং সমস্ত সিঙ্ক্রোনাস মেসেজকে স্থায়ীভাবে ব্লক করে দিতে পারে।
কোন স্ট্যাক ফ্রেম নেই
কিছু ANR রিপোর্টে ANR-এর সাথে স্ট্যাক অন্তর্ভুক্ত থাকে না, যার অর্থ হলো ANR রিপোর্টটি তৈরি করার সময় স্ট্যাক ডাম্পিং ব্যর্থ হয়েছে। স্ট্যাক ফ্রেম অনুপস্থিত থাকার কয়েকটি সম্ভাব্য কারণ রয়েছে:
- স্ট্যাক নিতে অনেক বেশি সময় লাগে এবং টাইম আউট হয়ে যায়।
- স্ট্যাকগুলো নেওয়ার আগেই প্রক্রিয়াটি বন্ধ হয়ে গিয়েছিল বা মেরে ফেলা হয়েছিল।
[...]
--- 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 -----
[...]
স্ট্যাক ফ্রেম ছাড়া ANR-গুলো ক্লাস্টার সিগনেচার বা ANR রিপোর্ট থেকে কার্যকর নয়। ডিবাগ করার জন্য, অ্যাপটির অন্যান্য ক্লাস্টারগুলো দেখুন, কারণ কোনো সমস্যা যথেষ্ট বড় হলে সাধারণত তার নিজস্ব একটি ক্লাস্টার থাকে যেখানে স্ট্যাক ফ্রেম উপস্থিত থাকে। আরেকটি বিকল্প হলো পারফেটটো ট্রেসগুলো দেখা।
পরিচিত সমস্যা
ANR ট্রিগার হওয়ার আগে ব্রডকাস্ট হ্যান্ডলিং শেষ করার উদ্দেশ্যে আপনার অ্যাপের প্রসেসে টাইমার রাখলে তা সঠিকভাবে কাজ নাও করতে পারে, কারণ সিস্টেমটি অ্যাসিঙ্ক্রোনাস পদ্ধতিতে ANR মনিটর করে।
