Sources used:
Main sources:
https://medium.com/@ssaurel/how-to-...r-a-crash-or-a-force-close-error-1a361677c0ce
https://www.b4x.com/android/forum/t...estartatexact-not-accurate.65117/#post-412286
Additional:
https://stackoverflow.com/a/2903866
https://mobikul.com/auto-restart-application-crashforce-close-android/
Known limitations:
This has only been tested with a single activity (Main) application. More explanation to follow below.
Part 1:
The first part involves installing a default uncaught exception handler. The solution requires some inline Java and the JavaObject library.
Add the following inline Java to your Main class:
Declare the following JavaObject in Globals (adjust name if necessary to avoid conflicts):
And add the following code in the Activity_Create sub:
That finishes installing your own default uncaught exception handler. With this in place, when you Main class crashes, the application will exit without requesting the user to restart the application. This is key in allowing the application to restart without user intervention. For applications that are set as the Home screen, this would suffice, allowing Android to restart it without user intervention.
Part 2:
First, a sub that allows us to schedule the starting of an Activity. It is a modified version of @Erel's
SetExactAndAllowWhileIdle sub he posted (the modification allowing it to start an Activity instead of a Service):
This sub should be placed in the Starter service. You will need to also declare the following in Process_Globals:
The sub needs to be called from the Application_Error method. For example:
With all these pieces in place, if your Main activity crashes, it will be scheduled to restart in 300 milliseconds (the + 300). Additionally, you can check Main's starting intent to determine if your app was restarted as a crash. For example, the following code placed in Activity_Create will produce a log after crash:
Notes:
1) Each Activity may need to register their own default uncaught exception handler. If so, it's left up to the reader to determine which Activity needs to be restarted via ScheduleRestartCrashedActivity.
2) I do not know what happens when a Service crashes.
3) The ScheduleRestartCrashedActivity does not require the Starter Service. It does require that a Service handles the Application_Error event.
4) I'm currently using ALM_RTC to schedule the intents. This will not wake the phone. If that is a requirement, replace with ALM_RTC_WAKEUP.
5) Could not decide between a Snippet post or Tutorial post. This seemed a little to long for a Snippet.
Main sources:
https://medium.com/@ssaurel/how-to-...r-a-crash-or-a-force-close-error-1a361677c0ce
https://www.b4x.com/android/forum/t...estartatexact-not-accurate.65117/#post-412286
Additional:
https://stackoverflow.com/a/2903866
https://mobikul.com/auto-restart-application-crashforce-close-android/
Known limitations:
This has only been tested with a single activity (Main) application. More explanation to follow below.
Part 1:
The first part involves installing a default uncaught exception handler. The solution requires some inline Java and the JavaObject library.
Add the following inline Java to your Main class:
B4X:
#if Java
//Sources:
//https://medium.com/@ssaurel/how-to-auto-restart-an-android-application-after-a-crash-or-a-force-close-error-1a361677c0ce
//https://stackoverflow.com/a/2903866
//https://mobikul.com/auto-restart-application-crashforce-close-android/
public void setDefaultUncaughtExceptionHandler() {
Thread.setDefaultUncaughtExceptionHandler(new MyExceptionHandler(this));
}
import android.app.Activity;
public class MyExceptionHandler implements Thread.UncaughtExceptionHandler {
private Activity activity;
public MyExceptionHandler(Activity a) {
activity = a;
}
@Override
public void uncaughtException(Thread thread, Throwable ex) {
activity.finish();
System.exit(2);
}
}
#End if
Declare the following JavaObject in Globals (adjust name if necessary to avoid conflicts):
B4X:
Private nativeMe As JavaObject
And add the following code in the Activity_Create sub:
B4X:
nativeMe.InitializeContext
nativeMe.RunMethod("setDefaultUncaughtExceptionHandler", Null)
That finishes installing your own default uncaught exception handler. With this in place, when you Main class crashes, the application will exit without requesting the user to restart the application. This is key in allowing the application to restart without user intervention. For applications that are set as the Home screen, this would suffice, allowing Android to restart it without user intervention.
Part 2:
First, a sub that allows us to schedule the starting of an Activity. It is a modified version of @Erel's
SetExactAndAllowWhileIdle sub he posted (the modification allowing it to start an Activity instead of a Service):
B4X:
'Based on: https://www.b4x.com/android/forum/threads/now-android-6-servicestartatexact-not-accurate.65117/#post-412286
'Time: The time that the Activity should start - in ticks
'ActivityName: The name of the Activity that should be started
'Message: A message that will be passed along in the intent to start the Activity (via Extras)
Sub ScheduleRestartCrashedActivity (Time As Long, ActivityName As String, message As String)
Dim in As Intent
in.Initialize("", "")
in.SetComponent(Application.PackageName & "/." & ActivityName.ToLowerCase)
in.PutExtra("Crash", message)
in.Flags = Bit.Or(FLAG_ACTIVITY_CLEAR_TASK, Bit.Or(FLAG_ACTIVITY_CLEAR_TOP, FLAG_ACTIVITY_NEW_TASK))
Dim jin As JavaObject = in
jin.RunMethod("setAction", Array(Null))
Dim ctxt As JavaObject
ctxt.InitializeContext
Dim am As JavaObject = ctxt.RunMethod("getSystemService", Array("alarm"))
Dim pi As JavaObject
pi = pi.InitializeStatic("android.app.PendingIntent").RunMethod("getActivity", Array(ctxt, 0, in, FLAG_ONE_SHOT))
Dim p As Phone
If p.SdkVersion < 20 Then
am.RunMethod("set", Array(ALM_RTC, Time, pi))
Else If p.SdkVersion < 23 Then
am.RunMethod("setExact", Array(ALM_RTC, Time, pi))
Else
am.RunMethod("setExactAndAllowWhileIdle", Array(ALM_RTC, Time, pi))
End If
End Sub
B4X:
Private const FLAG_ACTIVITY_CLEAR_TOP As Int = 0x04000000
Private const FLAG_ACTIVITY_CLEAR_TASK As Int = 0x00008000
Private const FLAG_ACTIVITY_NEW_TASK As Int = 0x10000000
Private const FLAG_ONE_SHOT As Int = 0x40000000
Private const ALM_RTC As Int = 0x00000001
Private const ALM_RTC_WAKEUP As Int = 0x00000000
B4X:
Sub Application_Error (Error As Exception, StackTrace As String) As Boolean
ScheduleRestartCrashedActivity(DateTime.Now + 300, "Main", Error)
Return True
End Sub
B4X:
Dim i As Intent
i = Activity.GetStartingIntent
If i.HasExtra("Crash") Then
Log("After crash: " & i.GetExtra("Crash"))
End If
Notes:
1) Each Activity may need to register their own default uncaught exception handler. If so, it's left up to the reader to determine which Activity needs to be restarted via ScheduleRestartCrashedActivity.
2) I do not know what happens when a Service crashes.
3) The ScheduleRestartCrashedActivity does not require the Starter Service. It does require that a Service handles the Application_Error event.
4) I'm currently using ALM_RTC to schedule the intents. This will not wake the phone. If that is a requirement, replace with ALM_RTC_WAKEUP.
5) Could not decide between a Snippet post or Tutorial post. This seemed a little to long for a Snippet.