Avoiding multiple instances of an activity [duplicate] - android

This question already has answers here:
Android singleTask or singleInstance launch mode? [closed]
(3 answers)
Closed 9 years ago.
I simply want that my activity has only one instance. I read about intent flags and launchmodes, but it just refuses to work.
I tried SingleTask, SingleTop, various intent flags etc. etc.
My manifest:
<activity
android:name="com.secret.domain.Player"
android:label="#string/title_activity_player"
android:launchMode="singleTask">
</activity>
and the launch code:
Intent intent = new Intent(getActivity(),Player.class);
intent.putExtra(Intent.EXTRA_TEXT,s);
intent.setData( Uri.parse( s ));
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
The Player activity obviously plays music, and still does it if I go back and create a new instance, both can play at the same time. OnNewIntent() is never called by the way.
I assume I've did something wrong, but I cant find out what.
EDIT: I know it sounds similar to other threads, but I read them and still couldn't figure out how to achieve what I want.

So you have made a shot to your leg, he he )))
As your activity should be run in single task (because of singleTask attribute). Every time when you start it, the system creates a new task for your Activity retaining the previous instance and it's media player component in memory.
That's why you hear several music tracks from several created tasks.
In such situation you may either make Activity to be as a singleInstance (using appropriate attribute in manifest), then if you already have created task with Activity in it, you just will need to handle intent in onNewIntent() and you should start it without any Intent flags. But you should make this Activity to have ACTION_MAIN and CATEGORY_LAUNCHER filters as described here in the second paragraph. Or you should make it standard in your manifest and launch it with FLAG_ACTIVITY_CLEAR_TOP considering that you will lose all the top activities.

Related

What is difference between using Intent flag "CLEAR_TOP" and launchMode="singleTask"?

What is difference between using Intent flag "FLAG_ACTIVITY_NEW_TASK" & "FLAG_ACTIVITY_CLEAR_TOP" and launchMode="singleTask"? and What is the difference in setting intent flag as FLAG_ACTIVITY_SINGLE_TOP and setting launchMode to "singleTop".
I understood your question from your comment you replied to Tim. So you want to know the
behavior differences when setting launchModes and when setting
Intentflags to an activity
Answer to your this question is that you set launchMode for an Activity inside AndroidManifest.xml file but the particular launch behavior can be changed in some ways at runtime through the Intent flags FLAG_ACTIVITY_SINGLE_TOP, FLAG_ACTIVITY_NEW_TASK, and FLAG_ACTIVITY_MULTIPLE_TASK etc.
Now lets come to your two more questions that you mentioned in your main question.
What is difference between using Intent flag "FLAG_ACTIVITY_NEW_TASK"
& "FLAG_ACTIVITY_CLEAR_TOP" and launchMode="singleTask"?
FLAG_ACTIVITY_NEW_TASK
When we set this flag through intent and launch that activity. In that case that activity will become the start of a new task on this history stack. A task (from the activity that started it to the next task activity) defines an atomic group of activities that the user can move to. It means it will create a separate history stack. For example, in your app you have a settings icon, when you click on that you go to settings activity where you have further activities. Here all the actions recorded will start from your setting activity only.
FLAG_ACTIVITY_CLEAR_TOP
As its name is telling clearly, if you start an Activity with this flag in a existing task(please understand task then everything will be very easy to understand), in that case all the activities in stack above this activity will be closed and this will become the last activity or oldest activity in the Task.
singleTask
When you start an activity for which you set launchMode = "singleTask" and there is already a task running that starts with this activity, then instead of starting a new instance the current task is brought to the front.
Your seconde question
What is the difference in setting intent flag as
FLAG_ACTIVITY_SINGLE_TOP and setting launchMode to "singleTop"?
FLAG_ACTIVITY_SINGLE_TOP and lanuchMode = "singleTop"
Both are have same behavior, flag is set at runtime and launchMode in AndroidManifest.xml in the beginning. The behavior is, activity this with this will be the only activity on the top in a Task. If it is already running at the top of the history stack then the activity will not be launched again.
NOTE: the best way to understand the behavior is to follow any tutorial and check it practically. Play around with code and see the behavior.
Here are some useful links:
Launch Modes : https://developer.android.com/reference/android/R.styleable#AndroidManifestActivity_launchMode
Intent flags : https://developer.android.com/reference/android/content/Intent
I think the Android documentation https://developer.android.com/reference/android/content/Intent#FLAG_ACTIVITY_CLEAR_TOP of FLAG_ACTIVITY_CLEAR_TOP explains the difference quite well. The launch modes are quite nicely explained at https://inthecheesefactory.com/blog/understand-android-activity-launchmode/en.

Same or different instance when starting same activity from various places in app?

When I start a activity from startActivity method from various places in my app, does vm launches same (if already started previously from somewhere else) or different instance of the activity?
And what about the stack of activities maintained ?
I am starting my activity as:
Intent intent = new Intent(this, Dashboard.class);
intent.putExtra("userid",getIntent().getStringExtra("userid"))
startActivity(intent);
Depend on the launch mode you set on the activity. It can be standard, singleTop, singleTask or singleInstance. This link may help:
http://www.intridea.com/blog/2011/6/16/android-understanding-activity-launchmode
By default, the launch mode is Standard which means Android will create multiple instances of the activity.

Android intent parameter FLAG_ACTIVITY_SINGLE_TASK missing?

I have just noticed that parameter FLAG_ACTIVITY_SINGLE_TASK is no more available in the Android developer documentation:
I am just trying to do this:
removeCard.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TASK);
startActivity(removeCard);
I have already seen such a parameter in code found in Google but the Java compiler just tells me it does not exist.
I am only able to start the main activity with this parameter but I have to configure the manifest file to perform this:
android:launchMode = "singleTask"
And this does not work for activities other than main activities launched upon app start.
Does someone know why this parameter disappear for Intent ?
Regards,
Franz
Ok so after having a look around, I managed to figure out that there is no such things as FLAG_ACTIVITY_SINGLE_TASK or FLAG_ACTIVITY_SINGLE_INSTANCE, nor has there even been. This is because you are looking for values which can only be defined through the application's launch mode which is defined in the manifest. Only FLAG_ACTIVITY_SINGLE_TOP is available as an intent flag. Therefore if you want to make use of any of the singleTask, singleInstance, singleTop or standard launch modes, they must be defined in the manifest:
<activity
android:name="com.company.ActivityName"
android:launchMode="singleTask">
</activity>
See the launchMode section in the documentation: http://developer.android.com/guide/topics/manifest/activity-element.html
android:launchMode = "singleTask" should work for all activities when used correctly and are you sure you're not referring the FLAG_ACTIVITY_SINGLE_TASK which is still present and appears to do what you are wanting.
public static final int FLAG_ACTIVITY_SINGLE_TOP
Since: API Level 1 If set, the activity will not be launched if it is
already running at the top of the history stack.
No it is not missing. From developer docs......Using Intent flags
FLAG_ACTIVITY_NEW_TASK
Start the activity in a new task. If a task is already running for the activity you are now starting, that task is brought to the foreground with its last state restored and the activity receives the new intent in onNewIntent().
This produces the same behavior as the "singleTask" launchMode value, discussed in the previous section.
That means FLAG_ACTIVITY_NEW_TASK do the same as Singletask do

Starting multiple instances of the same Activity from Service

I want to start multiple instance of the same Activity class from a Service. The reason I'm doing this, is because I have a Service that runs a "scan" daily, and if it finds any malfunctions it should display a popup for each malfunction.
The Activity that I'm starting is more like a Dialog, has a Dialog theme to display info about the malfunction.
Manfiest:
<activity
android:name=".ui.dialogs.MalfunctionActivity"
android:theme="#style/MyDialog"
android:launchMode="standard">
Intent to start the activity from Service:
Intent displayMalf=new Intent(this, MalfunctionActivity.class);
displayMalf.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(displayMalf);
PROBLEM: to start the Activity from a Service I need the FLAG_ACTIVITY_NEW_TASK which somehow cancels the launchMode="standard" from the manifest, and gives me just one Activity even if I try to start multiple diffrent instances.
Is there anyway in which I can achieve this?
It was so simple. There is the flag FLAG_ACTIVITY_MULTIPLE_TASK which according to the documentation :
Used in conjunction with FLAG_ACTIVITY_NEW_TASK to disable the behavior of bringing an existing task to the foreground. When set, a new task is always started to host the Activity for the Intent, regardless of whether there is already an existing task running the same thing.
Was exactly what I need. Thanks and sorry for answering on my question. It is not a habit. :)
Service will take the flag FLAG_ACTIVITY_NEW_TASK to start the activity but here you can try like this:
Set the instance of the handler of the activity of which you want multiple instances, in the service.
When you want the new instance of the activity use handler.sendMessage(msg) and on receiving this msg in your activity, start this activity again.
I guess your app works in the background and will display the popups even if the app is not in the foreground at the moment, right?
Otherwise I would use normal popup's (AlertViews) instead of starting new activities all the time.
If the app works in the background, you could tell the user with the first popup that your app has found one or more malfunctions and that he should activate the app for more details

Android AppWidget Configuration - Start in new task

I've searched and searched and searched for this!
So I've got an app widget and it has a configuration activity that I can open when pressing a button on the app. The scenario is:
Had the app opened.
Closed the app with the home button.
Selected to add my widget
I have configured the widget.
Placed on my home screen
Then open the configuration activity again with the button on the widget.
Cancel the new config by pressing back will put me back into the app.
When pressing back I want to just return home.
Basically what I'm asking is. How do I start the configuration activity in it's own task/stack?
I've looked into intent filters but I'm just not quite sure, or maybe it's something to do with the package it's in, or maybe it's just not possible!
I suppose it may have something to do with the intent I use to launch the config activity
Intent configIntent = new Intent(this, Configuration.class);
configIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
remoteView.setOnClickPendingIntent(R.id.config, PendingIntent.getActivity(this, 0, configIntent, PendingIntent.FLAG_UPDATE_CURRENT));
Perhaps because I launch it with 'this' as the context, it will always start in my applications stack...
but the pending intent api is:
PendingIntent API 1
"Note that the activity will be started outside of the context of an existing activity"
So yeah I'll stop talking now as I just end up going in circles!
EDIT
So tried android:launchMode="singleInstance" in the manifest like was stated. This worked however it stops the 'startActivityForResult' behaviour working correctly. (which is the whole reason for a config activity) Get the error:
WARN/ActivityManager(59): Activity is launching as a new task, so cancelling activity result.
So still haven't found a solution.
Ok sorted it :-) needed:
android:taskAffinity=""
in the manifest, setting the task affinity to an empty string allows for the activity to start in it's own stack, as it is not 'affiliated' with the rest of the application.
UPDATE
I have changed the task affinity to:
android:taskAffinity="com.my.package.alternative.task"
as each time I launched the activity it was showing up multiple times in the 'history'. So it now starts in it's own stack but is shared with other instances of the same activity.
Also need to add the Flag Intent.FLAG_ACTIVITY_NO_HISTORY to your intent :-) this stops your getting your application multiple time's in the history when you 'press and hold' the home button.
UPDATE
I've noticed FLAG_ACTIVITY_NO_HISTORY wasn't doing what I wanted, I've removed it and added:
android:excludeFromRecents="true"
into the activity tag in the manifest as well. The activity now behaves like I want :-)
Got this answer from the following link trail:
Tasks & Back Stack |
Managing Tasks |
Affiliation Tag
Try to put android:launchMode="singleInstance" for an activity of the app in AndroidManifest.xml

Categories

Resources