1 package jp
.gr
.java_conf
.ofnhwx
.olib
;
3 import java
.io
.BufferedReader
;
5 import java
.io
.FileNotFoundException
;
6 import java
.io
.FileOutputStream
;
7 import java
.io
.FileReader
;
8 import java
.io
.IOException
;
9 import java
.io
.PrintWriter
;
10 import java
.lang
.Thread
.UncaughtExceptionHandler
;
12 import jp
.gr
.java_conf
.ofnhwx
.olib
.utils
.OBitmap
;
13 import jp
.gr
.java_conf
.ofnhwx
.olib
.utils
.OUtil
;
14 import android
.app
.Activity
;
15 import android
.app
.ActivityManager
;
16 import android
.app
.ActivityManager
.MemoryInfo
;
17 import android
.app
.AlertDialog
;
18 import android
.content
.ActivityNotFoundException
;
19 import android
.content
.Context
;
20 import android
.content
.DialogInterface
;
21 import android
.content
.DialogInterface
.OnCancelListener
;
22 import android
.content
.DialogInterface
.OnClickListener
;
23 import android
.content
.Intent
;
24 import android
.content
.pm
.PackageInfo
;
25 import android
.content
.pm
.PackageManager
;
26 import android
.content
.pm
.PackageManager
.NameNotFoundException
;
27 import android
.graphics
.Bitmap
;
28 import android
.graphics
.drawable
.BitmapDrawable
;
29 import android
.net
.Uri
;
30 import android
.os
.Build
;
31 import android
.util
.Log
;
32 import android
.widget
.Toast
;
38 public final class ErrorReporter
implements UncaughtExceptionHandler
{
40 private static final String TAG
= ErrorReporter
.class.getSimpleName();
42 private static final UncaughtExceptionHandler DEFAULT_HANDLER
= Thread
.getDefaultUncaughtExceptionHandler();
43 private static final String ERROR_FILE
= "BUG";
44 private static final String REPORT_FILE
= "REPORT";
45 private static Context sContext
= null;
46 private static PackageInfo sPackageInfo
= null;
49 * バグ報告の準備、各Activityのなるべく早い段階で呼び出すこと.
50 * @param context 基本的には{@code this}を指定
52 public static void initialize(Context context
) {
55 if (sContext
!= null) {
60 sContext
= context
.getApplicationContext();
62 PackageManager pm
= sContext
.getPackageManager();
63 sPackageInfo
= pm
.getPackageInfo(sContext
.getPackageName(), 0);
64 } catch (NameNotFoundException e
) {
67 Thread
.setDefaultUncaughtExceptionHandler(new ErrorReporter());
72 * エラー報告の確認を行うダイアログを表示する.
73 * @param activity ダイアログを表示するアクティビティ
74 * @param dialogId 表示するダイアログの{@code id}
76 public static final void show(Activity activity
, int dialogId
) {
77 File file
= activity
.getFileStreamPath(ERROR_FILE
);
81 activity
.showDialog(dialogId
);
85 * エラー報告の確認を行うダイアログを取得する.
90 public static final AlertDialog
getDialog(final Activity activity
, int icon
) {
93 final File file
= activity
.getFileStreamPath(ERROR_FILE
);
96 float density
= activity
.getResources().getDisplayMetrics().density
;
97 Bitmap bitmap
= OBitmap
.decodeResource(activity
, icon
, (int)(32 * density
));
100 AlertDialog
.Builder dialog
= new AlertDialog
.Builder(activity
);
101 dialog
.setIcon(new BitmapDrawable(bitmap
));
102 dialog
.setTitle(R
.string
.bug_report_title
);
103 dialog
.setMessage(R
.string
.bug_report_message
);
106 dialog
.setPositiveButton(R
.string
.bug_report_positive
, new OnClickListener() {
107 public void onClick(DialogInterface dialog
, int which
) {
108 sendBugreport(activity
, file
);
113 dialog
.setNegativeButton(R
.string
.bug_report_negative
, new OnClickListener() {
114 public void onClick(DialogInterface dialog
, int which
) {
115 if (!file
.delete()) {
116 Log
.e(TAG
, "Couldn't delete error file.");
122 dialog
.setOnCancelListener(new OnCancelListener() {
123 public void onCancel(DialogInterface dialog
) {
124 if (!file
.delete()) {
125 Log
.e(TAG
, "Couldn't delete error file.");
131 return dialog
.create();
139 * @throws IOException
141 private static final void sendBugreport(Context context
, File errorFile
) {
144 File file
= context
.getFileStreamPath(REPORT_FILE
);
145 if (!errorFile
.exists() || !errorFile
.renameTo(file
)) {
150 BufferedReader reader
;
152 reader
= new BufferedReader(new FileReader(file
));
153 } catch (FileNotFoundException e
) {
160 StringBuilder text
= new StringBuilder();
162 subject
= reader
.readLine();
163 text
.append(subject
).append("\n");
165 while ((line
= reader
.readLine()) != null) {
166 text
.append(line
).append("\n");
168 } catch (IOException e
) {
171 try { reader
.close(); } catch (Exception e
) {}
172 if (!file
.delete()) {
173 Log
.e(TAG
, "Can't delete report file.");
178 String
[] mail
= new String
[] { context
.getString(R
.string
.mail
) };
179 Intent intent
= new Intent(Intent
.ACTION_SEND
);
180 intent
.setType("message/rfc822");
181 intent
.putExtra(Intent
.EXTRA_EMAIL
, mail
);
182 intent
.putExtra(Intent
.EXTRA_SUBJECT
, subject
);
183 intent
.putExtra(Intent
.EXTRA_TEXT
, text
.toString());
185 OUtil
.sendChoiceIntent(context
, intent
, R
.string
.choose_mailer
);
186 } catch (ActivityNotFoundException e
) {
187 String mailTo
= context
.getString(R
.string
.mail_to
);
188 intent
= new Intent(Intent
.ACTION_SENDTO
, Uri
.parse(mailTo
));
189 intent
.putExtra(Intent
.EXTRA_SUBJECT
, subject
);
190 intent
.putExtra(Intent
.EXTRA_TEXT
, text
.toString());
192 OUtil
.sendChoiceIntent(context
, intent
, R
.string
.choose_mailer
);
193 } catch (ActivityNotFoundException e2
) {
194 Toast
.makeText(context
, "Activity not found.", Toast
.LENGTH_SHORT
).show();
203 public void uncaughtException(Thread thread
, Throwable error
) {
206 error
.printStackTrace();
211 FileOutputStream fos
= sContext
.openFileOutput(ERROR_FILE
, Context
.MODE_WORLD_READABLE
);
212 writer
= new PrintWriter(fos
);
213 } catch (FileNotFoundException e
) {
214 // ここには到達しない、しても何もしない
219 if (sPackageInfo
!= null) {
220 writer
.printf("[BUG][%s] versionName:%s, versionCode:%d\n",
221 sPackageInfo
.packageName
,
222 sPackageInfo
.versionName
,
223 sPackageInfo
.versionCode
);
225 writer
.printf("[BUG][Unkown Package]\n");
228 // メモリ情報の記録(Total, Free, Used)
229 long total
= Runtime
.getRuntime().totalMemory() / 1024;
230 long free
= Runtime
.getRuntime().freeMemory() / 1024;
231 writer
.printf("Runtime Memory: total: %dKB, free: %dKB, used: %dKB\n",
232 total
, free
, total
- free
);
234 // メモリ情報の記録(Avail, LowMemory)
235 ActivityManager am
= (ActivityManager
)sContext
.getSystemService(Context
.ACTIVITY_SERVICE
);
236 MemoryInfo info
= new MemoryInfo();
237 am
.getMemoryInfo(info
);
238 writer
.printf("availMem: %dKB, lowMemory: %b\n",
239 info
.availMem
/ 1024, info
.lowMemory
);
242 writer
.printf("DEVICE: %s\n", Build
.DEVICE
);
243 writer
.printf("MODEL : %s\n", Build
.MODEL
);
244 writer
.printf("VERSION.SDK: %s\n", Build
.VERSION
.SDK
);
248 error
.printStackTrace(writer
);
254 DEFAULT_HANDLER
.uncaughtException(thread
, error
);