Android 捕获未知异常并提交给服务器

时间:2022-09-17 20:34:23

在Android应用中,即便应用已经投放市场,但有时也会遇到一些未知的异常,此时如果能够获得用户的反馈信息,那么对于我们应用的开发是一个很好的帮助

为了实现这样的效果,我们需要做如下工作

 写一个类实现UncaughtExceptionHandler接口,重写uncaughtException方法

功能描述:当应用出现了未知异常,应用强制退出,应用再次启动时,提示用户是否将错误信息反馈给开发者



public class MyUncaughtExceptionHandler implements UncaughtExceptionHandler {

    private static final String TAG = "MyUncaughtExceptionHandler";

    // 将错误信息保存到sharepreference中
    private static SharedPreferences bugPreferences;
    private static SharedPreferences.Editor bugEditor;

    private static Context mContext;
    private static PackageInfo packageInfo;
    private UncaughtExceptionHandler defaultUncaughtExceptionHandler;
    private static HandleProgressDialog progressDialog;

    // 保存错误原因的字段
    private static String bugExistStr = "";

    private static Handler handler = new Handler() {

        @Override
        public void handleMessage(Message msg) {

            progressDialog.dismiss();

        }
    };

    public MyUncaughtExceptionHandler(Context context) {

        try {
            mContext = context;
            packageInfo = context.getPackageManager().getPackageInfo(
                    context.getPackageName(), 0);
            bugPreferences = context.getSharedPreferences("bug", 0);
            bugEditor = bugPreferences.edit();
            defaultUncaughtExceptionHandler = Thread
                    .getDefaultUncaughtExceptionHandler();
        } catch (NameNotFoundException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    // 当异常发生时,会调用这个方法
    public void uncaughtException(Thread th, Throwable t) {
        try {
            // 保存bug
            saveBugText(t);
            defaultUncaughtExceptionHandler.uncaughtException(th, t);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    private void saveBugText(Throwable ex) throws FileNotFoundException {

        Writer writer = new StringWriter();
        PrintWriter printWriter = new PrintWriter(writer);
        ex.printStackTrace(printWriter);
        Throwable cause = ex.getCause();
        while (cause != null) {
            cause.printStackTrace(printWriter);
            cause = cause.getCause();
        }
        printWriter.close();
        bugEditor.putString("bugText", writer.toString());
        bugEditor.commit();

    }

    // 下次开启应用的时候,如果上次产生了未知异常则显示对话框应用与用户反馈
    public static void showBugReportDialog(final Context context) {

        bugExistStr = context.getSharedPreferences("bug", 0).getString(
                "bugText", "");
        if (bugExistStr != null && !bugExistStr.equals("")) {
            AlertDialog.Builder builder = new AlertDialog.Builder(context);
            builder.setTitle(R.string.bug_report);
            builder.setMessage(R.string.whether_report_to_developer);
            builder.setNegativeButton(R.string.cancel, new OnClickListener() {
                public void onClick(DialogInterface dialog, int which) {

                    finish(dialog);
                }
            });
            builder.setPositiveButton(R.string.send, new OnClickListener() {
                public void onClick(DialogInterface dialog, int which) {
                    // 提交bug到服务器
                    postBugReportInBackground(context);

                    dialog.dismiss();
                }
            });
            AlertDialog dialog = builder.create();
            dialog.show();
        }
    }

    private static void postBugReportInBackground(final Context context) {

        progressDialog = new HandleProgressDialog(context);
        progressDialog.show();
        new Thread(new Runnable() {
            public void run() {
                postBugReport();
                // 将之前的bug信息清除掉
                if (bugExistStr != null) {
                    bugEditor.putString("bugText", "");
                    bugEditor.commit();
                }

                handler.sendEmptyMessage(0);
            }
        }).start();
    }

    // -----------------------------------------------------------------
    /**
     * Send Bug Report.
     */
    // -----------------------------------------------------------------
    private static void postBugReport() {
        List<NameValuePair> nvps = new ArrayList<NameValuePair>();
        nvps.add(new BasicNameValuePair("device", Build.DEVICE));
        nvps.add(new BasicNameValuePair("model", Build.MODEL));
        nvps.add(new BasicNameValuePair("sdk-version", Build.VERSION.SDK));
        nvps.add(new BasicNameValuePair("apk-version", packageInfo.versionName));
        nvps.add(new BasicNameValuePair("bug", bugExistStr));

        try {
            HttpPost httpPost = new HttpPost(Constants.BaseUrl
                    + "c=main&a=androidCrash");
            httpPost.setEntity(new UrlEncodedFormEntity(nvps, HTTP.UTF_8));
            DefaultHttpClient httpClient = new DefaultHttpClient();
            HttpParams params = httpClient.getParams();
            HttpConnectionParams.setConnectionTimeout(params, 5000);
            HttpConnectionParams.setSoTimeout(params, 5000);
            httpClient.execute(httpPost);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static void finish(DialogInterface dialog) {
        if (bugExistStr != null) {
            bugEditor.putString("bugText", "");
            bugEditor.commit();
        }
        dialog.dismiss();
    }

}


在需要捕捉异常的地方调用

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

        setContentView(R.layout.activity_main);
        appApplication = (APPApplication) getApplication();
        appApplication.activites.add(this);
        initViews();

        Thread.setDefaultUncaughtExceptionHandler(new MyUncaughtExceptionHandler(
                MainActivity.this));
        MyUncaughtExceptionHandler.showBugReportDialog(this);
    }