I have an android app. I added an intent filter to one of my activities, so that if a url is clicked in the browser app, my activity can be launched. Looks like this:
<data android:host="www.mysite.com" android:scheme="http"></data>
this works well. The problem is that every time my activity is launched from the browser, a new instance of the activity is created, inside the browser app's task, instead of recycling any existing instance that may be in the system already.
This is a problem for me because this activity uses a singleton. If I allow more than one instance of this activity to exist, I can get into some weird situations where the two instances are in conflict when they try to share the singleton. I checked and can see that although the activity instances may be in separate tasks, they do share the same singleton instance.
An ideal solution for me would be if I could somehow bring a pre-existing instance of my application to the foreground, and launch or resume the target activity within whatever pre-existing instance of my app happens to be running.
So I tried this:
Register above filter to point to dummy activity which is just a catcher.
Dummy activity creates a broadcast intent, and tries to broadcast 'create me' message to system.
Real target activity is set to listen for this broadcast message. Hopefully if there is already an instance of the activity in the system, it will come to the foreground. If no instance yet, that's ok, allow creation in the browser task.
Not sure if this makes sense. My basic goal is to limit the activity to one instance in the system. The app is just social media app which has a login state that needs to be preserved. The singleton mentioned above preserves that login state, so I want to have only one around in the system, instead of allowing multiple login instances running around which would be a headache for the user.
Thanks
You can set the activity launch mode to singleTop to achieve this.
android:launchMode
An instruction on how the activity should be launched. There are four modes that work in conjunction with activity flags (FLAG_ACTIVITY_* constants) in Intent objects to determine what should happen when the activity is called upon to handle an intent. They are:
"standard"
"singleTop"
"singleTask"
"singleInstance"
The default mode is "standard".
https://developer.android.com/guide/topics/manifest/activity-element.html#lmode
Related
I understand that intents are used to start new activities and services and can contain information about these - certain UI options, etc. They can be emitted by some activities or apps to signal that others should begin or end, or that some change should occur.
I don't understand how these are handled by the System at runtime. Do these go to the OS, where they are relayed to the place where they are needed, or do all Activity instances constantly check every single intent that is emitted, to see if they apply?
Also, on that note, can all Activity instances "listen" to all intents and if not, how is this "listening privilege" given?
Do these go to the OS, where they are relayed to the place where they are needed
Yes. After all, the majority of the time, the activity that is to be started does not presently exist.
Also, on that note, can all Activity instances "listen" to all intents
Activities do not "listen" on any Intents. Activities, via the manifest, describe what Intent structures they are interested in, via <intent-filter> elements. The OS then determines the activity to handle any particular startActivity() call (perhaps with the help of the user, via a chooser UI) and starts that activity.
We write different activity classes in Android and declare those activities in AndroidManifest.xml
However, what I am not getting is when is the object of that Activity class created or how that activity class is loaded into memory ?
The doubt might seem naive but am confused.
An activity is a single, focused thing that the user can do. Almost all activities interact with the user, so the Activity class takes care of creating a window for you in which you can place your UI with setContentView(View). The activity contains the user interface of your application. There are various states of activity like Running, Paused, Stopped and Killed. The Activity base class contains several events that govern the life cycle of an activity.
Now, when Activities's onDestroy method is called, your Activities aren't necessarily garbage collected. When the system gets low on memory the process that your Application lives in can be killed, meaning your Application will disappear; Application's onTerminate method may or may not be called. At that time all the Activities, Services, etc, are killed too. The Application instance is always instantiated first, an Activity must have an associated Application, just like how you define it in the AndroidManifest.xml.
As always, the best resource for understanding all this is the official documentation.
An Activity is instantiated automatically by your Application when it receives an Intent that corresponds with one of the Activities you describe in your manifest. You don't need to worry about any constructor methods, or keeping a reference to your activity after its instantiated. That is done behind the scenes. Android handles the lifecycle, so you use the lifecycle callbacks to handle creation and cleanup of your own objects.
When someone clicks the icon for your app in the launcher, what actually happens is the launcher sends an Intent to your application to launch the activity associated with that Intent. If your application isn't open yet, Android will launch it so it can receive the Intent.
I made an app that makes streaming radio. How can I prevent that, the second time by clicking on the icon to open the app twice?
Here is one good suggestion:
*
How to launch activity only once when app is opened for first time?
What I've generally done is add a check for a specific shared
preference in the main Activity: if that shared preference is missing
then launch the single-run Activity, otherwise continue with the main
activity. When you launch the single run Activity create the shared
preference so it gets skipped next time
This solution is slightly different than the question you're asking, but should give you exactly the result you're looking for.
Another possibility might be to use android:launchMode = "singleInstance" in your androidmanifest.xml:
http://www.intridea.com/blog/2011/6/16/android-understanding-activity-launchmode#
IMHO...
To stream the music you should be using a Service so that you can keep it going even when your app is closed. At that point your Activity is only used to communicate with the Service. When you launch your app just check to see if the Service is running or not.
Typically this shouldn't happen, if your activity is already running the system will bring it it up if the user relaunches. If your activity is launched by another app/activity in a new task, or for some other reason an intent may be used to create a new instance of your already running activity, look into singleInstance or singleTask modes in the manifest:
http://developer.android.com/guide/topics/manifest/activity-element.html#lmode
As for streaming, you should use a Service (preferable a bound service) to contain your media player so that it can continue to play in the background, then the activity is just a client of the service that connects to it, and the service keeps a single instance. That has been described here:
Set Aac+player app as service in background
While application will be started, I want to launch one activity if some condition is satisfied else want to launch another activity. How to do this?
Start the one, and in onCreate() check the condition. If it is not satisfied start your another activity.
you must do it handling all conditions in an initial activity, which will check your rules and start the other activitys.
I don't know much about your particular use case, but if your application has to launch different activities depending on the task it is supposed to do, you should consider having appropriate intent-filters for each, and sending an Intent that's in accordance to the intended effect. That will make the correct activity be launched depending on the Intent, which is one of the great features of Android.
But of course, if you can only decide which activity is best once you launch your app, this approach doesn't work, and you have to launch an initial activity to decide which one to call next.
If it's highly likely that one activity will be launched, you might consider launching it as the first activity and then testing whether you need to launch another instead. That's probably cleaner than having a separate activity just to make the decision about which other activity to launch.
Bruno Oliveira, Developer Programs Engineer, Google
I am finding it hard to understand the exact circumstances in which each the various launch modes would be used in Android. Could anyone provide me with some examples to help understand when the various modes are appropriate?
Between the Browser and Alarm Clock applications, you cover all four launch modes:
BrowserActivity uses singleTask. There is only one browser activity at a time and it doesn't become part tasks that send it intents to open web pages. While it might return to whatever most recently launched it when you hit back it is actually fixed at the bottom of its own task activity stack. It will share its task with activities that it launches like bookmarks.
BrowserBookmarksPage uses singleTop. While there can be multiple instances of this activity, if there is already one at the top of the task's activity stack it will be reused and onNewIntent() will be called. This way you only have to hit back once to return to the browser if the bookmarks activity is started multiple times.
AlarmClock uses standard. The user can launch multiple instances of this activity and these instances can be part of any task and anywhere in the activity stack. As a fairly simple application it doesn't really demand tight control of its activity.
AlarmAlert uses singleInstance. Only one alert activity at a time and it is always its own task. Anything it launches (if anything) becomes part of its own new task.
The official documentation is a bit confusing so here's a table to help.
http://androidisland.blogspot.com/2010/12/activity-launch-modes-simple.html