Androidグローバルキャプチャ異常、appの優雅な崩壊

6754 ワード

このコードは実はプロジェクトが始まる前にネット上でcopyのので、今すでに出典が探し出せないで、だから厚かましい选択は自分のになりました
どのように優雅にappの崩壊を処理して、崩壊した後に弾いたあるプログラムの応答のないダイアログボックスを彼に取り除いて、彼に直接フラッシュバックさせて、とても牛が追い詰めているのではないでしょうか、ははは.あまり話さないで、コードをつけてください.
次の操作を行います.
アプリケーションのonCreateで初期化します.コードは次のとおりです.
  CrashHandler.getInstance().init(getApplicationContext());

次は完全なクラスです.
public class CrashHandler implements Thread.UncaughtExceptionHandler {
    public static final String TAG = "CrashHandler";

    // CrashHandler   
    private static CrashHandler INSTANCE = new CrashHandler();

    //     Context   
    private Context mContext;

    //       UncaughtException    
    private Thread.UncaughtExceptionHandler mDefaultHandler;

    //              
    private Map infos = new HashMap();

    //        ,           
    private DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");


    /**
     *        CrashHandler   
     */
    private CrashHandler() {
    }

    /**
     *    CrashHandler    ,    
     */
    public static CrashHandler getInstance() {
        return INSTANCE;
    }

    /**
     *    
     *
     * @param context
     */
    public void init(Context context) {
        mContext = context;

        //         UncaughtException    
        mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();

        //     CrashHandler          
        Thread.setDefaultUncaughtExceptionHandler(this);
    }

    /**
     *   UncaughtException             
     */
    @Override
    public void uncaughtException(Thread thread, Throwable ex) {
        if (!handleException(ex) && mDefaultHandler != null) {
            //                        
            mDefaultHandler.uncaughtException(thread, ex);
        } else {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            //     ,             
            android.os.Process.killProcess(android.os.Process.myPid());
            System.exit(1);


//            ex.printStackTrace();

            //       ,         
//            Intent intent = new Intent();
//            intent.setClass(mContext, MainActivity.class);
//            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
//            mContext.startActivity(intent);
//            android.os.Process.killProcess(android.os.Process.myPid());
        }
    }

    /**
     *        ,      ,              
     *
     * @param ex
     * @return true:          ;     false
     */
    private boolean handleException(Throwable ex) {
        if (ex == null) {
            return false;
        }
        //java util    logger
        //      logcat   err          ,   logger    
        Logger logger = Logger.getLogger("err");
        logger.log(Level.SEVERE, Thread.currentThread().getName(), ex);

        //    Toast                     ,      ,        
//        new Thread() {
//            @Override
//            public void run() {
//                Looper.prepare();
//                Toast.makeText(mContext, "   ,      ,    。", Toast.LENGTH_LONG).show();
//                Looper.loop();
//            }
//        }.start();

        //         
//        collectDeviceInfo(mContext);
        //       
//        saveCrashInfo2File(ex);
        return true;
    }

    /**
     *         
     *
     * @param ctx
     */
    public void collectDeviceInfo(Context ctx) {
        try {
            PackageManager pm = ctx.getPackageManager();
            PackageInfo pi = pm.getPackageInfo(ctx.getPackageName(), PackageManager.GET_ACTIVITIES);

            if (pi != null) {
                String versionName = pi.versionName == null ? "null" : pi.versionName;
                String versionCode = pi.versionCode + "";
                infos.put("versionName", versionName);
                infos.put("versionCode", versionCode);
            }
        } catch (PackageManager.NameNotFoundException e) {
            Log.e(TAG, "an error occured when collect package info", e);
        }

        Field[] fields = Build.class.getDeclaredFields();
        for (Field field : fields) {
            try {
                field.setAccessible(true);
                infos.put(field.getName(), field.get(null).toString());
                Log.d(TAG, field.getName() + " : " + field.get(null));
            } catch (Exception e) {
                Log.e(TAG, "an error occured when collect crash info", e);
            }
        }
    }

    /**
     *           
     * *
     *
     * @param ex
     * @return       ,            
     */
    private String saveCrashInfo2File(Throwable ex) {
        StringBuffer sb = new StringBuffer();
        for (Map.Entry entry : infos.entrySet()) {
            String key = entry.getKey();
            String value = entry.getValue();
            sb.append(key + "=" + value + "
"); } 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(); String result = writer.toString(); sb.append(result); try { long timestamp = System.currentTimeMillis(); String time = formatter.format(new Date()); String fileName = "crash-" + time + "-" + timestamp + ".log"; if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { String path = "/sdcard/crash/"; File dir = new File(path); if (!dir.exists()) { dir.mkdirs(); } FileOutputStream fos = new FileOutputStream(path + fileName); fos.write(sb.toString().getBytes()); fos.close(); } return fileName; } catch (Exception e) { Log.e(TAG, "an error occured while writing file...", e); } return null; } }

上のコードでは、私のプログラムがクラッシュした後、終了を選択したことがわかります.
もしあなたのメインインタフェースを再起動することを選択したら、クラッシュがメインインタフェースで発生したら、それはずっと再起動するのではないでしょうか.の
もう1つは異常をキャプチャした後、あまり処理していません.エラーのログをコンソールに印刷するだけです.
本格的なエラー収集はサードパーティが行い、エラーが多すぎるとサーバのリソースが消費されますが、サードパーティは異なります.
彼はサーバーの圧力を効果的に軽減することができ、インタフェースがはっきりしていて、エラーのヒントもあります.
ブロガーはbuglyと友盟の间违い収集を推荐して、すべて私が使ったので、感じはすべて悪くなくて、好きなのは波の関心を覚えています