I face the following very annoying problem:
I'm using the Google Compatibility Library in order to future-proof my apps.
Now... I'm keeping track of my backstack:
1) Launch App.
2) User Interaction A -> Fragment gets added to UI/ Back Stack.
--- Backstack Size: 1 ---
3) User "backgrounds" the app.
4) User kills the App with a Taskkiller / or the app gets killed by the android system
5) Launch app again. Full Restart of the application (Application.onCreate()) presented to the User.
6) User Interaction A -> Fragment gets added to UI/ Back Stack.
--- Backstack Size: 2 ---
At this point I would want to have a backstack size of 1.
If the user presses back now, the app takes him back to some former state, which doesn't make sense anymore, because the app presented a fresh start.
Any Idea on How to do this??
Thx
Although your application has indeed been killed, there is not technically a 'full restart' when you try to launch it again. This is certainly not the way Android would want you to consider the situation.
When you background your app, Android will save the state of the fragments that have been added to the fragment manager (as well as the state of which activities are open, and their view state). When you relaunch your app after getting killed, Android will give you back all of this state and so you should be able to resume from exactly where you left off. This means you should consider that 'User Interaction A' has already happened and really you are at step 2) again. As you have noticed, the backstack is preserved; this is because the fragment transactions you have performed are also preserved.
The problem is of course, that we don't always write our apps in a way to match this behaviour. If your app presents a 'fresh start' after being killed whilst backgrounded, then arguably it is not really following the Android approach (assuming there is some user state worth saving).
I think you should try as best you can to resume as at step 2); it will likely be (marginally!) easier than trying to prevent Android from saving this state.
Related
when I am in the last activity and I press back, my app goes to the background but when I return my app restarts going back to the "login" screen, if I am in "Home" and I go back it goes to the background because my login activity finished, I understand this is part of how the Android system works. Having an app with an sdk that uses bluetooh with asynTask tasks, I would like to be able to force an activity not to close or cancel when it goes to the background, I am looking for alternative solutions such as making the app stay in "widget" mode or being able to launch some kind of "service" that forces my activity as such not to close or restart when it goes to the background, I'm quite new to all this, any suggestion on how to solve this problem will be welcome
Backing out of the last Activity on the stack treats the app as "closed", and there are expected behaviours associated with that:
The user's assumption in these complete dismissal cases is that they have permanently navigated away from the activity, and if they re-open the activity they expect the activity to start from a clean state. The underlying system behavior for these dismissal scenarios matches the user expectation - the activity instance will get destroyed and removed from memory, along with any state stored in it and any saved instance state record associated with the activity.
So while it is possible to restore the previous state (the example they give is a web browser opening at the same page it was on) the system and components like Navigation are built around this idea that state shouldn't be preserved. You'd have to put in effort to work around that.
Running a Service only keeps your app's process alive - it won't do anything for background Activities, which the system will destroy if it needs the memory. And besides, like it says above, if you back out of an Activity it's considered dismissed and its state is wiped, whether it's been kicked out of memory or not.
Honestly it sounds like you just want to avoid redisplaying the login screen if the user's already logged in? That shouldn't be anything to do with Activity state, you should be storing that data somewhere so you can check it when the app starts, so you can send them to the appropriate screen
There's a whole section about this exact scenario in the Navigation docs. They don't show their UserViewModel (which we're supposed to imagine handling logged-in state, and actually doing the user/password auth if necessary) but the idea is pretty simple - you have a component that exposes a value saying whether the user is logged in or not (which could be stored in e.g. SharedPreferences) and it can automatically navigate away from the login screen based on that.
I am using Singleton pattern. When application goes into background the OS kills the app to release memory. When user comes back to app my application starts from same Activity User left off but my singleton instance is not available because it was released too when OS released memory.
Suppose I am at Activity 5 and I have values int a = singleton.getInt() it will give me a null pointer exception. Other local views initialized are null too. But if my application restarts from splash screen then its all good because app flow is starting from scratch. Sometimes it starts from Splash, some times it goes to Activity 5 or whatever activity User left off (which will cause null pointer exception). I have used a lifecycle Observer to monitor application state in MainApplication but what exactly is the root of this issue. Any ideas?
Why does this happen?
When the system kills your application to free the memory it saves a few pieces of data about the current state of your Application into the internal OS storage. Later on, when the user opens your app once again, the system takes that saved data from the storage and tries to restore the state of the Application.
The reason for that behavior is to make the user experience smoother. By restoring the state - the user can quickly continue doing things he was doing before quitting your application.
Some of the data that is stored in the OS storage:
Activities back stack (back stack of the Task)
FragmentManagers back stack
Bundle that you saved in the onSaveInstanceState methods
Please note: ViewModels are not saved between application re-creation. Even though they are saved upon Activity recreation(configuration change, such as screen rotation). So data that you store inside of your ViewModels (if any) would be lost!
In order to support this OS feature and ensure a smooth user experience in your application, you must design your application to not depend on any Launcher Activity to instantiate your singletons and instead use some other architectural approach that would not require your Launcher Screen to launch every time the application restarts.
What can you do?
You could try one of the following:
Save all the user input data (if any) to the Bundle in onSaveInstanceState method.
Migrate from Splash Screen Activity or Launcher Activity in favor of the Reactive approach to data instantiation.
Move your Singleton instantiation to Application class. Note: This could significantly increase the launch time of your application.
That is by no means an exhaustive list of actions you could do. I bet you would have better ideas that are applicable to your own application.
If migrating away from Launcher Activity is not possible at the moment, I suggest adding to your Activity onCreate method a check that everything is instantiated and ready to use. If not - immediately navigate the user to your Launcher Activity.
Please note: It would be good UX to save back stack and navigate back to the current activity as soon as your logic on Launcher Activity is done working.
I've noticed an odd behaviour in an app I'm analyzing and I would like to know if this is by design or it's simply a bug of the platform?
I have a complex application but to simplify my example lets say I have an application with Activity A and B. Now if I run my application and go from A -> B, given that I won't finish Activity A, then I will kill the process (but the app window is still visible in Recent applications) then if I tap the window in recent apps what would happen is:
1) Process is being created
2) Application object is being created
3) Stack is untached (A -> B) and after analyzing it by the framework Activity B is recreated
4) Activity A is "dead" untill I hit the back button
Now the interesting thing happens if I introduce a large singleton instance, lets say an instance of "Dictionary" which can hold many key-value pairs. If that dictionary instance is large enough the above scenario will not happen, meaning that the stack appears to be cleared and my application will follow a typical launch scenario so Activity A is being created instead of Activity B.
Is this a proper behaviour of the Android Framework and if so... why is that proper? I'm interested in the reason and why this occurs.
I know how Android works concerning killing not needed processes if the memory is needed by another app, bu I dont like the following behaviour of the App I develop at the moment:
I start my App, which has a lot of different screens/activities
After using it, i push the Home Button of my phone and switch to some other App.
(Lets say I did this while Activity C on Screen C was active).
My phone is a HTC One X, I checked, that there are always about 300MB of Memory available, when I run the Apps I usually need.
The Problem:
Even if I restart the App after a couple of days without using it, the App restarts with Activity C on screen C. In my opinion, after some days of not using the App, it should restart with the "Welcome Screen" i created.
As there are no Backgroundprocesses or ressources used (all these stuff is done by pushing buttons and has to be finished - so no automated backgroundprocesses are needed), I think, Android does not feel the need to kill it.
Does anybody know, how the "Android Best Practice" looks like for this or where I can read what behaviour the App should have in this case?
(... I am not looking for Code, but I dont know what way I should go to solve this)
Many Thanks for any help
I think you can easily do finish() the activity's on onPause() method.
Not sure whether this is a best practice. Awaiting other answers.
If I'm not mistaking, the following flag can help you when used by an Intent starting a new Activity: FLAG_ACTIVITY_NO_HISTORY. As the documentation says:
f set, the new activity is not kept in the history stack. As soon as the user navigates away from it, the activity is finished.
So if all your Activities, except of the welcome screen, are started using this flag, next time a user comes back to your app he arrives at the welcome screen. The drawback of this solution is that if a user receives a call while working with your application, he will also be transfered to welcome screen when the call is finished. Don't know if there is any other solution. Hope this helps.
Please help me to resolve this problem.
1 > I am having application which Uses Service to retrieve data from server.
2 > Now on Pressing Home key and i have opened new application..
3 > I have opened around 20 application.
4 > So my application might go out of memory stack.
5 > now i am resuming my application, application crashes as i am opening activity of my
application which is not in the stack.
Is there anyway by which i can handle this exception and redirect my activity to Homepage or relaunch application resume and is not in stack...
Indeed a very good question which I try to puzzle out myself.
I even wonder What's the difference between killing an app and restarting the phone.
If a user manually kills an app or opens 20 other apps, he'd probably want the app to start from the beginning.
Why Android aren't restoring state after phone restart?
Also, I see that when an app is killed (by the system), global variables turn to null upon activity reinitiating.
This kind of breaks the concept of Java. If you have some kind of state in the application and the application erases it, I would expect the application to restart.
The solution I propose:
1. Handle the case of a state problem: Initiate a simple state (new Object()) as a global variable. For each Activity, in the methods onCreate/Start/Resume check that the state is null. If it's null launch the first activity with 'Intent.FLAG_ACTIVITY_CLEAR_TOP' - as if the application is relaunched.
2. Try not to use global variables - Always put data in the intent.
3. Lazy load global variables - If you do want to use global data, don't count on one time initialization. Lazy load them 'if (A.MY_DATA == null) {A.MY_DATA = new ...}' - Don't forget to do it in the background if it will take a long time (AsyncTask). Loading partial state needs to be done carefully because it may not comply to other loaded state objects.
The downside of the first point is that the state problem handling needs to be done on every Activity (AOP is not yet implemented in Android).
Hope that helped.
Use SharedPreferences for save Application state