首页 文章

在ANR事件之后重新启动应用程序的问题

提问于
浏览
0

我使用这个GitHub repo在我的应用程序中实现了一个ANR看门狗 . 监视程序监视UI线程,如果它被阻止超过10秒,则重新启动应用程序 . 我的问题是它重新启动应用程序两次,从而弄乱了我的所有逻辑 .

这是我对WatchDog的实现:

public class ANRWatchdog extends Thread {

private final Handler uiHandler = new Handler(Looper.getMainLooper());
private int count = 0; //
private static final int DEFAULT_WAIT_TIME = 10000; // in milliseconds
private volatile boolean anr = false;
private Context context;

public ANRWatchdog(Context context) {
    super();
    this.context = context;
}

private final Runnable counter = () -> count = (count + 1) % Integer.MAX_VALUE;

@Override
public void run() {
    setName("WatchDog");
    int lastCount;
    while (!isInterrupted()) {
        if ( anr){
            anr = false;
            return;
        }
        lastCount = count;
        uiHandler.post(counter);
        try {
            Thread.sleep(DEFAULT_WAIT_TIME);
        } catch (InterruptedException e) {
            Log.e("WatchDog",
                    "Error while making the ANR thread sleep" + e);
            return;
        }
        if (count == lastCount) {// means the value hasn't been incremented. UI thread has been blocked
            anr = true;
            Log.d("WatchDog", "Count hasn't incremented. This means ANR. Will restart the app. Thread Id : " +
                    android.os.Process.getThreadPriority(android.os.Process.myTid()));
            uiHandler.removeCallbacks(counter, null);
            uiHandler.removeCallbacksAndMessages(null);
            ANRSharedPrefs.storeANR(context, true, SystemClock.elapsedRealtime());
            ANRError error = ANRError.NewMainOnly();
            Log.e("WatchDog", "" + error);
            Log.d("WatchDog", "Now restarting the app");
            RestartAppUtil.restartApp(context);
            return;
        }
    }
}
}

以下是看门狗的启动方式

public class FileLogger extends Application {


ANRWatchDog watchDog = new ANRWatchDog(this);

/**
 * Called when the application is starting, before any activity, service, or receiver objects (excluding content providers) have been created.
 */
@Override
public void onCreate() {
    super.onCreate();
    Log.i(TAG, "Now launching Android Application : " + BuildConfig.VERSION_NAME);
    File logFile = new File(ExternalStoragePath.getExternalCardPath(getApplicationContext()), "log.txt");
    try {
        String cmd = "logcat -v time -f " + logFile.getPath() + " TAG1:I TAG2:D TAG3:E *:S";
        Runtime.getRuntime().exec(cmd);
    } catch (IOException e) {
        Log.e(TAG, "Exception during writing to log " + e);
    }
    watchDog.start();
}

}

这是我如何重新启动应用程序,即RestartUtil

public static void restartApp(Context context){
    context.stopService(new Intent(context, Service.class));
    Intent mStartActivity = new Intent(context, MainActivity.class);
    mStartActivity.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
    mStartActivity.putExtra(KeyConstants.ANR, true);
    int mPendingIntentId = 123456;
    PendingIntent mPendingIntent = PendingIntent.getActivity(context, mPendingIntentId,    mStartActivity, PendingIntent.FLAG_CANCEL_CURRENT);
    AlarmManager mgr = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
    mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 100, mPendingIntent);
    Runtime.getRuntime().exit(0);
}

此代码有效,应用程序重新启动 .

我正在使用无限while循环在其中一个活动中模拟ANR . 当我这样做时,这就是日志中发生的事情

10-17 13:30:08.221 19588-19608/com.company.project D/TAG1 Count hasn't incremented. This means ANR. Will restart the app. Thread Id : 0
10-17 13:30:08.221 19588-19608/com.company.project D/TAG1 Storing the ANR time : 617417608
10-17 13:30:08.231 19588-19608/com.company.project D/TAG1 Now restarting the app
10-17 13:30:18.411 20333-20353/com.company.project D/TAG1 Count hasn't incremented. This means ANR. Will restart the app. Thread Id : 0
10-17 13:30:18.411 20333-20353/com.company.project D/TAG1 Storing the ANR time : 617427797
10-17 13:30:18.421 20333-20353/com.company.project D/TAG1 Now restarting the app
10-17 13:30:18.791 20362-20362/? D/TAG1: Getting the value of ANR time 617427797
10-17 13:30:18.791 20362-20362/? D/TAG1: Received intent in main screen
10-17 13:30:20.171 20362-20362/com.company.project D/TAG1 Getting the value of ANR time
10-17 13:30:20.171 20362-20362/com.company.project D/TAG1 Received intent in main screen 617427797

主要活动接收两个意图,而不是一个意图 . 另外,我不明白的存在

/? D/TAG1

在日志中

任何人都可以帮我弄清楚,为什么主屏幕有两个意图?

1 回答

  • 0

    所以我终于能够解决这个问题 .

    在我的情况下,System.exit()还不够 . 我不得不在导致ANR的活动上调用finish()或finishAffinity() .

    所以在

    onCreate()
    

    每个活动的方法,我在FileLogger中注册活动的实例,就像这样

    FileLogger.setActivityName(this);
    

    这就是FileLogger的修改方式

    /**to register the activity)
    public static void setActivityName(Activity activityName){
        anrActivity = activityName;
    }
    
    /**This method is called by RestartUtil method to restart the app**/
    public static void kill(){
        if ( anrActivity != null) {
            anrActivity.finish();
            anrActivity.finishAffinity();
        }
        android.os.Process.killProcess(android.os.Process.myPid());
    }
    

相关问题