在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
保存到数据库模型类。
问题
每次未处理的异常发生时(不要紧它是什么)在活动二奇怪的事情发生了:
- 的
logError()
方法被调用一次以上,有时甚至8-10倍。看着日志,我可以看到他们有几乎相同的时间戳。 - 消息“XXX申请已停止”显示在设备屏幕(这是好的),但关闭它后应用程序挂,我需要强制停止从应用程序设置屏幕。
灿任何人能帮助我吗?还是有解决问题的更好的办法?
在你的处理器
我设法最后用的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);
}
});
}
感谢您的答案!这部分解决了第一个问题。如果没有这一行,默认处理程序不会被调用,所以AndroidOS不会显示“应用程序已停止”消息,并且不会重新启动应用程序。结果我们在问题2中。 – jdabrowski
你知道有框架,会为你做这个吧? Crashlytics,Acra,Bugsense等 –
执行任何这些支持在同步期间将错误发送到自定义服务器应用程序?我需要澄清一点,我需要将错误存储在数据库中以备以后同步,因为即使脱机时,应用程序也会记录错误以供稍后同步。 – jdabrowski
所有这些都会缓存发生的错误,并在存在活动的网络连接时发送它们。我相信,ACRA(也许其他人,我不知道)会支持发送到您自己的定制服务器。 –