Android: How to Auto-Restart an Application After It Has Been "Force Closed"

Android: How to auto-restart an application after it has been force closed ?

To accomplish this you have to do two things:

  1. Avoid the "Force close" - standard way of application crash.
  2. Setup a restart mechanism when the crash happens anyway.

See below how to do these:

  1. Call Thread.setDefaultUncaughtExceptionHandler() in order to catch all uncaught exception, in which case uncaughtException() method will be called. "Force close" will not appear and the application will be unresponsive, which is not a quite good thing.
    In order to restart your application when it crashed you should do the following :

  2. In the onCreate method, in your main activity initialize a PendingIntent member:

    Intent intent = PendingIntent.getActivity(
    YourApplication.getInstance().getBaseContext(),
    0,
    new Intent(getIntent()),
    getIntent().getFlags());

Then put the following in your uncaughtException() method:

AlarmManager mgr = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 2000, intent);
System.exit(2);

You also must call System.exit(), otherwise will not work.
In this way your application will restart after 2 seconds.

Eventually you can set some flag in your intent that the application crashed and in your onCreate() method you can show a dialog "I'm sorry, the application crashed, hope never again :)".

Stop Android automatically restarting app after crash

Nevermind. I found it ... there's a setting under Developer Options

"Always show crash dialog". So, so frustrating!

Sample Image

Android App Restarts upon Crash/force close

  1. Best solution would be instead of using Static data, use Shared Preferences or store data in a Database and if any uncaught Exception occurs, show a message like Application has crashed and a report is sent to the admin and then restart the Activity that caused the Crash. This way user can continue using the application.

  2. Do the same but instead of restarting the Activity which caused the Exception restart the application.

create a class used to handle unCaughtException

public class MyExceptionHandler implements
java.lang.Thread.UncaughtExceptionHandler {
private final Context myContext;
private final Class<?> myActivityClass;

public MyExceptionHandler(Context context, Class<?> c) {

myContext = context;
myActivityClass = c;
}

public void uncaughtException(Thread thread, Throwable exception) {

StringWriter stackTrace = new StringWriter();
exception.printStackTrace(new PrintWriter(stackTrace));
System.err.println(stackTrace);// You can use LogCat too
Intent intent = new Intent(myContext, myActivityClass);
String s = stackTrace.toString();
//you can use this String to know what caused the exception and in which Activity
intent.putExtra("uncaughtException",
"Exception is: " + stackTrace.toString());
intent.putExtra("stacktrace", s);
myContext.startActivity(intent);
//for restarting the Activity
Process.killProcess(Process.myPid());
System.exit(0);
}
}

and in every Activity create an Object of this class and set it as the DefaultUncaughtExceptionHandler

    Thread.setDefaultUncaughtExceptionHandler(new MyExceptionHandler(this,
YourCurrentActivity.class));

How to restart service after the app is killed from recent tasks

Override onTaskRemoved() in your service and use alarm manager to start the service again. Below is code from our app that does the same and works fine:

@Override
public void onTaskRemoved(Intent rootIntent) {
super.onTaskRemoved(rootIntent);

Log.d(TAG, "TASK REMOVED");

PendingIntent service = PendingIntent.getService(
getApplicationContext(),
1001,
new Intent(getApplicationContext(), MyService.class),
PendingIntent.FLAG_ONE_SHOT);

AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, 1000, service);
}

As you may want to send location periodically even in the case if the service gets killed on low memory (or for any reason), I suggest you to handle the uncaughtException to restart it after N seconds. This is how we have done in our app that works perfectly:

private Thread.UncaughtExceptionHandler defaultUEH;
private Thread.UncaughtExceptionHandler uncaughtExceptionHandler = new Thread.UncaughtExceptionHandler() {

@Override
public void uncaughtException(Thread thread, Throwable ex) {
Log.d(TAG, "Uncaught exception start!");
ex.printStackTrace();

//Same as done in onTaskRemoved()
PendingIntent service = PendingIntent.getService(
getApplicationContext(),
1001,
new Intent(getApplicationContext(), MyService.class),
PendingIntent.FLAG_ONE_SHOT);

AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, 1000, service);
System.exit(2);
}
};

Note: I THINK and I remember I verified it on Kitkat that START_STICKY does not work on Kitkat and higher API levels. Please verify this for yourself.

MORE:

As you do loc sending periodically, you may have to consider the deep sleep mode. To get things work in deep sleep, use WakefulBroadcastReceiver combined with AlarmManager. Take a look at my other post How to use http in deep sleep mode.

UPDATE:

This solution does not work (in fact need not to work) if user "FORCE STOP" the application from Settings. This is good in fact as restarting the service is not a good way if user himself wants to stop application. So, it is fine.

How to restart app after closing using pm clear command

Edit:

In your StartActivity.java, you must set the Thread.setDefaultUncaughtExceptionHandler(handler) in the onCreate() method, like this:

public class StartActivity extends Activity {

final Context context;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.context = context;
setContentView(R.layout.start_activity);
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
public void uncaughtException(Thread t, Throwable e) {
StartActivity.restartApp(context);
}
});
//your code here
}

public static void restartApp(Context context)
{
Intent mStartActivity = new Intent(context, StartActivity.class); //Replace StartActivity with the name of the first activity in your app
int mPendingIntentId = 123456;
PendingIntent mPendingIntent = PendingIntent.getActivity(context, mPendingIntentId, mStartActivity, PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager mgr = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 100, mPendingIntent);
System.exit(0);
}

}

When you call the android pm clear data command, you force close the application (if it is opened); when the app gets force closed, it throws an unhandledException, that gets handled by the code above.



Related Topics



Leave a reply



Submit