2 package jp
.gr
.java_conf
.ofnhwx
.olib
;
4 import java
.io
.BufferedReader
;
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
;
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;
42 * バグ報告の準備、各Activityのなるべく早い段階で呼び出すこと.
45 public static final void initialize(final Context context
) {
47 if (mContext
!= null) {
51 mContext
= context
.getApplicationContext();
53 PackageManager pm
= mContext
.getPackageManager();
54 mPackageInfo
= pm
.getPackageInfo(mContext
.getPackageName(), 0);
55 } catch (NameNotFoundException e
) {
58 Thread
.setDefaultUncaughtExceptionHandler(new ErrorReporter());
61 * エラー報告の確認を行うダイアログを表示する.
65 public static final void show(final Activity activity
, final int dialogId
) {
66 final File errorFile
= activity
.getFileStreamPath(ERROR_FILE
);
67 if (!errorFile
.exists()) {
70 activity
.showDialog(dialogId
);
73 * エラー報告の確認を行うダイアログを取得する.
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() {
86 public void onClick(DialogInterface dialog
, int which
) {
88 sendBugreport(activity
, errorFile
);
89 } catch (IOException e
) {
95 dialog
.setNegativeButton(R
.string
.bug_report_negative
, new OnClickListener() {
97 public void onClick(DialogInterface dialog
, int which
) {
101 dialog
.setOnCancelListener(new OnCancelListener() {
103 public void onCancel(DialogInterface dialog
) {
107 return dialog
.create();
113 * @throws IOException
115 private static final void sendBugreport(final Activity activity
, final File errorFile
) throws IOException
{
117 final File reportFile
= activity
.getFileStreamPath(REPORT_FILE
);
118 if (!errorFile
.exists() || !errorFile
.renameTo(reportFile
)) {
122 final BufferedReader reader
;
124 reader
= new BufferedReader(new FileReader(reportFile
));
125 } catch (FileNotFoundException e
) {
129 final String subject
;
130 final StringBuilder body
;
132 subject
= reader
.readLine();
133 body
= new StringBuilder(subject
);
135 final String line
= reader
.readLine();
139 body
.append(line
).append("\n");
141 } catch (IOException e
) {
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
);
155 public void uncaughtException(Thread thread
, Throwable error
) {
156 error
.printStackTrace();
158 saveThrowable(error
);
159 } catch (Exception e
) {
163 mDefaultHandler
.uncaughtException(thread
, error
);
168 * @throws FileNotFoundException
170 private void saveThrowable(Throwable error
) throws FileNotFoundException
{
172 final FileOutputStream stream
= mContext
.openFileOutput(ERROR_FILE
, Context
.MODE_WORLD_READABLE
);
173 final PrintWriter writer
= new PrintWriter(stream
);
175 if (mPackageInfo
!= null) {
176 writer
.printf("[BUG][%s] versionName:%s, versionCode:%d\n", mPackageInfo
.packageName
, mPackageInfo
.versionName
, mPackageInfo
.versionCode
);
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
);
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
);
195 error
.printStackTrace(writer
);