Android get task stack

Tasks and the Back Stack

What actually happens when you tap the launcher icon for your app? If you said ‘my app launches’, you are technically correct, the best kind of correct. To dive in a bit deeper, it is helpful to understand what a task is and how it interacts with a little thing called the back button.

Tasks

A task is a collection of metadata and information around a stack of activities (you can see exactly what kind of data by looking at the RecentTaskInfo class).

So when you tap the launcher icon for your app, what the system is actually doing is looking for a previously existing task (determined by the Intent and Activity it points to) to resume — getting you back to exactly where you were. If no existing task is found, then a new task is created with your newly launched activity as the base activity on the task’s back stack.

Back Stack

As you might imagine, a task’s back stack is tied together with the back button, but it goes both ways. When you start a new activity using startActivity(), that is (by default) pushing a new activity onto your task, causing the previous Activity to be paused (and stopped if the new activity fully obscures the previous activity).

The back button (by default) then ‘pops’ the stack, calling finish() on the topmost activity, destroying it and removing it from the back stack and taking you back to the previous activity. This repeats until there’s nothing left in the back stack and you’re back at the launcher.

The Back Stack and Fragments

The back stack doesn’t apply only to activities: it also applies to fragments. When you provide a fragment transaction to add, replace, or remove a fragment from your UI, you can use addToBackStack() to effectively add the FragmentTransaction to the back stack.

This way when the back button is hit, the FragmentTransaction is reversed (an added fragment removed, a replaced fragment restored, or a removed fragment re-added). Each transaction added to the back stack is reversed in turn until they’re all removed at which time the default activity finishing behavior again kicks in.

Back isn’t the only navigation button

Of course, the back button isn’t the only navigation button on a modern Android device (no we don’t talk about the menu button anymore).

The home button is probably the most straightforward with its single focus: it puts the current task into the background, taking you back to your launcher.

Note: moving your task to the background does not kill your task (although the topmost activity is most certainly paused+stopped): it’ll live on until the process is killed. Learn more about process priorities and when your app can be killed in the ‘Who lives and who dies?’ blog post.

The overview button (formerly recents), takes you, as you might imagine, to the Overview screen. This is the ‘app switcher’ of the Android world — here you’ll see your most recent tasks and be able to select one to bring it back into the foreground.

Okay, that’s it. Nothing more to see.

Neat, startActivity() or addToBackStack() and the default back button behavior. Nothing special here, but nothing confusing either — these symmetric, consistent behavior serves as the defaults. In most cases, you should be using this default behavior.

Before you go running off and overriding onBackPressed() directly, there’s a few specific cases you might want to consider:

Preventing back button fatigue

Of course, the back button loses some of its luster when you need to press it 10+ times to get out where you are. One case where this is easy to avoid is when you are launching the same Activity you are currently on.

Instead of creating a stack of multiple copies of the same Activity (which is less fun both from a memory pressure perspective and back button fatigue), your Activity can use launchMode=”singleTop” in the Android manifest or you can add Intent.FLAG_ACTIVITY_SINGLE_TOP to your Intent.

This prevents multiple copies of the same Activity on the top of the back stack. Instead, you’ll get a callback to onNewIntent() with the new Intent and any extras.

Note: Read the documentation on onNewIntent() carefully: getIntent() will still return the original Intent unless you use setIntent() to override it.

The back stack and notifications

If you’re building a notification that points to an Activity deep within your app, there’s one case you want to avoid: tapping the back button exiting directly to the launcher. This occurs when the PendingIntent you provide starts a new task with just the one activity. And unless your notification is opening your launcher Activity, that’s not what you want. The user should be in the exact place they’d be as if they had navigated to that part of the app themselves. Your notification just saved them the intermediate steps.

Читайте также:  Ком андроид фон как работает

For something so important, it would be nice to have a class that does all the work for you. Enter TaskStackBuilder: a class specifically for handling the flags and back stack for you for exactly this case:

You’ll notice use of the addNextIntentWithParentStack() method — this is the shortcut to building an entire task stack with just passing in the normal Intent you’d have created a PendingIntent from. It does have one requirement though: each Activity needs to have its parent Activity declared in the Android manifest (see the example from the docs).

And you don’t need to throw out TaskStackBuilder if the defaults don’t work in your case: editIntentAt() allows you to retrieve a specific Intent and set the action, set the data URI, or add extras. If you need even more customization, you can forgo using the *ParentStack() methods entirely and use addNextIntent() to directly add the exact Intents you need for your specific case.

Note: as mentioned in the docs, the other type of Activity you might launch from a notification is one specific to the Notification (i.e., not one in your normal application flow). An example of this might be Hangout’s Direct Reply-like Activity used prior to Android N. These activities are generally semi-transparent — you can see the other app below your Activity — and generally don’t have any synthetic back stack or new task associated with them.

Tasks and the back stack, working together

Remember the important part here is being predictable. If you’re messing with your back stack, make sure to test very thoroughly to ensure the best user experience.

Источник

Task and Back Stack in Android

When doing a job, users engage with a task, which is a set of actions. The activities are stacked in the order in which they are opened in a stack called the back stack. One action in an email app, for example, maybe to display a list of fresh messages. When the user picks a message, a new activity appears in which the user may read the message. This new action has been sent to the back of the queue. When the user clicks the Back button, the new action is completed and removed from the stack. When numerous applications are running in a multi-windowed environment, which is allowed in Android 7.0 (API level 24) and above, the system maintains tasks for each window individually; each window may contain several tasks. The system organizes tasks, or groups of tasks, on a per-window basis for Android apps running on Chromebooks.

Figure 1. Understanding the Back Stack

For most tasks, the device’s Home screen is the starting point. The work of an app is brought to the front when the user taps an icon in the app launcher (or a shortcut on the Home screen). If no task for the app exists (because it hasn’t been used recently), a new task is created, and the app’s “main” activity is opened as the stack’s root activity.

When the current activity switches to a new one, the new activity is pushed to the top of the stack and takes control of the attention. The preceding action is still there in the stack, but it is no longer active. When a task is completed, the system saves the current state of the user interface. The current activity is plucked off the top of the stack (the activity is destroyed) when the user hits the Back button, and the prior activity restarts (the previous state of its UI is restored). The activities in the stack are only pushed onto and popped off the stack—pushed into the stack when the current activity starts it and popped off when the user exits it using the Back button. As a result, the back stack is an object structure that is “last in, first out.” Figure 1 depicts this behavior using a timeline that shows the progression of activities as well as the current back stack at each point in time.

Читайте также:  Kmplayer android без рекламы

What Happens on Back Press?

If the user presses Back repeatedly, each activity in the stack is popped off to show the one before it, until the user returns to the Home screen (or to whichever activity was running when the task began). The task is no longer active after all actions have been removed from the stack.

Figure 2. Losing Focus

A task is a logical unit that may be sent to the “background” when users start a new task or press the Home button to return to the Home screen. All operations in the task are paused while it is in the background, but the task’s back stack remains intact—the task has just lost focus while another task is being performed, as seen in figure 2. A task can then be brought back into the “foreground,” allowing users to resume their work where they left off. Assume that the current task (Task A) contains three activities in its stack, two of which are underneath the current activity. The user hits the Home button, then opens the app launcher and selects a new app. Task A is pushed to the background when the Home screen appears. When a new app is launched, the system creates a task (Task B) for it, which has its own set of activities. After interacting with that app, the user goes back to Home and picks the app that launched Task A in the first place. Task A now appears in the forefront, with all three activities in its stack intact and the activity at the top of the stack resumed. The user may now return to Task B by navigating to Home and choosing the app icon that initiated the task (or choosing the app’s task from the Recents page). On Android, this is an example of multitasking.

Because the activities in the back stack are never reorganized if your app allows users to launch a specific activity from multiple activities, a new instance of that activity is produced and placed onto the stack (rather than bringing any previous instance of the activity to the top). As a result, a single activity in your app may be invoked many times (even from distinct jobs). As a result, if the user uses the Back button to browse backward, each instance of the activity will be presented in the sequence in which it was accessed (each with its own UI state). If you don’t want an activity to be created more than once, however, you may change this behavior. In the section on Managing Tasks, we’ll go through how to accomplish that. To describe the default behavior for activities and tasks, consider the following:

  • Activity A is interrupted when Activity B begins, but the system’s state is preserved (such as scroll position and text entered into forms). When the user returns to Activity A after pressing the Back button in Activity B, the state of Activity A is restored.
  • When a user exits a task by hitting the Home button, the present activity is terminated and the task is placed in the background. Every activity in the task is saved in the system’s memory. The task comes to the foreground and resumes the activity at the top of the stack if the user subsequently continues it by clicking the launcher icon that started it in the first place.
  • The current activity is removed from the stack and deleted when the user hits the Back button. In the stack, the prior action is resumed. The system does not keep track of the status of activity when it is deleted.

Even from other tasks, activities can be instantiated several times.

Organizing Your Tasks

For most apps, the way Android manages tasks and the back stack (by placing all activities initiated in sequence in the same task and in a “last in, first out” stack) works fine, and you shouldn’t have to worry about how your activities are connected with tasks or how they appear in the back stack. You may, however, decide that you want to deviate from the standard. Perhaps you want an activity in your app to start a new task (rather than being placed within the current task), or perhaps you want to bring an existing instance of activity forward (rather than creating a new instance on top of the back stack) when the user leaves the task, or perhaps you want your back stack to be cleared of all activities except the root activity when the user leaves the task. With characteristics in the activity> manifest element and flags in the intent that you send to startActivity, you can perform all of these things and more.

Читайте также:  Телевизор филипс завис андроид

The following tags can be used for defining the Back Stack forcefully:

  • taskAffinity
  • launchMode
  • allowTaskReparenting
  • clearTaskOnLaunch
  • alwaysRetainTaskState
  • finishOnTaskLaunch

Источник

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 tag:

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

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:

Defining launch modes in Manifest File:

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?

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:

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:

2. “FLAG_ACTIVITY_SINGLE_TOP”:

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

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:

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.

Источник

Оцените статью