تعداد خطاهای «برنامه پاسخ نمی‌دهد»

وقتی رشته میانای کاربر برنامه Android برای مدت طولانی مسدود شود، خطای «برنامه پاسخ نمی‌دهد» (ANR) راه‌اندازی می‌شود. «معیارهای کلیدی Android» سنجه‌های ANR را در «کنسول Google Play» ردیابی و گزارش می‌کند تا به شما کمک کند پایداری و پاسخ‌گویی برنامه‌تان را در دستگاه‌های مختلف پایش کنید.

سنجه‌ها و آستانه‌های «معیارهای کلیدی Android»

«معیارهای کلیدی Android» می‌تواند به شما کمک کند بر نرخ خطای ANR برنامه‌تان نظارت داشته باشید و آن را بهبود دهید. «معیارهای کلیدی Android» چندین نرخ ANR را اندازه‌گیری می‌کند:

  • نرخ خطای ANR: درصد کاربران فعال روزانه شما که هر نوع خطای ANR را تجربه کرده‌اند.
  • میزان خطای ANR مشهود برای کاربر: درصد کاربران فعال روزانه شما که حداقل یک خطای ANR مشهود برای کاربر را تجربه کرده‌اند. درحال‌حاضر فقط خطاهای ANR از نوع Input dispatching timed out به‌عنوان خطاهای دیده‌شده توسط کاربر درنظر گرفته می‌شوند.
  • میزان خطاهای ANR مکرر: درصد کاربران فعال روزانه شما که حداقل دو خطای ANR را تجربه کرده‌اند.

کاربر فعال روزانه کاربر متمایزی است که در یک روز از برنامه‌تان در یک دستگاه استفاده می‌کند، که ممکن است در چندین جلسه باشد. اگر کاربری در یک روز از برنامه‌تان در بیش‌از یک دستگاه استفاده کند، هر دستگاه در تعداد کاربران فعال آن روز لحاظ خواهد شد.

میزان خطای ANR مشهود برای کاربر یک معیار کلیدی اصلی است، یعنی بر قابلیت یافتن برنامه‌تان در Google Play تأثیر می‌گذارد. این معیار مهم است زیرا خطاهای ANR که شمارش می‌کند همیشه زمانی رخ می‌دهند که کاربر با برنامه تعامل دارد و بیشترین اختلال را ایجاد می‌کند.

‫Play دو آستانه عملکرد بد برای این سنجه تعریف کرده است:

  • آستانه کلی عملکرد بد: حداقل ۰٫۴۷٪ از کاربران فعال روزانه در همه مدل‌های دستگاه، خطای ANR مشهود برای کاربر را تجربه می‌کنند.
  • آستانه عملکرد بد برای هر دستگاه: حداقل ۸٪ از کاربران روزانه خطای ANR مشهود برای کاربر را برای یک مدل دستگاه تجربه می‌کنند.

اگر برنامه‌تان از آستانه رفتار بد کلی فراتر برود، احتمالاً قابلیت یافتن آن در همه دستگاه‌ها کاهش می‌یابد. اگر برنامه‌تان از آستانه رفتار بد به‌ازای هر دستگاه در برخی‌از دستگاه‌ها فراتر برود، احتمالاً قابلیت یافتن آن در آن دستگاه‌ها کاهش می‌یابد و ممکن است هشداری در فهرستگان مکانتان نمایش داده شود.

وقتی برنامه‌تان ANR بیش‌ازحد نشان می‌دهد، «معیارهای کلیدی Android» می‌تواند ازطریق کنسول Play به شما هشدار دهد.

برای کسب اطلاعات درباره نحوه جمع‌آوری داده‌های معیارهای کلیدی Android توسط Google Play، به اسناد کنسول Play مراجعه کنید.

مشکل را شناسایی کنید

اگر هنگام وقوع ANR برنامه در پیش‌زمینه باشد، سیستم کادر گفتگویی را به کاربر نشان می‌دهد، همان‌طور که در شکل ۱ نشان داده شده است. کادر گفتگوی ANR به کاربر این فرصت را می‌دهد که برنامه را اجباراً متوقف کند.

کادر گفتگوی ANR به کاربر نشان داده شد.
شکل ۱. کادر گفتگوی 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 و نسخه‌های پایین‌تر را هدف قرار می‌دهند، خطاهای ANR بی‌صدا هستند و به برنامه گزارش نمی‌شوند. برای برنامه‌هایی که Android 14 و نسخه‌های بالاتر را هدف قرار می‌دهند، خطاهای ANR صریح هستند و به برنامه گزارش می‌شوند.

علاوه‌بر معیارهای کلیدی Android، می‌توانید از ابزارهای دیگر برای شناسایی خطاهای ANR در این زمینه استفاده کنید، هرچند ابزارهای شخص ثالث نمی‌توانند خطاهای ANR را در Android نسخه ۱۰ (سطح API‏ ۲۹) و پایین‌تر گزارش کنند.

تشخیص خطاهای ANR

هنگام تشخیص ANR، چند الگوی رایج وجود دارد که باید به‌دنبال آن‌ها باشید:

  • برنامه درحال انجام عملیات آهسته شامل ورودی/خروجی در رشته اصلی است.
  • برنامه درحال انجام محاسباتی طولانی در رشته اصلی است.
  • رشته اصلی درحال انجام فراخوانی همگام‌سازی Binder به فرایند دیگری است و آن فرایند دیگر زمان زیادی برای بازگشت صرف می‌کند.
  • رشته اصلی مسدود شده است و منتظر بلوک همگام‌سازی‌شده برای عملیات طولانی است که در رشته دیگری درحال انجام است.
  • رشته اصلی با رشته دیگری در بن‌بست است، چه در فرایند شما یا ازطریق فراخوانی بایندر. رشته اصلی فقط منتظر نیست تا عملیات طولانی به‌پایان برسد، بلکه در وضعیت بن‌بست قرار دارد.

روش‌های زیر می‌تواند به شما کمک کند علت خطاهای ANR را تعیین کنید.

HealthStats

HealthStats سنجه‌هایی درباره سلامت برنامه با ضبط کل زمان کاربر و سیستم، زمان واحد پردازش مرکزی، شبکه، آمار رادیو، زمان روشن و خاموش بودن صفحه‌نمایش، و زنگ‌های بیدارباش ارائه می‌دهد. این کار می‌تواند به شما کمک کند مصرف کلی CPU و تخلیه باتری را اندازه‌گیری کنید.

اشکال‌زدایی کردن

Debug به شما کمک می‌کند برنامه‌های Android را درطول توسعه بررسی کنید، ازجمله ردیابی و شمارش تخصیص برای شناسایی لرزش و تأخیر در برنامه‌ها. همچنین می‌توانید از Debug برای دریافت شمارنده‌های حافظه بومی و زمان اجرا، و سنجه‌های حافظه استفاده کنید که می‌توانند به شما در شناسایی ردپای حافظه یک فرایند خاص کمک کنند.

ApplicationExitInfo

ApplicationExitInfo در Android نسخه ۱۱ (سطح میانای برنامه‌سازی کاربردی ۳۰) و بالاتر دردسترس است و اطلاعاتی درباره دلیل خروج از برنامه ارائه می‌دهد. این شامل خطاهای ANR، حافظه کم، خرابی‌های برنامه، استفاده بیش‌ازحد از CPU، وقفه‌های کاربر، وقفه‌های سیستم، و تغییرات اجازه زمان اجرا می‌شود.

حالت سخت‌گیرانه

استفاده از StrictMode به شما کمک می‌کند تا عملیات ورودی/خروجی تصادفی را در رشته اصلی درحین توسعه برنامه‌تان پیدا کنید. می‌توانید از StrictMode در سطح برنامه یا فعالیت استفاده کنید.

فعال کردن کادرهای گفتگوی ANR پس‌زمینه

Android کادرهای گفتگوی ANR را برای برنامه‌هایی که پردازش پیام همه‌فرستی در آن‌ها بیش‌ازحد طول می‌کشد فقط درصورتی نشان می‌دهد که نمایش همه ANRها در گزینه‌های توسعه‌دهندگان دستگاه فعال باشد. به همین دلیل، کادرهای گفتگوی ANR پس‌زمینه همیشه به کاربر نشان داده نمی‌شود، حتی وقتی برنامه با مشکل عملکرد مواجه است.

ردیابی‌های سیستم و واحد پردازش مرکزی نمایه

از نمایه‌ساز واحد پردازش مرکزی Android Studio برای ضبط ردگیری‌های سیستم و فعالیت واحد پردازش مرکزی درحین اجرای بازی استفاده کنید. بازرسی رشته اصلی Activity درکنار رشته‌های عامل، صوتی، و رندر موتور بازی به شما کمک می‌کند فریم‌های طولانی، بارگیری‌های هم‌زمان دارایی، و رقابت رشته‌ها را قبل‌از اینکه موجب بروز خطای ANR شوند شناسایی کنید.

کشیدن فایل ردیابی

وقتی Android با ANR مواجه می‌شود، اطلاعات ردیابی را ذخیره می‌کند. در نسخه‌های قدیمی‌تر Android، یک فایل /data/anr/traces.txt در دستگاه وجود دارد. در نسخه‌های بالاتر Android، چندین فایل /data/anr/anr_* وجود دارد. می‌توانید بااستفاده از Android Debug Bridge (adb) به‌عنوان ریشه، به ردیابی‌های ANR از دستگاه یا شبیه‌ساز دسترسی پیدا کنید:

adb root
adb shell ls /data/anr
adb pull /data/anr/<filename>

می‌توانید بااستفاده از گزینه توسعه‌دهنده «گرفتن گزارش اشکال» در دستگاه یا فرمان adb bugreport در ماشین توسعه نرم‌افزار، گزارش اشکال را از دستگاه فیزیکی ضبط کنید. برای اطلاعات بیشتر، به ضبط و خواندن گزارش‌های اشکال مراجعه کنید.

برطرف کردن مشکلات

پس‌از شناسایی مشکل، می‌توانید از نکته‌های این بخش برای رفع مشکلات رایج استفاده کنید.

کد کند در رشته اصلی

مکان‌هایی را در کدتان شناسایی کنید که رشته اصلی برنامه برای بیش‌از ۵ ثانیه مشغول است. موارد استفاده مشکوک را در بازی‌تان پیدا کنید و سعی کنید خطای «برنامه پاسخ نمی‌دهد» را بازتولید کنید.

در بازی‌ها، توقف رشته اصلی معمولاً زمانی اتفاق می‌افتد که فشرده‌سازی هم‌زمان دارایی، کامپایل سایه‌زن، یا مقداردهی اولیه سنگین وضعیت بازی در رشته اصلی Android Activity اجرا می‌شود (مانند داخل onCreate، onResume، یا فراخوانی‌های JNI که از رشته میانای کاربر فراخوانی می‌شوند). اجرای حلقه بازی، پردازش دارایی، و مقداردهی اولیه صحنه را به رشته‌های عامل پس‌زمینه، موتور، یا رندر اختصاصی منتقل کنید تا رشته اصلی برای پردازش ورودی و رویدادهای چرخه حیات آزاد بماند.

ورودی/خروجی در رشته اصلی

اجرای عملیات ورودی/خروجی در رشته اصلی یکی از دلایل رایج عملکرد آهسته در رشته اصلی است که می‌تواند موجب بروز خطای ANR شود.

همه خواندن‌های دسته دارایی، سریال‌سازی بازی ذخیره‌شده، SharedPreferences دسترسی‌ها، و درخواست‌های شبکه را از رشته اصلی Activity به رشته‌های عامل پس‌زمینه منتقل کنید تا تأخیر فضای ذخیره‌سازی یا شبکه نتواند ارسال ورودی را مسدود کند.

بن‌بست‌ها

بن‌بست زمانی رخ می‌دهد که رشته‌ای وارد حالت انتظار می‌شود زیرا منبع موردنیاز توسط رشته دیگری نگه‌داشته شده است، که آن رشته نیز منتظر منبعی است که توسط رشته اول نگه‌داشته شده است. اگر رشته اصلی برنامه در این وضعیت باشد، احتمالاً خطای ANR رخ می‌دهد.

در بازی‌ها، بن‌بست و رقابت بر سر قفل اغلب بین رشته اصلی Activity Android (که مدیریت چرخه حیات، سطح، یا فراخوانی‌های ورودی را برعهده دارد) و رشته‌های بومی C یا C++‎ برای رندر، منطق، یا صدا رخ می‌دهد. از انتظار هم‌زمان در رشته اصلی برای قفل‌های موتور بومی اجتناب کنید و هنگام برقراری ارتباط در JNI و رشته‌های موتور، از ترتیب قفل ثابت یا صف‌های پیام بدون قفل استفاده کنید.

بن‌بست‌ها پدیده‌ای هستند که در علوم رایانه به‌خوبی مطالعه شده‌اند و الگوریتم‌های جلوگیری از بن‌بست وجود دارد که می‌توانید برای اجتناب از بن‌بست از آن‌ها استفاده کنید.

برای اطلاعات بیشتر، به بن‌بست و الگوریتم‌های جلوگیری از بن‌بست در ویکی‌پدیا مراجعه کنید.

گیرنده‌های رویداد ثبت‌شده کند

برنامه‌ها می‌توانند ازطریق گیرنده‌های رویداد ثبت‌شده به پیام‌های همه‌فرستی پاسخ دهند، مثلاً فعال یا غیرفعال کردن حالت هواپیما یا تغییر در وضعیت اتصال‌پذیری. وقتی برنامه برای پردازش پیام همه‌فرستی بیش‌ازحد طول بکشد، خطای «برنامه پاسخ نمی‌دهد» رخ می‌دهد.

خطای «برنامه پاسخ نمی‌دهد» در موارد زیر رخ می‌دهد:

  • گیرنده رویداد ثبت‌شده اجرای روش onReceive خود را در مدت زمان قابل‌توجهی به‌پایان نرسانده است.
  • گیرنده رویداد ثبت‌شده goAsync را فراخوانی می‌کند و نمی‌تواند finish را در شیء PendingResult فراخوانی کند.

برنامه شما باید فقط عملیات کوتاه را در روش onReceive BroadcastReceiver انجام دهد. بااین‌حال، اگر برنامه شما درنتیجه پیام همه‌فرستی به پردازش پیچیده‌تری نیاز دارد، باید تکلیف را به رشته عامل پس‌زمینه موکول کنید اگر انتظار می‌رود تکلیف حداکثر چند ثانیه طول بکشد، یا به WorkManager برای تکالیفی که انتظار می‌رود بیشتر از چند ثانیه طول بکشد.

GameActivity

کتابخانه GameActivity در مطالعات موردی بازی‌ها و برنامه‌هایی که به زبان C یا ++C نوشته شده‌اند، ANR را کاهش داده است. اگر فعالیت بومی موجودتان را با GameActivity جایگزین کنید، می‌توانید مسدود شدن رشته میانای کاربر را کاهش دهید و از وقوع برخی ANRها جلوگیری کنید.

اگر بازی‌تان را با Unity می‌سازید، به اشکال‌زدایی ANR برای بازی‌های Unity، ANRهای رایج بازی‌های Unity، و نمادین کردن خرابی‌های Android و ANR برای بازی‌های Unity مراجعه کنید.

برای اطلاعات بیشتر درباره ANR، به حفظ پاسخ‌گویی برنامه مراجعه کنید. برای اطلاعات بیشتر درباره رشته‌ها، به عملکرد بهتر ازطریق رشته‌سازی مراجعه کنید.