I experience a very strange problem.
From the MainActivity of my app, by clicking on one of my menu button, a new screen / fragment called MyFragment is loaded.
On the MyFragment screen there is a button called MyButton. If the MyButton button is clicked, it opens a link on a browser.
The problem is that, from the browser, if I click on the Back device button, the behavior is very different depending on the device I test the app (and you will all agree it should NOT) :
on a Samsung Galaxy Tab 2 tablet, the app gets back to its previous state, with the MyFragment loaded and opened (just as if nothing changed from the moment when I clicked on MyButton).
on a Nexus 4 phone, the app is like reset (and then the MyFragment is not loaded). Basically the previous state is lost.
Any idea ?
Here is the piece of code I call from the MyButton click event.
Intent i = new Intent(Intent.ACTION_VIEW);
i.setData(Uri.parse("http://www.example.com"));
i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); // I tried this but no luck
startActivity(i);
Thanks in advance.
It sounds like on some phones your Activity is geting killed by the OS. Android has the right to kill any Activity that goes in the background if it needs to reclaim the resources that it's using. This is the expected behavior. To mitigate this, you'll need to manage the Activity Lifecycle. The important thing to note from that page are that onSaveInstanceState() will allow you to save your state if the OS is about to kill your Activity, which will restart the lifecycle with onCreate() and provide you with a Bundle that contains all your saved state information.
Additionally, fragments have their own lifecycle, with the equivalent onSaveInstanceState() method, so any Fragment-specific info should be managed there.
Answer : on the Nexus 4 "Developer options", the "Don't keep activities" option was set to true. That's why...
Related
This is harder than it sounds, which is why I'm asking for solutions.
Basically I only want the disclaimer Toast shown once per run of the app.
The app is in two parts, all are Activities.
It's shown when it starts in the first part, but you can hit a menu button
taking you to the second part of the app, which has another menu button
to take you back to the first.
The problem is that whatever initial settings you try to make in the first
part, when it starts up, are run again when returning from the second
part of the app, so it'll show again.
My last idea was that in the first part's onDestroy(), when the app exits, but is not the case in this situation, you set a boolean in settings,
to reset that the disclaimer can be shown, but apparently, onDestroy() is called on the first part before it goes to the second part.
Or, if you can get it to not show the first run, but behave properly
every time after that, that would be okay.
And there doesn't seem to be any method to be called when the app truly
is "killed", if there was that would be the way to do it, you could reset it there. Or if there was a method that was only called when the app first started..
Thanks!
You just need a boolean flag. Say we call it disclaimerShown. In onCreate() of Activity A, we check both the Intent Bundle and the savedInstanceState Bundle for this flag.
You can add the boolean to a Bundle when launching the Intent to start Activity A from Activity B.
If the user is in Activity B and presses the Back button to return to Activity A, you can override onBackPressed() in Activity B and include your flag there as well (though you'll have to catch this flag on onActivityResult() in Activity A).
If system initiated process death occurs in Activity A, the system will call onSaveInstanceState(Bundle bundle). So you add your flag to this bundle as well.
And if system initiated process death occurs in Activity B, you have nothing to worry.
And that handles all possible cases.
An elegant solution for this problem would be the ProcessLifecycleOwner.
This class provides callbacks to the lifecycle of your whole app (not individual activities) and you could use the Lifecycle.Event.ON_CREATE callback to show your toast once. Look at this stackoverflow question for a usage example of the ProcessLifecycleOwner.
It turns out that I already had an Activity that started before
my "Activity A", and I moved my disclaimer Toast there
and it works fine. You can't beat that simplicity lol.
Thanks for your answers!
I have an Activity that opens a new Activity for result like this:
Intent i = new Intent(ActDocument.this, ActCustomers.class);
startActivityForResult(i, ActDocument.DIALOG_CUSTOMER);
when I press back in the child Activity and return back to the parent Activity onActivityResult is called in all of devices correctly but I have fount a device that onCreate is called instead of onActivityResult.
This device is Samsung Galaxy Tab-P5100 Android 4.0.3. It is strange that I have tested my application on other devices of Samsung Galaxy Tab-P5100 Android 4.0.3 and it was OK but I have problem only in this device.
Why? How can I solve that?
Update
I noticed onDestroy() of parent Activity is called after opening child Activity on this device.
most of the time Back button will finish the activity unless you specific override the
OnBackPressed()
I think your problem is lack of resources, or maybe you have some developer options like kill activty flag or limit background process check this.
Update
Go to setting-> developer options unchecked don't keep activities and background process limit set to standard limit.
Perhaps the back button doesn't finish the Acivity. So, override onBackPressed.
I have activities in sequence as Activity A calling Activity B,When I am on Activity B I press Home button and start another Application (for example Map). If i stay on this second application for a long time say 5-10 minutes and then press Home Button again and choose to Start my application again, then Activity B is started again and works fine. But when i Press Back key - I return to my Activity A again (which is also correct) but it shows a Blank Screen. Ideally in correct version it should show me Acitivty A with the XML data is ListView form.
Alternatively, in the above description, when the other Map Application is started and if the user stay on it only for 1-2 minutes then the above problem doesnt not occur.
Can anyone suggest a solution on the same.
Is it that i need to check in Activity B whether Activity A is still there in Activity Stack (How do i do the same) and If its not in my Activity stack then re-create it.
I tried doing alwaysRetainTaskstate in my Android manifest file for Activity A. But it doesnt work at all
You don't have to do any of that, Android takes care of the technicalities for you - it will recreate your Activity A.
You just need to remember to save A's state when B is opened (take a look at Activity.onSaveInstanceState). When A is restarted, your saved state will be passed to onCreate.
You should really read about Activity Lifecycle
This should help.
The problem is somewhat odd and after having trying to figure it out for about a day now, I am posting it here.
I have an application where an activity A(main activity) launches other activities(B,C or D).
The issue here happens when activity A has started Activity B and 'home' button is pressed.
Case 1 - When I test my application in debug mode on my device (HTC Desire) after pressing the 'home' button, I again click the application icon, it returns to the same activity (activity B), which is what is should do. No issues here.
Case 2 - When I export the signed package, and then install the application on the same device, then if I click the application icon after pressing the 'home' button, then a new instance of activity A (main activity) is launched ON TOP of activity B. I got to know this because when I press 'back' from that activity, it returns to activity B and pressing 'back' again shown activity A.
The behavior ceases to exist if the application is quit in the same order it was started, that is, if I press 'back' from activity B, then 'back' from activity A (exit).
After this everything runs fine.
I have tested it many times with different settings but I can't seem to figure out why the behavior is like this.
Any help is appreciated.
I think giving Activity A the 'single top' flag in your manifest should fix this.
Regarding Case 1:
When launching your intent from Activity A to start Activity B, add the flag FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET
This will ensure that when you go home and launch the the app again, Activity A will be shown.
Regarding Case 2:
I'm not exactly sure how this would occur. It seems like it thinks you have two versions of the app, the signed one and the unsigned one but keeps them both in the same task stack. You may want to consider using singleTask or singleInstance for your Activity if you only want one instance. See the doc on tasks and back stack for more details.
I would agree with Noel regarding the likely cause of Case 2. Without task reparenting or it being set to a launchmode preventing multiple instances of an activity, there is a chance that launching it from Home isn't deemed the same stack as launching it from Eclipse (assuming this to be the case).
In my talent calculator app I have the whole application set allowTaskReparenting=true to ensure nothing is left in other stacks (primarily email as it can email launch urls). I then have my main activity set to launchMode="singleTask" as I only ever want one instance of this to exist no matter what launches it or with whatever intent.
My only other activity is for loading and saving and that has noHistory="true" to make sure it is removed and never returned to. That basically means it only exists while you're in it, and can never return to it.
clearTaskOnLaunch="true" will also ensure only the main Activity remains in the stack when it's launched from Home, but this isn't always the case if you have other ways to get into your activity. If it's only ever launched from Home then set this.
Hope that all helps.
Do you start you application manually or using Eclipse or another IDE? When starting from Intellij IDEA I had exactly the same problems. Then I stopped and ran it manually and behaviour was as expected.
I'm experiencing kind of strange behavior of my application after hard Home button is pressed.
When you press Home, everything is OK - my app goes to the background, showing Home screen. But if you try to choose my app in the main menu or in the list of last tasks it behaves like it was not started before and does not show the last activity you were on - it just starts from scratch, namely, shows the splash screen and starts next corresponding activities. Moreover, old activities of this app remain on the activities stack, and previous instance of the app is not terminated - so if you press Back for a few times you'll just run into those activities which were undoubtedly started during the previous session of work with my app. Splash screen activity is filtered by "android.intent.action.MAIN" filter and "android.intent.category.LAUNCHER" category.
The strange thing is that all of that happens despite the fact that I do not intercept any Back key hits, or override any onPause or onResume methods. What's happening contradicts with my understanding of Android app lifecycle - I was sure that when you hit Home an app just goes to the background, and when you choose it in the menu later - it just unwinds and does not start anew. (Of course, unless stuff like that is stated in the app manifest or corresponding methods are overridden or something else).
I also checked it for some other lifecycle events - such as changing orientation or flipping hard keyboard out - and none of those led to such strange results. It appears that the problem occurs when you try to start the app from main menu or menu of last applications.
I hope you will be able to help me. Any advice on what to pay attention to or where to search for solution would be really great.
Regards, Alex
You need to set android:launchMode="singleTask" in your LAUNCHER activity in your manifest file.
For more info on the launchMode attribute see here
Note that:
The default mode is "standard".
and:
Every
time there's new intent for a
"standard" activity, a new instance of
the class is created to respond to
that intent.