As I read in several stackoverflow answeres. To start activity from the service you have to use FLAG_ACTIVITY_NEW_TASK, but it will create new instance of activity in separate task. I want to reuse already started activity. Im trying to do it from IntentService that listen for c2dm notifications.
In the manifest for the Activity, you could set android:launchMode="singleInstance".
Here's what the docs say about singleInstance:
Only allow one instance of this activity to ever be running. This
activity gets a unique task with only itself running in it; if it is
ever launched again with the same Intent, then that task will be
brought forward and its Activity.onNewIntent() method called. If this
activity tries to start a new activity, that new activity will be
launched in a separate task. See the Tasks and Back Stack document for
more details about tasks.
And here is where I got my info.
You must use this flag with your Intent:
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
IF you don't want a new instance of your Activity, set launchMode for your Activity in the AndroidManifest file:
android:launchMode="singleTask"
Related
The android documentation defines single task launch mode as :-
The system creates a new task and instantiates the activity at the
root of the new task. However, if an instance of the activity already
exists in a separate task, the system routes the intent to the
existing instance through a call to its onNewIntent() method, rather
than creating a new instance. Only one instance of the activity can
exist at a time
Now my question is what happens in the case where the instance of activity already exists in a separate task but it is not at the top of the task. Are all activities above this activity destroyed and the new intent is delivered to this activity ? (as in FLAG_ACTIVITY_CLEAR_TOP with FLAG_ACTIVITY_NEW_TASK)
Yes, it will. You can test it by making a simple test app. New intent will be received in onNewIntent()
This is an image from android documentation:
Activity Y has 'singleTask' launch mode but it is not root activity in the task, that is Activity X. How did it happen?
Upd.:
From the documentation:
"singleTask"
The system creates a new task and instantiates the activity at the root of the new task. However, if an instance of the activity already exists in a separate task, the system routes the intent to the existing instance through a call to its onNewIntent() method, rather than creating a new instance. Only one instance of the activity can exist at a time.
Note: Although the activity starts in a new task, the Back button still returns the user to the previous activity.
Single task only means that this activity can only be created once cf to this website: http://inthecheesefactory.com/blog/understand-android-activity-launchmode/en
It doesn't matter if the activity is root or not.
singleTask:
This mode is quite different from standard and singleTop. An Activity
with singleTask launchMode is allowed to have only one instance in the
system (a.k.a. Singleton). If there is an existed Activity instance in
the system, the whole Task hold the instance would be moved to top
while Intent would be delivered through onNewIntent() method.
Otherwise, new Activity would be created and placed in the proper
Task.
I think the answer is that this activity was launched with an intent with FLAG_ACTIVITY_SINGLE_TOP flag, because intents have higher priority than xml tags.
I want to start an activity from service context. But I am bound to use flag = Intent.FLAG_ACTIVITY_NEW_TASK which is creating multiple instance of the activity since it is throwing Run-Time-Exception with other flags.
How can we launch an activity from service so that multi instances of activity will not be created, if already activity in recent tasks it will launch that only??
You can combine different flags, like FLAG_ACTIVITY_CLEAR_TOP
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.
...
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.
and FLAG_ACTIVITY_CLEAR_TASK
If set in an Intent passed to Context.startActivity(), this flag will cause any existing task that would be associated with the activity to be cleared before the activity is started. That is, the activity becomes the new root of an otherwise empty task, and any old activities are finished. This can only be used in conjunction with FLAG_ACTIVITY_NEW_TASK.
with FLAG_ACTIVITY_NEW_TASK. Which one to use depends on what exactly do you want to achieve.
Check the documentation of the flags in the Intent class and Tasks and Back Stack.
I have an app which has multiple entry point activities. I want to be able to clear my activity stack programmatically. Imagine an app which requires user authentication, and the user wants to invalidate their session remotely (stolen device, for example).
In the case where an app has a single starting activity, we could just use:
Intent intent = new Intent(context, LoginActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
to get back to the root activity. But my app may have been launched from different entry points, and so there might be different activity classes at the root of the stack.
Some options:
Register a broadcast receiver in my base activity class which I can call from anywhere. In the handler, just call finish(), unwinding whatever stack may exist.
Use the frowned-upon System.exit().
In the above example, use Intent.FLAG_ACTIVITY_CLEAR_TASK in addition to the other two flags (but this is only available in api 11 and above...)
Thanks
You can check the name of activity at the root of the task stack and then start that activity with the FLAG_ACTIVITY_CLEAR_TOP. If this root activity is not the activity you want then start the activity you want in onCreate and call finish().
You can find the name of the root activity by
call getTaskId () to get the task id.
Obtain an ActivityManager object and call getRunningTasks to get a list of running tasks (check out the warning in the doc, I do not understand clearly)
When the task in the list match the id above you can get the activity in the root using the field baseActivity
I have created an activity. I made the launch mode as singleTask in manifest file. I donot want multiple instance of the same activity should start. I am lunching this activity on button click of another activity.
If i click the button more than once then as i have made the activity as single task then If the activity already running then nothing happens. But I want to relaunch the activity without creating another instance. How to achieve this.
Thanks
Deepak
But I want to relaunch the activity without creating another instance
What you meant my relaunch without creating. I think you may have set of code that you have placed in your onCreate and you want to run when the activity again got control. If so its better for you to place that code to your onResume or onNewIntent. Because onCreate of the single task will only execute once
singleTask
The system creates the activity at the root of a new task and routes the intent to it. However, if an instance of the activity already exists, the system routes the intent to existing instance through a call to its onNewIntent() method, rather than creating a new one.