/*
* 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.android.library.demos;
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 org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Build;
import at.wada811.utils.AndroidUtils;
import at.wada811.utils.LogUtils;
import at.wada811.utils.PreferenceUtils;
/**
* キャッチされなかったExceptionが発生した場合にログを記録する
*
* @author wada
*
*/
public final class CrashExceptionHandler implements UncaughtExceptionHandler {
public static final String FILE_NAME = "report.txt";
private final Context mContext;
private final UncaughtExceptionHandler mHandler;
public CrashExceptionHandler(Context context) {
mContext = context;
mHandler = Thread.getDefaultUncaughtExceptionHandler();
}
/**
* キャッチされなかった例外発生時に各種情報をJSONでテキストファイルに書き出す
*/
@Override
public void uncaughtException(Thread thread, Throwable throwable){
PrintWriter writer = null;
JSONObject json = new JSONObject();
try{
FileOutputStream outputStream = mContext.openFileOutput(FILE_NAME, Context.MODE_PRIVATE);
writer = new PrintWriter(outputStream);
json.put("Build", getBuildInfo());
json.put("PackageInfo", getPackageInfo(mContext));
json.put("Exception", getExceptionInfo(throwable));
json.put("SharedPreferences", getPreferencesInfo(mContext));
}catch(FileNotFoundException e){
e.printStackTrace();
}catch(JSONException e){
e.printStackTrace();
}finally{
LogUtils.e(json.toString());
writer.print(json.toString());
if(writer != null){
writer.close();
}
}
mHandler.uncaughtException(thread, throwable);
}
/**
* ビルド情報をJSONで返す
*
* @return
* @throws JSONException
*/
private 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
*/
private static JSONObject getPackageInfo(Context context){
JSONObject json = new JSONObject();
try{
json.put("packageName", context.getPackageName());
json.put("versionCode", AndroidUtils.getVersionCode(context));
json.put("versionName", AndroidUtils.getVersionName(context));
}catch(JSONException e){
e.printStackTrace();
}
return json;
}
/**
* 例外情報を返す
*
* @param throwable
* @return
* @throws JSONException
*/
private 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
*/
private 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;
}
}