a亚洲精品_精品国产91乱码一区二区三区_亚洲精品在线免费观看视频_欧美日韩亚洲国产综合_久久久久久久久久久成人_在线区

首頁 > 系統 > Android > 正文

Android 如何收集已發布程序的崩潰信息

2020-04-11 12:04:13
字體:
來源:轉載
供稿:網友

我們寫程序的時候都希望能寫出一個沒有任何Bug的程序,期望在任何情況下都不會發生程序崩潰。不過理想是豐滿的,現實是骨感的。沒有一個程序員能保證自己寫的程序絕對不會出現異常崩潰。特別是針對用戶數達到幾十萬幾百萬的程序,當你用戶數達到一定數量級后,就算你的程序出現個別異常崩潰情況也不用驚訝。

既然我們寫的程序都有可能發生異常崩潰,如果是還沒發布的程序,我們可以通過測試抓取Log來分析。不過針對已經發布的程序,我們沒法重現現象,所以讓用戶反饋程序異常信息就很重要。下面我們說說如何收集程序運行過程的異常信息。

1、Android異常捕獲接口

復制代碼 代碼如下:

//當線程因未捕獲的異常而突然終止時,調用處理程序的接口
static interface UncaughtExceptionHandler

2、設置線程捕獲異常
從上面的接口我們可以看到,這個接口是針對線程來說,也就是說我們如果需要監控某個線程運行情況,只要把這個接口實現了,然后把監控方法設置到具體的線程里面即可。一般來說,我們最需要監控的就是我們的UI線程也就是主線程。
復制代碼 代碼如下:

//設置當線程由于未捕獲到異常而突然終止,并且沒有為該線程定義其他處理程序時所調用的默認處理程序。
static void setDefaultUncaughtExceptionHandler(Thread.UncaughtExceptionHandler eh)

3、UncaughtExceptionHandler 實例
復制代碼 代碼如下:

class MythouCrashHandler implements UncaughtExceptionHandler
{
    private static final String TAG = "MythouCrashHandler---->";
    private UncaughtExceptionHandler defaultUEH;
  //構造函數,獲取默認的處理方法
    public MythouCrashHandler()
    {
        this.defaultUEH = Thread.getDefaultUncaughtExceptionHandler();
    }
  //這個接口必須重寫,用來處理我們的異常信息
    @Override
    public void uncaughtException(Thread thread, Throwable ex)
    {
        final Writer result = new StringWriter();
        final PrintWriter printWriter = new PrintWriter(result);
     //獲取跟蹤的棧信息,除了系統棧信息,還把手機型號、系統版本、編譯版本的唯一標示
        StackTraceElement[] trace = ex.getStackTrace();
        StackTraceElement[] trace2 = new StackTraceElement[trace.length+3];
        System.arraycopy(trace, 0, trace2, 0, trace.length);
        trace2[trace.length+0] = new StackTraceElement("Android", "MODEL", android.os.Build.MODEL, -1);
        trace2[trace.length+1] = new StackTraceElement("Android", "VERSION", android.os.Build.VERSION.RELEASE, -1);
        trace2[trace.length+2] = new StackTraceElement("Android", "FINGERPRINT", android.os.Build.FINGERPRINT, -1);
    //追加信息,因為后面會回調默認的處理方法
        ex.setStackTrace(trace2);
        ex.printStackTrace(printWriter);
     //把上面獲取的堆棧信息轉為字符串,打印出來
        String stacktrace = result.toString();
        printWriter.close();
        Log.e(TAG, stacktrace);
        //這里把剛才異常堆棧信息寫入SD卡的Log日志里面
        if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED))
        {
            String sdcardPath = Environment.getExternalStorageDirectory().getPath();
            writeLog(stacktrace, sdcardPath + "/mythou");
        }
        defaultUEH.uncaughtException(thread, ex);
    }
  //寫入Log信息的方法,寫入到SD卡里面
    private void writeLog(String log, String name)
    {
        CharSequence timestamp = DateFormat.format("yyyyMMdd_kkmmss", System.currentTimeMillis());
        String filename = name + "_" + timestamp + ".log";
        try
        {
            FileOutputStream stream = new FileOutputStream(filename);
            OutputStreamWriter output = new OutputStreamWriter(stream);
            BufferedWriter bw = new BufferedWriter(output);
       //寫入相關Log到文件
            bw.write(log);
            bw.newLine();
            bw.close();
            output.close();
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
    }
}

上面就是實現了獲取處理跟蹤信息的方法,上面的方法是參照VLC的異常處理機制編寫的。做了一些簡單修改。不過上面只是獲取了異常信息,如果程序安裝到用戶機器上,我們沒法獲取到這些信息,總不能讓用戶把機器拿過來給你,然后你把Log拷貝出來吧。(這個我以前做嵌入式的時候到試過,讓客戶把機器拿過來,拷貝里面的Log,那時候做的機器無法聯網。現在想起來都糾結,O(∩_∩)O哈哈~) 為了不再糾結,我們需要一個可以把Log發送到我們服務器的功能,下面是把一個服務信息發送到我們指定服務器功能。

3、通過網絡發送Log
復制代碼 代碼如下:

   public class SendCrashLog extends AsyncTask<String, String, Boolean>
    {
        public SendCrashLog() { }
        @Override
        protected Boolean doInBackground(String... params)
        {
            if (params[0].length() == 0)
                return false;
            HttpClient httpClient = new DefaultHttpClient();
       //你的服務器,這里只是舉個例子。把異常信息當作http請求發送到服務器
            HttpPost httpPost = new HttpPost("http://www.mythou/getlog.php");
       //這里把相關的異常信息轉為http post請求的數據參數
            try {
                List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(1);
                nameValuePairs.add(new BasicNameValuePair("model", params[0]));
                nameValuePairs.add(new BasicNameValuePair("device", params[1]));
                httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
         //發送相關請求信息
                httpClient.execute(httpPost);
            } catch (ClientProtocolException e) {
                e.printStackTrace();
                return false;
            } catch (IOException e) {
                e.printStackTrace();
                return false;
            }
            Log.d(TAG, "Device model sent.");
            return true;
        }
        @Override
        protected void onPostExecute(Boolean result) {
        }
    }

上面就是我上一篇文章講的異步任務的使用,我們在異步任務里面編寫了一個發送http請求的服務,用來把相關的異常信息發送到我們指定的服務器上面。這個需要你的服務器解析發送的http請求,這個難度不大,一般做個web的人都知道如何做。在上面的異常處理里面再調用這里的發送方法:
復制代碼 代碼如下:

SendCrashLogsendLog = new SendCrashLog();
//剛才的異常信息字符串
sendLog .execute(stacktrace);

通過上面的方法就可以把異常信息發送到指定的服務器,也就可以跟蹤客戶使用軟件的情況,方便我們修改程序的問題。當然這個信息收集一般都隱私和后臺流量問題,這個需要在程序里面做點提示,免得背上流氓軟件的罵名。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 日本精品久久 | 国产毛片在线 | 欧美日韩在线观看视频网站 | 国产成人精品久久 | 免费午夜电影 | 青娱乐青青草 | 青青操狠狠干 | 精品国产一区二区三区av片 | 成人国产精品一区二区毛片在线 | 精品一级 | 羞羞视频在线播放 | 一级毛片视频播放 | 国产黄色网页 | 免费看一区二区三区 | 在线免费av观看 | 国产精品成人国产乱一区 | 成人a级网站 | 精品亚洲一区二区三区四区五区 | 精品久久久久一区二区国产 | 97成人资源 | 91国自产区一二三区 | 日本一本不卡 | 免费成人在线视频网站 | 黄色视屏在线免费观看 | 91成人免费看片 | 九色社区| 国产在线小视频 | 在线欧美日韩 | 成人二区 | 中文字幕在线第一页 | 一区二区在线视频观看 | 久久精品国产清自在天天线 | 啪啪免费网站 | 国产精品www | 久久精品国产亚洲 | 国产精品www | 日本va欧美va精品发布 | 日韩在线不卡 | 精品久久一区二区 | 国产一区二区毛片 | 久久国产精品无码网站 |