Sunday, 15 September 2013

Android Activities and Tasks series – Intent flags

In this post of the series, we focus on Android’s intent concept and address the following questions:
  1. What are intents?
  2. How do we use them to launch activities?
  3. What options (flags) does Android provide to customize this launch? (e.g. in terms of target task or activity instance creation)

In order to ease understanding of intents and their various flags, akquinet Modular and Mobile Solutions provides an Android application to experiment with intent flags. With it, you can start different types of activities, specifying the intent flags you want to pass, and examine the effects. Install it by pointing your Android browser to this URL.

Intents and activity launching

An intent is a data structure containing a description of a to-be-performed operation. This operation primarily consists of an action and of data to operate on, although there are various optional parameters to describe the operation in more detail. Technically speaking, this action is just a constant, either a pre-defined one from Android, likeACTION_VIEW or ACTION_EDIT, or a custom one that we can define ourselves.
An intent is always handled by an Android component, namely an activity, a service or a broadcast receiver. In this blog post series, we will focus on activities as intent handlers. For our purposes, an intent is used to launch an activity.
To create an intent and launch an activity with it, we can write the following code within our caller activity:
1
2
3
Intent intent = new Intent(Intent.ACTION_VIEW,
    Uri.parse("http://www.akquinet.com/")
startActivity(intent);
In this example, we give two parameters to the Intent constructor: The action to be performed (here view) and the corresponding data(here a web page URL). Then, we simply pass the Intent object tostartActivity(Intent). Basically, what we do here is telling Android that we want to view the akquinet homepage. Android will look for activities capable of handling that intent, which in this case is aweb browser activity, and start it. Note that any activity can be declared capable of handling certain intent types by defining intent filters in the application’s AndroidManifest.xml file.
Instead of letting Android choose a suitable activity, an intent may also name the to-be-launched target activity explicitly by specifying the target activity’s class, like so:
1
2
Intent intent = new Intent(this, MyActivity.class);
startActivity(intent);
When run, this code snippet has the following consequences:
  1. A new instance of MyActivity is created
  2. The instance is pushed on top of the current task’s stack, which is the one the calling activity is in.
  3. The activity is started and brought to the foreground.

Customizing the launch of activities via intent flags

The described behavior can be modified by specifying intent flags on the intent instance before passing the intent tostartActivity(Intent), for example:
1
intent.addFlag(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
This will bring an existing instance of the called activity type present in the current stack to the foreground (if there is such an instance) instead of creating a new instance. Android 2.0 defines various intent flags, which are now explained in more detail.
FLAG_ACTIVITY_BROUGHT_TO_FRONT
This flag is set by the system as an indication that an existing activity with launch mode singleTask has been called and reused. Activity launch modes are discussed in more detail in the next blog post.
FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET
Bringing a task to foreground after using flag CLEAR_WHEN_TASK_RESET
This flag marks the called activity and all activities put on top of it to be cleared (removed from the stack) when the task is reset. This reset is performed as soon as the task is brought to the foreground usingFLAG_ACTIVITY_RESET_TASK_IF_NEEDED, which is always set by the system when the user resumes a task from the home screen, the main menu or the list of recently started activites.
You can use this to define a point in the task stack from where all started activities should be “forgotten” once the task is sent to the background.
FLAG_ACTIVITY_CLEAR_TOP
Using flag CLEAR_TOP to launch an activity
If there is already an instance of the called activity type present in the stack, then this instance is brought to the foreground instead of creating a new instance. Also, all activities in the stack that reside on top of that instance are cleared from the stack. For example, assuming that the current activity stack is ABCDE, launching an activity of type Cwill clear activities D and E from the task and result in the stack ABC.
FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
Normally, when launching an activity in a new task, the target activity is shown in the list of recently launched activities (accessible via long press of the home button). For example, this is the case when launching the browser from your activity to render a web page. Using this flag, we can suppress that behavior, effectively excluding the target activity from the list of recently launched activities.
FLAG_ACTIVITY_FORWARD_RESULT
By default, in order for an activity B to be able to propagate a result back to the calling activity AA has to use the methodstartActivityForResult(Intent) instead of methodstartActivity(Intent) to start B. When B defines its result viasetResult(int resultCode) and finishes, the callback methodonActivityResult() is called on A where the result can be retrieved.
Resulting forwarding with Flag FORWARD_RESULT
Suppose now that B calls another activity C, which defines the result, and we want to forward that result back to A. In order to avoid having to pass results manually from B to A, Android provides this flag.
In our example, this means that B calls C, specifying the forward flag and using startActivity(Intent)C may then define a result, which is forwarded back to A automatically once C and B are finished. The callback method onActivityResult() is called on A but not called on the intermediate activity B as B only forwards the result instead of explicitly handling it.
Note that the flag may only be used in conjunction withstartActivity(Intent), not withstartActivityForResult(Intent), because an activity using the latter method marks the end of a forwarding chain and should handle the result in its callback method.
FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY
This flag is set by the system as an indication that an activity has been launched from the list of recently launched activities.
FLAG_ACTIVITY_MULTIPLE_TASK
This flag has no effect unless used in conjunction withFLAG_ACTIVITY_NEW_TASK. If used together, a new task is always created and a new instance of the called activity type becomes the first (and at that time, the only) element of that task.
FLAG_ACTIVITY_NEW_TASK
If this flag is used on its own (withoutFLAG_ACTIVITY_MULTIPLE_TASK), a new task is only created if there is not already a task present that the target activity has an affinity for (task affinities are examined more closely in the next blog post). If such a task already exists, the activity is put into that task instead of creating a new one.
As all activities specified within the same application have a default affinity to remain in the same task (this can be customized), starting an activity defined in the same application as the calling activity using this flag will not create a new task, unlessFLAG_ACTIVITY_MULTIPLE_TASK is specified as well.
FLAG_ACTIVITY_NO_ANIMATION
Introduced with Android 2.0, this flag disables the usual animation accompanied by an activity transition. For example, this can be used to call an activity that itself launches another activity without further user interaction, resulting in only one transition animation to be shown instead of two.
FLAG_ACTIVITY_NO_HISTORY
This flag implies that the called activity is not kept in the task’s stack. When navigating away, the user cannot return to it. For example, this is useful to launch activities that perform an immediate dispatch to another activity. This activity is consequently skipped if the user presses the back button as it is not kept in the stack.
FLAG_ACTIVITY_NO_USER_ACTION
This flag may be used as an indication that the activity transition is not an action directly performed by the user but rather an automatic one. For example, this is true for the call-in activity that is automatically launched when the device receives a phone call. Technically, it means that the invocation of callback method onUserLeaveHint() on the caller activity is suppressed.
FLAG_ACTIVITY_REORDER_TO_FRONT
Starting an activity with Flag REORDER_TO_FRONT
If there is already an instance of the called activity type present in the task stack, that instance is brought to the foreground while the rest of the stack is kept intact. This effectively reorders the stack. For example, assuming that the current activity stack is ABCDEF, launching an activity of type C using this flag will result in the new stack ABDEFC.
FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
This flag has no effect unless the intent creates a new task or brings an existing task to the foreground. In that case, the task is reset, meaning that task affinities are applied (resulting in activities being moved from or to this task) and that, given thatFLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET is set as well, the task is cleared according that flag’s specification.
FLAG_ACTIVITY_SINGLE_TOP
If an instance of the target activity is already at the top of the stack, no new instance is created.

Conclusion

The akquinet Mobile and Modular Solutions provides an Android application to help you understand the effects of the intent flags. It lets you start exemplary activities using arbitrary intent flags and inspect the effects on the resulting task stack.
Intent Flags Tool - Main screen
Intent Flags Tool - Main screen
Intent Flags Tool - Selecting Flags
Intent Flags Tool - Selecting Flags
You can download the tool here. The source code is also available ongithub.
All described behavior not only depends on intent flags specified, but also on attributes defined on the called activity type (inAndroidManifest.xml), including task affinities and launch modes. While intent flags are specified by the caller, launch modes and affinities are properties of the callee. Those will be discussed in the next post of this series.

No comments:

Post a Comment