I observed that if I open some apps installed in my phone via Google Play's 'Open Now' button the app will open as normal, if I navigate to another Activity inside the app, then pressed home, then go to phone's launcher, open the app through there. It will start a new task -- I believe -- because the App's launcher activity has resurfaced. If I press back, I will then be in the second Activity -- which is the last Activity in the foreground when I launched the app from Google Play. Is there a way to avoid this? I'm expecting to see the second activity in this scenario. I want to have the same task whether my app is launched from the Launcher or Google Play store.
I found out that a lot of apps in the Playstore has this behavior. One good example is the Zomato app and for reference my app is Shake Eat Off
I've been experimenting the android:launchMode in the Manifest with no luck.
I tried setting singleTask to the root activity and `singleTop to the second Activity
I also tried adding android:alwaysRetainTaskState="true" to the root Activity.
I also tried setting singleTask to the root Activity and singleInstance to the second Activity
So to explain more the chain:
Google Play App Page -> Open Now -> Root Activity -> Second Activity(now foreground).
Press home, Click App Icon.
At this point, The root Activity is now again showing (But I'm expecting to see the second Activity because it's the last activity on the foreground).
Press back ->
The Second Activity will resurface.
It happens because launcher intent is started again.
I see someone post a short solution in a discussion community. And I came up with a fully solution with the original solution.
In your splash screen you place these codes in onCreate()
if (!isTaskRoot()) {
finish();
} else {
// Place your current onCreate() codes
// We put code here because finish() doesn't kill the activity immediately while OS takes a while to kill it and we don't need codes to be execute
}
These code help you not skip new task and bring up all old created tasks
In your splash screen if there are some codes in onResume()
Place them in the following condition
if (isTaskRoot()) {
// Place your current onResume() codes
}
This help your onResume() codes do only when the task the old root task. Use this because finish() function in onCreate() doesn't kill the new Splash screen immediately while OS takes a while to kill it.
Related
So my scenario is as such.
Let's say there is a MainActivity, which only job is to start, call installSplashScreen().setKeepOnScreenCondition { true } to show the Splash screen using the new backward compatible APIs, and then after checking some state it does startActivity(SomeActivity); finish()
Now we're on the SomeActivity and if we press the home button, the app is gone on the background. Then if we click on the launched icon, the SomeActivity is launched correctly, and the MainActivity's onCreate is never called, therefore the splash screen does not show again, and the SomeActivity shows instantly.
But if instead of pressing the home button, we press the back button, and the app is backgrounded that way, then when we click on the launcher icon, the MainActivity's oncreate is called again, and the splash screen icon flashes for a tiny fraction too making it look jarring.
My question is, does this sound like it's some wrong configuration on my part, or am I stuck with this behavior as long as I am not on a single activity architecture?
You are confused. Pressing the BACK button does not "send the app to the background". The default behaviour of the BACK button (assuming that you don't override this and provide your own behaviour) is to finish the current Activity. Normally this will take the user to the previous Activity in the current task. In your case, there is no other Activity in the task stack, so the current task is empty. This may appear to the user as "the app is sent to the background", but in reality there is nothing in the background. Your app's task is empty and so it is gone.
When the user then taps the app icon on the HOME screen or taps on the app's task in the list of recent tasks, there is no existing task to bring to the foreground, so the app is started again by creating a new task and launching the root Activity (in your case MainActivity) into the newly created task.
If you want the BACK button to just put your app into the background (instead of calling finish() on SomeActivity, which is the default behaviour) then just override onBackPressed() in SomeActivity and do this instead:
moveTaskToBack(true);
It seems like there is no solution to what I am facing as long as the Activity I want to resume to is not the Launcher activity.
From the the docs:
"Root launcher activities are activities that declare an Intent filter with both ACTION_MAIN and CATEGORY_LAUNCHER. These activities are unique because they act as entry points into your app from the app launcher and are used to start a task.
System behavior on Android 12 and higher
The system moves the activity and its task to the background instead of finishing the activity. This behavior matches the default system behavior when navigating out of an app using the Home button or gesture."
Reading the docs about the new back behavior on Android 12 and onwards tells us that pressing back when you got nothing else on the stack will act as if you pressed the home button.
There's a big exception here, and that is that when you re-open the application, if the one you just popped was not the launcher activity, it will then still need to launch that launcher activity and can't resume from where you left off in a hot state, exactly the reason why I am seeing the splash screen again.
So I think my best bet is to either ignore this for now, or fix my app to be a single-activity app, or at least keep the launcher activity be the top-level one that you exit the app from by pressing back
To indicate a couple of examples, if one wants to experience what I mean, the reproduction steps are to:
Open the app
Press the back button which will send you out of the app to the home screen
Click on the app icon again
As of today, apps like Google Photos, and Google Podcasts don't show the splash again. In contrast, apps like Google Maps, Twitter, Spotify do show the splash again for a brief second.
to call the launcher activity every time you have to clear the stack that means you have to use a flag in your manifest to tell your app not to keep activity in background try android:launchMode="singleTask" inside your activity tag in manifest the activity that you want to be killed everytime you go to background, and as far as how much time splash should be showing you can use timer for that after the timer is finished then your someActivity will be called.
I am building an Android app, which starts a service that keeps running in the background. When the user uses the Home button to close one of the activities (which communicate with the service), and then navigates to the app again, they get the last activity. This is correct behaviour.
However, when I explicitly stop the service (via an option in the menu), the app should "Quit". Currently, that works like this:
stopService(new Intent(this, MyService.class));
finish();
// just go to to the home screen, as it is intended in Android
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_HOME);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
and that works fine. But when I now navigate to the app again, it starts the previously opened Activity. What I want is that it starts the starting activity again (the launcher).
How could I accomplish that?
System.exit(0);
But you should have only one Activity in stack.
If you look at the description of android:excludeFromRecents it says:
Whether or not the task initiated by this activity should be excluded from the list of recently used applications ("recent apps").
isn't this what you are looking for ? Once the user hits exit, this app won't be in the recently used apps and hence will be completely removed from memory ? :)
I think that removing 'the app completely from memory on exit' is not the issue. Even if you stop your service the process is likely to remain in memory - that is the systems' decision.
You want an explicit, custom behaviour - user chooses your 'exit' option from menu --> next app launch starts at main activity - so you will need to handle this explicitly.
The default behaviour is that the user returns to their last activity when they re-launch. So they only return to the main activity if they exit by 'backing out' through your activities. Your use of an 'exit' menu option is non-standard (not to say it is bad).
One option would be to do the backing out through your activities yourself. Perhaps now you are just finishing the current activity and you should instead finish all the activities in the back stack.
Another option is that you could save a flag, and when the UI is launched again you could read that flag and launch the appropriate activity (but again be careful with the backstack). The easiest way to set that flag is probably by overriding onSaveInstanceState(Bundle) and then reading the bundle in onCreate (or use sharedpreferences).
Have you tried setting the clearTaskOnLaunch to true for your main activity (in your manifest).
From the documentation:
When the value is "true", every time users start the task again, they are brought to its root activity regardless of what they were last doing in the task and regardless of whether they used the Back or Home button to leave it.
This seems to describe what you want to do. I have never tried this personally, but it seems worth investigating for your purpose.
I have 3 activities ( say A, B, C were A-is the Launch activity). When I press home button when at activity C, app goes into background. After that, I took my app through all apps list menu. At that time, my launch activity is showing (activity A). When I press back button, It goes to previous activity (C). I want to retain in the same activity (C) while coming back from background. When I run application through Eclipse, It works fine. But when I send Apk file through mail and run it in device, It fails (previous problem occurs ).
I tried with
android:launchMode="standard"
AND
android:alwaysRetainTaskState="true"
in my launch activity (Login activity or A). Any body please help me, Thanks in advance.
Follow following steps to insure that you are following the right practice:
1. Make sure you are using finish(); on the Activity A or B if you want to finish it and dont if you want the back button functionality.
2. Try Implementing onpause() and onresume() even if you are not going to perform any functionality in them. Use super() for them there.
3. Also, in android when you start an activity by clicking on the icon instead of resuming it from already running activities, it exhibits a different behaviour.
I'm encountering the following scenario in my application:
Installing it and immediately opening it (using the open button
after the installation, instead of the icon in the applications
list).
Navigating through a few activities.
Clicking the home button.
Clicking the application icon to load it again.
Instead of returning to the activity I was in, the initial activity
is loaded. The previous activity is still there and can be accessed by clicking the back button, but there isn't really a way to know that and it looks like the app was completely restarted.
This may be an issue in this app, because in some cases it might require a registration after performing a few actions, and losing the focus on the activity could be very annoying
Is there anything that can be done to avoid that?
There's a couple of flags under Intent that might be helpful. You use them when an Activity is launched:
"FLAG_ACTIVITY_TASK_ON_HOME: If set in an Intent passed to Context.startActivity(), this flag will cause a newly launching task to be placed on top of the current home activity task (if there is one).
FLAG_ACTIVITY_REORDER_TO_FRONT: If set in an Intent passed to Context.startActivity(), this flag will cause the launched activity to be brought to the front of its task's history stack if it is already running."
http://developer.android.com/reference/android/content/Intent.html
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.