Android - need for task affinity, single task launch mode & task reparenting - android

I am trying to understand the need for task affinity in Android. I searched other SO answers as well.
I am particularly interested in the combination of a singleTask launch mode and task affinity.
For singleTask launch mode (OR Intent with NEW_TASK flag), system takes one of 3 actions:
If activity exists, it will resume it
If activity doesn't exist, it will look for a task with matching affinity to add the activity
Without finding a matching task, system will create a new task with this activity as root
I kind of understand the need to the first case from this answer. It talks about having same activity in multiple states, and how it can create inconsistency problems in user experience.
What I am more puzzled about is the second case - why does the system need to find an existing task with the same affinity ? What kind of use case does this fulfill and would break if this feature is disallowed ? Why is it necessary ?
From this link:
... if the intent passed to startActivity() contains the
FLAG_ACTIVITY_NEW_TASK flag, the system looks for a different task to
house the new activity. Often, it's a new task. However, it doesn't have to be.
If there's already an existing task with the same affinity as the new activity, the
activity is launched into that task. If not, it begins a new task.
The same link also talks about task reparenting. This is another feature
I cannot understand. The link does give an example of a weather/travel app:
... suppose that an activity that reports weather conditions in selected cities
is defined as part of a travel application. It has the same affinity as other
activities in the same application (the default application affinity) and it allows
re-parenting with this attribute. When one of your activities starts the weather
reporter activity, it initially belongs to the same task as your activity.
However, when the travel application's task comes to the foreground, the weather
reporter activity is reassigned to that task and displayed within it.
My question for this feature is similar. I'm not able to tell whether this feature is to fulfill some necessary user experience requirement OR is just a fancy add-on to tasks ? Why do activities need to be re-parented across tasks ?
Can someone please help me answer the above two questions ?

I'll take a stab at this!
I believe Android/Google's intentions were to have a seamless interaction for the user.
So when I read about affinity what came to mind were URLs, emails, documents and such. Does it make sense to ask the user what application to open especially if they already have one of the applications open that can handle the intent.
Same goes for re-parenting. The task opens another application but what happens when the user is finished with that task and wants to go back to the original application? In the user's perspective it is one experience regardless of how many applications are needed to meet that experience.
(I swear I read about this in a Material Design doc from Android....)

Related

Tasks in Android

I am trying to understand conceptually what a task is in Android. So is it correct that a task can have multiple activities and can run one activity at a time? But is a task like a unix process? And each activity can be thought of as a thread within the process? Looking to clarify my somewhat weak understanding.
A task, unlike a Unix process, is basically an UI concept.
From the documentation - Tasks and Back Stacks
A task is a collection of activities that users interact with when
performing a certain job. The activities are arranged in a stack (the
"back stack"), in the order in which each activity is opened.
The activities that make up a task can belong to different applications (and hence, to different processes). That's why inter-activity communication in Android is done via Intents (basically, messaging objects than can be serialized) and not via direct method calls -- even when the called activity is part of the same application as the caller.
A user can switch freely between tasks (with the "Recents" button) but cannot move arbitrarily between the activities that make up a task. Normally they can only go one step back, via the "Back" button.
You should take a look at the documentation -- it's quite well explained there.
An Android application maps to a Unix process (more or less, since an app can run more than one process if it so desires) . But there is not a one-to-one mapping with tasks -- a task can contain activities from multiple applications, and a single application can have activities in multiple tasks.

Intuitively Understanding Android Tasks

Tasks and Back Stack is the definitive resource for understanding the mechanism involving tasks and their interaction with the Back button. In an early paragraph:
A task is a collection of activities
that users interact with when
performing a certain job. The
activities are arranged in a stack
(the "back stack"), in the order in
which each activity is opened.
Tasks are then explained in terms of the home screen and how it launches processes. This makes sense. I'm curious, however: What should determine the use of multiple tasks in "user" applications?
I'm interested in a intuitive understanding or heuristic guiding task usage rather than simply trying to achieve specific orderings of activities on the back stack.
A task is a group of components that work coherently together to fulfill a purpose for the user (not necessarily a very specific purpose, but a purpose nonetheless). It's what the user sees as an application.
A music player exists to allow the user to manage and play songs. It may include various activities that display album/artist/song metadata, control playback, organize playlists, etc. It may also include services that implement the playback and that watch for new songs. The user doesn't know what an activity and a service are; he or she only knows that this series of screens lets him or her manage and play songs.
The activities in a task don't need to belong to the same 'application' from a development standpoint. If the music player task allows users to link an image to a song, then it might launch an image gallery activity or the camera activity. Since the new activity is still working toward the purpose of managing songs, it's still part of the same task.
On the other hand, if the user completely breaks out of the task's purpose, it might be time to start a different task. For example, if you launch a web browser to view the artist's website, the user is now doing something different. The user probably doesn't associate web browsing with managing and playing songs, so this should probably be a different task.
I think a task in that given context is sort of a workflow. Take email. Writing a new email may consist of
first filling in recipients and then in the next activity selecting recipients and clicking on send finally sends the email off.
Another task could be selecting multiple emails and then deleting all in one go.
In practice what you often find is an AsyncTask which is basically doing work in background which otherwise would block the UI thread and make the app non-responsive.

Difference between task and process in Android

I'm a bit confused about the difference between a task and a process in Android.
If I understand correctly a task is just a stack of activities. From what I read so far I think a task could look like this:
| Activity A running in Process P1 |
| Activity B running in Process P2 |
| Activity C running in Process P3 |
So basically activities from different processes can be contained in the same stack. Am I correct?
Another question: What is the real meaning of "application context"? The process or the task?
And final question: The application class (which is basically a singleton) represents the process or the task?
Everything I've ever learned about it, I've learned on this page.
Edit: I also just stumbled upon Activity and Task Design Guidelines. It looks to cover the exact topic you asked about. I learned a lot :)
So basically activities from different
processes can be contained in the same
stack. Am I correct?
Based on my understanding, you are correct. My grasp is that Processes are the units of actual execution while Tasks are about association to get things done. As an example from the aforementioned page, if you create an intent that opens a webpage, the Activity that it creates is created on the web browsers process but is associated with your applications Task. A task, therefore, becomes a virtual stack of Activities running on different processes depending on the application that provided the Activity.
Another question: What is the real
meaning of "application context"? The
process or the task?
This is a good question. Based on reading the page above, my understanding is that an Applications context is associated with the process. I'm basing that on the interpretation of this line from that page, but there may be other info:
Normally, a new instance of an
activity is launched into the process
of the application that defined it, so
all instances of the activity run in
the same process
And final question: The application
class (which is basically a singleton)
represents the process or the task?
With the same interpretation as above, my guess as to why an Application object represents a Singleton is because all of your applications activities get run on a single process and that process is tied to the Application. I don't know that this is a design point, but it appears to be, at the least, a consequence of the current design.
Edit: There are some caveats to this. It appears that your application can be spread across multiple processes so, my guess is that the Application Object and context act as a mechanism for tethering all the processes together. I'm pretty sure your mental model already allowed for this, assuming the processes were from different applications, so its only a small difference to allow it inside a single process.
The manifest element has the attribute android:process with the description as follows:
The name of the
process in which the activity should
run. Normally, all components of an
application run in the default process
created for the application. It has
the same name as the application
package. The element's
process attribute can set a different
default for all components. But each
component can override the default,
allowing you to spread your
application across multiple processes.
If the name assigned to this attribute
begins with a colon (':'), a new
process, private to the application,
is created when it's needed and the
activity runs in that process. If the
process name begins with a lowercase
character, the activity will run in a
global process of that name, provided
that it has permission to do so. This
allows components in different
applications to share a process,
reducing resource usage.
Process:
When an application component starts and the application does not have any other components running, the Android system starts a new Linux process for the application with a single thread of execution. By default, all components of the same application run in the same process and thread (called the "main" thread).Every application runs in its own process and all components of the application run in that process, by default.
for detail process: http://developer.android.com/guide/components/processes-and-threads.html
Tasks:
A task is a collection of activities that users interact with when performing a certain job. The activities are arranged in a stack (the "back stack"), in the order in which each activity is opened.
An activity can even start activities that exist in other applications on the device. For example, if your application wants to send an email, you can define an intent to perform a "send" action and include some data, such as an email address and a message. An activity from another application that declares itself to handle this kind of intent then opens. In this case, the intent is to send an email, so an email application's "compose" activity starts (if multiple activities support the same intent, then the system lets the user select which one to use). When the email is sent, your activity resumes and it seems as if the email activity was part of your application. Even though the activities may be from different applications, Android maintains this seamless user experience by keeping both activities in the same task.
for detail task-http://developer.android.com/guide/components/tasks-and-back-stack.html
An important note from Android Developer :
A common misunderstanding about Android multitasking is the difference
between a process and an application. In Android these are not tightly
coupled entities: applications may seem present to the user without an
actual process currently running the app; multiple applications may
share processes, or one application may make use of multiple processes
depending on its needs; the process(es) of an application may be kept
around by Android even when that application is not actively doing
something.

Task and Activity stack : what is difference between both.

I followed some tutorials but got confused with "Activity stack" and "Task".
Because both starts when a new activity is created.
Activity stack keeps a navigation history of activities, and Task is a sequence of activities.
Is this is only difference that Activity stack made up of one or more task(S)?
Give some example please.
Activities and Tasks
As noted earlier, one Activity can start another, including one defined in a different Application. Suppose, for example, that you'd like to let users display a street map of some location. There's already an activity that can do that, so all your activity needs to do is put together an Intent object with the required information and pass it to startActivity(). The map viewer will display the map. When the user hits the BACK key, your activity will reappear on screen.
To the user, it will seem as if the map viewer is part of the same application as your activity, even though it's defined in another application and runs in that application's process. Android maintains this user experience by keeping both activities in the same task. Simply put, a task is what the user experiences as an "application". It's a group of related activities, arranged in a stack.
Task = Application = Set of activities.
A task is not an application. The former is a set of Activities that the user has visited, while the latter is a collection of Android components (Activities, Services, ContentProviders and BroadcastReceivers) that are declared in an application's manifest.
The Activities of a given task can come from other applications as well as the current application. Taken together, these Activities represent the "path" that a user has taken to accomplish some objective. They are stored in the task's back stack in LIFO order; each task has its own back stack.
Task management, either through attributes such as launchMode, taskAffinity, etc, and/or intent flags, allows us to control the relationship between tasks and Activities.
For more information, please see: https://developer.android.com/guide/components/activities/tasks-and-back-stack

Instantiating activities into new tasks and processes

I have an application with a multi-instance activity. I would like each
instance of the activity to appear in a new task and process.
Any suggestions on how to do this? By manipulating the manifest I can
cause all instances of the activity to appear in a specific task and
process, but I haven't found any way to cause each instance to appear in
a different task and process.
(The requirement to have different tasks is that we want each instance
of the activity to appear separately in the task list; the requirement
for different processes is that each instance of the activity is backed
by a chunk of native code with global state. We can't change either of
these.)
Well, you could use FLAG_ACTIVITY_MULTIPLE_TASK but the documentation is pretty clear that you should not use it for what you want to do. It's possible that you could end up with a bunch of Activitys that the user has no method of getting back too.
I suggest reexamining your app's architecture. Maybe you can store the link to the native state in a Local Service and have the activity fetch the correct one from it depending on what is in its Intent.

Categories

Resources