AIM: To enable crash Reporting feature to android app
Solution:
A crash reporter is an feature whose function is to report crash data to a third party, usually to the party responsible for the crashed program. Crash reports often include data such as stack traces, type of crash, and version of software. This information helps software developers to diagnose and fix the underlying problem causing the crash.
There are third party tools that also provide it, like
BugSense :
BugSense is made for mobile developers. Get the context of the errors, track errors in specific app version or filter errors by device. There was Internet connectivity at the time of the crash? BugSense collects all the information the mobile developer needs.
ACRA (Application Crash Report for Android).
ACRA is a library enabling Android Application to automatically post their crash reports to a GoogleDoc form. It is targetted to android applications developers to help them get data from their applications when they crash or behave erroneously.
However you can add this feature with the following code block.
---------------------------------------------------------------------------------
/**
* Crash Error Reporter
*
* Captures any Uncaught exception to capture the conditions that caused the event.
* The event will be written to the Log file and can be retrieved through LogCat.
* In addition, the report will attempt to send an e-mail to <string name="CrashErrorReport_MailTo">xyz@GMail.com</string>
* through the default mail application
* *
*/
public class CrashErrorReporter implements Thread.UncaughtExceptionHandler {
private static final String LOG_TAG = "CrashErrorReporter";
private Thread.UncaughtExceptionHandler mDfltExceptionHandler;
private static CrashErrorReporter S_mInstance;
private static Context mCurContext;
// Even though these should be private variables,
// they are public to avoid creating getters and setters
String mPkg_VersionName;
String mPkg_PackageName;
String mCtx_FilePath;
String mPkg_OSBld_PhoneModel;
String mPkg_OSBld_AndroidVersion;
String mPkg_OSBld_Board;
String mPkg_OSBld_Brand;
String mPkg_OSBld_Device;
String mPkg_OSBld_Display;
String mPkg_OSBld_FingerPrint;
String mPkg_OSBld_Host;
String mPkg_OSBld_ID;
String mPkg_OSBld_Manufacturer;
String mPkg_OSBld_Model;
String mPkg_OSBld_Product;
String mPkg_OSBld_Tags;
long mPkg_OSBld_Time;
String mPkg_OSBld_Type;
String mPkg_OSBld_User;
/**
* Manages the uncaught exception.
*/
@Override
public void uncaughtException(Thread t, Throwable e) {
Log.d(LOG_TAG, "@Override uncaughtException");
Date CurDate = new Date();
String Report = "Error Report collected on : " + CurDate.toString() + "\n\n";
Report += "Environment Details : \n";
Report += "===================== \n";
Report += CreateInformationString();
Report += "Stack : \n";
Report += "======= \n";
final Writer result = new StringWriter();
final PrintWriter printWriter = new PrintWriter(result);
e.printStackTrace(printWriter);
String stacktrace = result.toString();
Report += stacktrace + "\n";
// If the exception was thrown in a background thread inside
// AsyncTask, then the actual exception can be found with getCause
Throwable cause = e.getCause();
while (cause != null) {
Report += "Cause : \n";
Report += "======= \n";
cause.printStackTrace( printWriter );
Report += result.toString();
cause = cause.getCause();
}
printWriter.close();
Report += "**** End of current Report ***";
SaveAsFile(Report);
// Try and send out the report now before calling the default handler
CheckCrashErrorAndSendMail(mCurContext);
mDfltExceptionHandler.uncaughtException(t, e);
}
/**
* Capture the newly created instance for singleton class management
*/
public static CrashErrorReporter getInstance() {
if ( S_mInstance == null )
S_mInstance = new CrashErrorReporter();
return S_mInstance;
}
public void Init( Context context ) {
mDfltExceptionHandler = Thread.getDefaultUncaughtExceptionHandler();
Thread.setDefaultUncaughtExceptionHandler( this );
mCurContext = context;
}
/**
* Obtains the available internal memory size
* @return long - integer with memory size available
*/
public long getAvailableInternalMemorySize() {
File path = Environment.getDataDirectory();
StatFs stat = new StatFs(path.getPath());
// place in stack variables for debugging purposes.
long blockSize = stat.getBlockSize();
long availableBlocks = stat.getAvailableBlocks();
return( availableBlocks * blockSize );
}
/**
* Obtains the Total internal memory size
* @return long - integer with total memory size
*/
public long getTotalInternalMemorySize() {
File path = Environment.getDataDirectory();
StatFs stat = new StatFs(path.getPath());
// place in stack variables for debugging purposes.
long blockSize = stat.getBlockSize();
long totalBlocks = stat.getBlockCount();
return( totalBlocks * blockSize );
}
void CollectPackageInformation( Context context ) {
Log.d(LOG_TAG, "@CollectPackageInformation");
try {
PackageManager pm = context.getPackageManager();
PackageInfo pi = pm.getPackageInfo(context.getPackageName(), 0);
mPkg_VersionName = pi.versionName;
mPkg_PackageName = pi.packageName;
mCtx_FilePath = context.getFilesDir().getAbsolutePath();
mPkg_OSBld_PhoneModel = android.os.Build.MODEL;
mPkg_OSBld_AndroidVersion = android.os.Build.VERSION.RELEASE;
mPkg_OSBld_Board = android.os.Build.BOARD;
mPkg_OSBld_Brand = android.os.Build.BRAND;
mPkg_OSBld_Device = android.os.Build.DEVICE;
mPkg_OSBld_Display = android.os.Build.DISPLAY;
mPkg_OSBld_FingerPrint = android.os.Build.FINGERPRINT;
mPkg_OSBld_Host = android.os.Build.HOST;
mPkg_OSBld_ID = android.os.Build.ID;
mPkg_OSBld_Model = android.os.Build.MODEL;
mPkg_OSBld_Product = android.os.Build.PRODUCT;
mPkg_OSBld_Tags = android.os.Build.TAGS;
mPkg_OSBld_Time = android.os.Build.TIME;
mPkg_OSBld_Type = android.os.Build.TYPE;
mPkg_OSBld_User = android.os.Build.USER;
} catch( Exception e ) {
Log.e(LOG_TAG, "!Error CollectPackageInformation: " + e.getMessage());
// e.printStackTrace()
}
}
/**
* Assemble the package information in a string format
* @return String - Package information collected
*/
private String CreateInformationString() {
CollectPackageInformation( mCurContext );
String ReturnVal = "";
ReturnVal = " Version : " + mPkg_VersionName + "\n";
ReturnVal += " Package : " + mPkg_PackageName + "\n";
ReturnVal += " FilePath : " + mCtx_FilePath + "\n\n";
ReturnVal += " Package Data \n";
ReturnVal += " Phone Model : " + mPkg_OSBld_PhoneModel + "\n";
ReturnVal += " Android Ver : " + mPkg_OSBld_AndroidVersion + "\n";
ReturnVal += " Board : " + mPkg_OSBld_Board + "\n";
ReturnVal += " Brand : " + mPkg_OSBld_Brand + "\n";
ReturnVal += " Device : " + mPkg_OSBld_Device + "\n";
ReturnVal += " Display : " + mPkg_OSBld_Display + "\n";
ReturnVal += " Finger Print: " + mPkg_OSBld_FingerPrint + "\n";
ReturnVal += " Host : " + mPkg_OSBld_Host + "\n";
ReturnVal += " ID : " + mPkg_OSBld_ID + "\n";
ReturnVal += " Model : " + mPkg_OSBld_Model + "\n";
ReturnVal += " Product : " + mPkg_OSBld_Product + "\n";
ReturnVal += " Tags : " + mPkg_OSBld_Tags + "\n";
ReturnVal += " Time : " + mPkg_OSBld_Time + "\n";
ReturnVal += " Type : " + mPkg_OSBld_Type + "\n";
ReturnVal += " User : " + mPkg_OSBld_User + "\n";
ReturnVal += " Internal Memory\n";
ReturnVal += " Total : " + (getTotalInternalMemorySize() /1024) + "k\n";
ReturnVal += " Available: " + (getAvailableInternalMemorySize() /1024) + "k\n\n";
return ReturnVal;
}
/**
*Saves the Crash Report to a File with the name stack-timestamp.stacktrace in SD card
*
*/
private void SaveAsFile( String ErrorContent ) {
try {
long timestamp = System.currentTimeMillis();
String ErrFileName = "stack-" + timestamp + ".stacktrace";
FileOutputStream trace = mCurContext.openFileOutput( ErrFileName, Context.MODE_PRIVATE);
trace.write(ErrorContent.getBytes());
trace.flush();
trace.close();
Log.e(LOG_TAG, "!Error Report: " + ErrFileName + "\n" + ErrorContent);
} catch( Exception e ) {
Log.e(LOG_TAG, "!Error SaveAsFile: " + e.getMessage());
}
}
/**
* Returns an array containing the names of available crash report files.
*
* @return an array containing the names of available crash report files.
*/
private String[] GetCrashErrorFileList() {
File dir = mCurContext.getFilesDir();
Log.d(LOG_TAG, "Looking for error files in " + dir.getAbsolutePath());
// Filter for "stack trace" files
FilenameFilter filter = new FilenameFilter() {
public boolean accept(File dir, String name) {
return name.endsWith(".stacktrace");
}
};
return dir.list(filter);
}
/**
* Checks to see if there are any crash reports to send and sends them if they exist
* Once finished with the report, then the report file is deleted from the system
*
* @param _context
*/
public void CheckCrashErrorAndSendMail(Context _context )
{
try {
if( null == mCtx_FilePath ) {
mCtx_FilePath = _context.getFilesDir().getAbsolutePath();
}
String[] reportFilesList = GetCrashErrorFileList();
TreeSet<String> sortedFiles = new TreeSet<String>();
sortedFiles.addAll(Arrays.asList(reportFilesList));
if((null != reportFilesList) && (0 < reportFilesList.length)) {
String line;
String WholeErrorText = "";
int curIndex = 0;
final int MaxSendMail = 5;
for ( String curString : sortedFiles )
{
if ( curIndex++ <= MaxSendMail )
{
WholeErrorText+="New Trace collected :\n";
WholeErrorText+="=====================\n ";
String filePath = mCtx_FilePath + "/" + curString;
BufferedReader input = new BufferedReader(new FileReader(filePath));
while (( line = input.readLine()) != null) {
WholeErrorText += line + "\n";
}
input.close();
}
// DELETE FILES !!!!
File curFile = new File( mCtx_FilePath + "/" + curString );
curFile.delete();
}
SendCrashErrorMail( _context , WholeErrorText,_context.getString(R.string.CrashErrorReport_MailTo) );
}
} catch( Exception e ) {
Log.e(LOG_TAG, "!Error CheckCrashErrorAndSendMail: " + e.getMessage());
// e.printStackTrace();
}
}
/**
* Send out the crash error report via e-mail
*
* @param _context
* @param ErrorContent
*/
private void SendCrashErrorMail( Context _context, String ErrorContent,String mailTo) {
Log.d(LOG_TAG, "SendCrashErrorMail: " + _context.getString(R.string.CrashErrorReport_MailTo));
//Toast.makeText(_context, _context.getString(R.string.CrashErrorReport_ToastText), Toast.LENGTH_LONG).show();
Intent sendIntent = new Intent(Intent.ACTION_SEND);
sendIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
sendIntent.putExtra(Intent.EXTRA_EMAIL, new String[]{_context.getString(R.string.CrashErrorReport_MailTo)});
sendIntent.putExtra(Intent.EXTRA_SUBJECT, _context.getString(R.string.CrashErrorReport_MailSubject));
sendIntent.putExtra(Intent.EXTRA_TEXT, ErrorContent + "\n");
sendIntent.setType("message/rfc822");
_context.startActivity( sendIntent );
}
/**
* Send out the crash report via HTTP connection
* NOTE: This is currently not used, but here for future implementation
* @param _context
* @param ErrorContent
*
* The below code would need to be placed on an server to receive HTTP transmissions.
* upload_server.php
* <?php
* if ( $_POST['stacktrace'] == "" || $_POST['package_version'] == "" || $_POST['package_name'] == "" ) {
* die("This script is used to collect field test crash stacktraces. No personal information is transmitted, collected or stored.<br/>For more information, please contact <a href='mailto:support@nullwire.com'>email@domain.com</a>");
* }
* $random = rand(1000,9999);
* $version = $_POST['package_version'];
* $package = $_POST['package_name'];
* $handle = fopen($package."-trace-".$version."-".time()."-".$random, "w+");
* fwrite($handle, $_POST['stacktrace']);
* fclose($handle);
*
* ?>
*
*/
@SuppressWarnings("unused")
private void SendCrashErrorHTTP( Context _context, String ErrorContent ) {
Log.d(LOG_TAG, "SendCrashErrorHTTP: " + _context.getString(R.string.CrashErrorReport_URL));
Toast.makeText(_context, _context.getString(R.string.CrashErrorReport_ToastText), Toast.LENGTH_LONG).show();
String sError = null;
// Transmit stack trace with POST request
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(_context.getString(R.string.CrashErrorReport_URL));
List <NameValuePair> nvps = new ArrayList <NameValuePair>();
nvps.add(new BasicNameValuePair("package_name", mPkg_PackageName));
nvps.add(new BasicNameValuePair("package_version", mPkg_VersionName));
nvps.add(new BasicNameValuePair("phone_model", mPkg_OSBld_PhoneModel));
nvps.add(new BasicNameValuePair("android_version", mPkg_OSBld_AndroidVersion));
nvps.add(new BasicNameValuePair("stacktrace", ErrorContent));
try {
httpPost.setEntity(new UrlEncodedFormEntity(nvps, HTTP.UTF_8));
// We don't care about the response, so we just hope it went well and on with it
httpClient.execute(httpPost);
} catch (UnsupportedEncodingException e) {
sError = e.getMessage();
} catch (ClientProtocolException e) {
sError = e.getMessage();
} catch (IOException e) {
sError = e.getMessage();
} finally {
sError = "Unknown Error condition";
}
if( null != sError ) {
Log.e(LOG_TAG, "!Error SendCrashErrorHTTP: " + sError);
}
}
// End Class
}
------------------------------------------------------
You can add this feature by intiating this code in any activity like Loading,SplashScreen.
// Register the Crash Reporting feature
------------------------------------------
// Initialize ErrorReporter with all required data
CrashErrorReporter mCrashErrorReporter = CrashErrorReporter.getInstance();
// Activate the ErrorReporter
mCrashErrorReporter.Init(getApplicationContext());
mCrashErrorReporter.CheckCrashErrorAndSendMail(getApplicationContext());
-------------------------------------------------
This just works amazing...
Let me know if any problems you have.
Solution:
A crash reporter is an feature whose function is to report crash data to a third party, usually to the party responsible for the crashed program. Crash reports often include data such as stack traces, type of crash, and version of software. This information helps software developers to diagnose and fix the underlying problem causing the crash.
The Android and iOS operating systems also have built in crash reporting functionality.
There are third party tools that also provide it, like
BugSense :
BugSense is made for mobile developers. Get the context of the errors, track errors in specific app version or filter errors by device. There was Internet connectivity at the time of the crash? BugSense collects all the information the mobile developer needs.
ACRA (Application Crash Report for Android).
ACRA is a library enabling Android Application to automatically post their crash reports to a GoogleDoc form. It is targetted to android applications developers to help them get data from their applications when they crash or behave erroneously.
However you can add this feature with the following code block.
---------------------------------------------------------------------------------
/**
* Crash Error Reporter
*
* Captures any Uncaught exception to capture the conditions that caused the event.
* The event will be written to the Log file and can be retrieved through LogCat.
* In addition, the report will attempt to send an e-mail to <string name="CrashErrorReport_MailTo">xyz@GMail.com</string>
* through the default mail application
* *
*/
public class CrashErrorReporter implements Thread.UncaughtExceptionHandler {
private static final String LOG_TAG = "CrashErrorReporter";
private Thread.UncaughtExceptionHandler mDfltExceptionHandler;
private static CrashErrorReporter S_mInstance;
private static Context mCurContext;
// Even though these should be private variables,
// they are public to avoid creating getters and setters
String mPkg_VersionName;
String mPkg_PackageName;
String mCtx_FilePath;
String mPkg_OSBld_PhoneModel;
String mPkg_OSBld_AndroidVersion;
String mPkg_OSBld_Board;
String mPkg_OSBld_Brand;
String mPkg_OSBld_Device;
String mPkg_OSBld_Display;
String mPkg_OSBld_FingerPrint;
String mPkg_OSBld_Host;
String mPkg_OSBld_ID;
String mPkg_OSBld_Manufacturer;
String mPkg_OSBld_Model;
String mPkg_OSBld_Product;
String mPkg_OSBld_Tags;
long mPkg_OSBld_Time;
String mPkg_OSBld_Type;
String mPkg_OSBld_User;
/**
* Manages the uncaught exception.
*/
@Override
public void uncaughtException(Thread t, Throwable e) {
Log.d(LOG_TAG, "@Override uncaughtException");
Date CurDate = new Date();
String Report = "Error Report collected on : " + CurDate.toString() + "\n\n";
Report += "Environment Details : \n";
Report += "===================== \n";
Report += CreateInformationString();
Report += "Stack : \n";
Report += "======= \n";
final Writer result = new StringWriter();
final PrintWriter printWriter = new PrintWriter(result);
e.printStackTrace(printWriter);
String stacktrace = result.toString();
Report += stacktrace + "\n";
// If the exception was thrown in a background thread inside
// AsyncTask, then the actual exception can be found with getCause
Throwable cause = e.getCause();
while (cause != null) {
Report += "Cause : \n";
Report += "======= \n";
cause.printStackTrace( printWriter );
Report += result.toString();
cause = cause.getCause();
}
printWriter.close();
Report += "**** End of current Report ***";
SaveAsFile(Report);
// Try and send out the report now before calling the default handler
CheckCrashErrorAndSendMail(mCurContext);
mDfltExceptionHandler.uncaughtException(t, e);
}
/**
* Capture the newly created instance for singleton class management
*/
public static CrashErrorReporter getInstance() {
if ( S_mInstance == null )
S_mInstance = new CrashErrorReporter();
return S_mInstance;
}
public void Init( Context context ) {
mDfltExceptionHandler = Thread.getDefaultUncaughtExceptionHandler();
Thread.setDefaultUncaughtExceptionHandler( this );
mCurContext = context;
}
/**
* Obtains the available internal memory size
* @return long - integer with memory size available
*/
public long getAvailableInternalMemorySize() {
File path = Environment.getDataDirectory();
StatFs stat = new StatFs(path.getPath());
// place in stack variables for debugging purposes.
long blockSize = stat.getBlockSize();
long availableBlocks = stat.getAvailableBlocks();
return( availableBlocks * blockSize );
}
/**
* Obtains the Total internal memory size
* @return long - integer with total memory size
*/
public long getTotalInternalMemorySize() {
File path = Environment.getDataDirectory();
StatFs stat = new StatFs(path.getPath());
// place in stack variables for debugging purposes.
long blockSize = stat.getBlockSize();
long totalBlocks = stat.getBlockCount();
return( totalBlocks * blockSize );
}
void CollectPackageInformation( Context context ) {
Log.d(LOG_TAG, "@CollectPackageInformation");
try {
PackageManager pm = context.getPackageManager();
PackageInfo pi = pm.getPackageInfo(context.getPackageName(), 0);
mPkg_VersionName = pi.versionName;
mPkg_PackageName = pi.packageName;
mCtx_FilePath = context.getFilesDir().getAbsolutePath();
mPkg_OSBld_PhoneModel = android.os.Build.MODEL;
mPkg_OSBld_AndroidVersion = android.os.Build.VERSION.RELEASE;
mPkg_OSBld_Board = android.os.Build.BOARD;
mPkg_OSBld_Brand = android.os.Build.BRAND;
mPkg_OSBld_Device = android.os.Build.DEVICE;
mPkg_OSBld_Display = android.os.Build.DISPLAY;
mPkg_OSBld_FingerPrint = android.os.Build.FINGERPRINT;
mPkg_OSBld_Host = android.os.Build.HOST;
mPkg_OSBld_ID = android.os.Build.ID;
mPkg_OSBld_Model = android.os.Build.MODEL;
mPkg_OSBld_Product = android.os.Build.PRODUCT;
mPkg_OSBld_Tags = android.os.Build.TAGS;
mPkg_OSBld_Time = android.os.Build.TIME;
mPkg_OSBld_Type = android.os.Build.TYPE;
mPkg_OSBld_User = android.os.Build.USER;
} catch( Exception e ) {
Log.e(LOG_TAG, "!Error CollectPackageInformation: " + e.getMessage());
// e.printStackTrace()
}
}
/**
* Assemble the package information in a string format
* @return String - Package information collected
*/
private String CreateInformationString() {
CollectPackageInformation( mCurContext );
String ReturnVal = "";
ReturnVal = " Version : " + mPkg_VersionName + "\n";
ReturnVal += " Package : " + mPkg_PackageName + "\n";
ReturnVal += " FilePath : " + mCtx_FilePath + "\n\n";
ReturnVal += " Package Data \n";
ReturnVal += " Phone Model : " + mPkg_OSBld_PhoneModel + "\n";
ReturnVal += " Android Ver : " + mPkg_OSBld_AndroidVersion + "\n";
ReturnVal += " Board : " + mPkg_OSBld_Board + "\n";
ReturnVal += " Brand : " + mPkg_OSBld_Brand + "\n";
ReturnVal += " Device : " + mPkg_OSBld_Device + "\n";
ReturnVal += " Display : " + mPkg_OSBld_Display + "\n";
ReturnVal += " Finger Print: " + mPkg_OSBld_FingerPrint + "\n";
ReturnVal += " Host : " + mPkg_OSBld_Host + "\n";
ReturnVal += " ID : " + mPkg_OSBld_ID + "\n";
ReturnVal += " Model : " + mPkg_OSBld_Model + "\n";
ReturnVal += " Product : " + mPkg_OSBld_Product + "\n";
ReturnVal += " Tags : " + mPkg_OSBld_Tags + "\n";
ReturnVal += " Time : " + mPkg_OSBld_Time + "\n";
ReturnVal += " Type : " + mPkg_OSBld_Type + "\n";
ReturnVal += " User : " + mPkg_OSBld_User + "\n";
ReturnVal += " Internal Memory\n";
ReturnVal += " Total : " + (getTotalInternalMemorySize() /1024) + "k\n";
ReturnVal += " Available: " + (getAvailableInternalMemorySize() /1024) + "k\n\n";
return ReturnVal;
}
/**
*Saves the Crash Report to a File with the name stack-timestamp.stacktrace in SD card
*
*/
private void SaveAsFile( String ErrorContent ) {
try {
long timestamp = System.currentTimeMillis();
String ErrFileName = "stack-" + timestamp + ".stacktrace";
FileOutputStream trace = mCurContext.openFileOutput( ErrFileName, Context.MODE_PRIVATE);
trace.write(ErrorContent.getBytes());
trace.flush();
trace.close();
Log.e(LOG_TAG, "!Error Report: " + ErrFileName + "\n" + ErrorContent);
} catch( Exception e ) {
Log.e(LOG_TAG, "!Error SaveAsFile: " + e.getMessage());
}
}
/**
* Returns an array containing the names of available crash report files.
*
* @return an array containing the names of available crash report files.
*/
private String[] GetCrashErrorFileList() {
File dir = mCurContext.getFilesDir();
Log.d(LOG_TAG, "Looking for error files in " + dir.getAbsolutePath());
// Filter for "stack trace" files
FilenameFilter filter = new FilenameFilter() {
public boolean accept(File dir, String name) {
return name.endsWith(".stacktrace");
}
};
return dir.list(filter);
}
/**
* Checks to see if there are any crash reports to send and sends them if they exist
* Once finished with the report, then the report file is deleted from the system
*
* @param _context
*/
public void CheckCrashErrorAndSendMail(Context _context )
{
try {
if( null == mCtx_FilePath ) {
mCtx_FilePath = _context.getFilesDir().getAbsolutePath();
}
String[] reportFilesList = GetCrashErrorFileList();
TreeSet<String> sortedFiles = new TreeSet<String>();
sortedFiles.addAll(Arrays.asList(reportFilesList));
if((null != reportFilesList) && (0 < reportFilesList.length)) {
String line;
String WholeErrorText = "";
int curIndex = 0;
final int MaxSendMail = 5;
for ( String curString : sortedFiles )
{
if ( curIndex++ <= MaxSendMail )
{
WholeErrorText+="New Trace collected :\n";
WholeErrorText+="=====================\n ";
String filePath = mCtx_FilePath + "/" + curString;
BufferedReader input = new BufferedReader(new FileReader(filePath));
while (( line = input.readLine()) != null) {
WholeErrorText += line + "\n";
}
input.close();
}
// DELETE FILES !!!!
File curFile = new File( mCtx_FilePath + "/" + curString );
curFile.delete();
}
SendCrashErrorMail( _context , WholeErrorText,_context.getString(R.string.CrashErrorReport_MailTo) );
}
} catch( Exception e ) {
Log.e(LOG_TAG, "!Error CheckCrashErrorAndSendMail: " + e.getMessage());
// e.printStackTrace();
}
}
/**
* Send out the crash error report via e-mail
*
* @param _context
* @param ErrorContent
*/
private void SendCrashErrorMail( Context _context, String ErrorContent,String mailTo) {
Log.d(LOG_TAG, "SendCrashErrorMail: " + _context.getString(R.string.CrashErrorReport_MailTo));
//Toast.makeText(_context, _context.getString(R.string.CrashErrorReport_ToastText), Toast.LENGTH_LONG).show();
Intent sendIntent = new Intent(Intent.ACTION_SEND);
sendIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
sendIntent.putExtra(Intent.EXTRA_EMAIL, new String[]{_context.getString(R.string.CrashErrorReport_MailTo)});
sendIntent.putExtra(Intent.EXTRA_SUBJECT, _context.getString(R.string.CrashErrorReport_MailSubject));
sendIntent.putExtra(Intent.EXTRA_TEXT, ErrorContent + "\n");
sendIntent.setType("message/rfc822");
_context.startActivity( sendIntent );
}
/**
* Send out the crash report via HTTP connection
* NOTE: This is currently not used, but here for future implementation
* @param _context
* @param ErrorContent
*
* The below code would need to be placed on an server to receive HTTP transmissions.
* upload_server.php
* <?php
* if ( $_POST['stacktrace'] == "" || $_POST['package_version'] == "" || $_POST['package_name'] == "" ) {
* die("This script is used to collect field test crash stacktraces. No personal information is transmitted, collected or stored.<br/>For more information, please contact <a href='mailto:support@nullwire.com'>email@domain.com</a>");
* }
* $random = rand(1000,9999);
* $version = $_POST['package_version'];
* $package = $_POST['package_name'];
* $handle = fopen($package."-trace-".$version."-".time()."-".$random, "w+");
* fwrite($handle, $_POST['stacktrace']);
* fclose($handle);
*
* ?>
*
*/
@SuppressWarnings("unused")
private void SendCrashErrorHTTP( Context _context, String ErrorContent ) {
Log.d(LOG_TAG, "SendCrashErrorHTTP: " + _context.getString(R.string.CrashErrorReport_URL));
Toast.makeText(_context, _context.getString(R.string.CrashErrorReport_ToastText), Toast.LENGTH_LONG).show();
String sError = null;
// Transmit stack trace with POST request
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(_context.getString(R.string.CrashErrorReport_URL));
List <NameValuePair> nvps = new ArrayList <NameValuePair>();
nvps.add(new BasicNameValuePair("package_name", mPkg_PackageName));
nvps.add(new BasicNameValuePair("package_version", mPkg_VersionName));
nvps.add(new BasicNameValuePair("phone_model", mPkg_OSBld_PhoneModel));
nvps.add(new BasicNameValuePair("android_version", mPkg_OSBld_AndroidVersion));
nvps.add(new BasicNameValuePair("stacktrace", ErrorContent));
try {
httpPost.setEntity(new UrlEncodedFormEntity(nvps, HTTP.UTF_8));
// We don't care about the response, so we just hope it went well and on with it
httpClient.execute(httpPost);
} catch (UnsupportedEncodingException e) {
sError = e.getMessage();
} catch (ClientProtocolException e) {
sError = e.getMessage();
} catch (IOException e) {
sError = e.getMessage();
} finally {
sError = "Unknown Error condition";
}
if( null != sError ) {
Log.e(LOG_TAG, "!Error SendCrashErrorHTTP: " + sError);
}
}
// End Class
}
------------------------------------------------------
You can add this feature by intiating this code in any activity like Loading,SplashScreen.
// Register the Crash Reporting feature
------------------------------------------
// Initialize ErrorReporter with all required data
CrashErrorReporter mCrashErrorReporter = CrashErrorReporter.getInstance();
// Activate the ErrorReporter
mCrashErrorReporter.Init(getApplicationContext());
mCrashErrorReporter.CheckCrashErrorAndSendMail(getApplicationContext());
-------------------------------------------------
This just works amazing...
Let me know if any problems you have.
Thanks..
ReplyDeleteThat is really attention-grabbing, You're a very professional blogger. I've joined your feed and stay up
ReplyDeletefor in quest of more of your wonderful post. Also, I've shared your web site in my social networks
Here is my web blog - metabolic rate calculator
Very nice article. I absolutely love this website. Thanks!
ReplyDeleteStop by my web blog US real estate agents
Hi mates, its impressive article regarding tutoringand completely defined, keep
ReplyDeleteit up all the time.
Stop by my site; definition essay examples
excellent issues altogether, you just won a brand new reader.
ReplyDeleteWhat would you recommend in regards to your put up that you simply made some days in the past?
Any certain?
Review my web site :: US real estate agents directory
What's up it's me, I am also visiting this website daily, this website is really good and the users are really sharing
ReplyDeletepleasant thoughts.
Visit my site - poetry research paper
Hello colleagues, how is the whole thing, and what you desire to say about this
ReplyDeleteparagraph, in my view its in fact awesome designed for me.
Feel free to surf to my web-site: us business directories
Please let me know if you're looking for a author for your weblog. You have some really great posts and I believe I would be a good asset. If you ever want to take some of the load off, I'd really like to
ReplyDeletewrite some material for your blog in exchange
for a link back to mine. Please shoot me an e-mail if interested.
Kudos!
my page: term paper formats
I love reading a post that will make people
ReplyDeletethink. Also, many thanks for allowing me to comment!
Look into my web-site top business directory sites
Everything is very open with a very clear description of
ReplyDeletethe challenges. It was definitely informative.
Your site is extremely helpful. Many thanks for
sharing!
my blog post; movie discussion guides
This page certainly has all of the information I wanted about this subject and didn't know who to ask.
ReplyDeletemy weblog: cartoon t shirts for adults
Post writing is also a fun, if you know after
ReplyDeletethat you can write if not it is complex to write.
Also visit my web site: cheap cartoon t-shirts
It's in reality a nice and helpful piece of information. I'm satisfied that you just shared this useful info with us.
ReplyDeletePlease keep us up to date like this. Thank you for sharing.
Feel free to visit my web blog ... custom college essays
Thanks for the auspicious writeup. It actually was a leisure account it.
ReplyDeleteGlance advanced to far added agreeable from you! However, how could we be in contact?
My web blog; buy old computers charlotte nc
whoah this blog is magnificent i love reading your articles.
ReplyDeleteStay up the good work! You know, lots of persons are searching
round for this info, you could help them greatly.
Also visit my webpage - local company directory
Thanks
ReplyDeleteExcelent!
ReplyDeleteThanks. It saved my day!
Excellent Work..Helps Me a Lot. But when the app crashes its ask for actions i am choosing by email . ,instead of asking any actions can we directly sends the email when app crashes without asking any actions like send by email or etc .., Waiting For Your response .Thanks in Advance
ReplyDeleteThanks for the detailed information!
ReplyDeleteThere are two other products that do a good job, Gryphonet and Crashlytics.
The advantage of Gryphonet is that it's automatic and reproduction of malfunction is very easy.
Excellent Post !!
ReplyDeleteThanks.
hi thanks for this wonderful idea to achieve success to my app crash reporting problem.i really like this post.
ReplyDelete