ANR (Application Not Responding) হল একটি Android সিস্টেম বিজ্ঞপ্তি যা দেখা যায় যখন একটি অ্যাপ 5 সেকেন্ডের বেশি সময় ধরে ব্যবহারকারীর ইনপুটে সাড়া দেওয়া বন্ধ করে দেয়। Android Developers-এর মতে, প্রধান কারণ হল মূল থ্রেডে দীর্ঘ অপারেশন যা টাচ প্রসেসিং এবং UI রেন্ডারিং ব্লক করে। প্রতিক্রিয়াশীল অ্যাপ তৈরি করার জন্য প্রতিটি Android ডেভেলপারের জন্য ANR মেকানিজম বোঝা আবশ্যক।
মূল বিষয়
ANR (Application Not Responding) হল Android অপারেটিং সিস্টেমের একটি ডায়ালগ বক্স যা দেখা যায় যখন অ্যাপ ব্যবহারকারীর ইনপুটে সাড়া দেওয়া বন্ধ করে দেয়। সিস্টেম InputDispatcher-এর মাধ্যমে ইভেন্ট প্রসেসিং সময় ট্র্যাক করে: যদি একটি স্পর্শ বা বাটন চাপ 5 সেকেন্ডের মধ্যে প্রক্রিয়া না হয়, Android অ্যাপ বন্ধ বা অপেক্ষা করার বিকল্প সহ একটি ডায়ালগ দেখায়।
ANR মেকানিজম ফ্রিজ হওয়া অ্যাপ থেকে ব্যবহারকারীর অভিজ্ঞতা রক্ষা করে। Android একটি অ্যাপকে পুরো সিস্টেম ব্লক করতে দেয় না — ডেস্কটপ OS-এর বিপরীতে, মোবাইল প্ল্যাটফর্ম জোর করে ইভেন্ট প্রসেসিং সময় সীমিত করে। BroadcastReceiver-এর 10 সেকেন্ডের সীমা রয়েছে এবং foreground সার্ভিসের 20 সেকেন্ডের সীমা রয়েছে।
ANR কোডে কোনো ব্যতিক্রম নয় — এটি Linux প্রসেস স্তরে একটি সিস্টেম মেকানিজম। Android প্রসেসে SIGQUIT সিগন্যাল পাঠায়, তারপরে সিস্টেম সমস্ত থ্রেডের কল স্ট্যাক traces.txt ফাইলে সংরক্ষণ করে। ডেভেলপার ANR একটি catch ব্যতিক্রম হিসেবে নয়, বরং অ্যাপ পুনরায় চালু হওয়ার পর একটি রিপোর্ট হিসেবে পায়। Android 11+-এ, ApplicationExitInfo API প্রোগ্রামেটিকভাবে প্রসেস সমাপ্তির কারণ পাওয়ার অনুমতি দেয়, যার মধ্যে ANR অন্তর্ভুক্ত — এটি ম্যানুয়াল traces.txt পার্সিং ছাড়াই পরিসংখ্যান সংগ্রহ সহজ করে।
পাঁচটি বিভাগ এর অপারেশন Android অ্যাপে ধারাবাহিকভাবে ANR-এর দিকে নিয়ে যায়। এদের প্রতিটি মূল থ্রেড ব্লক করে, সিস্টেমকে ইনপুট ইভেন্ট এবং স্ক্রিন পুনরায় অঙ্কন প্রক্রিয়া করতে বাধা দেয়।
UI থ্রেডে সম্পাদিত সিনক্রোনাস HTTP অনুরোধগুলি শিক্ষানবিশ ডেভেলপারদের মধ্যে ANR-এর সবচেয়ে সাধারণ কারণ। সার্ভারে একটি দ্রুত অনুরোধও 1–3 সেকেন্ড নিতে পারে, এবং খারাপ সংযোগে — 30 সেকেন্ড বা তার বেশি। Android API 11 থেকে মূল থ্রেডে নেটওয়ার্ক অপারেশন স্পষ্টভাবে নিষিদ্ধ করে, NetworkOnMainThreadException নিক্ষেপ করে।
অ্যাসিনক্রোনাস কলের জন্য Coroutines বা RxJava ব্যবহার করুন। Dispatchers.IO ডিসপ্যাচার সহ করুটিন ব্যাকগ্রাউন্ড থ্রেডে অনুরোধ সম্পাদন করে এবং Dispatchers.Main-এর মাধ্যমে মূল থ্রেডে ফলাফল পাঠায়। এটি নেটওয়ার্ক অপারেশন দ্বারা UI থ্রেড ব্লকিং সম্পূর্ণরূপে দূর করে।
fun fetchUserData() {
CoroutineScope(Dispatchers.Main).launch {
val result = withContext(Dispatchers.IO) {
api.getUserData() // ব্যাকগ্রাউন্ড অপারেশন
}
updateUI(result) // মূল থ্রেডে ফলাফল
}
}
বড় ডেটা অ্যারে প্রক্রিয়া করা, JSON বা XML পার্স করা, সরাসরি মূল থ্রেডে bitmap নিয়ে কাজ করা — ANR-এর দ্বিতীয় সবচেয়ে সাধারণ কারণ। ইভেন্ট লুপে ফিরে না এসে UI থ্রেডের 300 মিলিসেকেন্ড একটানা কাজ করলেও রেন্ডারিংয়ে লক্ষণীয় বিলম্ব হয়, এবং 5 সেকেন্ডের সীমা ANR হিসেবে নথিভুক্ত হয়।
WorkManager এবং ব্যাকগ্রাউন্ড সার্ভিসগুলি মূল থ্রেড থেকে ভারী গণনা সরানোর জন্য ডিজাইন করা হয়েছে। UI ব্লক না করে ডেটা খণ্ডে পাঠানোর জন্য AsyncTask (অপ্রচলিত), ListenableFuture বা Kotlin Flow ব্যবহার করুন।
Deadlock ঘটে যখন দুটি থ্রেড লক ধারণ করে এবং একে অপরের জন্য অপেক্ষা করে। যদি থ্রেডগুলির একটি মূল থ্রেড হয়, সিস্টেম ঠিক 5 সেকেন্ড পরে ANR নথিভুক্ত করে। UI থ্রেড থেকে কল করা Thread.join(), CountDownLatch.await() এবং synchronized ব্লকগুলি ব্লক হওয়ার ঝুঁকি বহন করে।
মূল থ্রেডে কোনো ব্লকিং অপারেশন এড়িয়ে চলুন। synchronized-এর পরিবর্তে ConcurrentHashMap ব্যবহার করুন; Thread.join()-এর পরিবর্তে async/await সহ করুটিন ব্যবহার করুন। এই নিয়ম Android-এর যেকোনো ভাষায় প্রযোজ্য: Java, Kotlin বা JNI-এর মাধ্যমে C++।
BroadcastReceiver ডিফল্টরূপে মূল থ্রেডে চলে। যদি onReceive() 10 সেকেন্ডের বেশি ব্যস্ত থাকে, Android ANR দেখায়। onReceive-এর ভিতরে ডাটাবেস বা নেটওয়ার্ক থেকে ডেটা লোড করা ফ্রিজের নিশ্চিত পথ।
ব্যাকগ্রাউন্ড থ্রেডে স্যুইচ করতে BroadcastReceiver-এর ভিতরে goAsync() ব্যবহার করুন, অথবা getBackgroundBroadcastReceiver() সহ registerReceiver ব্যবহার করুন। এটি UI ব্লক না করে ইভেন্ট প্রক্রিয়া করার অনুমতি দেয়।
ContentProvider-এ ভারী কোয়েরি বা UI থ্রেডে SQLite-এর সাথে সরাসরি কাজ — ANR-এর একটি কম স্পষ্ট কিন্তু সাধারণ কারণ। ডাটাবেস মাইগ্রেশন বা হাজার হাজার রেকর্ডের বাল্ক সন্নিবেশের সময়, সম্পাদনের সময় 5 সেকেন্ডের সীমা অতিক্রম করতে পারে।
সব ডাটাবেস অপারেশন suspend ফাংশন সহ Room-এর মাধ্যমে ব্যাকগ্রাউন্ড থ্রেডে সরান। Room স্বয়ংক্রিয়ভাবে পরীক্ষা করে যে কোয়েরি মূল থ্রেডে সম্পাদিত হচ্ছে না এবং লঙ্ঘন হলে ব্যতিক্রম নিক্ষেপ করে।
ANR নির্ণয় সাধারণ ব্যতিক্রম ডিবাগ করার থেকে আলাদা — আপনি try-catch ব্লকে ANR ধরতে পারবেন না। তথ্যের প্রধান উৎস হল traces.txt ফাইল, যা Android ফ্রিজের মুহূর্তে তৈরি করে।
traces.txt-এ ANR-এর সময় সমস্ত অ্যাপ থ্রেডের কল স্ট্যাক থাকে। একটি বাস্তব ডিভাইস থেকে ফাইল পড়তে, adb bugreport কমান্ড চালান, যা সাম্প্রতিক সমস্ত ANR সহ সম্পূর্ণ সিস্টেম রিপোর্ট সংগ্রহ করে। এমুলেটরের জন্য, ফাইল /data/anr/traces.txt-এ উপলব্ধ। কল স্ট্যাক দেখায় ব্লকিংয়ের সময় মূল থ্রেডে কোন পদ্ধতি সম্পাদিত হচ্ছিল।
adb bugreport bugreport.zip
unzip -p bugreport.zip "*traces*" > traces.txt
Google Play Console একত্রিত রিপোর্ট এবং ত্রুটি ফ্রিকোয়েন্সি সহ ANR & Crash বিভাগ প্রদান করে। প্রতিটি ANR-এর জন্য, কল স্ট্যাক এবং ডিভাইস পরিসংখ্যান দেখানো হয়: মডেল, Android সংস্করণ, অঞ্চল। এটি নির্দিষ্ট ডিভাইস বা সিস্টেম সংস্করণের উপর নির্ভরশীল ANR সনাক্ত করতে দেয়।
Android Studio 2021 থেকে প্রোফাইলারে ANR Watchdog অন্তর্ভুক্ত করেছে। এটি স্বয়ংক্রিয়ভাবে থ্রেড ডাম্প রেকর্ড করে যদি মূল থ্রেড নির্দিষ্ট সময়ের বেশি সাড়া না দেয়। টুলটি ইভেন্টের একটি সময়রেখা দেখায়: কোন অপারেশন শুরু হয়েছিল, কোন পদ্ধতিগুলি সম্পাদিত হয়েছিল এবং কোন পর্যায়ে ব্লকিং ঘটেছিল।
ANR-এর প্রতিরোধ একটি মৌলিক নিয়মের উপর নির্মিত: মূল থ্রেডের শুধুমাত্র UI ইভেন্ট হ্যান্ডেল করা উচিত। 16 মিলিসেকেন্ড (এক ফ্রেমের সময়) এর বেশি দীর্ঘ যেকোনো অপারেশন ব্যাকগ্রাউন্ড থ্রেডে চালানো উচিত।
StrictMode ডেভেলপমেন্টের সময় সম্ভাব্য ANR সনাক্ত করার জন্য Android-এর বিল্ট-ইন টুল। ডিস্ক এবং নেটওয়ার্ক অপারেশনের জন্য ফ্ল্যাগ সহ Application.onCreate()-এ এটি সক্রিয় করুন। লঙ্ঘন হলে, StrictMode ব্যতিক্রম নিক্ষেপ করে বা logcat-এ লেখে।
if (BuildConfig.DEBUG) {
StrictMode.ThreadPolicy.Builder()
.detectDiskReads()
.detectDiskWrites()
.detectNetwork()
.penaltyLog()
.build()
.let { StrictMode.setThreadPolicy(it) }
}
Kotlin Coroutines — আধুনিক Android অ্যাপে অ্যাসিনক্রোনাস কাজের মানক উপায়। মূল পদ্ধতি: I/O অপারেশন Dispatchers.IO-তে চলে, ফলাফল UI আপডেটের জন্য Dispatchers.Main-এ পাঠানো হয়। Flow-এর মতো পরিস্থিতির জন্য, CPU-গভীর কাজের জন্য Dispatchers.Default ব্যবহার করুন।
RxJava লিগ্যাসি প্রজেক্টে জনপ্রিয় রয়ে গেছে। subscribeOn(Schedulers.io()) এবং observeOn(AndroidSchedulers.mainThread()) — ANR প্রতিরোধের জন্য ন্যূনতম সেট। মূল নিয়ম একই: কোনো Observable বা Flowable মূল থ্রেড থেকে ডেটা নির্গত করা উচিত নয়।
Firebase Crashlytics SDK সংস্করণ 18.4.0 থেকে বক্সের বাইরে ANR মনিটরিং সমর্থন করে। Android 11+-এর জন্য, Crashlytics সিস্টেম API ApplicationExitInfo ব্যবহার করে, যা সঠিক সমাপ্তির কারণ প্রদান করে: ANR, Crash, বা সিস্টেম কিল। প্রাসঙ্গিক বিশ্লেষণের জন্য স্ক্রিন এবং অবস্থা প্যারামিটার সহ কাস্টম কী সক্রিয় করুন।
পাঁচটি টুল ANR-এর সাথে কাজ করার সমস্ত ধাপ কভার করে: ওয়ার্কস্টেশনে ডিবাগিং থেকে প্রোডাকশনে মনিটরিং পর্যন্ত। প্রতিটি টুল তার নিজস্ব কাজ সমাধান করে এবং বিভিন্ন পরিস্থিতির জন্য ডেটা সরবরাহ করে।
| টুল | উদ্দেশ্য | ডেটা ফরম্যাট |
|---|---|---|
| StrictMode | ডেভেলপমেন্টের সময় সনাক্তকরণ | Logcat / Exception |
| ANR Watchdog (Android Studio) | রিয়েল-টাইম ট্রেসিং | Thread dump + timeline |
| Google Play Console | একত্রিত পরিসংখ্যান | ANR rate + stack traces |
| Firebase Crashlytics | প্রোডাকশন মনিটরিং | ApplicationExitInfo |
| adb bugreport | সম্পূর্ণ সিস্টেম রিপোর্ট | traces.txt + logcat + dmesg |
প্রতিটি টুলের নিজস্ব ক্ষেত্র আছে: StrictMode প্রাথমিক পর্যায়ে স্পষ্ট লঙ্ঘন ধরে, Crashlytics ব্যবহারকারীদের মধ্যে বাস্তব ANR ফ্রিকোয়েন্সি দেখায়, এবং adb bugreport জটিল ক্ষেত্রে সবচেয়ে সম্পূর্ণ চিত্র সরবরাহ করে। সম্পূর্ণ কভারেজের জন্য এগুলি একত্রিত করুন।
Firebase Performance UI থ্রেড প্রতিক্রিয়া সময় ট্র্যাক করে এবং সন্দেহজনকভাবে দীর্ঘ অপারেশনের জন্য স্বয়ংক্রিয়ভাবে ট্রেস তৈরি করে। যদি মূল থ্রেড 500 মিলিসেকেন্ডের বেশি ব্লক হয়, Performance দায়ী পদ্ধতির নাম সহ একটি কাস্টম ট্রেস রেকর্ড করে। এটি ব্যবহারকারীর অংশগ্রহণ ছাড়াই এবং সমালোচনামূলক হওয়ার আগে ANR পরিস্থিতি সনাক্ত করতে দেয়।
Firebase Crashlytics-এর সাথে একীকরণ সম্পূর্ণ চিত্র দেয়: Performance ANR-এর আগে মন্থরতা দেখায়, এবং Crashlytics ফ্রিজ দেখায়। Firebase Console-এ ANR হার 0.1% এর উপরে হলে সতর্কতা সেট করুন, এবং আপনি বৃহৎ ব্যবহারকারী অভিযোগের আগে নতুন সমস্যা সম্পর্কে বিজ্ঞপ্তি পাবেন।
সচরাচর জিজ্ঞাসিত প্রশ্ন
ANR হল একটি ফ্রিজ যেখানে অ্যাপ সাড়া দেয় না কিন্তু মেমরিতে থাকে। Crash হল প্রসেস থেকে বেরিয়ে যাওয়ার সাথে সম্পূর্ণ অস্বাভাবিক সমাপ্তি। ANR “বেঁচে থাকা” সম্ভব যদি সিস্টেম বা ব্যবহারকারী প্রতিক্রিয়ার জন্য অপেক্ষা করে, যেখানে Crash সবসময় অ্যাপ সমাপ্ত করে।
না। ANR Java/Kotlin ব্যতিক্রম নয়, বরং প্রসেস স্তরে একটি সিস্টেম সিগন্যাল (SIGQUIT)। একজন ডেভেলপার এটি অ্যাপ কোডে হ্যান্ডেল করতে পারে না। ANR-এ সাড়া দেওয়ার একমাত্র উপায় হল পুনরায় চালুর পরে রিপোর্ট বিশ্লেষণ করা।
ডিভাইস কর্মক্ষমতা, Android সংস্করণ, CPU লোড এবং ব্যাকগ্রাউন্ড প্রসেসের সংখ্যা ANR-এর সম্ভাবনাকে প্রভাবিত করে। দুর্বল ডিভাইসে, একই অপারেশন 2–3 গুণ বেশি সময় নিতে পারে, 5 সেকেন্ডের সীমা অতিক্রম করে।
সাধারণ BroadcastReceiver-এর জন্য onReceive()-এ 10 সেকেন্ড। Foreground সার্ভিসের জন্য, সীমা 20 সেকেন্ড, এবং ContentProvider-এর জন্য — কোনো স্পষ্ট সীমা নেই, কিন্তু মূল থ্রেড 5 সেকেন্ডের বেশি ব্লক করলে এখনও ANR হয়।
সব ডিবাগ বিল্ডে StrictMode সক্রিয় করুন, Firebase Crashlytics-এর মাধ্যমে মনিটরিং যোগ করুন, এবং যখন ANR হয় তখন adb bugreport ব্যবহার করুন। অনিয়মিত ANR প্রায়শই রেস কন্ডিশন বা নির্দিষ্ট নেটওয়ার্ক অবস্থার সাথে সম্পর্কিত।
সারসংক্ষেপ
আমরা একটি মোবাইল অ্যাপ্লিকেশন টার্নকি তৈরি করব
IT Sectr 2017 সাল থেকে স্টার্টআপ এবং ব্যবসার জন্য iOS এবং Android অ্যাপ্লিকেশন তৈরি করে। আমরা আপনাকে পরামর্শ দেব এবং সেরা সমাধান প্রস্তাব করব।
আরও পড়ুন