2014-06-08 47 views
4

我想在没有任何第三方库的情况下处理未处理的异常。Android抓住未处理的异常并显示对话框

所以我写了一个代码。

活动:

@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.main); 
    Thread.setDefaultUncaughtExceptionHandler(new ReportHelper(this)); 
    throw new NullPointerException(); 
} 

我崩溃处理:

import android.app.AlertDialog; 
import android.content.Context; 
import android.content.DialogInterface; 
import android.os.Handler; 
import android.os.Looper; 
import android.os.Message; 
import android.os.MessageQueue; 
import android.widget.Toast; 

/** 
* Created by S-Shustikov on 08.06.14. 
*/ 
public class ReportHelper implements Thread.UncaughtExceptionHandler { 
    private final AlertDialog dialog; 
    private  Context  context; 

    public ReportHelper(Context context) { 
     this.context = context; 
     AlertDialog.Builder builder = new AlertDialog.Builder(context); 
     builder.setMessage("Application was stopped...") 
       .setPositiveButton("Report to developer about this problem.", new DialogInterface.OnClickListener() { 
        public void onClick(DialogInterface dialog, int id) { 

        } 
       }) 
       .setNegativeButton("Exit", new DialogInterface.OnClickListener() { 
        public void onClick(DialogInterface dialog, int id) { 
         // Not worked! 
         dialog.dismiss(); 
         System.exit(0); 
         android.os.Process.killProcess(android.os.Process.myPid()); 

        } 
       }); 

     dialog = builder.create(); 
    } 

    @Override 
    public void uncaughtException(Thread thread, Throwable ex) { 
     showToastInThread("OOPS!"); 
    } 

    public void showToastInThread(final String str){ 
     new Thread() { 
      @Override 
      public void run() { 
       Looper.prepare(); 
       Toast.makeText(context, "OOPS! Application crashed", Toast.LENGTH_SHORT).show(); 
       if(!dialog.isShowing()) 
        dialog.show(); 
       Looper.loop(); 

      } 
     }.start(); 
    } 
} 

当我启动应用程序,你看我扔NullPointerException异常。在我的处理逻辑中显示Toast,并显示对话框。但!对话单击无法正确处理。我的意思是onClick方法中的逻辑不起作用。什么问题和我如何解决这个问题?

+0

定义什么是不正确的?发生了什么以及您的onClick行为的预期行为是什么? –

+0

你期待什么,你看到了什么?即为什么你说'它不工作'? – ben75

+0

@ ben75我希望对话框将关闭,应用程序将完成按“退出”按钮。 –

回答

0

由于异常的UI线程出现:该线程的状态可能是意外

所以尽量简单,就是在点击处理程序:

.setNegativeButton("Exit", new DialogInterface.OnClickListener() { 
       public void onClick(DialogInterface dialog, int id) { 
        android.os.Process.killProcess(android.os.Process.myPid()); 

       } 
      }); 
+0

我试过了。没有效果。 –

2

this post,状态当调用setDefaultUncaughtExceptionHandler时,应用程序是未知的。这意味着您的onClick监听器可能不再活动。

为什么不使用这种方法:

@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    try { 
     setContentView(R.layout.main); 
     Thread.setDefaultUncaughtExceptionHandler(new ReportHelper(this)); 
     throw new NullPointerException(); 
    } catch (NullPointerException e) { 
     new ReportHelper(this); 
    } 
} 

,并删除ReportHelper实现Thread.UncaughtExceptionHandler接口。

您没有明确捕获异常的方法可以看作是anti-pattern

+0

但点击没有处理。我在调试中检查了这一点。 –

+0

确定更新了我的答案 –

+1

如果我删除我的ReportHelper,我将得到一个编译错误,因为'Thread.setDefaultUncaughtExceptionHandler'传递实现'Thread.UncaughtExceptionHandler'的参数。我希望你错过了这个。 –

5

在我的情况,我在线程的run函数移动AlertDialog.Builder这样的:

public void showToastInThread(final String str){ 
    new Thread() { 
     @Override 
     public void run() { 
      Looper.prepare(); 

      AlertDialog.Builder builder = new AlertDialog.Builder(context); 
      builder.setMessage("Application was stopped...") 
      .setPositiveButton("Report to developer about this problem.", new DialogInterface.OnClickListener() { 
       public void onClick(DialogInterface dialog, int id) { 

       } 
      }) 
      .setNegativeButton("Exit", new DialogInterface.OnClickListener() { 
       public void onClick(DialogInterface dialog, int id) { 
        // Not worked! 
        dialog.dismiss(); 
        System.exit(0); 
        android.os.Process.killProcess(android.os.Process.myPid()); 

       } 
      }); 

      dialog = builder.create(); 


      Toast.makeText(context, "OOPS! Application crashed", Toast.LENGTH_SHORT).show(); 
      if(!dialog.isShowing()) 
       dialog.show(); 
      Looper.loop(); 

     } 
    }.start(); 
} 

,所有的事情工作完美。

希望这对你有所帮助。

+0

你确定你一次处理崩溃行为吗?因为我抓到2-3个例外。 –

+0

当第一个异常发生时,我看到alertdialog和关闭按钮侦听器,杀死我的应用程序。你有2-3个例外意味着什么? –

+0

我的意思是ARM发送给我们的异常处理程序2-3次'uncaughtException(Thread thread,Throwable ex)' –