init commit
This commit is contained in:
7
ExceptionHandlerLib/.classpath
Normal file
7
ExceptionHandlerLib/.classpath
Normal file
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="src" path="src"/>
|
||||
<classpathentry kind="src" path="gen"/>
|
||||
<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
|
||||
<classpathentry kind="output" path="bin/classes"/>
|
||||
</classpath>
|
||||
6
ExceptionHandlerLib/.directory
Normal file
6
ExceptionHandlerLib/.directory
Normal file
@@ -0,0 +1,6 @@
|
||||
[Dolphin]
|
||||
Timestamp=2011,10,24,10,7,6
|
||||
Version=2
|
||||
|
||||
[Settings]
|
||||
ShowDotFiles=true
|
||||
33
ExceptionHandlerLib/.project
Normal file
33
ExceptionHandlerLib/.project
Normal file
@@ -0,0 +1,33 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>ExceptionHandlerLib</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>com.android.ide.eclipse.adt.ApkBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>com.android.ide.eclipse.adt.AndroidNature</nature>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
||||
12
ExceptionHandlerLib/AndroidManifest.xml
Normal file
12
ExceptionHandlerLib/AndroidManifest.xml
Normal file
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.TwentyCodes.android.exception"
|
||||
android:versionCode="1"
|
||||
android:versionName="1.0">
|
||||
<uses-sdk android:minSdkVersion="14" />
|
||||
|
||||
<application >
|
||||
|
||||
|
||||
</application>
|
||||
</manifest>
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
ExceptionHandlerLib/bin/exceptionhandlerlib.jar
Normal file
BIN
ExceptionHandlerLib/bin/exceptionhandlerlib.jar
Normal file
Binary file not shown.
20
ExceptionHandlerLib/exceptionhandler.properties
Normal file
20
ExceptionHandlerLib/exceptionhandler.properties
Normal file
@@ -0,0 +1,20 @@
|
||||
# exceptionhandler.properties
|
||||
# This is the default Twenty Codes, LLC Exception Handler properties file
|
||||
#
|
||||
# This file must be included in the main project's assets folder
|
||||
#
|
||||
# @author Twenty Codes, LLC
|
||||
# @author ricky barrette
|
||||
|
||||
|
||||
# The following is for using our custom server based exception handler web application
|
||||
# server is the physical web address for your server
|
||||
# file is the path to your filing script
|
||||
# get is the path to your json retrieval script
|
||||
server = http://powers.doesntexist.com:666/testing
|
||||
file = /index.php?post=1
|
||||
#get = /index.php?get=1
|
||||
|
||||
# uncomment the following if you want your application to use email to file reports.
|
||||
# if this is uncommented, email will always be used.
|
||||
#email = twentycodes@gmail.com
|
||||
@@ -0,0 +1,32 @@
|
||||
/* AUTO-GENERATED FILE. DO NOT MODIFY.
|
||||
*
|
||||
* This class was automatically generated by the
|
||||
* aapt tool from the resource data it found. It
|
||||
* should not be modified by hand.
|
||||
*/
|
||||
|
||||
package com.TwentyCodes.android.exception;
|
||||
|
||||
public final class R {
|
||||
public static final class attr {
|
||||
}
|
||||
public static final class id {
|
||||
public static int description=0x7f040001;
|
||||
public static int exception_text=0x7f040003;
|
||||
public static int exception_title=0x7f040002;
|
||||
public static int send=0x7f040000;
|
||||
}
|
||||
public static final class layout {
|
||||
public static int exception_activity=0x7f020000;
|
||||
public static int exception_list_item=0x7f020001;
|
||||
public static int list=0x7f020002;
|
||||
}
|
||||
public static final class string {
|
||||
public static int crash=0x7f030000;
|
||||
public static int description=0x7f030004;
|
||||
public static int send=0x7f030003;
|
||||
public static int sending=0x7f030002;
|
||||
public static int sorry=0x7f030001;
|
||||
public static int version=0x7f030005;
|
||||
}
|
||||
}
|
||||
34
ExceptionHandlerLib/proguard.cfg
Normal file
34
ExceptionHandlerLib/proguard.cfg
Normal file
@@ -0,0 +1,34 @@
|
||||
-optimizationpasses 5
|
||||
-dontusemixedcaseclassnames
|
||||
-dontskipnonpubliclibraryclasses
|
||||
-dontpreverify
|
||||
-verbose
|
||||
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
|
||||
|
||||
-keep public class * extends android.app.Activity
|
||||
-keep public class * extends android.app.Application
|
||||
-keep public class * extends android.app.Service
|
||||
-keep public class * extends android.content.BroadcastReceiver
|
||||
-keep public class * extends android.content.ContentProvider
|
||||
-keep public class com.android.vending.licensing.ILicensingService
|
||||
|
||||
-keepclasseswithmembernames class * {
|
||||
native <methods>;
|
||||
}
|
||||
|
||||
-keepclasseswithmembernames class * {
|
||||
public <init>(android.content.Context, android.util.AttributeSet);
|
||||
}
|
||||
|
||||
-keepclasseswithmembernames class * {
|
||||
public <init>(android.content.Context, android.util.AttributeSet, int);
|
||||
}
|
||||
|
||||
-keepclassmembers enum * {
|
||||
public static **[] values();
|
||||
public static ** valueOf(java.lang.String);
|
||||
}
|
||||
|
||||
-keep class * implements android.os.Parcelable {
|
||||
public static final android.os.Parcelable$Creator *;
|
||||
}
|
||||
12
ExceptionHandlerLib/project.properties
Normal file
12
ExceptionHandlerLib/project.properties
Normal file
@@ -0,0 +1,12 @@
|
||||
# This file is automatically generated by Android Tools.
|
||||
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
|
||||
#
|
||||
# This file must be checked in Version Control Systems.
|
||||
#
|
||||
# To customize properties used by the Ant build system use,
|
||||
# "ant.properties", and override values to adapt the script to your
|
||||
# project structure.
|
||||
|
||||
android.library=true
|
||||
# Project target.
|
||||
target=android-14
|
||||
32
ExceptionHandlerLib/res/layout/exception_activity.xml
Normal file
32
ExceptionHandlerLib/res/layout/exception_activity.xml
Normal file
@@ -0,0 +1,32 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="#ffffff">
|
||||
|
||||
<Button
|
||||
android:id="@+id/send"
|
||||
android:text="@string/send"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentTop="true"
|
||||
/>
|
||||
|
||||
<EditText
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/description"
|
||||
android:id="@+id/description"
|
||||
android:layout_below="@id/send"
|
||||
android:freezesText="true"
|
||||
/>
|
||||
|
||||
<ListView
|
||||
android:layout_below="@id/description"
|
||||
android:id="@android:id/list"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
/>
|
||||
|
||||
</RelativeLayout>
|
||||
27
ExceptionHandlerLib/res/layout/exception_list_item.xml
Normal file
27
ExceptionHandlerLib/res/layout/exception_list_item.xml
Normal file
@@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:background="#ffffff">
|
||||
|
||||
<TextView
|
||||
android:text="title"
|
||||
android:id="@+id/exception_title"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="?android:attr/textAppearanceLarge"
|
||||
android:gravity="center_vertical"
|
||||
android:textColor="#99CC00"
|
||||
/>
|
||||
|
||||
<TextView
|
||||
android:text="body"
|
||||
android:id="@+id/exception_text"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="#000000"
|
||||
/>
|
||||
|
||||
</LinearLayout>
|
||||
21
ExceptionHandlerLib/res/layout/list.xml
Normal file
21
ExceptionHandlerLib/res/layout/list.xml
Normal file
@@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
|
||||
>
|
||||
<ListView
|
||||
android:id="@android:id/list"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
/>
|
||||
<TextView android:id="@android:id/empty"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="?android:attr/textAppearanceLarge"
|
||||
android:gravity="center_vertical"
|
||||
android:textColor="#99CC00"
|
||||
android:text="No Reports"
|
||||
/>
|
||||
</LinearLayout>
|
||||
9
ExceptionHandlerLib/res/values/strings.xml
Normal file
9
ExceptionHandlerLib/res/values/strings.xml
Normal file
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="crash">Application Fault</string>
|
||||
<string name="sorry">I\'m sorry, but we found a problem. Please click here.</string>
|
||||
<string name="sending">Sending...</string>
|
||||
<string name="send">Send</string>
|
||||
<string name="description">Optional: Describe what happened</string>
|
||||
<string name="version">Version</string>
|
||||
</resources>
|
||||
@@ -0,0 +1,225 @@
|
||||
/**
|
||||
* ExceptionHandler.java
|
||||
* @date Feb 12, 2011
|
||||
* @author ricky barrette
|
||||
* @author Twenty Codes, LLC
|
||||
*/
|
||||
package com.TwentyCodes.android.exception;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.lang.Thread.UncaughtExceptionHandler;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.Properties;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.Notification;
|
||||
import android.app.NotificationManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.app.Service;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.PackageManager.NameNotFoundException;
|
||||
import android.content.res.AssetManager;
|
||||
import android.content.res.Resources;
|
||||
import android.os.Build;
|
||||
import android.util.Log;
|
||||
|
||||
/**
|
||||
* This is Twenty Codes, LLC Exception Handler of Awesomeness!
|
||||
* This class will be used to generate reports that will be emailed to us via the users email client after the users approval
|
||||
* @author ricky barrette
|
||||
*/
|
||||
public class ExceptionHandler implements UncaughtExceptionHandler, Runnable {
|
||||
|
||||
private static final String MSG_SUBJECT_TAG = "Exception Report";
|
||||
private static final String MSG_BODY = "Just click send to help make this application better. "+
|
||||
"No personal information is being sent (you can check by reading the rest of the email).";
|
||||
protected static final int SIMPLE_NOTFICATION_ID = 45684645;
|
||||
private Thread.UncaughtExceptionHandler mDefaultUEH;
|
||||
private Activity mApp= null;
|
||||
private Service mService = null;
|
||||
private BroadcastReceiver mBroadcastReceiver = null;
|
||||
private Context mContext;
|
||||
private Report mReport;
|
||||
private static final String TAG = "ExceptionHandler";
|
||||
private String mURL = null;
|
||||
private String mEmail;
|
||||
|
||||
/**
|
||||
* Creates a new ExceptionHandler
|
||||
* @param app
|
||||
* @author ricky barrette
|
||||
*/
|
||||
public ExceptionHandler(Activity app) {
|
||||
this.mDefaultUEH = Thread.getDefaultUncaughtExceptionHandler();
|
||||
this.mApp = app;
|
||||
this.mContext = app;
|
||||
parseProperties();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new ExceptionHandler
|
||||
* @param broadcastReceiver
|
||||
* @author ricky barrette
|
||||
*/
|
||||
public ExceptionHandler(BroadcastReceiver broadcastReceiver, Context context){
|
||||
this.mDefaultUEH = Thread.getDefaultUncaughtExceptionHandler();
|
||||
this.mBroadcastReceiver = broadcastReceiver;
|
||||
this.mContext = context;
|
||||
parseProperties();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new ExceptionHandler
|
||||
* @param service
|
||||
* @author ricky barrette
|
||||
*/
|
||||
public ExceptionHandler(Service service){
|
||||
this.mDefaultUEH = Thread.getDefaultUncaughtExceptionHandler();
|
||||
this.mService = service;
|
||||
this.mContext = service;
|
||||
parseProperties();
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates an email from the report
|
||||
* @author ricky barrette
|
||||
*/
|
||||
private void displayEmailNotification(){
|
||||
Log.i(TAG, "displayEmailNotification");
|
||||
|
||||
CharSequence title = null;
|
||||
if(mApp != null)
|
||||
title = mApp.getTitle();
|
||||
|
||||
if(mService != null)
|
||||
title = mService.getClass().getName();
|
||||
|
||||
if(mBroadcastReceiver != null)
|
||||
title = mBroadcastReceiver.getClass().getName();
|
||||
|
||||
Intent intent = new Intent(Intent.ACTION_SEND);
|
||||
String theSubject = title + " " + MSG_SUBJECT_TAG;
|
||||
String theBody = "\n\n"+MSG_BODY+this.mReport.toString();
|
||||
intent.putExtra(Intent.EXTRA_EMAIL,new String[] {this.mEmail});
|
||||
intent.putExtra(Intent.EXTRA_TEXT, theBody);
|
||||
intent.putExtra(Intent.EXTRA_SUBJECT, theSubject);
|
||||
intent.setType("message/rfc822");
|
||||
|
||||
displayNotification(intent);
|
||||
}
|
||||
|
||||
/**
|
||||
* displays an notification in the status bar, letting the user know that there was an issue
|
||||
* @param generatedReportIntent
|
||||
*/
|
||||
private void displayNotification(Intent generatedReportIntent) {
|
||||
Log.i(TAG, "displayNotification");
|
||||
Context context = mContext.getApplicationContext();
|
||||
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
Notification notifyDetails = new Notification(android.R.drawable.stat_notify_error, context.getString(R.string.sorry), System.currentTimeMillis());
|
||||
PendingIntent intent = PendingIntent.getActivity(context, 0, generatedReportIntent, android.content.Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
notifyDetails.setLatestEventInfo(context, context.getString(R.string.crash), context.getString(R.string.sorry), intent);
|
||||
notifyDetails.flags |= Notification.FLAG_AUTO_CANCEL;
|
||||
notificationManager.notify(SIMPLE_NOTFICATION_ID, notifyDetails);
|
||||
}
|
||||
|
||||
/**
|
||||
* parses in the exception handler options from the client application's assets folder. /assets/exceptionhandler.properties
|
||||
* @author ricky barrette
|
||||
*/
|
||||
private void parseProperties() {
|
||||
Resources resources = this.mContext.getResources();
|
||||
AssetManager assetManager = resources.getAssets();
|
||||
// Read from the /assets directory
|
||||
try {
|
||||
InputStream inputStream = assetManager.open("exceptionhandler.properties");
|
||||
Properties properties = new Properties();
|
||||
properties.load(inputStream);
|
||||
this.mURL = properties.getProperty("server") + properties.getProperty("file");
|
||||
this.mEmail = properties.getProperty("email");
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG, "Failed to open exceptionhandler.properties");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void run() {
|
||||
if(this.mEmail == null)
|
||||
displayNotification(new Intent(this.mContext, ExceptionReportActivity.class).putExtra("report", this.mReport));
|
||||
else
|
||||
displayEmailNotification();
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when there is an uncaught exception.
|
||||
* (non-Javadoc)
|
||||
* @see java.lang.Thread.UncaughtExceptionHandler#uncaughtException(java.lang.Thread, java.lang.Throwable)
|
||||
* @author ricky barrette
|
||||
*/
|
||||
@Override
|
||||
public void uncaughtException(Thread t, Throwable e) {
|
||||
Log.d(TAG, "uncaughtException()");
|
||||
|
||||
Log.d(TAG,"mURL = "+ this.mURL);
|
||||
Log.d(TAG,"mEmail = "+ this.mEmail);
|
||||
|
||||
Date theDate = new Date();
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd_HH.mm.ss_zzz");
|
||||
PackageManager pm = mContext.getPackageManager();
|
||||
|
||||
//app environment;
|
||||
PackageInfo pi;
|
||||
try {
|
||||
pi = pm.getPackageInfo(mContext.getPackageName(), 0);
|
||||
} catch (NameNotFoundException eNnf) {
|
||||
//doubt this will ever run since we want info about our own package
|
||||
pi = new PackageInfo();
|
||||
pi.versionName = "unknown";
|
||||
pi.versionCode = 69;
|
||||
}
|
||||
|
||||
StringBuffer report = new StringBuffer();
|
||||
for (StackTraceElement item : e.getStackTrace())
|
||||
report.append("at "+item.toString() + "\n");
|
||||
|
||||
StringBuffer causereport = new StringBuffer();
|
||||
Throwable cause = e.getCause();
|
||||
if (cause != null) {
|
||||
causereport.append(cause.toString() + "\n \n");
|
||||
for (StackTraceElement item : cause.getStackTrace())
|
||||
causereport.append("at "+item.toString() + "\n");
|
||||
}
|
||||
|
||||
//generate the report
|
||||
this.mReport = new Report(mURL).generateReport(e.toString(), report.toString(), causereport.toString(), sdf.format(theDate), Build.FINGERPRINT, pi.versionName+"b"+pi.versionCode, mContext.getPackageName());
|
||||
|
||||
//try to send file contents via email (need to do so via the UI thread)
|
||||
if(this.mApp != null){
|
||||
this.mApp.runOnUiThread(this);
|
||||
}
|
||||
|
||||
|
||||
if(this.mService != null){
|
||||
if(this.mEmail == null)
|
||||
displayNotification(new Intent(this.mContext, ExceptionReportActivity.class).putExtra("report", this.mReport));
|
||||
else
|
||||
displayEmailNotification();
|
||||
}
|
||||
|
||||
if(this.mBroadcastReceiver != null){
|
||||
if(this.mEmail == null)
|
||||
displayNotification(new Intent(this.mContext, ExceptionReportActivity.class).putExtra("report", this.mReport));
|
||||
else
|
||||
displayEmailNotification();
|
||||
}
|
||||
|
||||
//do not forget to pass this exception through up the chain
|
||||
mDefaultUEH.uncaughtException(t,e);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
/**
|
||||
* ExceptionActivity.java
|
||||
* @date May 31, 2011
|
||||
* @author Twenty Codes, LLC
|
||||
* @author ricky barrette
|
||||
*/
|
||||
package com.TwentyCodes.android.exception;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.apache.http.client.ClientProtocolException;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.ProgressDialog;
|
||||
import android.os.Bundle;
|
||||
import android.os.Looper;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.widget.EditText;
|
||||
import android.widget.ListView;
|
||||
|
||||
/**
|
||||
* This activity will be used to present the user with the exception report, and allows them to send it, or not
|
||||
* @author ricky barrette
|
||||
*/
|
||||
public class ExceptionReportActivity extends Activity implements OnClickListener {
|
||||
|
||||
private static final String TAG = "ExceptionActivity";
|
||||
private Report mReport;
|
||||
|
||||
/**
|
||||
* (non-Javadoc)
|
||||
* @see android.app.Activity#onCreate(android.os.Bundle)
|
||||
* @author ricky barrette
|
||||
*/
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
Log.d(TAG, "onCreate()");
|
||||
super.onCreate(savedInstanceState);
|
||||
this.mReport = (Report) this.getIntent().getParcelableExtra("report");
|
||||
|
||||
if(this.getIntent().hasExtra("display"))
|
||||
this.setContentView(R.layout.list);
|
||||
else {
|
||||
this.setContentView(R.layout.exception_activity);
|
||||
this.findViewById(R.id.send).setOnClickListener(this);
|
||||
}
|
||||
ListView list = (ListView) this.findViewById(android.R.id.list);
|
||||
list.setAdapter(new ReportAdapter(this, this.mReport.getReport()));
|
||||
list.setClickable(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* (non-Javadoc)
|
||||
* @see android.view.View.OnClickListener#onClick(android.view.View)
|
||||
* @author ricky barrette
|
||||
*/
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
EditText description = (EditText) findViewById(R.id.description);
|
||||
this.mReport.setDescription(description.getText().toString());
|
||||
v.setEnabled(false);
|
||||
final ProgressDialog progress = ProgressDialog.show(this, "", getString(R.string.sending), true, true);
|
||||
new Thread( new Runnable(){
|
||||
@Override
|
||||
public void run(){
|
||||
Looper.prepare();
|
||||
try {
|
||||
Log.d(TAG, ExceptionReportActivity.this.mReport.file());
|
||||
} catch (ClientProtocolException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
progress.dismiss();
|
||||
ExceptionReportActivity.this.finish();
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,192 @@
|
||||
/**
|
||||
* Report.java
|
||||
* @date May 29, 2011
|
||||
* @author Twenty Codes, LLC
|
||||
* @author ricky barrette
|
||||
*/
|
||||
package com.TwentyCodes.android.exception;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
|
||||
import org.apache.http.HttpEntity;
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.NameValuePair;
|
||||
import org.apache.http.client.ClientProtocolException;
|
||||
import org.apache.http.client.HttpClient;
|
||||
import org.apache.http.client.entity.UrlEncodedFormEntity;
|
||||
import org.apache.http.client.methods.HttpPost;
|
||||
import org.apache.http.impl.client.DefaultHttpClient;
|
||||
import org.apache.http.message.BasicNameValuePair;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
/**
|
||||
* This class will be used to generate a report, and insert it into our exception report database
|
||||
* @author ricky barrette
|
||||
*/
|
||||
public class Report implements Parcelable{
|
||||
|
||||
private String mUrl;
|
||||
private ArrayList<ReportItem> mReport;
|
||||
|
||||
public static final Parcelable.Creator<Report> CREATOR = new Parcelable.Creator<Report>() {
|
||||
public Report createFromParcel(Parcel in) {
|
||||
return new Report(in);
|
||||
}
|
||||
|
||||
public Report[] newArray(int size) {
|
||||
return new Report[size];
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a new Report
|
||||
* @param in
|
||||
* @author ricky barrette
|
||||
*/
|
||||
public Report(Parcel in){
|
||||
this.mUrl = in.readString();
|
||||
this.mReport = new ArrayList<ReportItem>();
|
||||
in.readTypedList(this.mReport, ReportItem.CREATOR);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new Report
|
||||
* @author ricky barrette
|
||||
*/
|
||||
public Report(String mysqlUrl) {
|
||||
this.mUrl = mysqlUrl;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Files the report with the remote database
|
||||
* @author ricky barrette
|
||||
* @throws IOException
|
||||
* @throws ClientProtocolException
|
||||
* @return String result
|
||||
*/
|
||||
public String file() throws ClientProtocolException, IOException{
|
||||
HttpClient httpclient = new DefaultHttpClient();
|
||||
HttpPost httppost = new HttpPost(mUrl);
|
||||
httppost.setEntity(new UrlEncodedFormEntity(getNameValuePairs()));
|
||||
|
||||
//return the results
|
||||
HttpResponse response = httpclient.execute(httppost);
|
||||
HttpEntity entity = response.getEntity();
|
||||
InputStream is = entity.getContent();
|
||||
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(is,"iso-8859-1"),8);
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(reader.readLine() + "\n");
|
||||
String line="0";
|
||||
while ((line = reader.readLine()) != null)
|
||||
sb.append(line + "\n");
|
||||
is.close();
|
||||
reader.close();
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a report to be displayed form a downloaded JSON object
|
||||
* @param report
|
||||
* @return
|
||||
* @author ricky barrette
|
||||
* @throws JSONException
|
||||
*/
|
||||
@SuppressWarnings("rawtypes")
|
||||
public Report generateReport(JSONObject report) throws JSONException{
|
||||
this.mReport = new ArrayList<ReportItem>();
|
||||
Iterator iter = report.keys();
|
||||
while(iter.hasNext()){
|
||||
String key = (String)iter.next();
|
||||
this.mReport.add(new ReportItem(key , report.getString(key)));
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a report to be sent.
|
||||
* @param msg
|
||||
* @param stackTrace
|
||||
* @param cause
|
||||
* @param device
|
||||
* @param appVersion
|
||||
* @param app
|
||||
* @return this
|
||||
* @author ricky barrette
|
||||
*/
|
||||
public Report generateReport(String msg, String stackTrace, String cause, String date, String device, String appVersion, String app){
|
||||
this.mReport = new ArrayList<ReportItem>();
|
||||
this.mReport.add(new ReportItem("app",app));
|
||||
this.mReport.add(new ReportItem("version",appVersion));
|
||||
this.mReport.add(new ReportItem("date",date));
|
||||
this.mReport.add(new ReportItem("msg",msg));
|
||||
this.mReport.add(new ReportItem("stackTrace",stackTrace));
|
||||
this.mReport.add(new ReportItem("cause",cause));
|
||||
this.mReport.add(new ReportItem("device",device));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the name value pairs from the report bundle
|
||||
* @return
|
||||
* @author ricky barrette
|
||||
*/
|
||||
private ArrayList<NameValuePair> getNameValuePairs() {
|
||||
ArrayList<NameValuePair> list = new ArrayList<NameValuePair>();
|
||||
for(ReportItem entry : this.mReport)
|
||||
list.add(new BasicNameValuePair(entry.getKey(), (String) entry.getValue()));
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the generated exception report
|
||||
* @author ricky barrette
|
||||
*/
|
||||
public ArrayList<NameValuePair> getReport(){
|
||||
return getNameValuePairs();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the optional users description of what happened
|
||||
* @param string
|
||||
* @author ricky barrette
|
||||
*/
|
||||
public Report setDescription(String description) {
|
||||
this.mReport.add(new ReportItem("description", description));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a human readable string of this report
|
||||
* @author ricky barrette
|
||||
*/
|
||||
@Override
|
||||
public String toString(){
|
||||
StringBuilder s = new StringBuilder();
|
||||
for(ReportItem item : this.mReport){
|
||||
s.append("\n\n-----"+ item.getKey()+"-----");
|
||||
s.append("\n"+item.getValue());
|
||||
}
|
||||
return s.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel out, int flags) {
|
||||
out.writeString(this.mUrl);
|
||||
out.writeTypedList(this.mReport);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
/**
|
||||
* ReportAdapter.java
|
||||
* @date May 31, 2011
|
||||
* @author Twenty Codes, LLC
|
||||
* @author ricky barrette
|
||||
*/
|
||||
package com.TwentyCodes.android.exception;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import org.apache.http.NameValuePair;
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.BaseAdapter;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.TwentyCodes.android.exception.R;
|
||||
|
||||
/**
|
||||
* This class will be used to populate a custom Listview used to display the Generated exception report
|
||||
* @author ricky barrette
|
||||
*/
|
||||
public class ReportAdapter extends BaseAdapter {
|
||||
|
||||
private ArrayList<NameValuePair> mReport;
|
||||
private LayoutInflater mInflater;
|
||||
|
||||
/**
|
||||
* Creates a new ReportAdapter
|
||||
* @author ricky barrette
|
||||
*/
|
||||
public ReportAdapter(Context context, ArrayList<NameValuePair> report) {
|
||||
super();
|
||||
// Cache the LayoutInflate to avoid asking for a new one each time.
|
||||
this.mInflater = LayoutInflater.from(context);
|
||||
this.mReport = report;
|
||||
}
|
||||
|
||||
/**
|
||||
* (non-Javadoc)
|
||||
* @see android.widget.Adapter#getCount()
|
||||
* @author ricky barrette
|
||||
*/
|
||||
@Override
|
||||
public int getCount() {
|
||||
return this.mReport.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* (non-Javadoc)
|
||||
* @see android.widget.Adapter#getItem(int)
|
||||
* @author ricky barrette
|
||||
*/
|
||||
@Override
|
||||
public NameValuePair getItem(int index) {
|
||||
return this.mReport.get(index);
|
||||
}
|
||||
|
||||
/**
|
||||
* (non-Javadoc)
|
||||
* @see android.widget.Adapter#getItemId(int)
|
||||
* @author ricky barrette
|
||||
*/
|
||||
@Override
|
||||
public long getItemId(int index) {
|
||||
return index;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@Override
|
||||
public View getView(final int position, View convertView, ViewGroup parent) {
|
||||
|
||||
// A ViewHolder keeps references to children views to avoid unnecessary calls to findViewById() on each row.
|
||||
ViewHolder holder;
|
||||
|
||||
// When convertView is not null, we can reuse it directly, there is no need
|
||||
// to reinflate it. We only inflate a new View when the convertView supplied
|
||||
// by ListView is null.
|
||||
if (convertView == null) {
|
||||
convertView = mInflater.inflate(R.layout.exception_list_item, null);
|
||||
|
||||
// Creates a ViewHolder and store references to the two children views
|
||||
// we want to bind data to.
|
||||
holder = new ViewHolder();
|
||||
holder.title = (TextView) convertView.findViewById(R.id.exception_title);
|
||||
holder.body = (TextView) convertView.findViewById(R.id.exception_text);
|
||||
|
||||
convertView.setTag(holder);
|
||||
} else {
|
||||
holder = (ViewHolder) convertView.getTag();
|
||||
}
|
||||
|
||||
/*
|
||||
* Bind the data efficiently with the holder.
|
||||
*/
|
||||
holder.title.setText(getItem(position).getName());
|
||||
holder.body.setText(getItem(position).getValue());
|
||||
|
||||
return convertView;
|
||||
}
|
||||
|
||||
class ViewHolder {
|
||||
TextView title;
|
||||
TextView body;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
/**
|
||||
* ReportItem.java
|
||||
* @date July 13, 2010
|
||||
* @author Twenty Codes, LLC
|
||||
* @author ricky barrette
|
||||
*/
|
||||
package com.TwentyCodes.android.exception;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
/**
|
||||
* This class will represent an individual report item. The ReportItems will be used in an array list that will be passed via intent.
|
||||
* This will allow for our report items to stay in the proper order.
|
||||
* @author ricky
|
||||
*/
|
||||
public class ReportItem implements Parcelable {
|
||||
|
||||
public static final Parcelable.Creator<ReportItem> CREATOR = new Parcelable.Creator<ReportItem>() {
|
||||
public ReportItem createFromParcel(Parcel in) {
|
||||
return new ReportItem(in);
|
||||
}
|
||||
|
||||
public ReportItem[] newArray(int size) {
|
||||
return new ReportItem[size];
|
||||
}
|
||||
};
|
||||
|
||||
private String mKey;
|
||||
private String mValue;
|
||||
|
||||
/**
|
||||
* Creates a new ReportItem
|
||||
* @author ricky barrette
|
||||
*/
|
||||
public ReportItem(String key, String value) {
|
||||
this.mKey = key;
|
||||
this.mValue = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new ReportItem from a parcel
|
||||
* @param in
|
||||
*/
|
||||
public ReportItem(Parcel in){
|
||||
this.mKey = in.readString();
|
||||
this.mValue = in.readString();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see android.os.Parcelable#describeContents()
|
||||
*/
|
||||
@Override
|
||||
public int describeContents() {
|
||||
// TODO Auto-generated method stub
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see android.os.Parcelable#writeToParcel(android.os.Parcel, int)
|
||||
*/
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeString(this.mKey);
|
||||
dest.writeString(this.mValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the key
|
||||
*/
|
||||
public String getKey() {
|
||||
return this.mKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the value
|
||||
*/
|
||||
public String getValue() {
|
||||
return this.mValue;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
/**
|
||||
* @author Twenty Codes
|
||||
* @author ricky barrette
|
||||
* @date June 29, 2011
|
||||
*/
|
||||
package com.TwentyCodes.android.exception;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.PackageManager.NameNotFoundException;
|
||||
import android.graphics.Typeface;
|
||||
import android.preference.Preference;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.Gravity;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
/**
|
||||
* this class will be a simple preference that contains only a text view that will display the application build information
|
||||
* @author ricky barrette
|
||||
*/
|
||||
public class VersionInformationPreference extends Preference {
|
||||
|
||||
private Context mContext;
|
||||
|
||||
|
||||
/**
|
||||
* creates a preference that is nothing but a text view
|
||||
* @param context
|
||||
*/
|
||||
public VersionInformationPreference(Context context) {
|
||||
super(context);
|
||||
mContext = context;
|
||||
}
|
||||
|
||||
/**
|
||||
* creates a preference that is nothing but a text view
|
||||
* @param context
|
||||
* @param attrs
|
||||
*/
|
||||
public VersionInformationPreference(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
mContext = context;
|
||||
}
|
||||
|
||||
/**
|
||||
* creates a preference that is nothing but a text view
|
||||
* @param context
|
||||
* @param attrs
|
||||
* @param defStyle
|
||||
*/
|
||||
public VersionInformationPreference(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
mContext = context;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* creates a linear layout the contains only a textview.
|
||||
* (non-Javadoc)
|
||||
* @see android.preference.Preference#onCreateView(android.view.ViewGroup)
|
||||
* @param parent
|
||||
* @return
|
||||
* @author ricky barrette
|
||||
*/
|
||||
@Override
|
||||
protected View onCreateView(ViewGroup parent){
|
||||
|
||||
/*
|
||||
* get the build information, and build the string
|
||||
*/
|
||||
PackageManager pm = mContext.getPackageManager();
|
||||
PackageInfo pi;
|
||||
try {
|
||||
pi = pm.getPackageInfo(mContext.getPackageName(), 0);
|
||||
} catch (NameNotFoundException eNnf) {
|
||||
//doubt this will ever run since we want info about our own package
|
||||
pi = new PackageInfo();
|
||||
pi.versionName = "unknown";
|
||||
pi.versionCode = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* create a vertical linear layout that width and height that wraps content
|
||||
*/
|
||||
LinearLayout layout = new LinearLayout(getContext());
|
||||
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
|
||||
// params.gravity = Gravity.CENTER;
|
||||
layout.setPadding(15, 5, 10, 5);
|
||||
layout.setOrientation(LinearLayout.VERTICAL);
|
||||
|
||||
layout.removeAllViews();
|
||||
|
||||
/*
|
||||
* create a textview that will be used to display the application's name and build information
|
||||
* and add it to the layout
|
||||
*/
|
||||
TextView title = new TextView(getContext());
|
||||
title.setText(mContext.getString(R.string.version)+" "+pi.versionName+" bulid "+pi.versionCode);
|
||||
title.setTextSize(16);
|
||||
title.setTypeface(Typeface.SANS_SERIF);
|
||||
title.setGravity(Gravity.LEFT);
|
||||
title.setLayoutParams(params);
|
||||
|
||||
/*
|
||||
* add the title views to the layout
|
||||
*/
|
||||
layout.addView(title);
|
||||
layout.setId(android.R.id.widget_frame);
|
||||
|
||||
return layout;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user