I'm having trouble with my activities when they go in the background. I have two activities, A and B. Only A can launch B (manifest copied below). This is what I do:
Launch the app from the app drawer (activity A)
There's a button on A to launch B, B now is displayed.
Hit the Home key, my app is now in the background.
Go to the app drawer again, hit my app icon.
Instead of resuming at ActivityB, Activity A is launched again. Why?
If I hit the Back key now, I get shown the old ActivityB. What?
This is very confusing. It's like Android knows my app is running, and puts a new instance of A on top of the old B instance running. I'd just expect that the application gets paused in-place, and whenever the user hits the app icon again, it just picks up where it left off (in this case, just show B again!) Below is the manifest, and the activity classes for this test are completely empty (except A which has a button to launch B).
<activity android:name=".ActivityA"
android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".ActivityB"
android:label="#string/app_name">
<intent-filter>
<!--
<action android:name="android.intent.action.VIEW" />
-->
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
If I had to take a guess because inside your app drawer is your .apk reference for your Program A. Regardless if B is already launched, the INTENT of the application when selected is to launch Program A.
I have only read a little on Android, so I can not say with 100% certainty, but that is my guess.
I hope this helps.
EDIT:
Holding down the Home key on the Android phone, shows the list of background apps, can you do the same inside of the emulator and see if Program B pops up? Or same problem occurs?
After reading things around Google, I came across this here is a little snippet:
All the activities in a task move together as a unit. The entire task (the entire activity stack) can be brought to the foreground or sent to the background. Suppose, for instance, that the current task has four activities in its stack — three under the current activity. The user presses the HOME key, goes to the application launcher, and selects a new application (actually, a new task). The current task goes into the background and the root activity for the new task is displayed. Then, after a short period, the user goes back to the home screen and again selects the previous application (the previous task). That task, with all four activities in the stack, comes forward. When the user presses the BACK key, the screen does not display the activity the user just left (the root activity of the previous task). Rather, the activity on the top of the stack is removed and the previous activity in the same task is displayed.
I hope this points you in the right direction
I'm experiencing this bug:
http://code.google.com/p/android/issues/detail?id=2373#makechanges
Thanks for your help, this has been so confusing.
Have you set the following property in your activity's xml definition?
android:launchMode="singleTop"
Related
I want my main activity to show every time after home screen is pressed and the app is opened again.
My layout is:
Main Screen --> Menu Page --> Sub Menu
I want to be able to use the back button to go from the sub menu to the menu page. However, regardless of which page I am on when the home screen is pressed I want to show the main screen when the app is reopened. I have tried onFinish() in my java class for MenuPage. That causes the return button to close the app because the previous activity was finished. I have researched how I can detect if the home button is pressed to finish the activity that way but it seems that's not an option. Does anyone know a way around this?
You can use FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET flag when starting your secondary activities. More information about intent's flags can be found here: link
To control your back presses, you can basically direct each activity or fragment to go wherever you which on back press by overriding the backpress event.
#Override
public void onBackPressed() {
// TO DO
}
To also handle backpress and state with fragments, it is advisable to manage the back stack.
Providing Proper Back Navigation
I also use a custom home button on my apps when I want the user to be able to go straight back to the main activity.
public void goHome() {
startActivity(new Intent(this, MainActivity.class));
}
edit
this was part of my original answer, but it was not addressing what the OP was asking. I left it here in case it helps any browsers who may also have misinterpreted the question and are looking for something like this.
You need to set your main activity to be the launcher activity for the app and then use BOOT_COMPLETED and DEFAULT. This means the user will have to choose a default option each time they press the home key, until they either set the app or the default device homescreen to 'always' be the default.
<activity android:name=".Main">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.HOME" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
I have a Notification which starts an Activity. After a long press on home button and selecting my app, I want to start my main Activity again, and not this Activity started by the Notification. I tried with FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS, but this removed my whole application from the recents, and that's not what I want to achieve. How can I have my app in the recents, but have the main Activity started?
Regards
Okay, I found the solution to my problem. I started an Activity from a Notification with FLAG_ACTIVITY_NEW_TASK. But it seems to me that this Activity only gets started in an own task if affinity is different from the default affinity. So I had to add a different affinity in the manifest.
And it seems that FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS does not (as documented) exlucde the Activity from the recents, rather it excludes the whole task (not the whole application) in which the Activity gets started from the recents. And as I hadn't set a different affinity the Activity which I wanted to exclude was started in the same task (although I had set FLAG_ACTIVITY_NEW_TASK) and so my whole application (as it was running in only one task) was excluded from the recents.
Now I've set a different affinity for the Activity that gets started from the Notification and I start it with FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS. When I leave this Activity and long-press the HOME button I can choose my app and the default task is started or brought to the front.
If it's wrong what I mentioned above, feel free to clear it up ...
It's not clear to me what you want.
"How can I have my app in the recents, but have the main Activity
started?"
If you want to always start one activity using the long home-press, you can define your activity as singleTask in the manifest.
That way, when you select the shortcut in the long press HOME, it will always show the MAIN, singleTask activity. I say this because I used this behavior before once. ;-)
I believe that by using this you can still start an activity from the notification normally, using, say, Intents.
In the activity tag:
android:launchMode="singleTask"
>
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
I am trying to solve an issue sort of similar to what was done here (link text)
Except in my case where Activity A, started Activity B, started Activity C, when the user resumes the app after pressing the home button - I want C, the last Activity, to be displayed. Instead what is happening is I am back to A.
Also on a side note I have discovered that even when I exit the application, if I hold down the Home button, my app is still listed as an active app even though in the LogCat I can see that it exited OK.
Also, in case it matters, I did recently add android:launchMode ="singleTask" in order to make some notification logic work correctly. I was seeing the Home button behavior before that though.
I really appreciate any ideas you might have.
[edit - adding some code snippets]
<activity
android:name =".connection.ActivityA"
android:label ="#string/app_name"
android:configChanges="orientation|keyboardHidden"
android:theme ="#android:style/Theme.NoTitleBar"
android:launchMode ="singleTask"
android:screenOrientation="portrait" >
<intent-filter>
<action android:name ="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name =".screens.AvtivityB"
android:label ="#string/app_name"
android:configChanges="orientation|keyboardHidden"
android:theme ="#android:style/Theme.NoTitleBar"
android:launchMode ="singleTask"
android:screenOrientation="portrait" >
</activity>
<activity android:name =".screens.ActivityC"
android:label ="#string/app_name"
android:configChanges="orientation|keyboardHidden"
android:theme ="#android:style/Theme.NoTitleBar"
android:screenOrientation="portrait" >
</activity>
Then here is how I kick off each Activity:
In Activity A:
private void startActivityB()
{
Intent activityBIntent = new Intent(this, ActivityB.class);
this.startActivityForResult(activityBIntent , ACTIVITYB_TAG);
}
Activity B actually has several Activities that it chooses from (it has a list of Intents) to display based on input it receives but launches them all the same way as Activty A launched B. Once the first Activity is displayed the user swipe the screen to navigate to the left or right screen. When the user swipes left or right, the current activity puts info in its return Intent that Activity B uses to display the next Activity. Also since logic outside of the user's control could prompt a change in the screen displayed, each Activty calls finish on itself in onStop to avoid back-button issues.
When you long press home it is showing a list of recently active applications, not applications that are currently running. So you should still see your app in the list, even if it is closed.
As the docs note:
The other modes — singleTask and
singleInstance — are not appropriate
for most applications, since they
result in an interaction model that is
likely to be unfamiliar to users and
is very different from most other
applications.
I'd imagine that your using singleTask is affecting the history stack, and thus preventing Activity C from being remembered. If you remove that from Activity C, does it resolve the problem?
Otherwise, I'd look at what you are doing in onPause/onDestroy etc for Activity C. Are you doing something that would cause it to finish or close?
Do you get this behavior only when running from Eclipse?
Check your "Run Configurations". There is a "Launch Action" that can be set to "Do Nothing".
Matt
I'm not sure this is what it happening to you, but the answer below solved my problem and I wanted the same behavior as you - that is, getting to the same activity when re-opening after home has been pushed (though in my case, I did actually want the first activity, just not a new one):
Save activity state in android when home button pressed
Now I realize you want to keep the activity stack intact and not go to the first activity like me. But if it is the same problem, then it is not from the fact that the activity stack is torn down, but because a new one (with the opening activity) is added when re-opening after home has been pressed on first install. I hope this is fairly legible, even though I (clearly) found it difficult to explain.
Edit: This is better described here and here.
I have the following activity structure in my application
A simple "splash screen" activity is started when the application is fired up (let's call it "Splash"). This activity starts the main activity when the user presses a button (I will call it "Main").
Main can in turn start two activities from the menu. The first activity presents a simple form (let's call this one "Form"), the second is a MapActivity that presents a map (it is called "Map").
Main, Form, and Map are declared exactly the same in the manifest:
<activity android:name="fully qualified activity class"
android:screenOrientation="landscape"
android:configChanges="keyboard|keyboardHidden|orientation"
>
<intent-filter>
<action android:name="android.intent.action.DEFAULT" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
When Main is active and I start Form and press "back", Main comes up again. Pressing "back" again brings up "Splash". Nothing strange here.
Now comes the strange part: when I am in Main, start Map, and press "back", Main comes up as expected. But pressing "back" again just restarts Main. A second press on "back" is needed to bring me back to Splash!
So it seems that starting the Map activity somehow results in Main ending up on the activity stack twice while starting the Form activity does not!
Both Form and Map are started like this:
startActivity(new Intent(this, MyActivity.class));
I don not catch the back key in any activity.
Any clues on what is going on or how to debug this?
I think I have seen this behavior before in one of my projects. Try setting the launchMode property of your launcher activity ( in your case Splash ) to - android:launchMode="singleTask" in the manifest file.
This should help clarify: http://developer.android.com/guide/topics/fundamentals.html#acttask
I have an application with 2 activities, LogonAct and MainAct. LogonAct is a logon activity which I want to force the user to go through each time they return to the application. I've set android:clearTaskOnLaunch="true" on LogonAct.
When I first start the app I go through this sequence of screens,
Home -> LogonAct -> MainAct -> Home
I then follow this sequence,
LogonAct -> Back -> MainAct
Why is it bringing me back to MainAct? Shouldn't that activity haven been closed since LogonAct has android:clearTaskOnLaunch="true". I expected to be brought back to Home when I hit the Back button from LogonAct.
Relevant snippets from AndroidManifest.xml,
<activity android:name=".LogonAct"
android:clearTaskOnLaunch="true">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity android:name=".MainAct">
<meta-data android:name="android.app.default_searchable"
android:value=".SearchResults" />
</activity>
I'm using 1.5.
Any help appreciated.
You can do following:
1. set clearTaskOnLaunch = "true" in AndroidManifest, in declaration of main activity
2. in activity that must close:
#Override
public void onBackPressed(){
moveTaskToBack(true);
}
so if user presses back - it comes back to homescreen
if user launches aplication again - task stack clears and he comes to root main activity
The docs for android:clearTaskOnLaunch mention that this attribute applies "whenever [the Activity] is re-launched from the home screen".
However, in your case you're pressing the Home button to return to the Home screen, rather than pressing the Back button. This means your application isn't actually relaunched because the MainAct was not "finished". That only happens when you press Back (or if Android kills the task to save resources etc.).
As you only have two activities in your application, you could set the android:noHistory attribute on MainAct, thus ensuring that users can never return to it and must pass through the LogonAct.
As an aside, it seems a bit annoying to force users to re-login every time they navigate away from the app (for example when they receive a phone call).
You could retain a session token with timeout in your app's persistent storage, or hold a network connection open using a service if that's how your app works — but of course that's up to you and your requirements. :)