在Android中记录未处理的异常活动

问题描述:

我创建了一个类BaseActivity extends AppCompatActivity,我的Android应用中的所有Activites都从中继承。在Android中记录未处理的异常活动

在这个类中,我打算捕获所有未处理的异常,所以我可以将它们写入本地SQLite数据库,以便以后检查/发送到远程服务器。

下面附上全班代码:

public class BaseActivity extends AppCompatActivity { 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 

    final Thread.UncaughtExceptionHandler defaultHandler = Thread.getDefaultUncaughtExceptionHandler(); 

    Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() { 
     @Override 
     public void uncaughtException(Thread paramThread, Throwable paramThrowable) { 
      Log.e("Uncaught Exception", paramThrowable.getMessage()); 
      logError(paramThrowable); 
      defaultHandler.uncaughtException(paramThread, paramThrowable); 
     } 
    }); 
} 

private void logError(final Throwable paramThrowable){ 
    try { 
     ApplicationError error = new ApplicationError(); 

     String stackTrace = ""; 
     for (int i = 0; i < paramThrowable.getStackTrace().length; i++) { 
      stackTrace += paramThrowable.getStackTrace()[i].toString() + "\n"; 
     } 

     Throwable tmp = paramThrowable; 
     int j = 0; 
     while ((tmp = tmp.getCause()) != null && j < 5) { 
      j++; 
      stackTrace += "Coused by:\n"; 
      for (int i = 0; i < tmp.getStackTrace().length; i++) { 
       stackTrace += tmp.getStackTrace()[i].toString() + "\n"; 
      } 
     } 

     Log.e("Saving error...", ""); 

     String deviceInfo = ""; 
     deviceInfo += "OS version: " + System.getProperty("os.version") + "\n"; 
     deviceInfo += "API level: " + Build.VERSION.SDK_INT + "\n"; 
     deviceInfo += "Manufacturer: " + Build.MANUFACTURER + "\n"; 
     deviceInfo += "Device: " + Build.DEVICE + "\n"; 
     deviceInfo += "Model: " + Build.MODEL + "\n"; 
     deviceInfo += "Product: " + Build.PRODUCT + "\n"; 

     error.mDeviceInfo = deviceInfo; 
     error.mErrorMessage = paramThrowable.getMessage(); 
     error.mStackTrace = stackTrace; 

     error.save(); 

     Log.e("Saved error:", error.mErrorMessage + "\n" + error.mStackTrace); 
    }catch(Exception e){ 

    } 
} 

} 

对于澄清:ApplicationError只是它处理使用DBFlow保存到数据库模型类。

问题

每次未处理的异常发生时(不要紧它是什么)在活动二奇怪的事情发生了:

  1. logError()方法被调用一次以上,有时甚至8-10倍。看着日志,我可以看到他们有几乎相同的时间戳。
  2. 消息“XXX申请已停止”显示在设备屏幕(这是好的),但关闭它后应用程序挂,我需要强制停止从应用程序设置屏幕。

灿任何人能帮助我吗?还是有解决问题的更好的办法?

在你的处理器
+1

你知道有框架,会为你做这个吧? Crashlytics,Acra,Bugsense等 –

+0

执行任何这些支持在同步期间将错误发送到自定义服务器应用程序?我需要澄清一点,我需要将错误存储在数据库中以备以后同步,因为即使脱机时,应用程序也会记录错误以供稍后同步。 – jdabrowski

+0

所有这些都会缓存发生的错误,并在存在活动的网络连接时发送它们。我相信,ACRA(也许其他人,我不知道)会支持发送到您自己的定制服务器。 –

我设法最后用的AAG's answer帮助解决这个问题。

@AAG你是对的,每次调用任何活动中的onCreate()方法时都会添加异常处理程序。

@AAG但是你错了没有使用defaultHandler。我必须使用它,以便Android正确处理应用程序崩溃。

感谢您的帮助!

这是固定的代码:

public class BaseActivity extends AppCompatActivity { 

    public static Context applicationContext = null; 
    public static Thread.UncaughtExceptionHandler defaultHandler = null; 
    public static Thread.UncaughtExceptionHandler exceptionHandler = null; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 

     if(defaultHandler == null){ 
      defaultHandler = Thread.getDefaultUncaughtExceptionHandler(); 
     } 

     if(applicationContext == null){ 
      applicationContext = getApplicationContext(); 
     } 

     if(exceptionHandler == null){ 
      exceptionHandler = new Thread.UncaughtExceptionHandler() { 
       @Override 
       public void uncaughtException(Thread paramThread, Throwable paramThrowable) { 
        Log.e("Uncaught Exception", paramThrowable.getMessage()); 
        logError(paramThrowable); 
        defaultHandler.uncaughtException(paramThread, paramThrowable); 

       } 
      }; 

      Thread.setDefaultUncaughtExceptionHandler(exceptionHandler); 
     } 
    } 

    private static void logError(final Throwable paramThrowable){ 
     try { 
      ApplicationError error = new ApplicationError(); 

      String stackTrace = ""; 
      for (int i = 0; i < paramThrowable.getStackTrace().length; i++) { 
       stackTrace += paramThrowable.getStackTrace()[i].toString() + "\n"; 
      } 

      Log.e("Saving error...", ""); 

      Throwable tmp = paramThrowable; 
      int j = 0; 
      while ((tmp = tmp.getCause()) != null && j < 5) { 
       j++; 
       stackTrace += "Coused by:\n"; 
       for (int i = 0; i < tmp.getStackTrace().length; i++) { 
        stackTrace += tmp.getStackTrace()[i].toString() + "\n"; 
       } 
      } 

      String deviceInfo = ""; 
      deviceInfo += "OS version: " + System.getProperty("os.version") + "\n"; 
      deviceInfo += "API level: " + Build.VERSION.SDK_INT + "\n"; 
      deviceInfo += "Manufacturer: " + Build.MANUFACTURER + "\n"; 
      deviceInfo += "Device: " + Build.DEVICE + "\n"; 
      deviceInfo += "Model: " + Build.MODEL + "\n"; 
      deviceInfo += "Product: " + Build.PRODUCT + "\n"; 

      error.mDeviceInfo = deviceInfo; 
      error.mErrorMessage = paramThrowable.getMessage(); 
      error.mStackTrace = stackTrace; 

      error.save(); 

      Log.e("Saved error:", error.mErrorMessage + "\n" + error.mStackTrace); 
     }catch(Exception e){ 

     } 
    } 

} 

,您呼叫

defaultHandler.uncaughtException(paramThread, paramThrowable);

你不应该这样做。每次的onCreate是调用(根据您的应用程序的使用情况,这可能很多) - 您正在创建一个调用旧处理程序的处理程序。所以第三次onCreate是调用,你将调用在第二次调用时创建的处理程序,然后调用在第一次调用时创建的处理程序。

删除此之后,您的onCreate方法现在应该是:

protected void onCreate(Bundle savedInstanceState) { 
super.onCreate(savedInstanceState); 


    Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() { 
     @Override 
     public void uncaughtException(Thread paramThread, Throwable paramThrowable) { 
      Log.e("Uncaught Exception", paramThrowable.getMessage()); 
      logError(paramThrowable); 
     } 
    }); 

}

+0

感谢您的答案!这部分解决了第一个问题。如果没有这一行,默认处理程序不会被调用,所以AndroidOS不会显示“应用程序已停止”消息,并且不会重新启动应用程序。结果我们在问题2中。 – jdabrowski