android应用检测anr的方法

时间:2025-01-25 07:00:55

android not response
anr 看到一些博客说android产生anr,ui线程阻塞5秒,广播阻塞10秒,service阻塞20秒都会产生anr异常。
而且anr异常会由系统捕捉,保存到文件中,好像是data/anr/.具体哪里我也不知道。在程序中捕捉异常
可以用android的异常类UncaughtExceptionHandler,在base类中使用。检测不到anr异常。
但是如果在程序中检测anr异常怎么检测呢?
看到网上有人提出的思路,开启线程给ui线程发送一个计数器,并且让计数器+1,保存上一次计数器。线程休眠5秒。如果两次计数器
的值不想等,则没有阻塞。如果相等主线程阻塞。
但是,为了检测界面,不能每一个activity,或者fragment都开启一个访问ui的线程吧。
后来,了解到service也同属于ui线程。
可以开启service后台服务,然后访问ui线程,采用上面的方法来探测anr产生。
如果产生anr,想读取anr文件,手机需要root的。但是至少可以检测出,用户在使用的时候发生了anr。但是至于在何处产生anr。
还有待考究。

但是,这种方法有一个弊端,就是如果你程序还没启动service,anr就已经发生了,那就检测不出来了。必须在发生anr前去
开启service。
下面是代码:

public class ANRService extends Service {
    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        ("gac","ANRService");
        exception();
    }
    private int lasttick,mTick;//两次计数器的值
    private Handler mHandler = new Handler();
    private boolean flag = true;
    private void exception(){

        new Thread(new Runnable() {
            @Override
            public void run() {
                while(flag){
                    lasttick = mTick;
                    (tickerRunnable);//向主线程发送消息 计数器值+1
                    try {
                        (5000);
                    } catch (InterruptedException e) {
                        ();
                    }
                    if(mTick == lasttick){
                        flag = false;
                        ("gac","anr happned in here");
                        handleAnrError();
                    }
                }
            }
        }).start();
    }

    //发生anr的时候,在此处写逻辑
    private void handleAnrError(){

    }
    private final Runnable tickerRunnable = new Runnable() {
        @Override public void run() {
            mTick = (mTick + 1) % 10;
        }
    };
}