/* This file is part of the Android Clementine Remote.
* Copyright (C) 2013, Andreas Muttscheller <asfa194@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.qspool.clementineremote;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.Debug;
import android.preference.PreferenceManager;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.PrintWriter;
import java.lang.Thread.UncaughtExceptionHandler;
import java.text.SimpleDateFormat;
import java.util.Date;
public class ClementineExceptionHandler implements UncaughtExceptionHandler {
private Context mContext;
private UncaughtExceptionHandler mDefaultUEH;
private SharedPreferences mSharedPref;
public ClementineExceptionHandler(Context context) {
mContext = context;
mDefaultUEH = Thread.getDefaultUncaughtExceptionHandler();
mSharedPref = PreferenceManager.getDefaultSharedPreferences(mContext);
}
@SuppressLint("CommitPrefEdits")
@Override
public void uncaughtException(Thread thread, Throwable ex) {
// Delete the last trace file!
removeLastTraceFile();
// Open the file and delete if it already exists
String filename = buildTraceFileName();
File f = new File(filename);
try {
// Write the stacktrace to the file
PrintWriter printer = new PrintWriter(f);
// Print Debug info
printer.write("== User Information ==\n");
printer.write("If you have any further information what you did to cause the crash or how to reproduce it, please write it here.\n\n\n");
printer.write("== Device Information ==\n");
printer.write("\nOS Version: " + android.os.Build.VERSION.RELEASE + " (" + System
.getProperty("os.version") + ")");
printer.write("\nOS API Level: " + android.os.Build.VERSION.SDK_INT);
printer.write("\nDevice: " + android.os.Build.DEVICE);
printer.write("\nModel (and Product): " + android.os.Build.MODEL + " ("
+ android.os.Build.PRODUCT + ")");
PackageInfo pInfo = mContext.getPackageManager()
.getPackageInfo(mContext.getPackageName(), 0);
printer.write("\nApp Version: " + pInfo.versionName + " (" + pInfo.versionCode + ")");
printer.write("\n\nMax memory: " + Runtime.getRuntime()
.maxMemory()); //the maximum memory the app can use
printer.write(
"\nCurrent heap: " + Runtime.getRuntime().totalMemory()); //current heap size
printer.write("\nHeap available: " + Runtime.getRuntime()
.freeMemory()); //amount available in heap
printer.write("\nNative Heap: " + Debug
.getNativeHeapAllocatedSize()); //is this right? I only want to account for native memory that my app is being "charged" for. Is this the proper way to account for that?
// Print stacktrace
printer.write("\n\n== Stacktrace ==\n\n");
ex.printStackTrace(printer);
printer.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (NameNotFoundException e) {
}
// Save the new filename
SharedPreferences.Editor edit = mSharedPref.edit();
edit.putString(SharedPreferencesKeys.SP_LAST_STACKTRACE, filename);
edit.commit();
// Call the default uncaught Exception handler to tell the
// system, that this app crashed
mDefaultUEH.uncaughtException(thread, ex);
}
/**
* Builds the filename for the stacktrace file (/data/data/de.qspool....)
*
* @return The filename with path as a string
*/
@SuppressLint("SimpleDateFormat")
private String buildTraceFileName() {
SimpleDateFormat ft =
new SimpleDateFormat("yyyy.MM.dd-hh:mm:ss");
StringBuilder sb = new StringBuilder();
sb.append(App.getApp().getApplicationInfo().dataDir);
sb.append("/stacktrace-");
sb.append(ft.format(new Date()));
sb.append(".txt");
return sb.toString();
}
public String getLastStracktraceFile() {
return mSharedPref.getString(SharedPreferencesKeys.SP_LAST_STACKTRACE, "");
}
public boolean removeLastTraceFile() {
File f = new File(getLastStracktraceFile());
return f.delete();
}
}