Android异常处理的最佳实践?

85

如果我的应用程序崩溃,它会在几秒钟内停顿一下,然后Android会告诉我应用程序崩溃了并需要关闭。所以我考虑使用通用的方式捕获应用程序中的所有异常:

try {
    // ... 
} catch(Exception e) { 
    // ...
} 

制作一个新的Activity,解释应用程序崩溃并给用户提供发送带有错误详情电子邮件的机会,而不是因为Android而出现的延迟。是否有更好的方法来实现这一点,或者这样做是被不鼓励的?

更新:我正在使用启用ART的Nexus 5,并且没有注意到以前遇到的应用崩溃后的延迟(我最初谈论的“挂起”)。我认为由于现在一切都是本地代码,崩溃立即发生,并获得所有崩溃信息。也许Nexus 5只是快了:)无论如何,在未来的Android版本中(考虑到ART将成为Android L中的默认运行时),这可能不是一个问题。


1
点击链接查看相关的编程内容。 - CRUSADER
当应用程序崩溃时,活动将被销毁,因此没有办法自行处理崩溃。 - Raghunandan
@Raghunandan 是的,但如果崩溃是由于未处理的异常引起的,您可以使用通用的异常处理程序来防止它完全崩溃。 - ldam
@LoganDam 你最终解决问题了吗? - theblang
@mattblang,我已经有一段时间没有碰我的Android项目了,工作太忙了。不过可能很快就会重新进入Android世界。根据我所了解的情况,CRUSADER的选项似乎是最好的选择。 - ldam
3个回答

107

在这里,检查参考链接

在这里创建一个类,例如ExceptionHandler,它实现java.lang.Thread.UncaughtExceptionHandler..

在此类中,您将执行类似创建堆栈跟踪和准备上传错误报告等生命-saving的操作....

Now comes the important part i.e. How to catch that exception. Though it is very simple. Copy following line of code in your each Activity just after the call of super method in your overriden onCreate method.

Thread.setDefaultUncaughtExceptionHandler(new ExceptionHandler(this));

Your Activity may look something like this…

public class ForceClose extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        Thread.setDefaultUncaughtExceptionHandler(new ExceptionHandler(this));

        setContentView(R.layout.main);
    }
}

这是一个样例ExceptionHandler类:

public class ExceptionHandler implements Thread.UncaughtExceptionHandler {
  private static final String TAG = "ExceptionHandler";

  @Override
  public void uncaughtException(@NonNull Thread thread, @NonNull Throwable exception) {
    Log.e(TAG, "uncaughtException: " + "\n" + getErrorReport(exception));
    Log.i(TAG, getDeviceInfo());
    Log.i(TAG, getFirmwareInfo());

    stopTheApp();
  }

  private String getErrorReport(@NonNull Throwable exception) {
    ApplicationErrorReport.CrashInfo crashInfo = new ApplicationErrorReport.CrashInfo(exception);

    return "\nCAUSE OF ERROR\n" +
      crashInfo.stackTrace;
  }

  private String getDeviceInfo() {
    return
      "\nDEVICE INFORMATION\n" +
        "Brand: " +
        Build.BRAND +
        "\n" +
        "Device: " +
        Build.DEVICE +
        "\n" +
        "Model: " +
        Build.MODEL +
        "\n" +
        "Id: " +
        Build.ID +
        "\n" +
        "Product: " +
        Build.PRODUCT +
        "\n";
  }

  private String getFirmwareInfo() {
    return "\nFIRMWARE\n" +
      "SDK: " +
      Build.VERSION.SDK_INT +
      "\n" +
      "Release: " +
      Build.VERSION.RELEASE +
      "\n" +
      "Incremental: " +
      Build.VERSION.INCREMENTAL +
      "\n";
  }

  private void stopTheApp() {
    android.os.Process.killProcess(android.os.Process.myPid());
  }
}

你的示例活动没有实现UncaughtExceptionHandler :) 感谢您的答案,我下班后会尝试它。 - ldam
另外,Thread.setDefaultUncaughtExceptionHandler() 应该放在你的主/第一个活动中,以便它处理应用程序中的所有异常吗? - ldam
我说过,要创建一个类,可以使用ExceptionHandler实现java.lang.Thread.UncaughtExceptionHandler接口.... 然后在你的正常活动中添加上述代码行... 请参考上面提到的链接以获得更广泛的想法. - CRUSADER
@CRUSADER 感谢您提供的参考链接,它已经完美地起到了作用。 - Ahmad Arslan
8
或者只需在BaseActivity中添加这行代码,并在整个应用程序中使用该Activity的子类。 - W.K.S
有人真的在这之前成功地做到了吗?我发现在异常处理期间环境似乎不稳定,很难防止应用程序/代码崩溃或冻结。 - Sam

10

你可以使用通用的警示对话框来快速显示错误信息。 例如...

//******************************************
//some generic method
//******************************************
private void doStuff()
{       
    try
    {
        //do some stuff here
    }
    catch(Exception e)
    {
        messageBox("doStuff", e.getMessage());
    }
}


//*********************************************************
//generic dialog, takes in the method name and error message
//*********************************************************
private void messageBox(String method, String message)
{
    Log.d("EXCEPTION: " + method,  message);

    AlertDialog.Builder messageBox = new AlertDialog.Builder(this);
    messageBox.setTitle(method);
    messageBox.setMessage(message);
    messageBox.setCancelable(false);
    messageBox.setNeutralButton("OK", null);
    messageBox.show();
}

你也可以在这个方法中添加其他错误处理选项,比如打印堆栈跟踪信息(print stacktrace)。


在向用户显示错误消息之前,您可能应该先处理它。 - hyena

4

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接