Androidは、発表されたプログラムのクラッシュ情報を収集する方法

6483 ワード

私たちはプログラムを書くとき、Bugのないプログラムを書くことを望んでいます.どんな状況でもプログラムのクラッシュが起こらないことを望んでいます.しかし、理想は豊満で、現実は骨感です.自分が書いたプログラムが絶対に異常にクラッシュしないことを保証できるプログラマーは一人もいません.特に、ユーザー数が数十万数百万人に達するプログラムについては、ユーザー数が一定のレベルに達した後、プログラムに個別の異常なクラッシュが発生しても驚く必要はありません.私たちが書いたプログラムが異常にクラッシュする可能性がある以上、まだ発表されていないプログラムであれば、テストでログをキャプチャして分析することができます.しかし、すでに発表されたプログラムに対しては、現象を再現することはできないので、ユーザーにプログラム異常情報をフィードバックさせることが重要です.次に、プログラム実行プロセスの異常情報を収集する方法について説明します.
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の異常処理メカニズムを参照して作成した.簡単な修正をしました.しかし、上は異常情報を取得しただけで、プログラムがユーザーマシンにインストールされている場合、私たちはこれらの情報を取得することができません.ユーザーにマシンを持ってきてもらうことはできません.そして、ログをコピーしてください.(これは私が以前埋め込み式をしていたときに試して、お客様に機械を持ってきてもらい、中のログをコピーしてもらいました.その時作った機械はインターネットに接続できませんでした.今思えばすべて葛藤しています.O(∩∩)Oハハ~)葛藤しないために、ログを私たちのサーバーに送信できる機能が必要です.次はサービス情報を私たちの指定したサーバー機能に送信します.
3、ネットワークを通じてLogを送る
 
  
   public class SendCrashLog extends AsyncTask
    {
        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 nameValuePairs = new ArrayList(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);

上記の方法で異常情報を指定したサーバに送信したり、お客様がソフトウェアを使用している状況を追跡したりすることができ、プログラムの問題を修正するのに便利です.もちろん、この情報収集は一般的にプライバシーとバックグラウンドのトラフィックの問題であり、チンピラソフトの悪口を背負わないようにプログラムの中でヒントを与える必要があります.