Java tutorial
/* * Copyright 2013 wada811<at.wada811@gmail.com> * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package at.wada811.dayscounter; import android.annotation.TargetApi; import android.app.Activity; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.os.Build; import android.os.Environment; import com.wada811.android.utils.ApplicationUtils; import com.wada811.android.utils.FileUtils; import com.wada811.android.utils.IntentUtils; import com.wada811.android.utils.LogUtils; import com.wada811.android.utils.PreferenceUtils; import com.wada811.android.utils.ResourceUtils; import com.wada811.android.utils.ToastUtils; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.PrintWriter; import java.lang.Thread.UncaughtExceptionHandler; import java.util.Map; import java.util.Map.Entry; import at.wada811.dayscounter.view.activity.CrashReportActivity; /** * ??????Exception?????? * * @author wada */ public final class CrashExceptionHandler implements UncaughtExceptionHandler { public static final int REQ_REPORT = 811; public static final String FILE_NAME = "report.txt"; public static final String MAILTO = "at.wada811+DaysCounterCrashReport@gmail.com"; private final Context mContext; private final UncaughtExceptionHandler mHandler; public CrashExceptionHandler(Context context) { mContext = context; mHandler = Thread.getDefaultUncaughtExceptionHandler(); } /** * ????????JSON????? */ @TargetApi(Build.VERSION_CODES.HONEYCOMB) @Override public void uncaughtException(Thread thread, Throwable throwable) { // make Crash report CrashExceptionHandler.makeReportFile(mContext, throwable); // launch CrashReportActivity Intent intent = new Intent(mContext, CrashReportActivity.class); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); mContext.startActivity(intent); // mHandler.uncaughtException(thread, throwable); } public static void makeReportFile(Context context, Throwable throwable) { PrintWriter writer = null; FileOutputStream outputStream; try { outputStream = context.openFileOutput(FILE_NAME, Context.MODE_PRIVATE); writer = new PrintWriter(outputStream); String report = CrashExceptionHandler.makeReport(context, throwable); writer.print(report); } catch (FileNotFoundException e) { e.printStackTrace(); } finally { if (writer != null) { writer.close(); } } } private static String makeReport(Context context, Throwable throwable) { JSONObject json = new JSONObject(); try { json.put("Build", CrashExceptionHandler.getBuildInfo()); json.put("PackageInfo", CrashExceptionHandler.getPackageInfo(context)); if (throwable != null) { json.put("Exception", CrashExceptionHandler.getExceptionInfo(throwable)); } json.put("SharedPreferences", CrashExceptionHandler.getPreferencesInfo(context)); } catch (JSONException e) { e.printStackTrace(); } LogUtils.e(json.toString()); return json.toString(); } /** * JSON?? * * @return * * @throws JSONException */ public static JSONObject getBuildInfo() { JSONObject json = new JSONObject(); try { json.put("BRAND", Build.BRAND); // ?????(docomo) json.put("MODEL", Build.MODEL); // ????(SO-01C) json.put("DEVICE", Build.DEVICE); // ???(SO-01C) json.put("MANUFACTURER", Build.MANUFACTURER); // ??(Sony Ericsson) json.put("VERSION.SDK_INT", Build.VERSION.SDK_INT); // ??(10) json.put("VERSION.RELEASE", Build.VERSION.RELEASE); // ????(2.3.4) } catch (JSONException e) { e.printStackTrace(); } return json; } /** * ? * * @return * * @throws JSONException */ public static JSONObject getPackageInfo(Context context) { JSONObject json = new JSONObject(); try { json.put("packageName", context.getPackageName()); json.put("versionCode", ApplicationUtils.getVersionCode(context)); json.put("versionName", ApplicationUtils.getVersionName(context)); } catch (JSONException e) { e.printStackTrace(); } return json; } /** * ? * * @param throwable * * @return * * @throws JSONException */ public static JSONObject getExceptionInfo(Throwable throwable) throws JSONException { JSONObject json = new JSONObject(); json.put("name", throwable.getClass().getName()); json.put("message", throwable.getMessage()); if (throwable.getStackTrace() != null) { // ExceptionStacktrace JSONArray exceptionStacktrace = new JSONArray(); for (StackTraceElement element : throwable.getStackTrace()) { exceptionStacktrace.put("at " + LogUtils.getMetaInfo(element)); } json.put("ExceptionStacktrace", exceptionStacktrace); } if (throwable.getCause() != null) { json.put("cause", throwable.getCause()); // CausedStacktrace if (throwable.getCause().getStackTrace() != null) { JSONArray causedStacktrace = new JSONArray(); for (StackTraceElement element : throwable.getCause().getStackTrace()) { causedStacktrace.put("at " + LogUtils.getMetaInfo(element)); } json.put("CausedStacktrace", causedStacktrace); } } return json; } /** * Preferences? * * @return * * @throws JSONException */ public static JSONObject getPreferencesInfo(Context context) { SharedPreferences preferences = PreferenceUtils.getDefaultSharedPreferences(context); JSONObject json = new JSONObject(); Map<String, ?> map = preferences.getAll(); for (Entry<String, ?> entry : map.entrySet()) { try { json.put(entry.getKey(), entry.getValue()); } catch (JSONException e) { e.printStackTrace(); } } return json; } public static boolean isCrashed(Context context) { File file = ResourceUtils.getFile(context, CrashExceptionHandler.FILE_NAME); return file.exists(); } public static void reportProblem(Context context) { File file = ResourceUtils.getFile(context, CrashExceptionHandler.FILE_NAME); File dirFile = new File(Environment.getExternalStorageDirectory(), context.getString(R.string.app_dir)); File attachmentFile = new File(dirFile, CrashExceptionHandler.FILE_NAME); Intent intent; String report = ResourceUtils.readFileString(context, CrashExceptionHandler.FILE_NAME); if (FileUtils.move(file, attachmentFile)) { intent = IntentUtils.createSendMailIntent(CrashExceptionHandler.MAILTO, context.getString(R.string.reportProblemMailTitle), context.getString(R.string.reportProblemMailBody)); intent = IntentUtils.addFile(intent, attachmentFile); } else { intent = IntentUtils.createSendMailIntent(CrashExceptionHandler.MAILTO, context.getString(R.string.reportProblemMailTitle), context.getString(R.string.reportProblemMailBody, report)); } Intent gmailIntent = IntentUtils.createGmailIntent(intent); if (IntentUtils.canIntent(context, gmailIntent)) { ((Activity) context).startActivityForResult(gmailIntent, REQ_REPORT); } else if (IntentUtils.canIntent(context, intent)) { ((Activity) context).startActivityForResult( Intent.createChooser(intent, context.getString(R.string.reportProblem)), REQ_REPORT); } else { ToastUtils.show(context, R.string.mailerNotFound); } } }