For simply, I write an app with Splash, Home, Child1 and Child2 with following flow: Splash -> Home -> Child1 -> Child2. And we can back from Child2 to Child1, from Child1 to Home, and back from Home to exit app.
It sounds simple. I can navigate between these screens correctly.
Problem when I install app via OTA. After enter Splash -> Home -> Child1 -> Child2. Staying Child2, I press HOME button to minimize app, and re-enter app by choose app icon. But when re-entering app, it doesn't resume at Child2 but start from Splash -> Home. I cannot understand what happens here. It should resume at Child2 instead.
More surprised thing is, at Home screen, when I press BACK button to exist app, now Child2 is resumed (o_O). And from Child2, now I can back to Child1, and to Home, and back again to exist app.
All these issues happen when I install app via OTA but app works normally when I install by cable.
Can anyone tell me what happens in my situation? Any help is appreciated
Many thanks.
P/S: I get this bug when testing on Nexus 1 (Android 2.2) and Nexus S(Android 2.3.x)
Edit: even CNN app for Android still have this issue... Is it belong to OS?
This has to do with task affinity I guess. And it's not just the CNN app, all apps behave like that because some developers (like me!) don't understand how the task concept works. I won't lie to you, even I don't understand this all the time.
I believe this happens because, when you launch your app from the Market, your app becomes part of the Market task. Therefore, you have an instance that "belongs" to the Market task. You can navigate normally from it. All the problems happen when you press Home because...
If you start the activity from the Launcher, you start a new task for the app, giving you 2 "instances" of the app, one belonging to the previous Market task, the other belonging to your own app (where you are the root of your own task).
On this new task, you can navigate back, and eventually you will reach the previous task, which has another instance of your app. You will reach the point where you left off (considering regular launch mode for the activities). Sometimes, this is odd because we normally think that one app has only one instance, when it's not how it works, nor it's how it should work. I loosely compare that with launching twice an app in Windows having two Windows open. In Android, this analogy is similar (at least to me).
This is all fine when you start your app from another app, when the task concept feels natural.
However, in this case it becomes weird because when we launch the activity from the Market, we expect the instance to be the same that will be in the Launcher (when launched from there). We naturally don't expect that the Market, used to download the app, will own an app that we installed, and that we (obviously) want to use separately from the Market app (I don't think a Market should own a task when using the "Open" button).
To solve that, I believe you could fiddle with allowTaskReparenting. However, in case it's really that which is causing this issue, I don't recommend it because this could break other legitimate uses for the task system.
Finally, this is how I believe tasks work, and that's my guess to where this problem comes from. I could be wrong, so please forgive me if this answer becomes useless later (if you find another cause that answers this).
Good luck!
Looking at your comment you kill your activities as soon as you start a new one..
E.g. if you do:
startActivity(intent);
finish(); // THIS WILL KILL THE ACTIVITY -> MAKING IT UNREACHABLE
The activity that launches the new activity is being killed and cannot be reached using the back button.
Remove the
finish(); // REMOVE THIS TO KEEP IT ON THE ACTIVITY STACK
after you call startActivity(intent), and all your activities should stay in memory. Hence, they will be reachable when you go back. NOTE: for the Splash, you should indeed call finish(), since you don't want to go back to the Splash activity after a succesfull launch!
Related
I have an app that acts as sortofa bridge between two other apps, A and B, both of which are mostly black boxes. The user almost always stays in app A but sometimes needs to do something that my app or app B know how to handle. App A supports external actions via URL so I have a custom scheme://host defined for my app.
If the user does an action that my app handles, I get launched via the URL then do my thing then call finish() and the user's back in app A where they started (edit: same activity and etc) - perfect.
If the user does an action that app B handles, my app needs to be in the middle so it can do some translation. App A launches me, I format the message for app B and launch it. When it's done and comes back to my app, I call finish() and.. end up back in app B. Understandable I guess but I really want to end up in app A.
So the question is, how to I tell Android to put A back on top/in front without changing it? I can find the URL for app A via getReferrer() but when I put that into an Intent, it acts like I'm restarting app A instead of just going back to where it was. The doc for Intent.FLAG_ACTIVITY_NEW_TASK looked promising but it still acts like a new instance of the app.
It seems like this should totally be possible but I'm not seeing it. Java/api25.
The problem is that App B is not ending, returning control to your app. App B is launching your app, putting your app on top of it. When your app finishes, your app goes away revealing the still running App B underneath.
So basically App B has bad behaviour (at least, behaviour that is inappropriate for what you are trying to do).
To solve the problem you can either fix App B, or you can do the following:
Instead of just calling finish(), when you want to return to App A just launch it the same way that Android launches an app when the user presses on the app icon:
Intent intent = getPackageManager.getLaunchIntentForPackage("package.name.of.app.A");
startActivity(intent);
finish();
This will bring App A to the front in whatever state it was in when it was put in the background (ie: doesn't actually launch any new Activity). If App A isn't running, it will launch the root Activity of App A, as if the user pressed the app's icon on the HOME screen.
I'm assuming that both App A and App B are running in separate tasks. If that isn't the case, I'll need you to provide more information about which activities are running in which tasks.
The Android docs say
If the user continues to press Back, then each activity in the stack is popped off to reveal the previous one, until the user returns to the Home screen (or to whichever activity was running when the task began). When all activities are removed from the stack, the task no longer exists.
Well I tried this on a galaxy s4 with android 4.3, but afterwards when I hold the home button to show all tasks the task is still there (tried with settings app, help app, internet app, my own app). In what way does it not exist?
Edit:
I'm reading up on tasks to understand the Android system. I have no specific app development problem.
I am working on a fitness app which has a home activity which launches a workouts activity which launches a specific workout activity. In the workout activity, one may start a workout. Thereafter, one might want to then press the Home button and launch a music player or perhaps the web browser. At some point, one would probably launch the app again to return to the already running workout, but that ends up launching a new instance of the app. When I set the launchMode on the home activity to singleTask, it simply goes back to the existing home activity when I tap the launcher icon. What I would like is for it to go back to the workout in progress, which is where you would depart the app.
Essentially, I'm looking for behavior identical to iOS where it would simply restore the app to its current state if you "relaunched" the app and it was still running.
It is supposed to work as you've described. In most cases, it actually does work like that. However, there is a long-standing nasty Android bug which causes the behaviour you've described. This happens when you launch the app for the first time from an IDE (like Eclipse) or by clicking the "open" button on the Installer screen. To see if this is what you're seeing, just do this:
Go to Settings->Applications, choose your app and click "Force close"
Launch your app, do something, press the HOME button
Launch your app again.
You should return to where you left off. If not, something else bad is going on. If that is the case, please post your manifest in your question, because the problem is likely in these.
Don't try to use special launchModes to fix this. This just creates more problems.
See this answer for more information about the nasty long-standing Android bug.
I'm having a bit of an issue with interaction beween my app and other apps on my phone, but I'm starting to think that maybe it's working as designed? Anyway, here's the problem.
My App, call it App A is a photo-manipulation app. So a user goes in, plays around to make changes and then uses the Share button to pass it on (SEND Intent). The photo is sent to another app, chosen from the Share menu, call it App B. This stand-alone app has its own menus, completely different look and feel, etc. The user does his thing in this app for a bit, then hits the home button and goes his way to do something else.
Sometime later, he decides he wants to run my app again. He goes into the launcher, hits the icon for App A (my app), and up pops App B. Very confusing. If he happens to remember that last time he ran App A, he used the share button to get into App B, maybe he'll think to use the back button, to get back into App A. If he doesn't remember, all he knows is that he is trying to use App A, but Android is giving him App B.
(I have one app on my phone that takes over the back button for its own use so you more-or-less get stuck in App B with no way out. Ugh. You hit the icon for App A and always end up in App B)
Is there any solution to this, or is it working as designed? None of my onCreate, OnResume, onStart, etc. methods get called when this is second-open is occurring, so I can't trap it. And realistically, I can see the desire for this behavior when timelines are short - i.e. hit the home button, quickly use some other tool, and then go back to what you were doing. But with a timeline any longer than a minute or two, it gets very confusing.
Anybody else dealing with this problem? Is there a basic Android architectural issue here? Is the SEND intent being mis-used by being accepted by stand-alone apps instead of small utilities?
I think you may use Intent flag 'FLAG_ACTIVITY_NO_HISTORY'. It means starting intent never goes into activity stack.
hi guys i am finding the strange behaviour in android while launching the Application. Let me explain the senerio. I am launching my application from android's launcher page and my application starts and runs fine and after few minute i press home button and go to android home page and then go to launcher page and again select my application and it is starting it again from first but it should have resumed from the last place where i left. And when i press back button on the launch screen of second instance of my app i am able to go back to the last page where i have left. I am more confused about what was happening and it too happens sometimes only not every time. Hope you people could help me sort this problem, Hoping for better responses. Thanks in Advance.
Edit #1:
It is not happening in all the device it happens only with Samsung and Sony but works fine with LG and HTC.
To keep an activity running in the background is not in your hand. When you press the home button, your current activity goes to the background and can be killed (onDestroy() will be called) at any time depending on the need for memory of the other applications you launch.
The more apps you launch, the more chances of killing your background app is.
The behavior may be device specific - try saving your game settings in a persisted location within the 'onPause()' function, and retrieving it on 'onResume()'. Then it doesn't matter if a new activity gets launched or the old one gets called.