ANR در اندروید: چیست، علل و روش‌های رفع

نویسنده: IT Sectr منتشر شده: 2026-07-28 زمان مطالعه: 9 دقیقه

ANR (Application Not Responding) — اعلان سیستمی اندروید است که وقتی برنامه به مدت ۵ ثانیه به ورودی پاسخ نمی‌دهد ظاهر می‌شود. برخلاف گلیچ‌ها (خطاهای منطقی بدون مسدود کردن UI) و لگ‌ها (کندی بدون توقف کامل)، ANR یک خرابی بحرانی است که توسط سیستم عامل ثبت می‌شود: اندروید دیالوگ «برنامه پاسخ نمی‌دهد» را با پیشنهاد بستن یا صبر کردن نمایش می‌دهد. طبق Android Vitals Documentation، برنامه‌هایی با نرخ ANR بالای ۰.۵٪ رتبه پایین‌تری در Google Play دارند و ممکن است از توصیه‌ها پنهان شوند. تشخیص شامل تحلیل /data/anr/traces.txt، استفاده از StrictMode و پروفایل‌کردن نخ اصلی است.

نکات اصلی

  • ANR — اعلان سیستمی اندروید هنگام مسدود شدن نخ اصلی بیش از ۵ ثانیه، منجر به دیالوگ «برنامه پاسخ نمی‌دهد»
  • علل اصلی — مسدود شدن نخ اصلی (BroadcastReceiver, Service)، بن‌بست بین نخ‌ها، عملیات طولانی در ContentProvider
  • تشخیص — تحلیل /data/anr/traces.txt، Android Studio Profiler، Firebase Performance Monitoring
  • رفع — انتقال وظایف به WorkManager، استفاده از Kotlin Coroutines با Dispatchers.IO، StrictMode برای تشخیص زودهنگام
  • پیشگیری — محدود کردن زمان BroadcastReceiver به ۱۰ ثانیه، Service به ۲۰ ثانیه، ContentProvider به ۱۵ ثانیه

ANR در اندروید چیست

ANR (Application Not Responding) — مکانیزم حفاظت از کاربر در اندروید است که وقتی برنامه از پاسخ‌دهی به ورودی بازمی‌ایستد فعال می‌شود. سیستم زمان پردازش رویدادها را ردیابی می‌کند: اگر BroadcastReceiver onReceive را در ۱۰ ثانیه تمام نکند، Service در ۲۰ ثانیه از onCreate برنگردد، و ContentProvider در ۱۵ ثانیه پاسخ ندهد — اندروید ANR تولید می‌کند.

ANR چگونه برای کاربر نمایش داده می‌شود

وقتی ANR رخ می‌دهد، اندروید یک دیالوگ سیستمی بالای همه پنجره‌ها نشان می‌دهد: «برنامه پاسخ نمی‌دهد. آن را ببندیم یا صبر کنیم؟». کاربر می‌تواند برنامه را ببندد یا منتظر بازیابی آن بماند. اگر ANR مکرراً تکرار شود، کاربر برنامه را حذف می‌کند. Google Play نرخ ANR — درصد جلسات با ANR — را در الگوریتم‌های رتبه‌بندی در نظر می‌گیرد.

تفاوت ANR با هنگ کردن در iOS

در iOS معادلی برای ANR با دیالوگ سیستمی وجود ندارد. در عوض اپل از Watchdog استفاده می‌کند که برنامه را با کد 0x8badf00d خاتمه می‌دهد. کاربر دیالوگی نمی‌بیند — برنامه simplement به صفحه اصلی بسته می‌شود. این باعث می‌شود ANR در اندروید برای کاربر بیشتر قابل توجه باشد، اما اطلاعات بیشتری برای تشخیص به سیستم می‌دهد.

علل اصلی ANR

ANR زمانی رخ می‌دهد که سیستم زمان‌سنجی را برای یکی از چهار نوع مؤلفه ردیابی می‌کند. هر مؤلفه محدودیت زمانی خود را دارد.

مسدود شدن در BroadcastReceiver

BroadcastReceiver در نخ اصلی اجرا می‌شود. اگر onReceive یک درخواست شبکه همزمان، عملیات نوشتن طولانی در پایگاه داده یا انتظار برای مسدودیت راه‌اندازی کند — پس از ۱۰ ثانیه ANR رخ می‌دهد. راه‌حل: برای پردازش در پس‌زمینه از goAsync() و WorkManager استفاده کنید. سناریوی معمول — دریافت اعلان Push از FCM و ذخیره همزمان در Room.

عملیات طولانی در Service

Service.onCreate و Service.onStartCommand محدودیت ۲۰ ثانیه دارند. اگر سرویس راه‌اندازی سنگین (بارگذاری کتابخانه‌ها، خواندن پیکربندی از شبکه) را در نخ اصلی انجام دهد — ANR اجتناب‌ناپذیر است. برای اجرای تضمینی در نخ پس‌زمینه از IntentService (منسوخ) یا WorkManager استفاده کنید.

ContentProvider با راه‌اندازی طولانی

ContentProvider.onCreate قبل از فراخوانی Application.onCreate اجرا می‌شود و محدودیت ۱۵ ثانیه دارد. اگر ارائه‌دهنده مهاجرت پایگاه داده، بارگذاری دیکشنری‌ها یا راه‌اندازی SDK از شبکه را انجام دهد — این باعث ANR هنگام راه‌اندازی برنامه می‌شود. راه‌حل: راه‌اندازی تنبل، انتقال عملیات سنگین به WorkManager.

  • BroadcastReceiver — ۱۰ ثانیه برای onReceive; برای پردازش پس‌زمینه از goAsync() استفاده کنید
  • Service — ۲۰ ثانیه برای onCreate/onStartCommand; از WorkManager یا CoroutineWorker استفاده کنید
  • ContentProvider — ۱۵ ثانیه برای onCreate; راه‌اندازی را با اجرای تأخیری به Application.onCreate منتقل کنید
  • نخ UI — ۵ ثانیه بدون پردازش رویداد; هر مسدودیتی بیش از ۵ ثانیه باعث ANR می‌شود

چگونه ANR را تشخیص دهیم

اندروید چندین ابزار برای تحلیل ANR ارائه می‌دهد: از لاگ‌های سیستمی تا کتابخانه‌های تخصصی.

تحلیل traces.txt

در هر ANR، اندروید فایل /data/anr/traces.txt را با تخلیه پشته تمام نخ‌های برنامه ذخیره می‌کند. نخ «main» را پیدا کنید — آخرین متد در پشته علت را نشان می‌دهد. الگوهای معمول: Thread.sleep(), InputStream.read(), BinderProxy.transact(). برای استخراج فایل از دستگاه از adb با مجوز سوپریوزر استفاده کنید.

Firebase Crashlytics با گزارش‌های ANR

Firebase Crashlytics به طور خودکار ANRها را جمع‌آوری کرده و در داشبورد به همراه ردیابی نمایش می‌دهد. برای Android 11+ گزارش‌های ANR با پشته کامل نخ اصلی می‌آیند. ادغام نیاز به افزودن وابستگی و راه‌اندازی FirebaseApp در Application.onCreate دارد.

Android Studio Profiler با ردیابی نخ‌ها

CPU Profiler در Android Studio به شما امکان می‌دهد ردیابی عملکرد برنامه را ضبط کرده و ببینید کدام متدها زمان CPU را مصرف می‌کنند. «Record with method traces» را فعال کنید و سناریوی ایجاد ANR را بازتولید کنید. در خط زمانی مشخص می‌شود که کدام متدها در لحظه هنگ در نخ اصلی اجرا می‌شدند.

نمونه ادغام Firebase Crashlytics برای جمع‌آوری ANR در اندروید:

kotlin
class App : Application() {
    override fun onCreate() {
        super.onCreate()
        FirebaseApp.initializeApp(this)
        FirebaseCrashlytics.getInstance()
            .setCrashlyticsCollectionEnabled(true)
        StrictMode.setThreadPolicy(StrictMode.ThreadPolicy.Builder()
            .detectAll()
            .penaltyLog()
            .build())
    }
}

روش‌های رفع ANR

رفع ANR قبل از هر چیز انتقال تمام عملیات طولانی از نخ اصلی به نخ‌های پس‌زمینه است. بیایید تکنیک‌های خاص برای هر نوع مؤلفه را بررسی کنیم.

استفاده از WorkManager برای وظایف پس‌زمینه

WorkManager — راه‌حل توصیه شده Google برای کار در پس‌زمینه است. اجرای وظیفه را در نخ پس‌زمینه با در نظر گرفتن وضعیت دستگاه تضمین می‌کند. برخلاف Service، WorkManager نخ اصلی را مسدود نمی‌کند و در برابر راه‌اندازی مجدد برنامه مقاوم است. برای BroadcastReceiver از goAsync() استفاده کنید و نتیجه PendingResult را به WorkManager منتقل کنید.

Kotlin Coroutines با توزیع‌کننده‌های صحیح

تمام درخواست‌های شبکه، کار با پایگاه داده و عملیات فایل را با Dispatchers.IO اجرا کنید. نخ اصلی فقط باید UI را به‌روزرسانی کند. برای لغو خودکار کوروتین‌ها هنگام نابودی Activity از viewModelScope استفاده کنید. از runBlocking() در هر زمینه‌ای خودداری کنید — این یک مسدودیت همزمان نخ جاری است.

راه‌اندازی تنبل ContentProvider

اگر ContentProvider راه‌اندازی طولانی انجام می‌دهد، از مکانیزم بارگذاری تأخیری استفاده کنید: ارائه‌دهنده‌ای ایجاد کنید که فوراً داده را برمی‌گرداند، و راه‌اندازی سنگین را از طریق WorkManager با تأخیر اجرا کنید. این کار از ANR هنگام راه‌اندازی برنامه جلوگیری می‌کند، زمانی که سیستم بیشترین حساسیت را به تأخیر دارد.

نمونه استفاده صحیح از BroadcastReceiver با goAsync در اندروید:

kotlin
class FcmReceiver : BroadcastReceiver() {
    override fun onReceive(context: Context?, intent: Intent?) {
        val pendingResult = goAsync()
        WorkManager.getInstance(context!!)
            .enqueue(OneTimeWorkRequest.from(NotificationWorker::class.java))
        pendingResult.finish()
    }
}

پیشگیری از ANR در توسعه

بهترین راه مبارزه با ANR جلوگیری از ظهور آنها در مرحله توسعه از طریق ابزارها و راه‌حل‌های معماری است.

StrictMode برای تشخیص مسدودیت‌های نخ اصلی

StrictMode با سیاست‌های detectNetwork() و detectDiskReads()/detectDiskWrites() فعال شده، ANRهای بالقوه را در مرحله توسعه شناسایی می‌کند. در ساخت Debug penaltyDeath را تنظیم کنید — هر نقضی منجر به سقوط فوری می‌شود و توسعه‌دهنده مشکل را قبل از commit می‌بیند.

Firebase Performance Monitoring برای معیارهای تولید

Firebase Performance زمان اجرای عملیات کلیدی را ردیابی کرده و نشان می‌دهد کدام سناریوها از آستانه ANR فراتر می‌روند. ردیابی سفارشی برای هر صفحه و درخواست شبکه تنظیم کنید. اگر زمان اجرا از ۳ ثانیه بیشتر شود — این یک ANR بالقوه نیازمند بهینه‌سازی است.

تست با تأخیرهای شبکه و دیسک

شرایط کند را شبیه‌سازی کنید: سرعت شبکه را از طریق Network Link Conditioner در iOS یا Android Emulator محدود کنید. خواندن از دیسک را از طریق شبیه‌سازی حافظه کند کاهش دهید. ANR اغلب دقیقاً در چنین شرایطی ظاهر می‌شود و در دستگاه‌های سریع توسعه‌دهنده قابل مشاهده نیست.

  • BroadcastReceiver — همیشه برای پردازش بیش از ۱ ثانیه از goAsync() استفاده کنید
  • Service — با WorkManager یا CoroutineWorker با توزیع‌کننده پس‌زمینه جایگزین کنید
  • ContentProvider — در onCreate از شبکه و پایگاه داده خودداری کنید، از lazy-init با WorkManager استفاده کنید
  • نخ UI — StrictMode با penaltyDeath در Debug، Firebase Performance برای نظارت تولید

سوالات متداول

چرا ANR در اندروید رخ می‌دهد اما در iOS نه؟

اندروید به صراحت زمان پردازش رویدادها را در نخ اصلی ردیابی کرده و دیالوگ ANR را نشان می‌دهد. iOS از Watchdog استفاده می‌کند که پس از ۱۰–۲۰ ثانیه هنگ برنامه را به زور می‌بندد. ANR ویژگی معماری اندروید است که در آن چندین مؤلفه (BroadcastReceiver, Service) محدودیت‌های زمانی سخت دارند.

چگونه traces.txt را در دستگاه بدون root پیدا کنیم؟

در Android 11+ می‌توان تخلیه ANR را از طریق adb shell dumpsys dropbox --print data_app_anr دریافت کرد. در Android 10 و پایین‌تر بدون root دسترسی به /data/anr/traces.txt وجود ندارد. از Firebase Crashlytics استفاده کنید — به طور خودکار گزارش‌های ANR را برای Android 11+ جمع‌آوری می‌کند.

چه نرخ ANR قابل قبول در نظر گرفته می‌شود؟

Google Play نرخ ANR کمتر از ۰.۵٪ را توصیه می‌کند — یعنی حداکثر ۵ ANR در ۱۰۰۰ جلسه. برنامه با نرخ بالای ۱٪ اخطار در Google Play Console دریافت می‌کند و ممکن است از توصیه‌ها پنهان شود. در حالت ایده‌آل نرخ ANR باید زیر ۰.۱٪ باشد.

آیا کوروتین می‌تواند باعث ANR شود؟

کوروتین به خودی خود نخ را مسدود نمی‌کند. اما اگر در داخل کوروتین runBlocking در نخ اصلی اجرا شود یا کوروتین با Dispatchers.Main راه‌اندازی شده و عملیات طولانی CPU انجام دهد — این باعث ANR می‌شود. برای ورودی-خروجی از Dispatchers.IO و برای محاسبات از Dispatchers.Default استفاده کنید.

چگونه ANR را در شبیه‌ساز تست کنیم؟

از Android Emulator با پروفایل «Slow Network» استفاده کنید یا تستی بنویسید که Thread.sleep(6000) را در نخ اصلی فراخوانی کند. برنامه را از طریق Debug اجرا کنید و بعد از ۵ ثانیه دیالوگ ANR را خواهید دید. بررسی کنید که در logcat یک رکورد ANR با ردیابی ظاهر شده است.

خلاصه

  • ANR — اعلان سیستمی اندروید هنگام مسدود شدن نخ اصلی بیش از ۵ ثانیه یا فراتر رفتن از محدودیت‌های زمانی مؤلفه‌ها
  • محدودیت‌های زمانی: BroadcastReceiver — ۱۰ ثانیه، Service — ۲۰ ثانیه، ContentProvider — ۱۵ ثانیه، UI — ۵ ثانیه
  • تشخیص — /data/anr/traces.txt، Firebase Crashlytics، CPU Profiler در Android Studio
  • رفع — WorkManager، goAsync()، Kotlin Coroutines با Dispatchers.IO، راه‌اندازی تنبل ContentProvider
  • پیشگیری — StrictMode با penaltyDeath، Firebase Performance Monitoring، تست با تأخیرهای شبکه
  • Google Play نرخ ANR < ۰.۵٪ را توصیه می‌کند; در نرخ > ۱٪ برنامه تحت محدودیت‌های مشاهده قرار می‌گیرد
  • توصیه: Firebase Crashlytics و Performance را برای جمع‌آوری ANR در تولید پیکربندی کرده و در صورت فراتر رفتن از آستانه ۰.۳٪ هشدار تنظیم کنید

ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد

IT Sectr از سال 2017 برنامه‌های iOS و Android را برای استارتاپ‌ها و کسب‌وکارها ایجاد می‌کند. ما به شما مشاوره می‌دهیم و بهترین راه‌حل را پیشنهاد خواهیم کرد.

بحث درباره پروژه

همچنین بخوانید