ANR ใน Android: มันคืออะไร สาเหตุ และวิธีแก้ไข

ผู้แต่ง: IT Sectr เผยแพร่เมื่อ: 2026-07-28 เวลาอ่าน: 9 นาที

ANR (Application Not Responding) คือการแจ้งเตือนระบบใน Android ที่ปรากฎตัวเมื่อแอพไม่ตอบสนองต่ออินพุตภายใน 5 วินาที แตกต่างจากข้อผิดพลาดเล็กน้อย (ข้อผิดพลาดเชิงตรรกะที่ไม่มีการบล็อก UI) และลาก (การช้าลงโดยไม่หยุดโดยสิ้นเชิง), ANR เป็นความล้มเหลวรุแบบร้ายแรงที่ถูกบันทึกโดยระบบปฏิบัติการ: Android แสดงกล่องโต้ตอบสนองระบบ “แอปไม่ตอบสนอง” พร้อมตัวเลือกในการปิดหรือรอเผ้าชมากละ. ตาม Android Vitals Documentation แอพที่มีอัตรา ANR สูงกว่า 0.5% จะได้รับการจัดอันดับที่ต่ำลงใน Google Play และอาจถูกซ่อนจากคำแนะนำ การวิจัยรวมถึงการวิเคราะฮ์ /data/anr/traces.txt, การใช้ StrictMode และการทำโปรไฟล์เธรดหลัก

หัวข้อสำคัญ

  • ANR — การแจ้งเตือนระบบใน Android เมื่อเธรดหลักถูกบล็อกนานกว่า 5 วินาที นำไปสู่กล่องโต้ตอบสนอง “แอปไม่ตอบสนอง”
  • สาเหตุหลัก — การบล็อกเธรดหลัก (BroadcastReceiver, Service), deadlock ระหว่างเธรด, การดำเนินการยาวใน ContentProvider
  • การวิจัย — การวิเคราะฮ์ /data/anr/traces.txt, Android Studio Profiler, Firebase Performance Monitoring
  • การแก้ไข — การโออฟโหลดงานไปยัง WorkManager, ใช้ Kotlin Coroutines กับ Dispatchers.IO, StrictMode สำหรับการตรวจจับแต่เนิน
  • การป้องกัน — การจำกัดเวลา BroadcastReceiver เป็น 10 วินาที, Service เป็น 20 วินาที, ContentProvider เป็น 15 วินาที

ANR ใน Android คืออะไร

ANR (Application Not Responding) เป็นกลไกการป้องกันผู้ใช้ใน Android ที่ทำงานเมื่อแอพหยุดตอบสนองต่ออินพุต ระบบจะติดตามเวลาการประมวลผลเหตุการณ์: หาก BroadcastReceiver ไม่เสร็จ onReceive ภายใน 10 วินาที, Service ไม่กลับจาก onCreate ภายใน 20 วินาที หรือ ContentProvider ไม่ตอบสนองภายใน 15 วินาที — Android จะสร้าง ANR

ANR แสดงอย่างไรต่อผู้ใช้

เมื่อเกิด ANR, Android จะแสดงกล่องโต้ตอบสนองระบบเทอบหน้าต่างทั้งหมด: “แอปไม่ตอบสนอง คุณต้องการปิดหรือรอเผ้าชมากละ?” ผู้ใช้สามารถปิดแอพหรือรอให้มันกลับมาใช้งานได้ หากเกิด ANR บ่อยครั้ง ผู้ใช้จะถอนแอพออก Google Play พิจารณา อัตรา ANR — เปอร์เซนต์ของเซสชั่นที่มี ANR — ในอัลกอริทึมการจัดอันดับ

ความแตกต่างระหว่าง ANR และการค้างของ iOS

iOS ไม่มีสิ่งที่เทียบเท่ากับ ANR ที่มีกล่องโต้ตอบสนองระบบ แทนนั้น Apple ใช้ Watchdog ซึ่งจะสิ้นสุดกระบวนการด้วยรหัสออก 0x8badf00d ผู้ใช้จะไม่เห็นกล่องโต้ตอบสนอง — แอพจะปิดกลับไปยังหน้าจอหลัก ทำให้ ANR บน Android สังเกตแก่ผู้ใช้มากกว่า แต่ให้ข้อมูลการวิจัยแก่ระบบมากขึ้น

สาเหตุหลักของ 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 โดยเริ่มต้นที่ล่าช้า
  • เธรด UI — 5 วินาทีโดยไม่มีการประมวลผลเหตุการณ์; การบล็อกใดๆ ที่นานกว่า 5 วินาทีจะทริเกอร์ ANR

วิธีการวิจัย ANR

Android มีเครื่องมือหลายอย่างสำหรับการวิเคราะฮ์ ANR: ตั้งแต่บันทึกระบบไปจนถึงไลบรารีเฉพาะทาง

การวิเคราะฮ์ traces.txt

ในแต่ละ ANR, Android จะบันทึกไฟล์ /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 บน Android:

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 กับตัวจัดส่งที่เหมาะสม

เริ่มคำขอเครือข่ายทั้งหมด, การดำเนินการฐานข้อมูล และ I/O ไฟล์ด้วย Dispatchers.IO เธรดหลักควรอัพเดต UI เท่านั้น ใช้ viewModelScope สำหรับการยกเลิก coroutine โดยอัตโนมัติเมื่อ Activity ถูกทำลาย หลีกเลี่ยง runBlocking() ในทุกบริบท — มันบล็อกเธรดปัจจุบันแบบซิงโครนัส

การเริ่มต้นแบบขีเฉือยของ ContentProvider

หาก ContentProvider ทำการเริ่มต้นที่ช้า, ใช้กลไกการโหลดแบบขีเฉือย: สร้างโปรไวเดอร์ที่ส่งคืนข้อมูลทันทีและเริ่มการเริ่มต้นที่หนักผ่าน WorkManager โดยการหน่วงเวลา ซึ่งป้องกัน ANR ในการเริ่มต้นแอพ เมื่อระบบอ่อนไหวต่อความล่าช้ามากที่สุด

ตัวอย่างการใช้งาน BroadcastReceiver กับ goAsync ใน Android อย่างถูกต้อง:

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() เสมอสำหรับการประมวลผลที่นานกว่า 1 วินาที
  • Service — แทนที่ด้วย WorkManager หรือ CoroutineWorker ที่มีตัวจัดส่งเบื้องหลัง
  • ContentProvider — หลีกเลี่ยงเครือข่ายแลฐานข้อมูลใน onCreate, ใช้ lazy-init กับ WorkManager
  • เธรด UI — StrictMode กับ penaltyDeath ใน Debug, Firebase Performance สำหรับการตรวจสอบการผลิต

คำถามที่พบบ่อย

ทำไม ANR เกิดขึ้นใน Android แต่ไม่ใน iOS

Android ติดตามเวลาการประมวลผลเหตุการณ์บนเธรดหลักอย่างชัดเจนและแสดงกล่องโต้ตอบสนอง ANR iOS ใช้ Watchdog ซึ่งปิดแอพอย่างบังคับเมื่อมันค้างนานกว่า 10–20 วินาที ANR เป็นลักษณะของสถาปัตยกรรม Android ที่ส่วนประกอบหลายอย่าง (BroadcastReceiver, Service) มีการหมดเวลาที่เข้มงวด

วิธีค้นหา traces.txt บนอุปกรณ์ที่ไม่มี root

บน Android 11+ คุณสามารถรับ ANR dump ผ่าน adb shell dumpsys dropbox --print data_app_anr บน Android 10 และต่ำกว่า, ไม่สามารถเข้าถึง /data/anr/traces.txt ได้โดยไม่มีสิทธิผู้ใช้ระดับสูง ใช้ Firebase Crashlytics — มันจะรวบรวมรายงาน ANR โดยอัตโนมัติสำหรับ Android 11+

อัตรา ANR เท่าไรที่ถือว่ายอมรับได้

Google Play แนะนำอัตรา ANR ต่ำกว่า 0.5% — ไม่เกิน 5 ANR ต่อ 1000 เซสชั่น แอพที่มีอัตราเกิน 1% จะได้รับคำเตือนใน Google Play Console และอาจถูกซ่อนจากคำแนะนำ อย่างในอุดมคติ อัตรา ANR ควรต่ำกว่า 0.1%

coroutine สามารถทำให้เกิด ANR ได้หรือไม่

coroutine เองไม่ได้บล็อกเธรด แต่หากภายใน coroutine คุณเริ่มทำงาน runBlocking บนเธรดหลักหรือ coroutine ถูกเริ่มด้วย Dispatchers.Main และดำเนินการ CPU ที่ยาว — สิ่งนี้จะทำให้เกิด ANR ใช้ Dispatchers.IO สำหรับ I/O และ Dispatchers.Default สำหรับการคำนวณ

วิธีทดสอบ ANR ในโปรแกรมจำลอง

ใช้ Android Emulator ที่มีโปรไฟล์ “Slow Network” หรือเขียนการทดสอบที่เรียก Thread.sleep(6000) บนเธรดหลัก เริ่มแอผ่าน Debug และหลังจาก 5 วินาที คุณจะเห็นกล่องโต้ตอบสนอง ANR ตรวจสอบว่า logcat แสดงรายการ ANR พร้อมการติดตาม

สรุป

  • ANR — การแจ้งเตือนระบบใน Android เมื่อเธรดหลักถูกบล็อกนานกว่า 5 วินาทีหรือเกินกำหนดเวลาของคอมโพนันต์
  • กำหนดเวลา: BroadcastReceiver — 10 วินาที, Service — 20 วินาที, ContentProvider — 15 วินาที, UI — 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 เราจะให้คำแนะนำและเสนอวิธีแก้ปัญหาที่ดีที่สุดแก่คุณ

ปรึกษาโครงการ

อ่านเพิ่มเติม