FC2ブログ
ヽ|∵|ゝ(Fantom) の 開発blog? ホーム » Android »【Android】【Java】エラーをSDカードに書き出す

【Android】【Java】エラーをSDカードに書き出す  


 エミュレータではエラーが出ない(もしくは操作などの関係でテストしにくいなど)のに、実機ではエラーが出るときってあるよね。だけど「エラー:〇〇が予期せず停止しました。」だけだとデバッグするのが難しいので、例外のスタックトレースをそのままSDカードに保存する方法をやってみよう。あくまでも開発者用で特別な機能は何も付いてないので、その辺は自分で自由に付け足して使って欲しい。

●例外(エラー)のスタックトレースをSDカードに書き出すクラス
import java.io.File;
import java.io.FileOutputStream;
import java.io.PrintWriter;
import java.lang.Thread.UncaughtExceptionHandler;
import android.os.Environment;

/**<h1>エラーを SDカードに書き出す</h1>
* <p>マニフェストファイルに WRITE_EXTERNAL_STORAGE の属性と、SDカードをあらかじめマウントしておくことが必要。</p>
*/
public class ErrorReporter implements UncaughtExceptionHandler {

//マニフェストファイルに
//<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
//が必要

//※SDカードのルートに保存される。ルートは実機によって「/sdcard」や「/mnt/sdcard」など異なる。
static final File errorReportFile = new File(Environment.getExternalStorageDirectory().getPath()
+ File.separator + "error_report.txt"); //※ファイル名は任意

//コンストラクタ
public ErrorReporter() {
}

//catch されなかった例外を受け取るハンドラ
@Override
public void uncaughtException(Thread thread, Throwable ex) {
PrintWriter pw = null;
try {
//※ここでエラーにならないように注意(要 SD カード[マウント])
pw = new PrintWriter(new FileOutputStream(errorReportFile));
ex.printStackTrace(pw);
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
pw.close();
} catch (Exception e2) {
}
pw = null;
}
}
}

 使い方は以下に示す使用例のように Activity のコンストラクタ(または onCreate()) などでハンドラとしてインスタンス化すれば良いだけだ。ボタンなどはテスト用なので任意で良い。終了処理などは何も付けてないので、実際にエラーが発生したときはフリーズしたようになる。なので、アプリは手動で終了して欲しい。

 try~catch~finally ブロックは少し冗長に感じるが、try-with-resources 文は API 19(Android4.4)以降しか使えないようなので、この方が無難だろう。使用中はSDカードが実機に入っていることを前提としている。普通にSDカードが読み書きできている分にはここで例外が発生することは無いハズだ。もちろん、マニフェストファイルに「SDカードへ書き込み許可」を書いておくことも必要となる。例外捕捉中に例外を発生させないよう気をつけよう(笑)。

●SD カードの書き込みを許可するタグ(<manifest>~</manifest>の間が良い)
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />


●使用例(ボタンを押すとエラーが発生するテスト用)
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;

public class MainActivity extends Activity {

int[] data = new int[3]; //エラーテスト用

public MainActivity() {
//catch されなかった例外を受け取るハンドラを設定
Thread.setDefaultUncaughtExceptionHandler(new ErrorReporter()); //onCreate() でも良い
}

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

setContentView(R.layout.activity_main); //ボタン1個のレイアウト(任意)

//わざと例外を発生させるボタン
Button button1 = (Button)this.findViewById(R.id.button1);
button1.setOnClickListener(new Button.OnClickListener() {
@Override
public void onClick(View v) {
Log.d("LOG", "button1 onClick");
data[5] = 1; //ArrayIndexOutOfBoundsException
}
});
}
}

●出力された「error_report.txt」の内容
java.lang.ArrayIndexOutOfBoundsException
at com.example.testandroid.MainActivity$1.onClick(MainActivity.java:28)
at android.view.View.performClick(View.java:2408)
at android.view.View$PerformClick.run(View.java:8816)
at android.os.Handler.handleCallback(Handler.java:587)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:123)
at android.app.ActivityThread.main(ActivityThread.java:4627)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:521)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
at dalvik.system.NativeStart.main(Native Method)

 実際にメインに必要なコードは「Thread.setDefaultUncaughtExceptionHandler(new ErrorReporter());」の1行だけになる。上の例ではコンストラクタで定義しているが、onCreate() でも構わない。もちろん、エラーが発生する前である必要はある。

 出力されたテキストファイルはSDカードのルートに置かれ(実機によって「/sdcard」や「/mnt/sdcard」など異なる)、スマホに元から入っている「マイファイル」(アプリ名は端末よる)などでそのまま覗ける。エミュレータ上でも「DDMS」で右上にある「pull」ボタンを押せば、ローカルに落とせる。テキストエディタなどで確認すれば良い。なお、ファイル名は任意で良い。


 ちなみに元ネタは「アプリがエラーで強制終了したときに、バグレポートを送信する機能」で、それを超簡単にして、SDカードにエラーを吐き出させる機能のみに限定したものだったりする。なのでユーザー向けでなく、自分用(開発者用)という感じなので、ダイアログすら付けてない。ちゃんとしたものが欲しければ以下のURLを参照して欲しい。メモリ使用状況やビルドのバージョン情報などを付加するのもデバッグの役に立つかも知れない。

(参考)
Androidアプリのバグ報告システムを考える
Android キャッチされなかった例外を処理する
Android でアプリケーションが強制終了したとき、エラーレポートを送るようにする

(SDカードの書き込み権限など)
【スマホのコツ】Android5.0以上でSDカードへ書き込みができるファイラーアプリとその方法





(関連記事)
【Android】エミュレータでSDカードをマウントして使う方法 その2
【Android】SDカードにテキストファイルを保存する
【Android】SDカードからテキストファイルを読み込む
【Android】内部ストレージにテキストファイルを保存する
【Android】Preference 機能を使ってデータを読み込み・保存する
【Android】【Applet】【Java】テキストファイルの読み込み・保存 まとめ


スポンサーサイト

category: Android

thread: プログラミング

janre: コンピュータ

tag: テキストファイル保存  SDカード 
tb: 0   cm: --



トラックバック

トラックバックURL
→http://fantom1x.blog130.fc2.com/tb.php/226-eba3c8ed
この記事にトラックバックする(FC2ブログユーザー)

プロフィール

Social

検索フォーム

全記事一覧

カテゴリ

ユーザータグ

最新記事

リンク

PR

▲ Pagetop