Whenever I start the app I want to know if the app recovered from a crash. Can I store it in a flag ?
Do the crash and regular app exit scenario go through the same steps(lifecycle) in android ?
You can override your crash exception by using Thread.setDefaultUncaughtExceptionHandler. But do not forget, If you would not close your application it will freeze the screen by OS.
Example code :
//variable that inside the application class
private Thread.UncaughtExceptionHandler defaultUEH;
public void onCreate(){
super.onCreate();
defaultUEH = Thread.getDefaultUncaughtExceptionHandler();
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler(){
#Override
public void uncaughtException(Thread t, Throwable e) {
handleUncaughtException(t,e);
defaultUEH.uncaughtException(thread,e);
}
});
}
private void handleUncaughtException(Thread thread,Throwable e){
//do whatever you like!
}
NOTE : There is no way to understand how is your program is opened
You don't get this information at all from the Android SDK. There are two options you could try, first is would be to have extensive logging/tracking of the apps life-cycle. In all of your activities keep track of when you activities are started, resumed, paused, stopped, and destroyed. (Also handle special usecase of when the device is rotated and the activity will experience a tear-down and restart). From here you will have information of when an activity has been stopped and you check the last state in the onCreate, onStart, or onResume of you activities to make sure that you're expected life-cycles where hit. If not, then you more than likely experienced a crash. Also note, on older version of Android certain teardown life-cycle callbacks weren't guaranteed to be called.
Second option would be to try using Thread.setDefaultUncaughtExceptionHandler. I have never personally used it but it may help in the usecase where an uncaught exception occurs. You could log such an event and check that flag once, the app is resumed. I am not sure of all of the side effects of using this mechanism such as, will this override the default uncaught exception behavior and remove the default stack trace that gets printed out, which would be very very very bad.
There is no way for the app to know whether it started from a crash; this is indistinguishable from starting the application for the first time after booting. In both cases you will see the onCreate lifecycle event for your activity.
If your application crashes, it stops processing lifecycle events. So no, lifecycle events will not be processed in the same way.
If you want to know whether your application is crashing, perhaps a better approach is to directly record when the application crashes. There are tools like Errbit that help record this when the application is running on general users' devices.
Try to add Exception handling to the code to whatever is causing a crash.
try{
//code causing the crash
} catch (Exception e){
//code to set flags whenever an event causing crash occurs.
}
Related
I'm adding a Day/Night mode to my app, but my app does not request location services for various reasons, so the automatic modes times of 10/6 don't work for my app.
I'm using my own times which will work fine given the use case, but I'm running into a problem on automatically changing them smoothly.
If the app is restarted, the switch works correctly, as the values get set in the application class, but if they app is already opened, I need to trigger it in the onResume or onStart as far as I can tell.
If I call getDelegate().applyDayNight(); to trigger to switch in onResume, this caught exception gets thrown (no app crash)
E/ActivityThread: Performing pause of activity that is not resumed:
java.lang.RuntimeException: Performing pause of activity that is not resumed:
at android.app.ActivityThread.performPauseActivity(ActivityThread.java:3196)
at android.app.ActivityThread.performPauseActivity(ActivityThread.java:3184)
at android.app.ActivityThread.handlePauseActivity(ActivityThread.java:3159)
at android.app.ActivityThread.access$1000(ActivityThread.java:144)
The exception makes sense, I'm interrupting the onResume and the activity is getting re-created by the day/night application. I did some looking, and for things like this people suggest using a handler to delay post it, but when I do that, I see a flicker of the color changes, rather than the app simply opening with change which is a much better user experience.
This is the code I'm using in onResume
#Override
protected void onResume() {
handler.postDelayed(new Runnable() {
#Override
public void run() {
int currentNightMode = AppCompatDelegate.getDefaultNightMode();
((MyApplication) getApplication()).updateNightModeFlag();
if (currentNightMode != AppCompatDelegate.getDefaultNightMode()) {
getDelegate().applyDayNight();
}
}
}, 0);
super.onResume();
}
A couple questions
1 - Is there a better way to be doing this so the app will switch the next time the app resumes after the sunset/sunrise time and not have it flicker with the change and not throwing the exception.
2 - Is the exception actually bad and going to cause me problems in some unknown way now, or in the future, if there is no better way than what I'm doing right now, and decide to take it out of the handler for the smooth transition?
I have a very important initialization to do when the app starts. I found the best way to do is to put that code inside onCreate() of the class which extends Application class.
class ApplicationDemo extends Application{
#Override
public void onCreate(){
super.onCreate();
Log.d("LOG", "Inside onCreate()");
}
}
The Problem
I do not find the log statement to be executed every time the app is run. Like I start the app for the first time, get the log statement, then close the app and start again from the launcher. No, the log statement doesn't come.
What is the problem? How can I ensure a particular code is run every time my app is run and before anything else is performed?
My guess is that you truly have open your application just once.
I'm pretty sure that, after you closed your application, it truly just goes into the background, waiting to be put in the foreground again. (It does not get created again, you only reuse something you already have created.)
Try making sure you actually killed the process of your application before re-opening it; to make sure you actually closed & reopen it, and not just do a simple background-foreground thingy.
This sounds like an Android activity lifecycle problem.
I've included a link about pausing and resuming an activity
http://developer.android.com/training/basics/activity-lifecycle/pausing.html
It looks like when you are exiting the app, your activity is being paused. Likewise when you re enter the app, if the process is still running, the activity is getting resumed rather than recreated.
From here, you can either move the code to the onResume() or you can leave it in onCreate() but make sure that exiting the app kills the process. that could be done by putting
getActivity().finish();
System.exit(0);
in any path that directs the user to the home screen (onBackPressed(), exit buttons, etc.)
for starting, try putting a Log statement in onResume and watch where the two get called.
I hope this helps.
In Android you usually do not 'close' an application, but rather suspend it.
So, when you run it again, it just pops back.
To ensure your app is closed, open the list of running application, find your one and force stop it.
An application or an activity can exist even if it's UI is not displaying. The onCreate() callback is only called when the object is created anew.
This simply means that "every time an user opens the app from the launcher icon".
Then you should be putting the code in the onResume() callback of your launcher activity declared in the manifest. You can make the launcher activity a thin activity that only does this once-per-activation init and then launches the actual main activity.
Sure, there can be prior code run, such as onCreate() of the Application and onCreate() of the Activity so it won't always be the first thing to run, but it will be guaranteed to run every time you launch from the menu.
You can use from bellow code for Kotlin:
override fun onTrimMemory(level: Int) {
super.onTrimMemory(level)
when (level) {
ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN -> {
/*
Release any UI objects that currently hold memory.
"release your UI resources" is actually about things like caches.
You usually don't have to worry about managing views or UI components because the OS
already does that, and that's why there are all those callbacks for creating, starting,
pausing, stopping and destroying an activity.
The user interface has moved to the background.
*/
System.exit(0);
}
ComponentCallbacks2.TRIM_MEMORY_RUNNING_MODERATE,
ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW,
ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL -> {
/*
Release any memory that your app doesn't need to run.
The device is running low on memory while the app is running.
The event raised indicates the severity of the memory-related event.
If the event is TRIM_MEMORY_RUNNING_CRITICAL, then the system will
begin killing background processes.
*/
}
ComponentCallbacks2.TRIM_MEMORY_BACKGROUND,
ComponentCallbacks2.TRIM_MEMORY_MODERATE,
ComponentCallbacks2.TRIM_MEMORY_COMPLETE -> {
/*
Release as much memory as the process can.
The app is on the LRU list and the system is running low on memory.
The event raised indicates where the app sits within the LRU list.
If the event is TRIM_MEMORY_COMPLETE, the process will be one of
the first to be terminated.
*/
}
}
}
And bellow code for Java:
public void onTrimMemory(int level) {
// Determine which lifecycle or system event was raised.
switch (level) {
case ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN:
/*
Release any UI objects that currently hold memory.
"release your UI resources" is actually about things like caches.
You usually don't have to worry about managing views or UI components because the OS
already does that, and that's why there are all those callbacks for creating, starting,
pausing, stopping and destroying an activity.
The user interface has moved to the background.
*/
System.exit(0);
break;
case ComponentCallbacks2.TRIM_MEMORY_RUNNING_MODERATE:
case ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW:
case ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL:
/*
Release any memory that your app doesn't need to run.
The device is running low on memory while the app is running.
The event raised indicates the severity of the memory-related event.
If the event is TRIM_MEMORY_RUNNING_CRITICAL, then the system will
begin killing background processes.
*/
break;
case ComponentCallbacks2.TRIM_MEMORY_BACKGROUND:
case ComponentCallbacks2.TRIM_MEMORY_MODERATE:
case ComponentCallbacks2.TRIM_MEMORY_COMPLETE:
/*
Release as much memory as the process can.
The app is on the LRU list and the system is running low on memory.
The event raised indicates where the app sits within the LRU list.
If the event is TRIM_MEMORY_COMPLETE, the process will be one of
the first to be terminated.
*/
break;
default:
/*
Release any non-critical data structures.
The app received an unrecognized memory level value
from the system. Treat this as a generic low-memory message.
*/
break;
}
}
On my phone even if I close an app it'll keep running in the background until you close from there manually.
You can use
onResume() {}
To run something every time the Activity gets called again.
You should in AndroidManifest.xml in tag "application" set field android:name=".ApplicationDemo"
UPD
author edited question with my assertions.
I wrote a game using libgdx on Android. When my app crashes I still can hear the music play. I think that I forgot to dispose something.
I use assetsmanager to load my resources. I call assetsmanger dispose function in the game class in dispose function of it. I think that it should stop the music and dispose of it.
what I'm doing wrong?
Originally the recommendation would be to release resources using the life cycle methods like "onPause", "onStop", "onDestroy", however, since in some specific cases like this one where the app is crashing and for any reason you just don't get the chance to release resources, there's a last resource that you can use:
public class MyApplication extends Application
{
public void onCreate ()
{
Thread.setDefaultUncaughtExceptionHandler (new Thread.UncaughtExceptionHandler()
{
#Override
public void uncaughtException (Thread thread, Throwable e)
{
//Do here whatever you want to do when the app crashes
}
});
}
}
The "Thread.UncaughtExceptionHandler" gives you the chance to get a callback when an exception was propagated without being handled at any level of the stack, hence, it gives you the chance to do things like "logging the crash to a server" or in your case you might be able to use it to release some extra resources.
Hope it Helps!
Regards!
I'm using ACRA in my android application.
But I find that when exception happens within Application#onCreate() method,it only save the report file,rather than raising the dialog to send it.
It there something wrong with my code?
#ReportsCrashes(formKey="")
public class MyAndroidApplication extends Application
{
public void onCreate()
{
ACRAConfiguration config = ACRA.getConfig();
config.setMailTo("test#test.com");
config.setResToastText(R.string.acra_toast);
config.setResDialogText(R.string.acra_dlg_txt);
config.setResDialogCommentPrompt(R.string.acra_dlg_comment_prpmpt);
try
{
config.setMode(ReportingInteractionMode.DIALOG);
}
catch (ACRAConfigurationException e)
{
logger.error("fail to config ACRA", e);
return;
}
ACRA.setConfig(config);
ACRA.init(this);
someMethodThrowsException();
}
}
The onCreate of the Application is called before any Activity is created and does not have a UI, therefore ACRA cannot display a dialog. From the android docs for onCreate
Called when the application is starting, before any activity, service,
or receiver objects (excluding content providers) have been created.
Implementations should be as quick as possible (for example using lazy
initialization of state) since the time spent in this function
directly impacts the performance of starting the first activity,
service, or receiver in a process. If you override this method, be
sure to call super.onCreate().
So, be sure to call super.onCreate(), which your example above is missing, and you should not be doing a whole lot in there that would cause exceptions.
I'm seeing two problems with your code.
You don't call super.onCreate() after initializing ACRA
Your class should have tha annotation #Reportscrashes even if the parameters are set at runtime. Otherwise you will get an error in logcat saying ACRA#init called but no ReportsCrashes annotation on Application
Also, I'm not sure if the Application can show a dialog because it has no UI layout associated with it. Toast reporting works fine if you change both points above.
If Java provides Garbage Collection, then what is the need of onDestroy() in Activity Lifecycle?
onDestroy: The final call you receive before your activity is destroyed. This can happen either because the activity is finishing (someone called finish() on it), or because the system is temporarily destroying this instance of the activity to save space.
Here is an example......
public void onDestroy() {
super.onDestroy();
}
OS decides when things "go away." The onDestroy is there to let your app have a final chance to clean things up before the activity does get destroyed but it does not mean that the activity will, in fact, be GCed. Here is a good article that I recommend people to read that relates to creating an exit button. While it's not exactly what you asked about, the concepts will help you understand what's going on.
You can use onDestroy() to finalise the program. I have used it in the code bellow to tell the server that the client is closing its socket to the server so I can notify the user on the server end that the client has disconnected.
client:
...
protected void onDestroy(){
super.onDestroy();
if(connected) {
clientMessage.println("exit");
clientMessage.close();
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
finish();
}
...
server:
...
while (connected) {
input = clientMessage.readLine();
if ("exit".equals(input)){
break;
}
...
}
...
onDestroy() is a method called by the framework when your activity is closing down. It is called to allow your activity to do any shut-down operations it may wish to do. The method doesn't really have anything to do with garbage collection (although your shut-down operations—if any—might involve releasing additional resources that can be gc'ed). In particular, it has nothing to do with C++ destuctors (despite its name).
If you have no shut-down operations to do, you don't need to override it. The base class does essentially nothing.
onDestroy may be called when an activity is destroyed, but you can not count on it. There are situations where the system will simply kill the activity's hosting process without calling this method (or any others) in it, so it should not be used to do things that are intended to remain around after the process goes away.
See: http://developer.android.com/reference/android/app/Activity.html#onDestroy()
In the Android Activity Lifecycle's onDestroy docs:
onDestroy() is called before the activity is destroyed. The system
invokes this callback either because:
the activity is finishing (due to the user completely dismissing the activity or due to finish() being called on the activity), or the
system is temporarily destroying the activity due to a configuration change (such as device rotation or multi-window mode)
The Activity#onDestroy() API docs also answers it quite well:
This method is usually implemented to free resources like threads that are associated with an activity, so that a destroyed activity does not leave such things around while the rest of its application is still running. source
As the quote from the docs say, its for preventing a destroyed activity leaving things around (e.g. memory leaks through referencing, threads), but only when the rest of the app still runs. If the application process ends, it doesn't matter if you forget to clean up threads or other resources since the OS will do it for you. You don't need to override onDestroy.
There is no need to do what sam786 is doing (overriding and just calling the super method) as that is absolutely useless. All other answers seem to go along the lines of "clean up", but don't explain what kind of clean-up or when. You should not be saving any data in onDestroy(), as you can't guarantee it will be called, so you will lose data sometimes. It won't be called when you press the home button, for example (the case where you want data to be saved).
The onDestroy is there to let your app have a final chance to clean things up before the activity does get destroyed
Article Exit Button in Android
It gives your program a chance to do things like cleanup resources (say threads) so that they don't pollute the associated application. If you don't have any use for it, then don't override it.
See:onDestroy()-Android Reference