throw Life - Androidアプリのバグ報告システムを考えるとかコジオニルク - Android - 独自のバグレポート機能とかを参考に
独自クラッシュレポート送信機能を実装してみた。
[Android]Logクラスをもっと使いやすく!クラス名、メソッド名、行数を表示するLogUtilクラス | DevAchieveのクラスにスタックトレースからクラス名、メソッド名、行数を取得する処理を依存しています。
/**
* キャッチされなかったExceptionが発生した場合にログを記録する
*
* @author wada
*
*/
public final class CrashExceptionHandler implements UncaughtExceptionHandler {
public static final String FILE_NAME = "report.txt";
public static final String MAILTO = "my.mail@address.com";
private final Context mContext;
private final PackageInfo mPackageInfo;
private final UncaughtExceptionHandler mHandler;
public CrashExceptionHandler(Context context) {
mContext = context;
try{
mPackageInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), 0);
}catch(NameNotFoundException e){
throw new RuntimeException(e);
}
mHandler = Thread.getDefaultUncaughtExceptionHandler();
}
/**
* キャッチされなかった例外発生時に各種情報をJSONでテキストファイルに書き出す
*/
@Override
public void uncaughtException(Thread thread, Throwable throwable){
PrintWriter writer = null;
try{
FileOutputStream outputStream = mContext.openFileOutput(FILE_NAME, Context.MODE_PRIVATE);
writer = new PrintWriter(outputStream);
JSONObject json = new JSONObject();
json.put("Build", getBuildInfo());
json.put("PackageInfo", getPackageInfo());
json.put("Exception", getExceptionInfo(throwable));
json.put("SharedPreferences", getPreferencesInfo());
writer.print(json.toString());
}catch(FileNotFoundException e){
e.printStackTrace();
}catch(JSONException e){
e.printStackTrace();
}finally{
if(writer != null){
writer.close();
}
}
mHandler.uncaughtException(thread, throwable);
}
/**
* ビルド情報をJSONで返す
*
* @return
* @throws JSONException
*/
private JSONObject getBuildInfo() throws JSONException{
JSONObject buildJson = new JSONObject();
buildJson.put("BRAND", Build.BRAND); // キャリア、メーカー名など(docomo)
buildJson.put("MODEL", Build.MODEL); // ユーザーに表示するモデル名(SO-01C)
buildJson.put("DEVICE", Build.DEVICE); // デバイス名(SO-01C)
buildJson.put("MANUFACTURER", Build.MANUFACTURER); // 製造者名(Sony Ericsson)
buildJson.put("VERSION.SDK_INT", Build.VERSION.SDK_INT); // フレームワークのバージョン情報(10)
buildJson.put("VERSION.RELEASE", Build.VERSION.RELEASE); // ユーザーに表示するバージョン番号(2.3.4)
return buildJson;
}
/**
* パッケージ情報を返す
*
* @return
* @throws JSONException
*/
private JSONObject getPackageInfo() throws JSONException{
JSONObject packageInfoJson = new JSONObject();
packageInfoJson.put("packageName", mPackageInfo.packageName);
packageInfoJson.put("versionCode", mPackageInfo.versionCode);
packageInfoJson.put("versionName", mPackageInfo.versionName);
return packageInfoJson;
}
/**
* 例外情報を返す
*
* @param throwable
* @return
* @throws JSONException
*/
private JSONObject getExceptionInfo(Throwable throwable) throws JSONException{
JSONObject exceptionJson = new JSONObject();
exceptionJson.put("name", throwable.getClass().getName());
exceptionJson.put("cause", throwable.getCause());
exceptionJson.put("message", throwable.getMessage());
// StackTrace
JSONArray stackTrace = new JSONArray();
for(StackTraceElement element : throwable.getStackTrace()){
stackTrace.put("at " + LogUtil.getMetaInfo(element));
}
exceptionJson.put("stacktrace", stackTrace);
return exceptionJson;
}
/**
* Preferencesを返す
*
* @return
* @throws JSONException
*/
private JSONObject getPreferencesInfo() throws JSONException{
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(mContext);
JSONObject preferencesJson = new JSONObject();
Map<String, ?> map = preferences.getAll();
for(Entry<String, ?> entry : map.entrySet()){
preferencesJson.put(entry.getKey(), entry.getValue());
}
return preferencesJson;
}
}呼び出しは1アプリにつき1回で良いらしいです。Thread.setDefaultUncaughtExceptionHandler(new CrashExceptionHandler(getApplicationContext()));
[Android]独自クラッシュレポート送信機能を実装する レポート送信編 | DevAchieveに続く。