Recently, for reasons of work, the development of Android application found that the application in the presence of exceptions such as null pointers, throws an uncaught exception, the Android system has a default uncaught exception handler, the default behavior is to end the corresponding thread, but does not directly exit the program, And when the app has a background service, the service is still running, and if service will throw some exception information while requesting the network, and it will further cause an exception if it is reused in an application that is not fully exited, it is not good for the user experience.
Therefore, you need to exit the app immediately after the app has an exception, and then restart the app. Search the Internet a lot of information, many can not solve this problem very well, because Android may start a lot of activity, and before the end of the application process should finish all the activity in the task, otherwise there will be some unwanted results, And, of course, end-of-the-scenes service.
Android has a Thread.uncaughtexceptionhandler interface, you need to implement the interface, and implement the Uncaughtexception function, the following directly paste the relevant code:
public class Mycrashhandler implements Thread.uncaughtexceptionhandler {
private static final String TAG = "Mycaughtexception";
Application
Private MyApplication mapplication;
System default non-catching exception handler
Private Thread.uncaughtexceptionhandler Mdefaulthandler;
Custom non-catching exception handler
private static Mycrashhandler gcaughtexception;
/**
* Protection of single case mode
*/
Private Cepm360crashhandler () {
}
/**
* Single case mode
* @param application
* @return
*/
public static synchronized Mycrashhandler getinstance (application application) {
if (gcaughtexception = = null) {
Gcaughtexception = new Mycrashhandler (application);
}
return gcaughtexception;
}
/**
* Constructor function
* @param application
*/
Private Mycrashhandler (Application application) {
Mapplication = (myapplication) application;
Get the system default Uncaughtexceptionhandler
Mdefaulthandler = Thread.getdefaultuncaughtexceptionhandler ();
Setting the exception handler
Thread.setdefaultuncaughtexceptionhandler (this);
}
/**
* No exception handling function is caught
*/
@Override
public void uncaughtexception (thread thread, Throwable ex) {
LOG.E (TAG, "Ocurrs uncaughtexception!");
Print Stack
Ex.printstacktrace ();
Intent Intent = new Intent (mapplication, Myservice.class);
if (!handleexception (ex) && Mdefaulthandler! = null) {
Mdefaulthandler.uncaughtexception (thread, ex);
} else {
try {
Mapplication.stopservice (Intent);
Thread.Sleep (2000);
} catch (Interruptedexception e) {
E.printstacktrace ();
}
}
After exiting the program, start applying the first loginactivity
Intent = new Intent (mapplication, mainactivity.class);
Pendingintent restartintent =
Pendingintent.getactivity (Mapplication,
0,
Intent
Intent.flag_activity_new_task);
Alarmmanager Alarmmanager = (Alarmmanager)
Mapplication.getsystemservice (Context.alarm_service);
Alarmmanager.set ( ALARMMANAGER.RTC,
System.currenttimemillis () + 1000,
Restartintent);
Mapplication.exit ();
}
/**
* Exception Handling function
* @param ex
* @return
*/
Private Boolean handleexception (Throwable ex) {
if (ex = = null) {
return false;
}
Restart a thread to display exception information
New Thread () {
@Override
public void Run () {
Looper.prepare ();
Showexceptiontoast ();
Looper.loop ();
}
}.start ();
return true;
}
/**
* Show exception toast, confirm restart app
*/
private void Showexceptiontoast () {
Toast toast = Toast.maketext (Mapplication,
"I'm sorry," CEPM360 "has stopped running, is about to restart", Toast.length_short);
Set Center display
Toast.setgravity (gravity.center, 0, 0);
LinearLayout toastlayout = (linearlayout) Toast.getview ();
Toastlayout.setlayoutdirection (linearlayout.horizontal);
ImageView image = new ImageView (mapplication);
Image.setimageresource (r.drawable.exception_picture);
Toastlayout.addview (image, 0);
Toast.setview (toastlayout);
Toast.show ();
}
}
Above is a custom uncaught exception handler that you want to work with application, by default Android does not require you to manually implement or instantiate a Application object, However, the custom uncaught exception handler will finish all the activity, but there is no corresponding task-related API in application, there is no way to get all the activity currently applied in the task, So we need to implement a application class ourselves, and maintain a list of activity, and when we start an activity, we add it to the list, and when an uncaught exception occurs, all the activity here is erased.
public class MyApplication extends application {
Activity list to completely exit the app
Private list<activity> mactivities = new arraylist<activity> ();
Sharing data
Private map<string, object> mappshareddata = new hashmap<string, object> ();
@Override
public void OnCreate () {
Super.oncreate ();
Mycrashhandler.getinstance (this);
}
/**
* Get data that should be shared
* @return
*/
Public map<string, Object> Getappshareddata () {
return mappshareddata;
}
/**
* Add a shared map element
* @param map
*/
public void Addshareddata (map<string, object> Map) {
Mappshareddata.putall (map);
}
/**
* Add a shared element
* @param string
* @param Object
*/
public void Addshareddata (string string, Object object) {
Mappshareddata.put (String, object);
}
/**
* Get shared element values
* @param string
* @return
*/
Public Object GetValue (string string) {
return Mappshareddata.get (String);
}
/**
* When an activity is started, it is added to the list
* @param activity
*/
public void addactivity (activity activity) {
Mactivities.add (activity);
}
/**
* Exit the App
*/
public void exit () {
Loop out of activity
try {
for (Activity activity:mactivities) {
if (activity! = NULL)
Activity.finish ();
}
} catch (Exception e) {
E.printstacktrace ();
} finally {
Finally exit the virtual machine
System.exit (0);
}
}
@Override
public void Onlowmemory () {
Super.onlowmemory ();
System.GC ();
}
}
The above Mappshareddata mapping table is a data share for the app, not the focus of this article. It is important to note that all processing of the exception is done in the Uncaughtexception function in Mycrashhandler, including stopping the service and activity, exiting the virtual machine after sending the restart broadcast, or using the following code:
Android.os.Process.killProcess (Android.os.Process.myPid ());
Copyright NOTICE: This article for Bo Master original article, without Bo Master permission not reproduced.
Uncaught exception handling for custom application