Android ANR 知多少


極力推薦文章:歡迎收藏
Android 干貨分享

閱讀五分鍾,每日十點,和您一起終身學習,這里是程序員Android

ANR(Application Not Responding ) 應用無響應的簡稱,是為了在 APP卡死時,用戶 可以強制退出APP的選擇,從而避免卡機無響應問題,這是Android 系統的一種自我保護機制。

通過本篇閱讀,您將學習到以下內容

  1. 什么是ANR
  2. ANR的類型
  3. ANR 產生的原因
  4. 如何分析解決 ANR問題
  5. ANR 問題分析解決建議
  6. MTK 平台 ANR問題分析

1. 什么是ANR

Android 中,應用程序響應由Activity ManagerWindow Manager 系統服務進行監視。ANR(Application Not Responding ),則是Android的一種自我保護措施,當主線程出現卡頓時候,Android 系統會給用戶一個彈出提示,讓用戶手動選擇繼續等待還是強制關閉此APP

當Android檢測到以下情況之一時,Android將顯示特定應用程序的ANR對話框,比如以下三種情況下ANR 將經常發生:

  1. UI Thread 超過 5 s 沒有響應
  2. Broadcast 廣播超過10 s沒響應
  3. Service 服務超過 20s 沒響應
    因此,為避免ANR 發生,請不要在主線程中進行耗時操作,耗時操作請盡量在子線程中運行。
  4. 發生ANR 截圖 如下:

ANR Dialog 舉例

2. ANR的類型

ANR Android 手機中很常見,按其相應類型可以分為以下 常見 三種類型。

ANR類型:

  1. 按鍵響應分發超時(Key Dispatch Timeout)
    默認 5 s,超過則會出現ANR。
  2. 廣播超時(Broadcast Timeout)
    默認 10 s,超過則會出現ANR。
  3. 服務超時(Service Timeout)
    默認 20 s,超過則會出現ANR。

3. ANR 產生的原因

Android系統中,APP 通常運行在一個UI Thread 或者叫MainThread里。並且Android中只有一個MainThreadMain Message QueueMainThread主要用於UI的繪制、事件響應,監聽與接收事件處理等功能。Main Message Queue 主要存放用戶要處理消息的隊列,主線程MainThread從消息隊列Main Message Queue中取消息Message后,盡快分發下去,一旦某條消息分發超時,則ANR可能發生。

因此,當ANR 發生時,我們要分析ANR 產生的原因,也就是查找消息處理不及時的原因。例如可以從以下幾個疑問點進行分析:

    1. 為什么 APP 不能獲取CPU 時間片?
    1. APP 是否是等待一些沒能及時處理的事件完成?
  • 3 . 消息處理流程是不是太復雜?

4. 如何分析解決 ANR問題

在分析ANR時有一些常見的模式可供選擇:

  1. APP正在主線程上進行緩慢的I/O操作。
  2. APP正在主線程中進行很復雜的計算操作
  3. 主線程正在對另一個進程執行同步Binder程序調用,但另一個進程需要很長時間才能返回結果。
  4. 主線程在等待另一個正在長時間執行塊操作的子線程時被阻塞。
  5. 主線程因為另一個線程死鎖,無論是Bind調用還是主線程調用,都不能讓主線程等待很久,更不能在主線程中進行復雜的計算。

知道產生ANR的原因,那么如何避免ANR 問題呢?

a.Strict mode

使用StrictMode可以幫助您在開發應用程序時在主線程上發現意外的I / O操作。 您可以在applicationactivity使用StrictMode

b.關閉 ANR Dialog 提示

查看方法ANR控制的方法:
設置---- 開發者選項---顯示所有ANR

注意 :
如沒有開發者選項,請進入設置---關於手機--- 多次連擊 版本號 即可打開隱藏的開發者選項的item

后台 app ANR 開關

c.Traceview

Traceview獲取正在運行的應用程序的跟蹤信息,分析此traces.txt文件 可以推測出主線程在忙於某些事情。

traces 文件通常保存在/data/anr/traces.txt下,你可以直接用adb cat 查看,或者 adb pull 出來都可以。

  • 直接查看trace 信息

個人不太建議

adb root
adb shell
cat /data/anr/traces.txt

  • pull trace 文件到桌面

建議使用此方法

adb root
adb remount
adb pull /data/anr/traces.txt C:\Users\Administrator\Desktop\新建文件夾

pull traces 文件到桌面

5. ANR 問題分析解決建議

分析查看ANR原因,接着解決ANR問題。

  1. 耗時操作
    請放在工作現場中進行,可以使用Handler、AsyncTask 等。

  2. IO 操作
    (比如:網絡操作、存儲操作等)也是引起ANR的常見因素。強烈建議在工作線程中進行。

  3. 程序鎖競爭

某些情況,ANR產生的原因不是直接因為在主線程中產生的。 比如: 工作線程對某個資源等上鎖,恰好此時,主線程需要此資源,如等待超時,則此時ANR可能發生。

  1. 死鎖

當主線程因為請求一個其他線程正在持有的資源而進入等待狀態時,ANR可能會發生。

  1. 廣播接收慢

應用程序可以通過廣播接收器響應廣播消息,例如啟用或禁用飛行模式或更改連接狀態。 當應用程序花費太長時間來處理廣播消息時,理論上超過10s 未處理完成,ANR可能會發生。

廣播 ANR發生在下列情況下:

  1. onReceive() 方法長時間未執行完畢。

盡量避免在onReceive() 中進行耗時操作。

  1. 廣播接收者調用goAsync()方法並且未能在PendingResult對象上調用finish()

如要處理的廣播內容較多,請使用IntentService 進行處理。

比如下面例子:

  • 不建議在onReceive 方法中進行耗時操作,超過10s 未處理,會引起ANR

不建議在onReceive 方法中進行耗時操作,超過10s 未處理,會引起ANR

  • 建議使用IntentService ,避免ANR發生

IntentService 避免處理廣播消息過多引起ANR

您的廣播接收機可以使用goAsync()來通知系統需要更多的時間來處理消息。 但是,您應該在PendingResult對象上調用finish()。 以下示例顯示如何調用finish()以讓系統回收廣播接收器並避免ANR:

goAsync()---finish 獲取更多廣播響應時間

6. MTK 平台 ANR問題分析

前提,抓取一份ANR MTK log

1.event_log 中 搜索關鍵字 am_anr或者anr,分析並查看ANR原因

event_log 分析 ANR原因

2. main_log中 搜索關鍵字Application Not Responding或者anr ,分析並查看ANR原因。

main_log 中分析ANR 原因

3. MTK ANR 策略建議

MTK 官方總結圖

MTK ANR 分析步驟

MTK ANR  Debug SOP

MTK ANR  Debug SOP

常見ANR 舉例分析如下:

Main Thread is idle

Stuck in IO

Main Thread Waiting a lock

Wait Binder Transaction

Main Thread Query DB

至此,本篇已結束,如有不對的地方,歡迎您的建議與指正。同時期待您的關注,感謝您的閱讀,謝謝!

微信關注公眾號:  程序員Android,領福利


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM