I have a scenario like:- There are three Ativities A, B, C.
1. A's launch mode is 'singleTask' and C's launchmode is 'singleTop' in manifest. A calls B and then B calls C.
2. Now C is the top most activity of the application stack.
3. Now Activity C is put to background by presseing device home key.
4. I have a service running which Sends broadcast for every say 15 mins.
5. In broadcast receiver i have an intent which is like this
Intent i = new Intent(context, A.class);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i);
Now Activity 'A' comes in foreground and in its onResume() i call Activity 'C' as ACTIVITY_RESET_TASK_IF_NEEDED (have some flag that tells me that Activity 'C' was invoked alreday, so lets bring it in foreground. If that flag is set to false then it would never invoke Activity 'C' directly rather Activity 'B' will get called and then 'B' will call
Activity 'C').
What i trying to achieve here is the user perspection that when Activity 'C' was running then that Activity 'C' should come in foreground.
Here is the Problem now:- I never get the same Actvity 'C' instance due to FLAG_ACTIVITY_NEW_TASK and thus my app goes in wierd state. But when my app is put to background using device back key and i exceute all those steps it works i.e i get the same instance of Activity 'C' (Don't know how android is handling it internally this, but in both the flows home and back key there is not consistency).
So how do i achieve or maintain my app state in case for home key being pressed..?
Help Appreciated.
Hi use following flags while launching the Activity
Intent.FLAG_ACTIVITY_REORDER_TO_FRONT
This flags insures that only allow one instance of your Activity if its already running then it has been brought to front from the stack if its not running then a new Activity is created.
Related
I have 8 Activities in my Android app and I want:
1)Every time I press Back button during my first 7 Activities to go back to my previous Activity(Act1< Act2< Act3< Act4< Act5< Act6< Act7) BUT
2)ONLY when I am in the 8th Activity I want to definitely exit my Android app and go to my phone's Home Screen.I try to do it by overriding onBackPressed method in my 8th Activity (Phone Home Screen<-Act8)
I found an Android implementation in which I insert finish();in every intent of all my 8 Activities but this is not what I want since this way I can't go back to the previous Activity whenever I want(with finish(); every current Activity is removed from back stack).
How will I do it please?
My code so far in my 8th Activity is:
#Override
public void onBackPressed()
{
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_HOME);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
finish();
}
Another way: create a 9th Activity and call it FinishAllActivity or something like that. Make this activity call finish() and then return in its onCreate().
In onBackPressed() in Activity 8, start FinishAllActivity using the FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK flags (see this question for more details). Activities 1-8 will be removed from the stack, then the 9th Activity will start and immediately terminate and your task stack is clear. When you reopen the app it should start from Activity 1.
The advantage of doing it this way is that you don't have to modify Activities 1-7.
Add a public static boolean to one of your classes that indicates the app is exiting. Set this boolean in activity 8 when you want the app to finish, and have all of your other activities check it in their onResume() and finish immediately if it is true. Make sure the first activity clears it before finishing, or it may still be set the next time the app runs. (Android doesn't necessarily discard the VM when your last activity finishes, so the class and its static members may be reused next time.)
Note that this is the simple way, not the "Android way." Global variables are generally frowned upon, for reasons you can Google. The "correct" way to do this would be to start each activity for result and return a result to onActivityResult(...) that indicates whether the app is exiting.
You can implement a broadcast receiver and have each of your Activities that you want to close call finish() when they receive the broadcast (which will be sent from your last activity). I would imagine you'd need to have your broadcast receiver class be either an anonymous inner class or a private class within your activity(s) so that you can easily access your enclosing Activity's finish method.
Here's a good example of broadcast receivers:
http://www.tutorialspoint.com/android/android_broadcast_receivers.htm
Look at the custom intents section.
Doing it this way is a loosely coupled way to implement what you are looking to do.
use FLAG_ACTIVITY_CLEAR_TOP Flag in your intent like below example.
Intent intent = new Intent(getApplicationContext(),FirstActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.putExtra("EXIT", true);
startActivity(intent);
in your first activity check below condition.
if (getIntent().getBooleanExtra("EXIT", false)) {
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_HOME);
startActivity(intent);
finish();
}
here FLAG_ACTIVITY_CLEAR_TOP work like below example
consider a task consisting of the activities: A, B, C, D. If D calls startActivity() with an Intent that resolves to the component of activity B, then C and D will be finished and B receive the given Intent, resulting in the stack now being: A, B.
so here you have to call D is your last activity and A is your first activity.
This way you are finishing your 8th Activity returning to your 7th Activity and same time you are like emulating a pressing of Home button on a device. When you rerun your app it will appear with 7th Activity on a screen. If you wish to see the 8th Activity in this case then just remove the finish() method. If you wish next time your app to start with 1st Activity then you should finish all the activities from 8 to 2nd but not the 1st. Also you could launch your 1st Activity adding a FLAG NEW_TASK or some other flags.
UPDATE
My advise (for the quick result without changing the workflow) is to use startActivityForResult() to start all activities in chain. When user exits the app just return a special parameter using setActivityResult() to get all nested activities know about user's choice making all nested Activities to run finish(). This way all your 8 activities will be finished properly.
Scenario:
Activity A (MAIN and LAUNCHER in manifest) starts up when clicking on launcher icon.
In turn it launches Activity B.
Activity B then launches our main app Activity C (MAIN and singleTask in manifest).
Behaviour I require:
Once Activity C has been shown and the home key is then pressed, the next time the launcher icon is pressed I would like to skip straight to Activity C (and not show Activity A (and consequently B) again).
I have tried using FLAG_ACTIVITY_CLEAR_TOP from A, but I still get Activity A whenever I hit icon on launch screen.
Is appearance of my singletask Activity C from launcher achievable?
Update: Use of FLAG_ACTIVITY_CLEAR_TOP from A and not calling finish() creates the situation whereby Activity B appears on press of launcher icon. However, also applying use of FLAG_ACTIVITY_CLEAR_TOP from B and not calling finish() does not resolve situation. now I don't get A on launcher icon press, but get B. What gives!
See similar scenario here.
In your case, I would recommend using a similar approach, where you would have a SharedPreference that would persist a value representing whether your app had previously been launched.
Create a simple Activity that will contain the logic for what you are trying to do here. In that activity's ("pre-A" Activity) onResume() method, check the value of the preference representing whether the app has ran previously.
If it has not previously been ran, launch an intent to Activity A, which calls the subsequent B and C activities; otherwise, launch an intent to Activity C.
Seems pretty straightforward, just remember to define the new "Pre-A" activity in your manifest!
I was going through Android Task and Back Stack documentation and at one point they mention this:
if your application allows users to start a particular activity from more than one activity, a new instance of that activity is created and pushed onto the stack (rather than bringing any previous instance of the activity to the top). As such, one activity in your application might be instantiated multiple times (even from different tasks), as shown in figure 3. As such, if the user navigates backward using the Back button, each instance of the activity is revealed in the order they were opened (each with their own UI state)
Let's take an example:
I have Activity A Starting Activity B which Starts Activity C which starts D.
Stack is A->B->C->D now it is possible to Start C from D so when we start C from D stack will be
A->B->C->D->C
Now instead of this standard behavior I want Activity to have only 1 instance or only 1 entry in the Back Stack. "SingleTop" will not work since Activity C was not on top when we started it from D.
I might be missing something but is there any way to achieve this making sure an activity has only 1 backstack entry?
Thanks
Pranay
Use Intent.FLAG_ACTIVITY_CLEAR_TOP, e.g.:
Intent intent = new Intent(context, <your_activity_here>);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
context.startActivity(intent);
So, all the activities in stack after activity C will be finished automatically. If you use the specified flag
A->B->C->D
will become
A->B->C
You can also use android:launchMode="singleInstance" in your activity tag in manifest
I already know that I can pass Bundled data through setResult from one Activity back to another. However, suppose I have an global Activity that can be launched from anywhere in my app since it is mapped to a button that appears in my title bar in almost all of my activities.
Long story short, after it completes its user-driven process, I want it to signal back to the very first activity in the back stack, basically my Home activity, so that it updates the UI accordingly.
Part of the problem is that since if I use a BroadcastReceiver, it is unregistered when my activity is in the background, and it will not get the signal to refresh its data set.
What I want to achieve is the following:
From either Home (ActivityA), or any other activity (Activity B, C, etc...) that can open out my global activity (ActivityX), it should find a way to call back to ActivityA without bringing it to the front.
Should I use FLAG_ACTIVITY_FORWARD_RESULT and if so, how should I model it from my subsequent activities after Home. In other words, if I launch a child activity from Home, should I launch it with startActivityForResult with whatever request code I define and then pass FLAG_ACTIVITY_FORWARD_RESULT when opening my global activity so that the result will be set from there?
Also, suppose I launch a child activity from Home with a result, and then from my child activity I add more to the stack, from which I open ActivityX. Would the system still remember the result chain as long as I opened the first child from Home with a result?
EDIT: I am not looking for just clearing the entire stack back to home immediately after the process is completed in ActivityX; just a way to signal the Home activity to refresh it's UI when the user eventually returns to the Home screen. I guess probably setting a SharedPreference flag that Home checks in onStart when the user re-focuses on that Activity which in turn gives me the condition to do the end result, after which the flag is reset.
Your home-screen should just update it's UI in onResume, this way whenever a user returns to it will be displaying the latest data. There's no need to pass callbacks. Otherwise you could register a Broadcast receiver in onCreate (and unregister in onDestroy... not ideal) in your home activity and then send out a broadcast when you want the home activity to update (although the home activity shouldn't actually update itself until it is resumed).
Here's how to get back to your home activity:
Intent goHome = new Intent(getContext(), HomeActivity.class);
goHome.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
goHome.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(goHome);
FLAG_ACTIVITY_CLEAR_TOP: This ensures that when the activity is launched, it displays its initial activity.
FLAG_ACTIVITY_NEW_TASK: we're starting a new task (i.e. the back button should not go back to the previous screen so that pressing back at your home screen will exit your app).
I'll update on the rest tomorrow.
In my application you can navigate through several Activities until the Activity stack is quite deep.
We'd like a button on every Activity that will take you straight back to the main menu - i.e. pop all Activities from the stack except the first one.
I've put the button in a View that I can easily put on every Activity in the application, but I can't figure out how to close several Activities in one fell swoop.
(If possible, it would be good if the View could work out how many Activities to close by itself - i.e. detect how deep on the stack its own Activity is.)
Have a look at the intent flag FLAG_ACTIVITY_CLEAR_TOP which says it brings the targeted activity to the top of the stack, removing everything else that might have been above it. So use that button you can add to all your activities to launch an intent which targets your main menu, with that flag set.
From the documentation:
If set, and the activity being
launched is already running in the
current task, then instead of
launching a new instance of that
activity, all of the other activities
on top of it will be closed and this
Intent will be delivered to the (now
on top) old activity as a new Intent.
For example, consider a task
consisting of the activities: A, B, C,
D. If D calls startActivity() with an
Intent that resolves to the component
of activity B, then C and D will be
finished and B receive the given
Intent, resulting in the stack now
being: A, B.
The currently running instance of
activity B in the above example will
either receive the new intent you are
starting here in its onNewIntent()
method, or be itself finished and
restarted with the new intent. If it
has declared its launch mode to be
"multiple" (the default) and you have
not set FLAG_ACTIVITY_SINGLE_TOP in
the same intent, then it will be
finished and re-created; for all other
launch modes or if
FLAG_ACTIVITY_SINGLE_TOP is set then
this Intent will be delivered to the
current instance's onNewIntent().
This launch mode can also be used to
good effect in conjunction with
FLAG_ACTIVITY_NEW_TASK: if used to
start the root activity of a task, it
will bring any currently running
instance of that task to the
foreground, and then clear it to its
root state. This is especially useful,
for example, when launching an
activity from the notification
manager.
You could declare that first activity android:launchMode="singleTask" (more) and then just start it with an Intent.
EDIT: My suggestion is based on the assumption that you want to have a single instance of the Activity to return to. Otherwise it's incorrect.