Yash Soni
AndroidPub
Published in
6 min readJan 10, 2018

--

A short story to begin with:

In a place named Androidland, there lived a guy called Droid. He was a chef by profession and made delicious Apps for living. He was very happy doing what he did. He had to be so, as he was following his passion.

One fine day, Droid was sitting in his verandah- sipping his favorite tea and wondering “How good a chef am I? I do know how to make best APP-dishes in the world, given I already have best ingredients ready for me, but do I really know how these ingredients behave on their own? OR How they complement each other? If not, then may be I’ve to learn that first. Because without clear fundamentals I can never become best Chef for APP-dishes ever.”

From that very day, Droid went on to the pursuit of becoming the best Chef in the Androidland, and guess what — at the end he did become one!

So with that story, we will begin with our Topic of the Day : Android Tasks (and everything around it!)

What is a Task in Android?

Simply put: A task is collection of Activities, usually co-related — but not necessarily. What you see in your “Recent-Apps” screen, is in-turn a collection of such Tasks.

What is a Back Stack?

While user navigates from one Activity to other, a stack is maintained by Android to persist the order of activities. This stack helps in which Activity to show when user clicks back button. Hence the name, Back Stack.

In most cases, you won’t need to worry about explicitly handling Tasks and Back Stack. But if you aspire become best Chef in Androidland, then you must know how to handle this stuff. 😉

Consider this scenario:

Say you have an App with 2 Activities: A and B.
Your Activity stack looks like this right now: A →B (B on the top of stack)

You are currently on Activity B. Now let’s say you get the notification that in-turn lands you to Activity B in your App.
What should ideally happen?
You should stay on the same screen that is already open, right?

Well, this ideal scenario won’t happen on it’s own, you will end up making a new Activity on top of your current Activity. Resulting your Activity stack to look like: A → B → B

To get the desired output, let’s start with learning some new terms.

a) Task Affinity:

In general, what is affinity?

Like all of you have affinity for Android App Development,
Activities also have affinity towards default package, that is the reason all the Activities in one App falls under one task, by default.

Where can one define Task Affinity?

You define affinity per activity in your AndroidManifest.xml.
Affinity of an Activity is defined by following attribute within <activity> tag:

<activity
android:taskAffinity=""
..
/>

This parameter accepts a String. By default, every activity has same affinity as your package attribute value of mainfest tag.

<manifest package="com.example"...>

Affinity of a Task is defined by the affinity of its root Activity.

b) Launch modes:

It is used to instructs Android system on how to launch a particular activity.
Two ways to define
launchMode for an Activity:

1. In Manifest file

2. Using Intent Flags

Defining launch modes in Manifest File:

“android:launchMode” is an attribute defined inside <activity .../> tag in AndroidManifest.xml

<activity android:launchMode = [“standard” | “singleTop” | “singleTask” | “singleInstance”] ../>

1. “standard”:

This is the default mode. In case you don’t define any launchMode, the new activity is launched in standard mode.
Here, a new instance of the Activity will be created — everytime.

2. “singleTop”

This is just as same as “standard” mode, except for — Android will perform an extra check “whether this activity is already on the top of the Activity Stack.”
If YES, then it won’t create a new instance of the Activity but instead it will call the onNewIntent() of the same Activity.

Have a look at the Activity Stack for “standard” & “singleTop” launch modes. Consider the Activity Intent order as: A → B → B → B

3. “singleTask”

Here, the referred Activity will be launched in the new Task.
(PS: You can notice this in Recents window)

So, you just define “launchMode”: “singleTask” and it will all work magically, huh?

Look Who’s Talking ;)

Your current activity has to have a “taskAffinity” value defined other than the default package name. Or else, even though you have tagged it as “singleTask” it will still open it in the same damn Task.
One last important point to note is:

You CAN still have other Activities coming on top of this Activity, even in the newly created Task.

4. “singleInstance”

Well, this is exactly same as “singleTask” with one teeny-tiny difference.
That is:

You CANNOT have other Activities coming on top of this Activity. This Activity is a lone warrior in the Tasks playground. 😎

General Note on using “singleTask” & “singleInstance”:

When you launch an activity with a launchMode defined in Manifest, the Android system looks for the taskAffinity first. Then in the main stack of Tasks (i.e. Recents screen), Android checks if there is a task already present with the root Activity having same taskAffinity as the one for intended Activity, if Yes, then the Activity is opened in that task, else a new task is created and with Intended Activity placed at its root.

Defining launch modes using Intent Flags:

1. “FLAG_ACTIVITY_NEW_TASK”:

Now, putting it straight — this is just as same behaviour as
launchMode — singleTask.
Here, you do the same thing programmatically while creating your Intent for new Activity. Your code will look something like this:

Intent i = new Intent(FirstActivity.this, SecondActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(i);

Notes:

a) If you haven’t defined taskAffinity value different from the default one, setting this flag will have no effect. (Just like you did when using launchMode — singleTask)

b) The default behaviour of back press on newly created activity in a new task is — GO TO HOMESCREEN. If you want to go back to the Activity in your main task, that started this new Activity, then you have to define it in Manifest of your app. See the following snippet:

<activity android:name=".SecondActivity"
android:taskAffinity="com.yash.soni"
android:parentActivityName=".FirstActivity"/>

2. “FLAG_ACTIVITY_SINGLE_TOP”:

Again, this is same as launchMode — singleTop. You have to set the Intent Flag as follows:

Intent i = new Intent(FirstActivity.this, FirstActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
startActivity(i);

Now, if the Activity to be launched is on the Top of the Activity stack, then instead of creating a new Activity, it will call onNewIntent() of the already open Activity. A sample snippet is as follows:

@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
Toast.makeText(this, "Welcome again!", Toast.LENGTH_SHORT).show();
}

3. “FLAG_ACTIVITY_CLEAR_TOP”:

There are two scenarios of use here:
a) All Activities in the same Task:
As expected, this flag will clear all the Activities on the top of Intended Activity in the stack and bring it to Foreground.

b) Activities spread across different tasks:
If this flag is set along with FLAG_ACTIVITY_NEW_TASK then the system will bring the required Task that contains the intended Activity to Foreground, and clear all the Activities on the top of that Activity.

That will be a wrap on Android Tasks from my side.

Checkout the following interesting articles as well:

Kotlin — Initial Impressions:

Machine Learning Fundamentals:

Make sure you press the follow button for my upcoming blogs.
Likes and Comments are always appreciated and loved. ❤

Happy 2018!

--

--

Yash Soni
AndroidPub

engineering @IBMcloud • minimalist • stoic • bibliophile • finance & tech aficionado • yoga • peak performance enthusiast • https://iyashsoni.carrd.co