ANR في أندرويد: ما هو، الأسباب وطرق الإصلاح

المؤلف: IT Sectr نُشر: 2026-07-28 وقت القراءة: 9 دق

ANR (Application Not Responding) هو إشعار نظام في أندرويد يظهر عندما لا يستجيب التطبيق للإدخال لمدة 5 ثوانٍ. على عكس الأخطاء المنطقية (أخطاء منطقية دون حظر واجهة المستخدم) والتباطؤ (بطء دون توقف كامل)، ANR هو عطل خطير يسجله نظام التشغيل: يعرض أندرويد حوار «التطبيق لا يستجيب» مع خيار الإغلاق أو الانتظار. وفقاً لـ Android Vitals Documentation، التطبيقات التي يزيد معدل ANR فيها عن 0.5% تحصل على تقييم أقل في Google Play وقد يتم إخفاؤها من التوصيات. يشمل التشخيص تحليل /data/anr/traces.txt، واستخدام StrictMode، وتوصيف السلسلة الرئيسية.

الخلاصة

  • ANR — إشعار نظام في أندرويد عند حظر السلسلة الرئيسية لأكثر من 5 ثوانٍ، مما يؤدي إلى حوار «التطبيق لا يستجيب»
  • الأسباب الرئيسية — حظر السلسلة الرئيسية (BroadcastReceiver، Service)، الجمود بين السلاسل، عملية طويلة في ContentProvider
  • التشخيص — تحليل /data/anr/traces.txt، Android Studio Profiler، Firebase Performance Monitoring
  • الإصلاح — تفريغ المهام إلى WorkManager، استخدام Kotlin Coroutines مع Dispatchers.IO، StrictMode للكشف المبكر
  • الوقاية — تحديد وقت BroadcastReceiver بـ 10 ثوانٍ، Service بـ 20 ثانية، ContentProvider بـ 15 ثانية

ما هو ANR في أندرويد

ANR (Application Not Responding) هو آلية حماية للمستخدم في أندرويد يتم تفعيلها عندما يتوقف التطبيق عن الاستجابة للإدخال. يتتبع النظام وقت معالجة الأحداث: إذا لم يكمل BroadcastReceiver onReceive خلال 10 ثوانٍ، أو لم يعد Service من onCreate خلال 20 ثانية، أو لم يستجب ContentProvider خلال 15 ثانية — يقوم أندرويد بتوليد ANR.

كيف يبدو ANR للمستخدم

عند حدوث ANR، يعرض أندرويد حوار نظام فوق جميع النوافذ: «التطبيق لا يستجيب. هل تريد إغلاقه أو الانتظار؟». يمكن للمستخدم إغلاق التطبيق أو انتظار استرداده. إذا تكرر ANR بشكل متكرر، يقوم المستخدم بإلغاء تثبيت التطبيق. يراعي Google Play معدل ANR — النسبة المئوية للجلسات مع ANR — في خوارزميات التصنيف الخاصة به.

الفرق بين ANR والتجميد في iOS

لا يوجد في iOS ما يعادل ANR مع حوار النظام. بدلاً من ذلك، تستخدم Apple Watchdog الذي ينهي العملية برمز الخروج 0x8badf00d. لا يرى المستخدم حواراً — يتم إغلاق التطبيق ببساطة إلى الشاشة الرئيسية. هذا يجعل ANR على أندرويد أكثر وضوحاً للمستخدم ولكنه يعطي النظام مزيداً من معلومات التشخيص.

الأسباب الرئيسية لـ ANR

يحدث ANR عندما يتتبع النظام مهلة لأحد أربعة أنواع من المكونات. لكل مكون حد زمني خاص به.

الحظر في BroadcastReceiver

BroadcastReceiver يتم تنفيذه في السلسلة الرئيسية. إذا بدأ onReceive طلب شبكة متزامن، أو كتابة طويلة في قاعدة البيانات، أو انتظر قفلاً — يحدث ANR خلال 10 ثوانٍ. الحل: استخدم goAsync() و WorkManager للمعالجة في الخلفية. السيناريو النموذجي هو استلام إشعار Push من FCM وحفظه بشكل متزامن في Room.

عملية طويلة في Service

Service.onCreate و Service.onStartCommand لهما حد 20 ثانية. إذا بدأ الخدمة تهيئة ثقيلة (تحميل المكتبات، قراءة التهيئة من الشبكة) في السلسلة الرئيسية — ANR أمر لا مفر منه. استخدم IntentService (قديم) أو WorkManager للتنفيذ المضمون في الخلفية.

ContentProvider مع تهيئة بطيئة

ContentProvider.onCreate يتم تنفيذه قبل Application.onCreate وله حد 15 ثانية. إذا قام المزود بترحيل قاعدة البيانات، أو تحميل القواميس، أو تهيئة SDK من الشبكة — فهذا يسبب ANR عند بدء تشغيل التطبيق. الحل: التهيئة البطيئة، تفريغ العمليات الثقيلة إلى WorkManager.

  • BroadcastReceiver — 10 ثوانٍ لـ onReceive؛ استخدم goAsync() للمعالجة في الخلفية
  • Service — 20 ثانية لـ onCreate/onStartCommand؛ استخدم WorkManager أو CoroutineWorker
  • ContentProvider — 15 ثانية لـ onCreate؛ انقل التهيئة إلى Application.onCreate مع بدء مؤجل
  • سلسلة واجهة المستخدم — 5 ثوانٍ بدون معالجة الأحداث؛ أي حظر أطول من 5 ثوانٍ يسبب ANR

كيفية تشخيص ANR

يوفر أندرويد عدة أدوات لتحليل ANR: من سجلات النظام إلى المكتبات المتخصصة.

تحليل traces.txt

عند كل ANR، يحفظ أندرويد الملف /data/anr/traces.txt مع تفريغ مكدس لجميع سلاسل التطبيق. ابحث عن السلسلة «main» — تشير آخر طريقة في المكدس إلى السبب. الأنماط النموذجية: Thread.sleep()، InputStream.read()، BinderProxy.transact(). لاستخراج الملف من الجهاز، استخدم adb بصلاحيات المستخدم المتميز.

Firebase Crashlytics مع تقارير ANR

Firebase Crashlytics يقوم تلقائياً بجمع ANR وعرضها في لوحة المعلومات مع التتبع. لأندرويد 11+، تأتي تقارير ANR مع مكدس كامل للسلسلة الرئيسية. يتطلب التكامل إضافة تبعية وتهيئة FirebaseApp في Application.onCreate.

Android Studio Profiler مع تتبع السلاسل

CPU Profiler في Android Studio يتيح لك تسجيل تتبع التطبيق ورؤية أي الطرق تستهلك وقت المعالجة. فعّل «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. يجب أن تقوم السلسلة الرئيسية فقط بتحديث واجهة المستخدم. استخدم viewModelScope للإلغاء التلقائي للكوروتينات عند تدمير Activity. تجنب 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 — أي انتهاك سيؤدي إلى تعطل فوري وسيرى المطور المشكلة قبل الالتزام.

Firebase Performance Monitoring لمقاييس الإنتاج

Firebase Performance يتتبع وقت تنفيذ العمليات الرئيسية ويظهر أي السيناريوهات تتجاوز عتبة ANR. قم بإعداد تتبعات مخصصة لكل شاشة وطلب شبكة. إذا تجاوز وقت التنفيذ 3 ثوانٍ — فهذا ANR محتمل يتطلب تحسيناً.

الاختبار مع تأخير الشبكة والقرص

قم بمحاكاة الظروف البطيئة: حدد سرعة الشبكة باستخدام Network Link Conditioner على iOS أو Android Emulator. أبطئ قراءة القرص من خلال محاكاة الذاكرة البطيئة. ANR غالباً ما تظهر في هذه الظروف تحديداً، بينما تكون غير مرئية على أجهزة المطور السريعة.

  • BroadcastReceiver — استخدم دائماً goAsync() للمعالجة التي تستغرق أكثر من ثانية واحدة
  • Service — استبدله بـ WorkManager أو CoroutineWorker مع مرسل خلفية
  • ContentProvider — تجنب الشبكة وقاعدة البيانات في onCreate، استخدم التهيئة البطيئة مع WorkManager
  • سلسلة واجهة المستخدم — StrictMode مع penaltyDeath في Debug، Firebase Performance للمراقبة في الإنتاج

الأسئلة الشائعة

لماذا يحدث ANR على أندرويد ولكن ليس على iOS؟

أندرويد يتتبع وقت معالجة الأحداث بشكل صريح على السلسلة الرئيسية ويعرض حوار ANR. iOS يستخدم Watchdog الذي يغلق التطبيق قسراً عندما يتجمد لأكثر من 10–20 ثانية. ANR هي ميزة في معمارية أندرويد حيث تحتوي عدة مكونات (BroadcastReceiver، Service) على مهلات زمنية صارمة.

كيفية العثور على traces.txt على جهاز بدون روت؟

على أندرويد 11+ يمكنك الحصول على تفريغ ANR عبر adb shell dumpsys dropbox --print data_app_anr. على أندرويد 10 والإصدارات الأقدم، لا يمكن الوصول إلى /data/anr/traces.txt بدون صلاحيات الروت. استخدم Firebase Crashlytics — فهو يجمع تقارير ANR تلقائياً لأندرويد 11+.

ما هو معدل ANR المقبول؟

يوصي Google Play بمعدل ANR أقل من 0.5% — أي لا يزيد عن 5 ANR لكل 1000 جلسة. التطبيق الذي يزيد معدله عن 1% يتلقى تحذيراً في Google Play Console وقد يتم إخفاؤه من التوصيات. من الناحية المثالية، يجب أن يكون معدل ANR أقل من 0.1%.

هل يمكن أن تسبب الكوروتين ANR؟

الكوروتين في حد ذاته لا يحظر السلسلة. ولكن إذا قمت بتنفيذ runBlocking داخل كوروتين على السلسلة الرئيسية أو تم تشغيل الكوروتين مع Dispatchers.Main وقامت بعملية CPU طويلة — فسيؤدي ذلك إلى ANR. استخدم Dispatchers.IO للإدخال/الإخراج و Dispatchers.Default للحسابات.

كيفية اختبار ANR في المحاكي؟

استخدم Android Emulator مع ملف تعريف «Slow Network» أو اكتب اختباراً يستدعي Thread.sleep(6000) على السلسلة الرئيسية. قم بتشغيل التطبيق عبر Debug وبعد 5 ثوانٍ سترى حوار ANR. تحقق من ظهور سجل ANR مع تتبع في logcat.

الخلاصة

  • ANR — إشعار نظام في أندرويد عند حظر السلسلة الرئيسية لأكثر من 5 ثوانٍ أو تجاوز مهلات المكونات
  • المهلات: BroadcastReceiver — 10 ث، Service — 20 ث، ContentProvider — 15 ث، واجهة المستخدم — 5 ث
  • التشخيص — /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 < 0.5%؛ مع معدل > 1% يواجه التطبيق قيوداً على الرؤية
  • توصية: قم بإعداد Firebase Crashlytics و Performance لجمع ANR في الإنتاج وتعيين تنبيهات عند تجاوز الحد 0.3%

سنقوم بتطوير تطبيق جوال جاهز

تقدم IT Sectr تطبيقات iOS وAndroid للشركات الناشئة والشركات منذ عام 2017. سوف نقدم لك النصح ونقترح أفضل حل.

مناقشة المشروع

اقرأ أيضًا