Android應用捕獲全局異常自定義處理


 

[2016-06-30]最新的全局異常處理DRCrashHandler已經集成在DR_support_lib庫中

具體請看: https://coding.net/u/wrcold520/p/DR_support_lib/git/tree/master

[2016-06-28] 1 增加log4j的支持
[2016-06-28] 2 增加全局異常處理(可自定義程序崩潰提示消息,自定義發送錯誤報告到服務器)
[2016-06-28] 3 增加兩種應用退出方法:① appExit,結束掉所有Acitivity的生命周期,正常退出;② appKill,結束掉所有Acitivity的生命周期,殺掉程序進程后退出。
[2016-06-29] 4 增加透明狀態欄和導航欄(默認開啟,藍色背景)

在Android程序中,我們通常會在可能發生錯誤的地方加上try {} catch (Exception e) {}語句來捕獲異常,但是,我們無法保證程序就一定不會出錯,比如,你玩Android游戲的過程中經常會碰到黑屏或者直接退出的情況,那么這些異常就應該是沒有被捕獲到(一般獲取到都會提示用戶錯誤,並提示用戶是否將錯誤上傳至服務器),那么現在我們來看下如何捕獲全局異常,然后自己處理。

1、新建DRCrashHandler.java(這是一個抽象類,我放在了DR_supprot_lib庫中,以便以后再寫應用程序的時候直接使用,里面用到了一些變量是DRConstants類中的,這是一個常量類,用來定義常用的常量的)

默認Toast彈窗提示用戶(消息可以自定義)

package cn.dr.lib.app;

import java.io.File;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.lang.Thread.UncaughtExceptionHandler;
import java.lang.reflect.Field;
import java.util.Date;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;

import org.apache.log4j.Logger;

import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.Build;
import android.os.Looper;
import android.widget.Toast;
import cn.dr.lib.common.DRConstants;
import cn.dr.lib.utils.DateUtil;
import cn.dr.lib.utils.FileUtil;

/**
 * DarkRanger的全局異常處理類
 * 
 * @author DarkRanger
 *
 */
public abstract class DRCrashHandler implements UncaughtExceptionHandler {

    /** log4j **/
    private static final Logger log = Logger.getLogger(DRCrashHandler.class);

    /** 系統默認的UncaughtException處理類 **/
    private Thread.UncaughtExceptionHandler mDefaultHandler;

    /** 程序context **/
    private DRApplication mContext;

    /** 存儲設備信息和異常信息 **/
    private Map<String, String> mInfos = new HashMap<String, String>();

    /** 程序出錯提示信息 **/
    private String mDRTipMsg = "抱歉,程序異常,3s后退出!";

    /** 設置crash文件位置 **/
    private String mDRCrashFilePath = DRConstants.CRASH_FILE_PATH;

    /** 生成的log文件 **/
    private File logFile;

    /** 生成的crash文件 **/
    private File crashFile;

    /**
     * 初始化
     * 
     * @param context
     */
    public void init(DRApplication context) {
        log.info("DRCrashHandler is Ready For Application! ");

        // 1、上下文
        mContext = context;

        // 2、獲取系統默認的UncaughtException處理器
        mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();

        // 3、初始化參數
        initParams();

        // 4、設置當前CrashHandler為默認處理異常類
        Thread.setDefaultUncaughtExceptionHandler(this);
    }

    /**
     * 3.1 初始化參數 <br/>
     * <br/>
     * 
     * {@link #setTipMsg(String)} setTipMsg("this is crash tip msg!!!"); <br/>
     * {@link #setCrashFilePath(String)}
     * setCrashFilePath(Constants.CRASH_FILE_PATH); <br/>
     * <br/>
     * 
     * 如果想使用自己的CrashHandler,則復寫initParams()方,然后設置參數<br/>
     * 
     * <code>
     * public class MyCrashHandler extends DRCrashHandler {<br/>
     *        private static final Logger log = Logger.getLogger(MyCrashHandler.class);<br/>
     *    
     *        &#64;Override<br/>
     *        public void initParams() {<br/>
     *            log.trace("MyCrashHandler: initParams()");<br/>
     *    
     *            setDRTipMsg("MyCrashHandler tip msg!!!");<br/>
     *            setDRCrashFilePath(Constants.CRASH_FILE_PATH);<br/>
     *        }<br/>
     *    }<br/>
     * </code>
     */
    public abstract void initParams();

    @Override
    public void uncaughtException(Thread thread, Throwable ex) {
        log.info("DRCrashHandler dispatcher uncaughtException! ");

        if (mDefaultHandler != null && !handlerException(ex)) {
            mDefaultHandler.uncaughtException(thread, ex);
        } else {
            // 程序休眠3s后退出
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            ((DRApplication) mContext.getApplicationContext()).appExit();
        }

    }

    /**
     * 5、處理異常<br>
     * <br>
     * 
     * 5.1 收集設備參數信息<br>
     * 5.2 彈出窗口提示信息<br>
     * 5.3 保存log和crash到文件<br>
     * 5.4 發送log和crash到服務器<br>
     * 
     * @param ex
     * @return 是否處理了異常
     */
    protected boolean handlerException(Throwable ex) {
        log.info("DRCrashHandler is handling Exception! ");

        if (ex == null) {
            return false;
        } else {

            // 5.1 收集設備參數信息
            collectDeviceInfo(mContext);

            // 5.2 彈出窗口提示信息
            new Thread(new Runnable() {
                public void run() {
                    log.info("DRCrashHandler is ready send crash-info to device!");

                    Looper.prepare();
                    Toast.makeText(mContext, getDRTipMsg(), Toast.LENGTH_SHORT).show();
                    Looper.loop();
                }
            }).start();

            // 5.3 保存log和crash到文件
            saveLogAndCrash(ex);
            // 5.4 發送log和crash到服務器
            sendLogAndCrash();

            return true;
        }

    }

    /**
     * 5.1 收集設備信息
     * 
     * @param ctx
     */
    protected void collectDeviceInfo(Context ctx) {
        log.info("DRCrashHandler is collecting DeviceInfo! ");

        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 + "";
                mInfos.put("versionName", versionName);
                mInfos.put("versionCode", versionCode);
            }
        } catch (NameNotFoundException e) {
            log.error("An error occured when collect package info, Error: " + e);
        }
        Field[] fields = Build.class.getDeclaredFields();
        for (Field field : fields) {
            try {
                field.setAccessible(true);
                mInfos.put(field.getName(), field.get(null).toString());
            } catch (Exception e) {
                log.error("An error occured when collect crash info, Error: " + e);
            }
        }
    }

    /**
     * 5.3 保存log和crash到文件
     * 
     * @param ex
     */
    protected void saveLogAndCrash(Throwable ex) {
        log.info("DRCrashHandler is saving Log! ");

        StringBuffer sb = new StringBuffer();

        sb.append("[DateTime: " + DateUtil.date2String(new Date()) + "]\n");
        sb.append("[DeviceInfo: ]\n");
        // 遍歷infos
        for (Map.Entry<String, String> entry : mInfos.entrySet()) {
            String key = entry.getKey().toLowerCase(Locale.getDefault());
            String value = entry.getValue();
            sb.append("  " + key + ": " + value + "\n");
        }
        // 將錯誤手機到writer中
        Writer writer = new StringWriter();
        PrintWriter pw = new PrintWriter(writer);
        ex.printStackTrace(pw);
        Throwable cause = ex.getCause();
        while (cause != null) {
            cause.printStackTrace(pw);
            cause = cause.getCause();
        }
        pw.close();
        String result = writer.toString();
        sb.append("[Excetpion: ]\n");
        sb.append(result);

        // 將異常寫入日志文件
        log.error(result);

        // 5.3.1 記錄異常到特定文件中
        saveToCrashFile(sb.toString());

    }

    /**
     * 5.3.1寫入文本
     * 
     * @param crashText
     */
    protected void saveToCrashFile(String crashText) {
        log.info("DRCrashHandler is writing crash-info to CrashFile(" + this.mDRCrashFilePath + ")! ");

        crashFile = new File(mDRCrashFilePath);

        // 創建文件(自己寫的操作文件相關的工具類)
        FileUtil.createFileAndFolder(crashFile);

        // 追加文本(自己寫的操作文件相關的工具類)
        FileUtil.appendToFile(crashFile, crashText);

    }

    /**
     * 5.4 發送log和crash到服務器
     */
    protected void sendLogAndCrash() {
        logFile = new File(mContext.getDrLogHelper().getLog4jFilePath());
        crashFile = new File(getDRCrashFilePath());
        // 5.4.1
        sendToServer(logFile, crashFile);
    }

    /**
     * 5.4.1 將錯誤報告發送到服務器
     * 
     * @param crashFile
     * @param logFile
     */
    protected abstract void sendToServer(File logFile, File crashFile);

    public String getDRTipMsg() {
        return mDRTipMsg;
    }

    /**
     * 設置程序崩潰提示信息
     * 
     * @param mDRTipMsg
     */
    public void setDRTipMsg(String mDRTipMsg) {
        this.mDRTipMsg = mDRTipMsg;
    }

    public String getDRCrashFilePath() {
        return mDRCrashFilePath;
    }

    /**
     * 設置記錄崩潰信息的文件位置
     * 
     * @param mDRCrashFilePath
     */
    public void setDRCrashFilePath(String mDRCrashFilePath) {
        this.mDRCrashFilePath = mDRCrashFilePath;
    }

}

2、新建DRApplication.java(抽象類,里面用到了Log4j,上一篇有講到如果在Android中集成Log4j,這里在Application中使用DRLogHelper來初始化log4j)

package cn.dr.lib.app;

import java.io.File;
import java.util.LinkedList;
import java.util.List;

import org.apache.log4j.Logger;

import android.app.Activity;
import android.app.Application;
import cn.dr.lib.log.DRLogHelper;
import cn.dr.lib.ui.DRAcitivity;

/**
 * DarkRanger的Application
 * 
 * @author DarkRanger
 *
 */
public abstract class DRApplication extends Application {

    // 當前類的log
    private static Logger log;

    // Activity列表
    private List<DRAcitivity> mActivityList = new LinkedList<DRAcitivity>();

    // drLog實例
    public DRLogHelper mDRLogHelper = DRLogHelper.getInstance();

    // 全局異常處理類的實例
    public DRCrashHandler mDRCrashHandler = new DRCrashHandler() {

        @Override
        public void initParams() {

        }

        @Override
        public void sendToServer(File logFile, File crashFile) {

        }

    };

    @Override
    public void onCreate() {

        super.onCreate();

        // 1、初始化DRLog參數
        initDRLogHelperParam();

        // 2、初始化DRLog
        initDRLogHelper();

        // 3、初始化全局異常處理類
        initCrashHandler();
    }

    /**
     * 1、初始化DRLog參數,如: <br/>
     * 
     * {@link DRApplication#getDrlog()} DRLog drLog = getDrlog(); <br/>
     * {@link DRLogHelper#setLog4jFilePath(String)}
     * drLog.setLog4jFilePath(Constants.LOG4J_FILE_PATH); <br/>
     * {@link DRLogHelper#setType(cn.dr.lib.log.DRLogHelper.LogType)}
     * drLog.setType(LogType.TYPE_LOG4J); <br/>
     * 
     * 只有在子類中完成initDRLogParam參數設置以后才能使用log
     */
    protected abstract void initDRLogHelperParam();

    /**
     * 2、初始化DRLog
     */
    private void initDRLogHelper() {
        getDrLogHelper().init();

        log = Logger.getLogger(DRApplication.class);
    }

    /**
     * 3、初始化CrashHandler
     */
    private void initCrashHandler() {
        log.trace("DRApplication: initCrashHandler()");

        // 3.1
        setHandler();

        // 3.2
        getDRCrashHandler().init(this);
    }

    /**
     * 
     * 3.1 調用以下方法為mCrashHandler設置實例<br/>
     * <br/>
     * 
     * {@link #setCrashHandler(DRCrashHandler)}
     */
    public abstract void setHandler();

    /**
     * 獲取DRLog單例
     * 
     * @return
     */
    public DRLogHelper getDrLogHelper() {
        return mDRLogHelper;
    }

    public DRCrashHandler getDRCrashHandler() {
        return mDRCrashHandler;
    }

    public void setDRCrashHandler(DRCrashHandler mCrashHandler) {
        this.mDRCrashHandler = mCrashHandler;
    }

    /**
     * 添加activity到App的mActivityList
     * 
     * @param activity
     */
    public void addActivity(DRAcitivity activity) {
        this.mActivityList.add(activity);
    }

    /**
     * 遍歷mActivityList,結束每一個activity的聲明周期
     */
    private void finishActivityList() {
        for (Activity activity : mActivityList) {
            activity.finish();
        }
    }

    @Override
    public void onTerminate() {
        log.trace("DRApplication: onTerminate()");

        super.onTerminate();
        appExit();
    }

    /**
     * 完全退出程序
     */
    public void appExit() {
        log.trace("DRApplication: appExit()");

        finishActivityList();
        // 正常退出
        System.exit(0);
    }

    /**
     * 出現異常殺掉進程
     */
    public void appKill() {
        log.trace("DRApplication: appKill()");

        finishActivityList();
        android.os.Process.killProcess(android.os.Process.myPid());
        System.exit(1);
    }

}

 3、

首先要說明的是:前面兩個類我已經集成在DR_supprot_lib庫中,在新的應用程序中只需要繼承這兩個類,分類初始化一些參數即可。

寫個App程序測試:

3.1 新建MyCrashHandler.java繼承DRCrashHandler,復寫兩個抽象方法initParams()和sendToServer()

package cn.darkranger.test;

import java.io.File;

import org.apache.log4j.Logger;

import android.os.Environment;
import cn.dr.lib.app.DRCrashHandler;

public class MyCrashHandler extends DRCrashHandler {
    private static final Logger log = Logger.getLogger(MyCrashHandler.class);

    String crashFilePath = Environment.getExternalStorageDirectory() + File.separator + "MyApp" + File.separator
            + "Crash.txt";

    @Override
    public void initParams() {
        // 設置程序崩潰提示信息
        setDRTipMsg("this is my msg - -");
        // 設置程序崩潰的文件位置
        setDRCrashFilePath(crashFilePath);
    }

    @Override
    protected void sendToServer(File logFile, File crashFile) {
        log.info("logFile: " + logFile + "; crashFile: " + "\naction:sendToServer - -");
        // 這里要寫上傳錯誤信息到服務器的代碼,暫時不寫,看需求,自己實現
    }

}

 

3.2 新建MyApplication.java繼承DRApplication,復寫兩個抽象方法initDRLogHelperParam()和setHandler()

package cn.darkranger.test;

import java.io.File;

import org.apache.log4j.Logger;

import android.os.Environment;
import cn.dr.lib.app.DRCrashHandler;

public class MyCrashHandler extends DRCrashHandler {
    private static final Logger log = Logger.getLogger(MyCrashHandler.class);

    String crashFilePath = Environment.getExternalStorageDirectory() + File.separator + "MyApp" + File.separator
            + "Crash.txt";

    @Override
    public void initParams() {
        // 設置程序崩潰提示信息
        setDRTipMsg("this is my msg - -");
        // 設置程序崩潰的文件位置
        setDRCrashFilePath(crashFilePath);
    }

    @Override
    protected void sendToServer(File logFile, File crashFile) {
        log.info("logFile: " + logFile + "; crashFile: " + "\naction:sendToServer - -");
        // 這里要寫上傳錯誤信息到服務器的代碼,暫時不寫,看需求,自己實現
    }

}

 

3.3 新建MainActivity,這里暫時不繼承DRActivity,繼承AppCompatActivity,兩個testview,點擊第一個,調用DRApplication的退出,點擊第二個,拋出異常,我們自己捕獲。

package cn.darkranger.test;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.TextView;public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        TextView exitTv = (TextView) findViewById(R.id.id_exit);
        exitTv.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                ((MyApplication) getApplication()).appExit();
            }
        });

        TextView testCrashTv = (TextView) findViewById(R.id.id_testCrash);
        testCrashTv.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                throw new IllegalArgumentException("this is an IllegalArgumentException! ");
            }
        });

    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        int id = item.getItemId();
        if (id == R.id.action_settings) {
            return true;
        }
        return super.onOptionsItemSelected(item);
    }
}

 3.4 更改AndroidManifest.xml(添加讀寫文件的權限,設置application為:cn.darkranger.test.MyApplication)

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="cn.darkranger.test"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="11"
        android:targetSdkVersion="21" />

    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

    <application
        android:name="cn.darkranger.test.MyApplication"
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

測試:

運行,點擊第一個按鈕,退出程序,查看log文件:

[2016-06-30 22:19:09][Class: cn.dr.lib.log.DRLogHelper.initLog4j(DRLogHelper.java:89)] 
[Level: INFO ] - Msg: Log4j is Ready For DRApplication! 

[2016-06-30 22:19:09][Class: cn.dr.lib.app.DRApplication.initCrashHandler(DRApplication.java:87)] 
[Level: TRACE] - Msg: DRApplication: initCrashHandler()

[2016-06-30 22:19:09][Class: cn.dr.lib.app.DRCrashHandler.init(DRCrashHandler.java:65)] 
[Level: INFO ] - Msg: DRCrashHandler is Ready For Application! 

[2016-06-30 22:19:12][Class: cn.dr.lib.app.DRApplication.appExit(DRApplication.java:152)] 
[Level: TRACE] - Msg: DRApplication: appExit()

[2016-06-30 22:19:58][Class: cn.dr.lib.log.DRLogHelper.initLog4j(DRLogHelper.java:89)] 
[Level: INFO ] - Msg: Log4j is Ready For DRApplication! 

[2016-06-30 22:19:58][Class: cn.dr.lib.app.DRApplication.initCrashHandler(DRApplication.java:87)] 
[Level: TRACE] - Msg: DRApplication: initCrashHandler()

[2016-06-30 22:19:58][Class: cn.dr.lib.app.DRCrashHandler.init(DRCrashHandler.java:65)] 
[Level: INFO ] - Msg: DRCrashHandler is Ready For Application! 

[2016-06-30 22:20:02][Class: cn.dr.lib.app.DRApplication.appExit(DRApplication.java:152)] 
[Level: TRACE] - Msg: DRApplication: appExit()

 

運行,點擊第二個按鈕,拋出異常,查看log文件和crash文件:

Log.txt

[2016-06-30 22:19:09][Class: cn.dr.lib.log.DRLogHelper.initLog4j(DRLogHelper.java:89)] 
[Level: INFO ] - Msg: Log4j is Ready For DRApplication! 

[2016-06-30 22:19:09][Class: cn.dr.lib.app.DRApplication.initCrashHandler(DRApplication.java:87)] 
[Level: TRACE] - Msg: DRApplication: initCrashHandler()

[2016-06-30 22:19:09][Class: cn.dr.lib.app.DRCrashHandler.init(DRCrashHandler.java:65)] 
[Level: INFO ] - Msg: DRCrashHandler is Ready For Application! 

[2016-06-30 22:19:12][Class: cn.dr.lib.app.DRApplication.appExit(DRApplication.java:152)] 
[Level: TRACE] - Msg: DRApplication: appExit()

[2016-06-30 22:19:58][Class: cn.dr.lib.log.DRLogHelper.initLog4j(DRLogHelper.java:89)] 
[Level: INFO ] - Msg: Log4j is Ready For DRApplication! 

[2016-06-30 22:19:58][Class: cn.dr.lib.app.DRApplication.initCrashHandler(DRApplication.java:87)] 
[Level: TRACE] - Msg: DRApplication: initCrashHandler()

[2016-06-30 22:19:58][Class: cn.dr.lib.app.DRCrashHandler.init(DRCrashHandler.java:65)] 
[Level: INFO ] - Msg: DRCrashHandler is Ready For Application! 

[2016-06-30 22:20:02][Class: cn.dr.lib.app.DRApplication.appExit(DRApplication.java:152)] 
[Level: TRACE] - Msg: DRApplication: appExit()

[2016-06-30 22:20:48][Class: cn.dr.lib.log.DRLogHelper.initLog4j(DRLogHelper.java:89)] 
[Level: INFO ] - Msg: Log4j is Ready For DRApplication! 

[2016-06-30 22:20:48][Class: cn.dr.lib.app.DRApplication.initCrashHandler(DRApplication.java:87)] 
[Level: TRACE] - Msg: DRApplication: initCrashHandler()

[2016-06-30 22:20:48][Class: cn.dr.lib.app.DRCrashHandler.init(DRCrashHandler.java:65)] 
[Level: INFO ] - Msg: DRCrashHandler is Ready For Application! 

[2016-06-30 22:20:50][Class: cn.dr.lib.app.DRCrashHandler.uncaughtException(DRCrashHandler.java:109)] 
[Level: INFO ] - Msg: DRCrashHandler dispatcher uncaughtException! 

[2016-06-30 22:20:50][Class: cn.dr.lib.app.DRCrashHandler.handlerException(DRCrashHandler.java:139)] 
[Level: INFO ] - Msg: DRCrashHandler is handling Exception! 

[2016-06-30 22:20:50][Class: cn.dr.lib.app.DRCrashHandler.collectDeviceInfo(DRCrashHandler.java:175)] 
[Level: INFO ] - Msg: DRCrashHandler is collecting DeviceInfo! 

[2016-06-30 22:20:50][Class: cn.dr.lib.app.DRCrashHandler.saveLogAndCrash(DRCrashHandler.java:206)] 
[Level: INFO ] - Msg: DRCrashHandler is saving Log! 

[2016-06-30 22:20:50][Class: cn.dr.lib.app.DRCrashHandler.run(DRCrashHandler.java:151)] 
[Level: INFO ] - Msg: DRCrashHandler is ready send crash-info to device!

[2016-06-30 22:20:50][Class: cn.dr.lib.app.DRCrashHandler.saveLogAndCrash(DRCrashHandler.java:233)] 
[Level: ERROR] - Msg: java.lang.IllegalArgumentException: this is an IllegalArgumentException! 
    at cn.darkranger.test.MainActivity$2.onClick(MainActivity.java:33)
    at android.view.View.performClick(View.java:4792)
    at android.view.View$PerformClick.run(View.java:19936)
    at android.os.Handler.handleCallback(Handler.java:739)
    at android.os.Handler.dispatchMessage(Handler.java:95)
    at android.os.Looper.loop(Looper.java:135)
    at android.app.ActivityThread.main(ActivityThread.java:5595)
    at java.lang.reflect.Method.invoke(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:372)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:964)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:759)


[2016-06-30 22:20:50][Class: cn.dr.lib.app.DRCrashHandler.saveToCrashFile(DRCrashHandler.java:246)] 
[Level: INFO ] - Msg: DRCrashHandler is writing crash-info to CrashFile(/storage/emulated/0/MyApp/Crash.txt)! 

[2016-06-30 22:20:50][Class: cn.dr.lib.utils.FileUtil.createFileAndFolder(FileUtil.java:444)] 
[Level: INFO ] - Msg: File[/storage/emulated/0/MyApp/Crash.txt] was created successfully! 

[2016-06-30 22:20:50][Class: cn.darkranger.test.MyCrashHandler.sendToServer(MyCrashHandler.java:26)] 
[Level: INFO ] - Msg: logFile: /storage/emulated/0/MyApp/Log.txt; crashFile: 
action:sendToServer - -

[2016-06-30 22:20:53][Class: cn.dr.lib.app.DRApplication.appExit(DRApplication.java:152)] 
[Level: TRACE] - Msg: DRApplication: appExit()

Crash.txt

[DateTime: 2016-06-30 22:20:50]
[DeviceInfo: ]
  supported_64_bit_abis: [Ljava.lang.String;@16d078ef
  versioncode: 1
  board: mozart
  bootloader: unknown
  type: user
  matchers: [Ljava.lang.String;@3d5b7685
  id: HUAWEIM2-801W
  time: 1437332391000
  brand: HUAWEI
  tag: Build
  serial: TJF4C15804003585
  hardware: hi3635
  supported_abis: [Ljava.lang.String;@33767ffc
  no_hota: false
  cpu_abi: arm64-v8a
  radio: unknown
  is_debuggable: false
  replacements: [Ljava.lang.String;@2dec2cda
  manufacturer: HUAWEI
  supported_32_bit_abis: [Ljava.lang.String;@3271c1ce
  tags: ota-rel-keys,release-keys
  cpu_abi2: 
  unknown: unknown
  user: huawei
  fingerprint: HUAWEI/M2/HWMozart:5.1.1/HUAWEIM2-801W/C233B009:user/release-keys
  host: WUH1000005635
  product: M2
  versionname: 1.0
  display: M2-801WV100R001C233B009
  hide_product_info: false
  model: HUAWEI M2-801W
  device: HWMozart
[Excetpion: ]
java.lang.IllegalArgumentException: this is an IllegalArgumentException! 
    at cn.darkranger.test.MainActivity$2.onClick(MainActivity.java:33)
    at android.view.View.performClick(View.java:4792)
    at android.view.View$PerformClick.run(View.java:19936)
    at android.os.Handler.handleCallback(Handler.java:739)
    at android.os.Handler.dispatchMessage(Handler.java:95)
    at android.os.Looper.loop(Looper.java:135)
    at android.app.ActivityThread.main(ActivityThread.java:5595)
    at java.lang.reflect.Method.invoke(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:372)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:964)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:759)

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM