修正:エラー報告の仕様を変更2
[ofnhwx.olib.git] / src / jp / gr / java_conf / ofnhwx / olib / ErrorReporter.java
blobd8553ff520e0460e5669a66e8ec0f184d07e09c0
2 package jp.gr.java_conf.ofnhwx.olib;
4 import java.io.BufferedReader;
5 import java.io.File;
6 import java.io.FileNotFoundException;
7 import java.io.FileOutputStream;
8 import java.io.FileReader;
9 import java.io.IOException;
10 import java.io.PrintWriter;
11 import java.lang.Thread.UncaughtExceptionHandler;
12 import jp.gr.java_conf.ofnhwx.olib.utils.OBitmapUtils;
13 import android.app.Activity;
14 import android.app.ActivityManager;
15 import android.app.ActivityManager.MemoryInfo;
16 import android.app.AlertDialog;
17 import android.content.Context;
18 import android.content.DialogInterface;
19 import android.content.DialogInterface.OnCancelListener;
20 import android.content.DialogInterface.OnClickListener;
21 import android.content.Intent;
22 import android.content.pm.PackageInfo;
23 import android.content.pm.PackageManager;
24 import android.content.pm.PackageManager.NameNotFoundException;
25 import android.graphics.drawable.BitmapDrawable;
26 import android.net.Uri;
27 import android.os.Build;
29 /**
30 * バグ報告用のクラス(頂いてきた).
31 * @author Y.FUJITA
32 * @since 1.0.0
33 * @version 1.0.2
35 public final class ErrorReporter implements UncaughtExceptionHandler {
36 private static final UncaughtExceptionHandler mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();
37 private static final String ERROR_FILE = "BUG";
38 private static final String REPORT_FILE = "REPORT";
39 private static Context mContext = null;
40 private static PackageInfo mPackageInfo = null;
41 /**
42 * バグ報告の準備、各Activityのなるべく早い段階で呼び出すこと.
43 * @param context
45 public static final void initialize(final Context context) {
46 // 2回目以降は何もしない
47 if (mContext != null) {
48 return;
50 // 標準の例外処理をすり替える
51 mContext = context.getApplicationContext();
52 try {
53 PackageManager pm = mContext.getPackageManager();
54 mPackageInfo = pm.getPackageInfo(mContext.getPackageName(), 0);
55 } catch (NameNotFoundException e) {
56 e.printStackTrace();
58 Thread.setDefaultUncaughtExceptionHandler(new ErrorReporter());
60 /**
61 * エラー報告の確認を行うダイアログを表示する.
62 * @param activity
63 * @param dialogId
65 public static final void show(final Activity activity, final int dialogId) {
66 final File errorFile = activity.getFileStreamPath(ERROR_FILE);
67 if (!errorFile.exists()) {
68 return;
70 activity.showDialog(dialogId);
72 /**
73 * エラー報告の確認を行うダイアログを取得する.
74 * @param activity
75 * @param icon
76 * @return
78 public static final AlertDialog getDialog(final Activity activity, final int icon) {
79 final File errorFile = activity.getFileStreamPath(ERROR_FILE);
80 final AlertDialog.Builder dialog = new AlertDialog.Builder(activity);
81 dialog.setIcon(new BitmapDrawable(OBitmapUtils.decodeResource(activity, icon, 48.0f)));
82 dialog.setTitle(R.string.bug_report_title);
83 dialog.setMessage(R.string.bug_report_message);
84 dialog.setPositiveButton(R.string.bug_report_positive, new OnClickListener() {
85 @Override
86 public void onClick(DialogInterface dialog, int which) {
87 try {
88 sendBugreport(activity, errorFile);
89 } catch (IOException e) {
90 e.printStackTrace();
92 dialog.dismiss();
94 });
95 dialog.setNegativeButton(R.string.bug_report_negative, new OnClickListener() {
96 @Override
97 public void onClick(DialogInterface dialog, int which) {
98 errorFile.delete();
101 dialog.setOnCancelListener(new OnCancelListener() {
102 @Override
103 public void onCancel(DialogInterface dialog) {
104 errorFile.delete();
107 return dialog.create();
110 * エラー報告の送信
111 * @param activity
112 * @param errorFile
113 * @throws IOException
115 private static final void sendBugreport(final Activity activity, final File errorFile) throws IOException {
116 // バグ報告ファイルをリネーム
117 final File reportFile = activity.getFileStreamPath(REPORT_FILE);
118 if (!errorFile.exists() || !errorFile.renameTo(reportFile)) {
119 return;
122 final BufferedReader reader;
123 try {
124 reader = new BufferedReader(new FileReader(reportFile));
125 } catch (FileNotFoundException e) {
126 return;
129 final String subject;
130 final StringBuilder body;
131 try {
132 subject = reader.readLine();
133 body = new StringBuilder(subject);
134 while (true) {
135 final String line = reader.readLine();
136 if (line == null) {
137 break;
139 body.append(line).append("\n");
141 } catch (IOException e) {
142 return;
143 } finally {
144 reader.close();
145 reportFile.delete();
147 // メールの送信
148 final Uri uri = Uri.parse(activity.getString(R.string.mail_to));
149 final Intent intent = new Intent(Intent.ACTION_SENDTO, uri);
150 intent.putExtra(Intent.EXTRA_SUBJECT, subject);
151 intent.putExtra(Intent.EXTRA_TEXT , body.toString());
152 activity.startActivity(intent);
154 @Override
155 public void uncaughtException(Thread thread, Throwable error) {
156 error.printStackTrace();
157 try {
158 saveThrowable(error);
159 } catch (Exception e) {
160 // さすがにどうしようもない
161 e.printStackTrace();
163 mDefaultHandler.uncaughtException(thread, error);
166 * エラーの内容などをファイルに保存.
167 * @param error
168 * @throws FileNotFoundException
170 private void saveThrowable(Throwable error) throws FileNotFoundException {
171 // ファイル書込みの準備
172 final FileOutputStream stream = mContext.openFileOutput(ERROR_FILE, Context.MODE_WORLD_READABLE);
173 final PrintWriter writer = new PrintWriter(stream);
174 // パッケージ情報の記録
175 if (mPackageInfo != null) {
176 writer.printf("[BUG][%s] versionName:%s, versionCode:%d\n", mPackageInfo.packageName, mPackageInfo.versionName, mPackageInfo.versionCode);
177 } else {
178 writer.printf("[BUG][Unkown Package]\n");
180 // メモリ情報の記録(Total, Free, Used)
181 final long total = Runtime.getRuntime().totalMemory() / 1024;
182 final long free = Runtime.getRuntime().freeMemory() / 1024;
183 writer.printf("Runtime Memory: total: %dKB, free: %dKB, used: %dKB\n", total, free, total - free);
184 // メモリ情報の記録(Avail, LowMemory)
185 final ActivityManager am = (ActivityManager)mContext.getSystemService(Context.ACTIVITY_SERVICE);
186 final MemoryInfo info = new MemoryInfo();
187 am.getMemoryInfo(info);
188 writer.printf("availMem: %dKB, lowMemory: %b\n", info.availMem / 1024, info.lowMemory);
189 // デバイス情報の記録
190 writer.printf("DEVICE: %s\n", Build.DEVICE);
191 writer.printf("MODEL : %s\n", Build.MODEL);
192 writer.printf("VERSION.SDK: %s\n", Build.VERSION.SDK);
193 writer.printf("\n");
194 // スタックトレースを記録
195 error.printStackTrace(writer);
196 // ファイルを保存して閉じる
197 writer.close();