The example in this article describes how the Android implementation will apply crash information to developers and restart applications. Share to everyone for your reference, specific as follows:
In the development process, although tested, but after the release, in the vast number of users in a variety of operating environment and operation, may occur some unexpected errors cause the program crashes. Collecting these error messages and feeding them back to developers is important for developers to improve the optimization process. Well, here's how to do it.
(Correction time: February 9, 2012 18:42 07 seconds)
For historical reasons, the following practices are more wasteful, but the effect of grabbing an exception is the same.
1. For the not-caught exception thrown by the UI thread (that is, the main thread in Android), store the exception information and close it to the entire application. and start the program again, then enter the crash information feedback interface to let users send the error message to the developer in the form of email.
2. For exceptions thrown by non-UI threads, immediately wake up crash feedback interface prompts the user to send an error message to email.
The effect chart is as follows:
process, you need to know a few points of knowledge as follows:
1. Intercept Uncaughtexception
Application.oncreate () is the entry method for the entire Android application. You can intercept uncaughtexception by executing the following code in this method:
Uehandler = new Uehandler (this);
Set exception Handling instance
Thread.setdefaultuncaughtexceptionhandler (Uehandler);
2. Crawl causes the program crashes the exception information
Uehandler is the implementation class for Thread.uncaughtexceptionhandler, in its public void uncaughtexception (thread thread, throwable ex) The implementation of the crash information can be obtained, the code is as follows:
Fetch Excpetion Info
String info = null;
Bytearrayoutputstream BAOs = null;
PrintStream printstream = null;
try {
BAOs = new Bytearrayoutputstream ();
PrintStream = new PrintStream (BAOs);
Ex.printstacktrace (PrintStream);
byte[] data = Baos.tobytearray ();
info = new String (data);
data = null;
} catch (Exception e) {
e.printstacktrace ();
} finally {
try {
if (printstream!= null) {
Printstream.close ();
}
if (BAOs!= null) {
baos.close ();
}
catch (Exception e) {
e.printstacktrace ();
}
}
3. After the program throws an exception, wants to close the entire application
Sad reminders of programmers, alas, the following three ways are invalid, how AH!!!
3.1 Android.os.Process.killProcess (Android.os.Process.myPid ());
3.2 Activitymanager am = (activitymanager) getsystemservice (Activity_service);
Am.restartpackage ("Lab.sodino.errorreport");
3.3 System.exit (0)
Well, Chairman Mao told us: we have plenty of hands.
Softapplication declares a variable need2exit whose value is true to indicate that the current program requires a full exit; The variable evaluates to False at the startup Activity.oncreate () that is applied.
After capturing the crash information, the call Softapplication.setneed2exit (TRUE) identifies the program that needs to exit and finish () off the Acterrorreport, then acterrorreport the stack, The wrong Actoccurerror occupies the mobile screen, and according to the life cycle of the activity it calls OnStart (), then we read the state of Need2exit at OnStart (), and if true, close to the current activity, Then quit the entire application. This method resolves a one-time exit application that has multiple activity open. Detailed code Please read the example source below.
OK, the code is as follows:
Lab.sodino.errorreport.SoftApplication.java
package lab.sodino.errorreport; import java.io.File; import android.app.Application; * * * @author sodino e-mail:sodinoopen@hotmail.com * @version time:2011-6-9 PM 11:49:56/public class Softapplication E Xtends Application {/** "/data/data/<app_package>/files/error.log" * * public static final String Path_error_log = File.separator + "Data" + file.separator + "data" + File.separator + "Lab.sodino.errorreport" + File.separator +
"Files" + file.separator + "Error.log"; /** whether the identity needs to exit. True indicates that the current activity is performing finish ().
* * Private Boolean need2exit; /** exception Handling class.
* * Private Uehandler Uehandler;
public void OnCreate () {need2exit = false;
Uehandler = new Uehandler (this);
Set exception Handling instance Thread.setdefaultuncaughtexceptionhandler (Uehandler);
} public void Setneed2exit (Boolean bool) {need2exit = bool;
public Boolean need2exit () {return need2exit; }
}
Lab.sodino.errorreport.ActOccurError.java
Package lab.sodino.errorreport;
Import Java.io.File;
Import Java.io.FileInputStream;
Import android.app.Activity;
Import android.content.Intent;
Import Android.os.Bundle;
Import Android.util.Log;
Import Android.view.View;
Import Android.widget.Button;
public class Actoccurerror extends activity {private softapplication softapplication; /** called the activity is a.
* * @Override public void onCreate (Bundle savedinstancestate) {super.oncreate (savedinstancestate);
Setcontentview (R.layout.main);
Softapplication = (softapplication) getapplication ();
The first entry program reverts to "Need2exit=false".
Softapplication.setneed2exit (FALSE);
LOG.D ("Android_lab", "Actoccurerror.oncreate ()");
Button Btnmain = (button) Findviewbyid (R.id.btnthrowmain); Btnmain.setonclicklistener (New Button.onclicklistener () {public void OnClick (View v) {log.d ("Android_lab")
"Thread.main.run ()");
int i = 0;
i = 100/i;
}
}); Button Btnchild = (Button) Findviewbyid (r.id.btnthrowchild);
Btnchild.setonclicklistener (New Button.onclicklistener () {public void OnClick (View v) {new Thread () {
public void Run () {LOG.D ("Android_lab", "Thread.child.run ()");
int i = 0;
i = 100/i;
}}.start ();
}
});
Handles the exception String errorcontent = Geterrorlog () that is logged in Error.log.
if (errorcontent!= null) {Intent Intent = new Intent (this, acterrorreport.class);
Intent.setflags (Intent.flag_activity_new_task);
Intent.putextra ("error", errorcontent);
Intent.putextra ("by", "Error.log");
StartActivity (Intent);
} public void OnStart () {Super.onstart ();
if (Softapplication.need2exit ()) {LOG.D ("Android_lab", "Actoccurerror.finish ()");
ActOccurError.this.finish (); else {//Do normal Things}}/** * Read for unhandled error information. <br/> * Error.log will be emptied after each read.
<br/> * * @return Returns the unhandled error message or null.
* * Private String Geterrorlog () {File Fileerrorlog = new file (Softapplication.path_error_log);
String content = null;
FileInputStream FIS = null;
try {if (fileerrorlog.exists ()) {byte[] data = new byte[(int) fileerrorlog.length ()];
FIS = new FileInputStream (fileerrorlog);
Fis.read (data);
Content = new String (data);
data = null;
} catch (Exception e) {e.printstacktrace ();
Finally {try {if (FIS!= null) {fis.close ();
} if (Fileerrorlog.exists ()) {fileerrorlog.delete ();
} catch (Exception e) {e.printstacktrace ();
} return content;
}
}
Lab.sodino.errorreport.ActErrorReport.java
Package lab.sodino.errorreport;
Import android.app.Activity;
Import android.content.Intent;
Import Android.os.Bundle;
Import Android.util.Log;
Import Android.view.View;
Import Android.widget.Button;
Import Android.widget.EditText;
Import Android.widget.TextView; /** * @author Sodino e-mail:sodinoopen@hotmail.com * @version time:2011-6-12 PM 01:34:17/public class Acterrorreport
Extends activity {private softapplication softapplication;
Private String info; /** identification to place.
* * Private String by;
Private Button Btnreport;
Private Button Btncancel;
Private Btnlistener Btnlistener;
public void OnCreate (Bundle savedinstancestate) {super.oncreate (savedinstancestate);
Setcontentview (R.layout.report);
Softapplication = (softapplication) getapplication ();
by = Getintent (). Getstringextra (' by ');
info = getintent (). Getstringextra ("error");
TextView txthint = (TextView) Findviewbyid (r.id.txterrorhint);
Txthint.settext (by) (Geterrorhint); EditText EditeRror = (edittext) Findviewbyid (r.id.editerrorcontent);
Editerror.settext (info);
Btnlistener = new Btnlistener ();
Btnreport = (Button) Findviewbyid (R.id.btnreport);
Btncancel = (Button) Findviewbyid (r.id.btncancel);
Btnreport.setonclicklistener (Btnlistener);
Btncancel.setonclicklistener (Btnlistener);
private string Geterrorhint (string by) {string hint = "";
String append = "";
if ("Uehandler". Equals (by)) {append = ' when the app running ';
else if ("Error.log". Equals (by)) {append = ' When is last time the app running ';
} hint = String.Format (Getresources (). getString (R.string.errorhint), append, 1);
return hint;
public void OnStart () {Super.onstart ();
if (Softapplication.need2exit ()) {//activity of the previous fallback stack has an operation to perform an "exit".
LOG.D ("Android_lab", "Acterrorreport.finish ()");
ActErrorReport.this.finish (); else {//go ahead normally}} class Btnlistener implements Button.onclickListener {@Override public void OnClick (View v) {if (v = = Btnreport) {//Required Android.permission.SE
nd permission Intent mailintent = new Intent (intent.action_send);
Mailintent.settype ("Plain/text");
String[] Arrreceiver = {"Sodinoopen@hotmail.com"};
String mailsubject = "App Error info[" + getpackagename () + "]";
String mailbody = info;
Mailintent.putextra (Intent.extra_email, arrreceiver);
Mailintent.putextra (Intent.extra_subject, mailsubject);
Mailintent.putextra (Intent.extra_text, mailbody);
StartActivity (Intent.createchooser (mailintent, "Mail sending ..."));
ActErrorReport.this.finish ();
else if (v = = btncancel) {ActErrorReport.this.finish ();
}} public void Finish () {super.finish ();
if ("Error.log". Equals (by)) {//Does nothing} else if (' Uehandler '. Equals (by)) {//1. Android.os.Process.killProcess (Android.os.Process.myPid());
2.
Activitymanager am = (activitymanager)//Getsystemservice (Activity_service);
Am.restartpackage ("Lab.sodino.errorreport");
3.
System.exit (0);
1.2.3, Google you let the sad reminders of the programmer's love.
Softapplication.setneed2exit (TRUE); ///Another replacement option is to return directly to "home"//Intent i = new Intent (inte Nt.
Action_main);
In the case of a service call, the NewTask identification//I.setflags (Intent.flag_activity_new_task) must be added;
I.addcategory (Intent.category_home);
StartActivity (i);
// ////////////////////////////////////////////////////
}
}
}
Lab.sodino.errorreport.UEHandler.java
Package lab.sodino.uncaughtexception;
Import Java.io.ByteArrayOutputStream;
Import Java.io.File;
Import Java.io.FileOutputStream;
Import Java.io.PrintStream;
Import android.content.Intent;
Import Android.util.Log; /** * @author Sodino e-mail:sodinoopen@hotmail.com * @version time:2011-6-9 PM 11:50:43 * * public class Uehandler Implem
Ents Thread.uncaughtexceptionhandler {private softapplication SoftApp;
Private File Fileerrorlog;
Public Uehandler (Softapplication app) {SoftApp = app;
Fileerrorlog = new File (softapplication.path_error_log); @Override public void uncaughtexception (thread thread, Throwable ex) {//Fetch excpetion info String info =
Null
Bytearrayoutputstream BAOs = null;
PrintStream printstream = null;
try {BAOs = new Bytearrayoutputstream ();
PrintStream = new PrintStream (BAOs);
Ex.printstacktrace (PrintStream);
byte[] data = Baos.tobytearray ();
info = new String (data);
data = null; } CATCH (Exception e) {e.printstacktrace ();
Finally {try {if (PrintStream!= null) {printstream.close ();
} if (BAOs!= null) {baos.close ();
} catch (Exception e) {e.printstacktrace ();
}//Print long threadId = Thread.getid ();
LOG.D ("Android_lab", "thread.getname () =" + thread.getname () + "id=" + threadId + "state=" + thread.getstate ());
LOG.D ("Android_lab", "error[" + info + "]");
if (threadId!= 1) {//Here The example jumps to the report exception interface.
Intent Intent = new Intent (SoftApp, Acterrorreport.class);
Intent.setflags (Intent.flag_activity_new_task);
Intent.putextra ("error", info);
Intent.putextra ("by", "Uehandler");
Softapp.startactivity (Intent);
else {//Here The example has an exception, restart the application Intent Intent = new Intent (SoftApp, Actoccurerror.class); If <span style= "Background-color:rgb (255, 255, 255); "> An exception with no New_task identity and </span> UI line Cheng is stuck to the interface.Until ANR intent.setflags (intent.flag_activity_new_task);
Softapp.startactivity (Intent);
Write 2/data/data/<app_package>/files/error.log Write2errorlog (Fileerrorlog, info);
Kill App Progress Android.os.Process.killProcess (Android.os.Process.myPid ());
} private void Write2errorlog (file file, String content) {FileOutputStream fos = null;
try {if (file.exists ()) {//Empty previous record file.delete ();
else {file.getparentfile (). Mkdirs ();
} file.createnewfile ();
FOS = new FileOutputStream (file);
Fos.write (Content.getbytes ());
catch (Exception e) {e.printstacktrace ();
Finally {try {if (fos!= null) {fos.close ();
} catch (Exception e) {e.printstacktrace ();
}
}
}
}
/res/layout/main.xml
<?xml version= "1.0" encoding= "Utf-8"?> <linearlayout xmlns:android=
"http://schemas.android.com/apk/" Res/android "
android:orientation=" vertical "
android:layout_width=" fill_parent "
android:layout_" height= "Fill_parent"
>
<textview
android:layout_width= "fill_parent"
android:layout_ height= "Wrap_content"
android:text= "@string/hello"/> <button android:layout_width=
"Fill_ Parent "
android:layout_height=" wrap_content "
android:text=" Throws Exception by Main Thread "
Android : id= "@+id/btnthrowmain"
></Button>
<button android:layout_width= "Fill_parent"
android:layout_height= "Wrap_content"
android:text= "Throws Exception by Child Thread"
android:id= "@+id/ Btnthrowchild "
></Button>
</LinearLayout>
/res/layout/report.xml
<?xml version= "1.0" encoding= "Utf-8"?> <linearlayout xmlns:android= "http://schemas.android.com/apk/res/" Android "android:orientation=" vertical "android:layout_width=" fill_parent "android:layout_height=" Fill_parent " > <textview android:layout_width= "fill_parent" android:layout_height= wrap_content "android:text=" @string Errorhint "android:id=" @+id/txterrorhint "/> <edittext android:layout_width=" Fill_parent "Android:layout_h eight= "Wrap_content" android:id= "@+id/editerrorcontent" android:editable= "false" android:layout_weight= "1" > </EditText> <linearlayout android:layout_width= "fill_parent" android:layout_height= "Wrap_content" Android : background= "#96cdcd" android:gravity= "center" android:orientation= "Horizontal" > <button Android:layout_widt H= "Fill_parent" android:layout_height= "wrap_content" android:text= "" "Android:id=" @+id/btnreport "Android : layout_weight= "1" ></Button> <button android:layout_width= "fill_parent" android:layout_height= "Wrap_content" android:text= "Cancel" android:id= "@+"
Id/btncancel "android:layout_weight=" 1 "></Button> </LinearLayout> </LinearLayout>
The String.xml resources used are:
Copy Code code as follows:
<string name= "Errorhint" >a error has happened%1$s.please click <i><b> "" "</b></i> To send the error information to us by email,!!! </string>
The important point is to set the android:name= for the <application> node in Androidmanifest.xml. Softapplication "
For more information on Android-related content readers can view the site topics: "Android Debugging techniques and common problems solution summary", "Android Development introduction and Advanced Course", "Android Multimedia operating skills Summary (audio, video, recording, etc.)", " Android Basic Components Usage Summary, Android View tips Summary, Android layout layout tips and Android Control usage summary
I hope this article will help you with the Android program.