diff options
Diffstat (limited to 'docs/html/guide')
| -rw-r--r-- | docs/html/guide/topics/fundamentals.jd | 12 | ||||
| -rw-r--r-- | docs/html/guide/topics/fundamentals/activities.jd | 762 | ||||
| -rw-r--r-- | docs/html/guide/topics/fundamentals/tasks-and-back-stack.jd | 568 | ||||
| -rw-r--r-- | docs/html/guide/topics/resources/string-resource.jd | 67 | ||||
| -rw-r--r-- | docs/html/guide/topics/ui/dialogs.jd | 17 | ||||
| -rw-r--r-- | docs/html/guide/tutorials/notepad/notepad-ex2.jd | 4 |
6 files changed, 1402 insertions, 28 deletions
diff --git a/docs/html/guide/topics/fundamentals.jd b/docs/html/guide/topics/fundamentals.jd index a095087..84c2ed2 100644 --- a/docs/html/guide/topics/fundamentals.jd +++ b/docs/html/guide/topics/fundamentals.jd @@ -294,8 +294,8 @@ onActivityResult()}</code> method. <li><p>A service is started (or new instructions are given to an ongoing service) by passing an Intent object to <code>{@link android.content.Context#startService Context.startService()}</code>. -Android calls the service's <code>{@link android.app.Service#onStart -onStart()}</code> method and passes it the Intent object.</p> +Android calls the service's <code>{@link android.app.Service#onStartCommand +onStartCommand()}</code> method and passes it the Intent object.</p> <p> Similarly, an intent can be passed to <code>{@link @@ -1510,9 +1510,9 @@ a music playback service could create the thread where the music will be played in {@code onCreate()}, and then stop the thread in {@code onDestroy()}.</li> <li><p>The <b>active lifetime</b> of a service begins with a call to -<code>{@link android.app.Service#onStart onStart()}</code>. This method +<code>{@link android.app.Service#onStartCommand onStartCommand()}</code>. This method is handed the Intent object that was passed to {@code startService()}. -The music service would open the Intent to discover which music to +The music service would open the Intent to discover which music to play, and begin the playback.</p> <p> @@ -1527,7 +1527,7 @@ services, whether they're started by <code>{@link android.content.Context#startService Context.startService()}</code> or <code>{@link android.content.Context#bindService Context.bindService()}</code>. -However, {@code onStart()} is called only for services started by {@code +However, {@code onStartCommand()} is called only for services started by {@code startService()}. </p> @@ -1631,7 +1631,7 @@ to the activity that the user is interacting with.</p></li> <li><p>It has a {@link android.app.Service} object that's executing one of its lifecycle callbacks (<code>{@link android.app.Service#onCreate -onCreate()}</code>, <code>{@link android.app.Service#onStart onStart()}</code>, +onCreate()}</code>, <code>{@link android.app.Service#onStartCommand onStartCommand()}</code>, or <code>{@link android.app.Service#onDestroy onDestroy()}</code>).</p></li> <li><p>It has a {@link android.content.BroadcastReceiver} object that's diff --git a/docs/html/guide/topics/fundamentals/activities.jd b/docs/html/guide/topics/fundamentals/activities.jd new file mode 100644 index 0000000..b616ab8 --- /dev/null +++ b/docs/html/guide/topics/fundamentals/activities.jd @@ -0,0 +1,762 @@ +page.title=Activities +parent.title=Application Fundamentals +parent.link=index.html +@jd:body + +<div id="qv-wrapper"> +<div id="qv"> +<h2>Quickview</h2> +<ul> + <li>An activity provides a user interface for a single screen in your application</li> + <li>Activities can move into the background and then be resumed with their state restored</li> +</ul> + +<h2>In this document</h2> +<ol> + <li><a href="#Creating">Creating an Activity</a> + <ol> + <li><a href="#UI">Implementing a user interface</a></li> + <li><a href="#Declaring">Declaring the activity in the manifest</a></li> + </ol> + </li> + <li><a href="#StartingAnActivity">Starting an Activity</a> + <ol> + <li><a href="#StartingAnActivityForResult">Starting an Activity for a Result</a></li> + </ol> + </li> + <li><a href="#Lifecycle">Managing the Activity Lifecycle</a> + <ol> + <li><a href="#ImplementingLifecycleCallbacks">Implementing the lifecycle callbacks</a></li> + <li><a href="#SavingActivityState">Saving activity state</a></li> + <li><a href="#ConfigurationChanges">Handling configuration changes</a></li> + <li><a href="#CoordinatingActivities">Coordinating activities</a></li> + </ol> + </li> +</ol> + +<h2>Key classes</h2> +<ol> + <li>{@link android.app.Activity}</li> +</ol> + +<h2>See also</h2> +<ol> + <li><a href="{@docRoot}resources/tutorials/hello-world.html">Hello World Tutorial</a></li> + <li><a href="{@docRoot}guide/topics/fundamentals/tasks-and-back-stack">Tasks and Back +Stack</a></li> +</ol> + +</div> +</div> + + + +<p>An {@link android.app.Activity} is an application component that provides a screen with which +users can interact in order to do something, such as dial the phone, take a photo, send an email, or +view a map. Each activity is given a window in which to draw its user interface. The window +typically fills the screen, but may be smaller than the screen and float on top of other +windows.</p> + +<p> An application usually consists of multiple activities that are loosely bound +to each other. Typically, one activity in an application is specified as the "main" activity, which +is presented to the user when launching the application for the first time. Each +activity can then start another activity in order to perform different actions. Each time a new +activity starts, the previous activity is stopped, but the system preserves the activity +in a stack (the "back stack"). When a new activity starts, it is pushed onto the back stack and +takes user focus. The back stack abides to the basic "last in, first out" queue mechanism, +so, when the user is done with the current activity and presses the BACK key, it +is popped from the stack (and destroyed) and the previous activity resumes. (The back stack is +discussed more in the <a href="{@docRoot}guide/topics/fundamentals/tasks-and-back-stack.html">Tasks +and Back Stack</a> document.)</p> + +<p>When an activity is stopped because a new activity starts, it is notified of this change in state +through the activity's lifecycle callback methods. +There are several callback methods that an activity might receive, due to a change in its +state—whether the system is creating it, stopping it, resuming it, or destroying it—and +each callback provides you the opportunity to perform specific work that's +appropriate to that state change. For instance, when stopped, your activity should release any +large objects, such as network or database connections. When the activity resumes, you can +reacquire the necessary resources and resume actions that were interrupted. These state transitions +are all part of the activity lifecycle.</p> + +<p>The rest of this document discusses the basics of how to build and use an activity, +including a complete discussion of how the activity lifecycle works, so you can properly manage +the transition between various activity states.</p> + + + +<h2 id="Creating">Creating an Activity</h2> + +<p>To create an activity, you must create a subclass of {@link android.app.Activity} (or +an existing subclass of it). In your subclass, you need to implement callback methods that the +system calls when the activity transitions between various states of its lifecycle, such as when +the activity is being created, stopped, resumed, or destroyed. The two most important callback +methods are:</p> + +<dl> + <dt>{@link android.app.Activity#onCreate onCreate()}</dt> + <dd>You must implement this method. The system calls this when creating your + activity. Within your implementation, you should initialize the essential components of your +activity. + Most importantly, this is where you must call {@link android.app.Activity#setContentView + setContentView()} to define the layout for the activity's user interface.</dd> + <dt>{@link android.app.Activity#onPause onPause()}</dt> + <dd>The system calls this method as the first indication that the user is leaving your +activity (though it does not always mean the activity is being destroyed). This is usually where you +should commit any changes that should be persisted beyond the current user session (because +the user might not come back).</dd> +</dl> + +<p>There are several other lifecycle callback methods that you should use in order to provide a +fluid user experience between activities and handle unexpected interuptions that cause your activity +to be stopped and even destroyed. All of the lifecycle callback methods are discussed later, in +the section about <a href="#Lifecycle">Managing the Activity Lifecycle</a>.</p> + + + +<h3 id="UI">Implementing a user interface</h3> + +<p> The user interface for an activity is provided by a hierarchy of views—objects derived +from the {@link android.view.View} class. Each view controls a particular rectangular space +within the activity's window and can respond to user interaction. For example, a view might be a +button that initiates an action when the user touches it.</p> + +<p>Android provides a number of ready-made views that you can use to design and organize your +layout. "Widgets" are views that provide a visual (and interactive) elements for the screen, such +as a button, text field, checkbox, or just an image. "Layouts" are views derived from {@link +android.view.ViewGroup} that provide a unique layout model for its child views, such as a linear +layout, a grid layout, or relative layout. You can also subclass the {@link android.view.View} and +{@link android.view.ViewGroup} classes (or existing subclasses) to create your own widgets and +layouts and apply them to your activity layout.</p> + +<p>The most common way to define a layout using views is with an XML layout file saved in your +application resources. This way, you can maintain the design of your user interface separately from +the source code that defines the activity's behavior. You can set the layout as the UI for your +activity with {@link android.app.Activity#setContentView(int) setContentView()}, passing the +resource ID for the layout. However, you can also create new {@link android.view.View}s in your +activity code and build a view hierarchy by inserting new {@link +android.view.View}s into a {@link android.view.ViewGroup}, then use that layout by passing the root +{@link android.view.ViewGroup} to {@link android.app.Activity#setContentView(View) +setContentView()}.</p> + +<p>For information about creating a user interface, see the <a +href="{@docRoot}guide/topics/ui/index.html">User Interface</a> documentation.</p> + + + +<h3 id="Declaring">Declaring the activity in the manifest</h3> + +<p>You must declare your activity in the manifest file in order for it to +be accessible to the system. To decalare your activity, open your manifest file and add an <a +href="{@docRoot}guide/topics/manifest/activity-element.html">{@code <activity>}</a> element +as a child of the <a +href="{@docRoot}guide/topics/manifest/application-element.html">{@code <application>}</a> +element. For example:</p> + +<pre> +<manifest ... > + <application ... > + <activity android:name=".ExampleActivity" /> + ... + </application ... > + ... +</manifest > +</pre> + +<p>There are several other attributes that you can include in this element, to define properties +such as the label for the activity, an icon for the activity, or a theme to style the activity's +UI. See the <a +href="{@docRoot}guide/topics/manifest/activity-element.html">{@code <activity>}</a> element +reference for more information about available attributes.</p> + + +<h4>Using intent filters</h4> + +<p>An <a href="{@docRoot}guide/topics/manifest/activity-element.html">{@code +<activity>}</a> element can also specify various intent filters—using the <a +href="{@docRoot}guide/topics/manifest/intent-filter-element.html">{@code +<intent-filter>}</a> element—in order to declare how other application components may +activate it.</p> + +<p>When you create a new application using the Android SDK tools, the stub activity +that's created for you automatically includes an intent filter that declares the activity +responds to the "main" action and should be placed in the "launcher" category. The intent filter +looks like this:</p> + +<pre> +<activity android:name=".ExampleActivity" android:icon="@drawable/app_icon"> + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + <category android:name="android.intent.category.LAUNCHER" /> + </intent-filter> +</activity> +</pre> + +<p>The <a href="{@docRoot}guide/topics/manifest/action-element.html">{@code +<action>}</a> element specifies that this is the "main" entry point to the application. The <a +href="{@docRoot}guide/topics/manifest/category-element.html">{@code +<category>}</a> element specifies that this activity should be listed in the +system's application launcher (to allow users to launch this activity).</p> + +<p>If you intend for your application to be self-contained and not allow other applications to +activate its activities, then you don't need any other intent filters. Only one activity should +have the "main" action and "launcher" category, as in the previous example. Activities that +you don't want to make available to other applications should have no intent filters and you can +start them yourself using explicit intents (as discussed in the following section).</p> + +<p>However, if you want your activity to respond to implicit intents that are delivered from +other applications (and your own), then you must define additional intent filters for your +activity. For each type of intent to which you want to respond, you must include an <a +href="{@docRoot}guide/topics/manifest/intent-filter-element.html">{@code +<intent-filter>}</a> that includes an +<a href="{@docRoot}guide/topics/manifest/action-element.html">{@code +<action>}</a> element and, optionally, a <a +href="{@docRoot}guide/topics/manifest/category-element.html">{@code +<category>}</a> element and/or a <a +href="{@docRoot}guide/topics/manifest/data-element.html">{@code +<data>}</a> element. These elements specify the type of intent to which your activity can +respond.</p> + +<p>For more information about how your activities can respond to intents, see the <a +href="{@docRoot}guide/topics/intents/intents-filters.html">Intents and Intent Filters</a> +document.</p> + + + +<h2 id="StartingAnActivity">Starting an Activity</h2> + +<p>You can start another activity by calling {@link android.app.Activity#startActivity + startActivity()}, passing it an {@link android.content.Intent} that describes the activity you + want to start. The intent specifies either the exact activity you want to start or describes the + type of action you want to perform (and the system selects the appropriate activity for you, +which + can even be from a different application). An intent can also carry small amounts of data to be + used by the activity that is started.</p> + +<p>When working within your own application, you'll often need to simply launch a known activity. + You can do so by creating an intent that explicitly defines the activity you want to start, +using the class name. For example, here's how one activity starts another activity named {@code +SignInActivity}:</p> + +<pre> +Intent intent = new Intent(this, SignInActivity.class); +startActivity(intent); +</pre> + +<p>However, your application might also want to perform some action, such as send an email, text + message, or status update, using data from your activity. In this case, your application might + not have its own activities to perform such actions, so you can instead leverage the activities + provided by other applications on the device, which can perform the actions for you. This is where +intents are really valuable—you can create an intent that describes an action you want to +perform and the system + launches the appropriate activity from another application. If there are + multiple activities that can handle the intent, then the user can select which one to use. For + example, if you want to allow the user to send an email message, you can create the + following intent:</p> + +<pre> +Intent intent = new Intent(Intent.ACTION_SEND); +intent.putExtra(Intent.EXTRA_EMAIL, recipientArray); +startActivity(intent); +</pre> + +<p>The {@link android.content.Intent#EXTRA_EMAIL} extra added to the intent is a string array of + email addresses to which the email should be sent. When an email application responds to this + intent, it reads the string array provided in the extra and places them in the "to" field of the + email composition form. In this situation, the email application's activity starts and when the + user is done, your activity resumes.</p> + + + + +<h3 id="StartingAnActivityForResult">Starting an activity for a result</h3> + +<p>Sometimes, you might want to receive a result from the activity that you start. In that case, + start the activity by calling {@link android.app.Activity#startActivityForResult + startActivityForResult()} (instead of {@link android.app.Activity#startActivity + startActivity()}). To then receive the result from the subsequent +activity, implement the {@link android.app.Activity#onActivityResult onActivityResult()} callback + method. When the subsequent activity is done, it returns a result in an {@link +android.content.Intent} to your {@link android.app.Activity#onActivityResult onActivityResult()} +method.</p> + +<p>For example, perhaps you want the user to pick one of their contacts, so your activity can +do something with the information in that contact. Here's how you can create such an intent and +handle the result:</p> + +<pre> +private void pickContact() { + // Create an intent to "pick" a contact, as defined by the content provider URI + Intent intent = new Intent(Intent.ACTION_PICK, Contacts.CONTENT_URI); + startActivityForResult(intent, PICK_CONTACT_REQUEST); +} + +@Override +protected void onActivityResult(int requestCode, int resultCode, Intent data) { + // If the request went well (OK) and the request was PICK_CONTACT_REQUEST + if (resultCode == Activity.RESULT_OK && requestCode == PICK_CONTACT_REQUEST) { + // Perform a query to the contact's content provider for the contact's name + Cursor cursor = getContentResolver().query(data.getData(), + new String[] {Contacts.DISPLAY_NAME}, null, null, null); + if (cursor.moveToFirst()) { // True if the cursor is not empty + int columnIndex = cursor.getColumnIndex(Contacts.DISPLAY_NAME); + String name = cursor.getString(columnIndex); + // Do something with the selected contact's name... + } + } +} +</pre> + +<p>This example shows the basic logic you should use in your {@link +android.app.Activity#onActivityResult onActivityResult()} method in order to handle an +activity result. The first condition checks whether the request was successful—if it was, then +the {@code resultCode} will be {@link android.app.Activity#RESULT_OK}—and whether the request +to which this result is responding is known—in this case, the {@code requestCode} matches the +second parameter sent with {@link android.app.Activity#startActivityForResult +startActivityForResult()}. From there, the code handles the activity result by querying the +data returned in an {@link android.content.Intent} (the {@code data} parameter).</p> + +<p>What happens is, a {@link +android.content.ContentResolver} performs a query against a content provider, which returns a +{@link android.database.Cursor} that allows the queried data to be read. For more information, see +the <a +href="{@docRoot}guide/topics/providers/content-providers.html">Content Providers</a> document.</p> + +<p>For more information about using intents, see the <a +href="{@docRoot}guide/topics/intents/intents-filters.html">Intents and Intent +Filters</a> document.</p> + + +<h2 id="ShuttingDown">Shutting Down an Activity</h2> + +<p>You can shut down an activity by calling its {@link android.app.Activity#finish +finish()} method. You can also shut down a separate activity that you previously started by calling +{@link android.app.Activity#finishActivity finishActivity()}.</p> + +<p class="note"><strong>Note:</strong> In most cases, you should not explicitly finish an activity +using these methods. As discussed in the following section about the activity lifecycle, the +Android system manages the life of an activity for you, so you do not need to finish your own +activities. Calling these methods could adversely affect the expected user +experience and should only be used when you absolutely do not want the user to return to this +instance of the activity.</p> + + +<h2 id="Lifecycle">Managing the Activity Lifecycle</h2> + +<p>Managing the lifecycle of your activities by implementing callback methods is +crucial to developing a strong +and flexible application. The lifecycle of an activity is directly affected by its association with +other activities, its task and back stack.</p> + +<p>An activity can exist in essentially three states:</p> + +<dl> + <dt><i>Resumed</i></dt> + <dd>The activity is in the foreground of the screen and has user focus. (This state is +also sometimes referred to as "running".)</dd> + + <dt><i>Paused</i></dt> + <dd>Another activity is in the foreground and has focus, but this one is still visible. That is, +another activity is visible on top of this one and that activity is partially transparent or doesn't +cover the entire screen. A paused activity is completely alive (the {@link android.app.Activity} +object is retained in memory, it maintains all state and member information, and remains attached to +the window manager), but can be killed by the system in extremely low memory situations.</dd> + + <dt><i>Stopped</i></dt> + <dd>The activity is completely obscured by another activity (the activity is now in the +"background"). A stopped activity is also still alive (the {@link android.app.Activity} +object is retained in memory, it maintains all state and member information, but is <em>not</em> +attached to the window manager). However, it is no longer visible to the user and it +can be killed by the system when memory is needed elsewhere.</dd> +</dl> + +<p>If an activity is paused or stopped, the system can drop it from memory either by asking it to +finish (calling its {@link android.app.Activity#finish finish()} method), or simply killing its +process. When the activity is opened again (after being finished or killed), it must be created all +over.</p> + + + +<h3 id="ImplementingLifecycleCallbacks">Implementing the lifecycle callbacks</h3> + +<p>When an activity transitions into and out of the different states described above, it is notified +through various callback methods. All of the callback methods are hooks that you +can override to do appropriate work when the state of your activity changes. The following skeleton +activity includes each of the fundamental lifecycle methods:</p> + + +<pre> +public class ExampleActivity extends Activity { + @Override + public void {@link android.app.Activity#onCreate onCreate}(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + // The activity is being created. + } + @Override + protected void {@link android.app.Activity#onStart onStart()} { + super.onStart(); + // The activity is about to become visible. + } + @Override + protected void {@link android.app.Activity#onResume onResume()} { + super.onResume(); + // The activity has become visible (it is now "resumed"). + } + @Override + protected void {@link android.app.Activity#onPause onPause()} { + super.onPause(); + // Another activity is taking focus (this activity is about to be "paused"). + } + @Override + protected void {@link android.app.Activity#onStop onStop()} { + super.onStop(); + // The activity is no longer visible (it is now "stopped") + } + @Override + protected void {@link android.app.Activity#onDestroy onDestroy()} { + super.onDestroy(); + // The activity is about to be destroyed. + } +} +</pre> + +<p class="note"><strong>Note:</strong> Your implementation of these lifecycle methods must +always call the superclass implementation before doing any work, as shown in the examples above.</p> + +<p>Taken together, these methods define the entire lifecycle of an activity. By implementing these +methods, you can monitor three nested loops in the activity lifecycle: </p> + +<ul> +<li>The <b>entire lifetime</b> of an activity happens between the call to {@link +android.app.Activity#onCreate onCreate()} and the call to {@link +android.app.Activity#onDestroy}. Your activity should perform setup of +"global" state (such as defining layout) in {@link android.app.Activity#onCreate onCreate()}, and +release all remaining resources in {@link android.app.Activity#onDestroy}. For example, if your +activity has a thread running in the background to download data from the network, it might create +that thread in {@link android.app.Activity#onCreate onCreate()} and then stop the thread in {@link +android.app.Activity#onDestroy}.</li> + +<li><p>The <b>visible lifetime</b> of an activity happens between the call to {@link +android.app.Activity#onStart onStart()} and the call to {@link +android.app.Activity#onStop onStop()}. During this time, the user can see the activity +on-screen and interact with it. For example, {@link android.app.Activity#onStop onStop()} is called +when a new activity starts and this one is no longer visible. Between these two methods, you can +maintain resources that are needed to show the activity to the user. For example, you can register a +{@link android.content.BroadcastReceiver} in {@link +android.app.Activity#onStart onStart()} to monitor changes that impact your UI, and unregister +it in {@link android.app.Activity#onStop onStop()} when the user can no longer see what you are +displaying. The system might call {@link android.app.Activity#onStart onStart()} and {@link +android.app.Activity#onStop onStop()} multiple times during the entire lifetime of the activity, as +the activity alternates between being visible and hidden to the user.</p></li> + +<li><p>The <b>foreground lifetime</b> of an activity happens between the call to {@link +android.app.Activity#onResume onResume()} and the call to {@link android.app.Activity#onPause +onPause()}. During this time, the activity is in front of all other activities on screen and has +user input focus. An activity can frequently transition in and out of the foreground—for +example, {@link android.app.Activity#onPause onPause()} is called when the device goes to sleep or +when a dialog appears. Because this state can transition often, the code in these two methods should +be fairly lightweight in order to avoid slow transitions that make the user wait.</p></li> +</ul> + +<p>Figure 1 illustrates these loops and the paths an activity might take between states. +The rectangles represent the callback methods you can implement to perform operations when +the activity transitions between states. <p> + +<img src="{@docRoot}images/activity_lifecycle.png" alt="" /> +<p class="img-caption"><strong>Figure 1.</strong> The activity lifecycle.</p> + +<p>The same lifecycle callback methods are listed in table 1, which describes each of the callback +methods in more detail and locates each one within the +activity's overall lifecycle, including whether the system can kill the activity after the +callback method completes.</p> + +<p class="table-caption"><strong>Table 1.</strong> A summary of the activity lifecycle's +callback methods.</p> + +<table border="2" width="85%" frame="hsides" rules="rows"> +<colgroup align="left" span="3"></colgroup> +<colgroup align="left"></colgroup> +<colgroup align="center"></colgroup> +<colgroup align="center"></colgroup> + +<thead> +<tr><th colspan="3">Method</th> <th>Description</th> <th>Killable after?</th> <th>Next</th></tr> +</thead> + +<tbody> +<tr> + <td colspan="3" align="left"><code>{@link android.app.Activity#onCreate onCreate()}</code></td> + <td>Called when the activity is first created. + This is where you should do all of your normal static set up — + create views, bind data to lists, and so on. This method is passed + a Bundle object containing the activity's previous state, if that + state was captured (see <a href="#actstate">Saving Activity State</a>, + later). + <p>Always followed by {@code onStart()}.</p></td> + <td align="center">No</td> + <td align="center">{@code onStart()}</td> +</tr> + +<tr> + <td rowspan="5" style="border-left: none; border-right: none;"> </td> + <td colspan="2" align="left"><code>{@link android.app.Activity#onRestart +onRestart()}</code></td> + <td>Called after the activity has been stopped, just prior to it being + started again. + <p>Always followed by {@code onStart()}</p></td> + <td align="center">No</td> + <td align="center">{@code onStart()}</td> +</tr> + +<tr> + <td colspan="2" align="left"><code>{@link android.app.Activity#onStart onStart()}</code></td> + <td>Called just before the activity becomes visible to the user. + <p>Followed by {@code onResume()} if the activity comes + to the foreground, or {@code onStop()} if it becomes hidden.</p></td> + <td align="center">No</td> + <td align="center">{@code onResume()} <br/>or<br/> {@code onStop()}</td> +</tr> + +<tr> + <td rowspan="2" style="border-left: none;"> </td> + <td align="left"><code>{@link android.app.Activity#onResume onResume()}</code></td> + <td>Called just before the activity starts + interacting with the user. At this point the activity is at + the top of the activity stack, with user input going to it. + <p>Always followed by {@code onPause()}.</p></td> + <td align="center">No</td> + <td align="center">{@code onPause()}</td> +</tr> + +<tr> + <td align="left"><code>{@link android.app.Activity#onPause onPause()}</code></td> + <td>Called when the system is about to start resuming another + activity. This method is typically used to commit unsaved changes to + persistent data, stop animations and other things that may be consuming + CPU, and so on. It should do whatever it does very quickly, because + the next activity will not be resumed until it returns. + <p>Followed either by {@code onResume()} if the activity + returns back to the front, or by {@code onStop()} if it becomes + invisible to the user.</td> + <td align="center"><strong style="color:#800000">Yes</strong></td> + <td align="center">{@code onResume()} <br/>or<br/> {@code onStop()}</td> +</tr> + +<tr> + <td colspan="2" align="left"><code>{@link android.app.Activity#onStop onStop()}</code></td> + <td>Called when the activity is no longer visible to the user. This + may happen because it is being destroyed, or because another activity + (either an existing one or a new one) has been resumed and is covering it. + <p>Followed either by {@code onRestart()} if + the activity is coming back to interact with the user, or by + {@code onDestroy()} if this activity is going away.</p></td> + <td align="center"><strong style="color:#800000">Yes</strong></td> + <td align="center">{@code onRestart()} <br/>or<br/> {@code onDestroy()}</td> +</tr> + +<tr> + <td colspan="3" align="left"><code>{@link android.app.Activity#onDestroy +onDestroy()}</code></td> + <td>Called before the activity is destroyed. This is the final call + that the activity will receive. It could be called either because the + activity is finishing (someone called <code>{@link android.app.Activity#finish + finish()}</code> on it), or because the system is temporarily destroying this + instance of the activity to save space. You can distinguish + between these two scenarios with the <code>{@link + android.app.Activity#isFinishing isFinishing()}</code> method.</td> + <td align="center"><strong style="color:#800000">Yes</strong></td> + <td align="center"><em>nothing</em></td> +</tr> +</tbody> +</table> + +<p>The column labeled "Killable after?" indicates whether or not the system can +kill the process hosting the activity at any time <em>after the method returns</em>, without +executing another line of the activity's code. Three methods are marked "yes": ({@link +android.app.Activity#onPause +onPause()}, {@link android.app.Activity#onStop onStop()}, and {@link android.app.Activity#onDestroy +onDestroy()}). Because {@link android.app.Activity#onPause onPause()} is the first +of the three, once the activity is created, {@link android.app.Activity#onPause onPause()} is the +last method that's guaranteed to be called before the process <em>can</em> be killed—if +the system must recover memory in an emergency, then {@link +android.app.Activity#onStop onStop()} and {@link android.app.Activity#onDestroy onDestroy()} might +not be called. Therefore, you should use {@link android.app.Activity#onPause onPause()} to write +crucial persistent data (such as user edits) to storage. However, you should be selective about +what information must be retained during {@link android.app.Activity#onPause onPause()}, because any +blocking procedures in this method block the transition to the next activity and slow the user +experience.</p> + +<p> Methods that are marked "No" in the <b>Killable</b> column protect the process hosting the +activity from being killed from the moment they are called. Thus, an activity is killable +from the time {@link android.app.Activity#onPause onPause()} returns to the time +{@link android.app.Activity#onResume onResume()} is called. It will not again be killable until +{@link android.app.Activity#onPause onPause()} is again called and returns. </p> + +<p class="note"><strong>Note:</strong> An activity that's not technically "killable" by this +definition in table 1 might still be killed by the system—but that would happen only in +extreme circumstances when there is no other recourse. When an activity might be killed is +discussed more in the <a +href="{@docRoot}guide/topics/fundamentals/processes-and-threading.html">Processes and +Threading</a> document.</p> + + +<h3 id="SavingActivityState">Saving activity state</h3> + +<p>The introduction to <a href="Lifecycle">Managing the Activity Lifecycle</a> briefly mentions that +when an activity is paused or stopped, the state of the activity is retained. This is true because +the {@link android.app.Activity} object is still held in memory when it is paused or +stopped—all information about its members and current state is still alive. Thus, any changes +the user made within the activity are retained in memory, so that when the activity returns to the +foreground (when it "resumes"), those changes are still there.</p> + +<div class="figure" style="width:615px"> +<img src="{@docRoot}images/fundamentals/restore_instance.png" alt="" /> +<p class="img-caption"><strong>Figure 2.</strong> The two ways in which an activity returns to user +focus with its state intact: either the activity is stopped, then resumed and the activity state +remains intact (left), or the activity is destroyed, then recreated and the activity must restore +the previous activity state (right).</p> +</div> + +<p>However, when the system destroys an activity in order to recover memory, the {@link +android.app.Activity} object is destroyed, so the system cannot simply resume it with its state +intact. Instead, the system must recreate the {@link android.app.Activity} object if the user +navigates back to it. Yet, the user is unaware +that the system destroyed the activity and recreated it and, thus, probably +expects the activity to be exactly as it was. In this situation, you can ensure that +important information about the activity state is preserved by implementing an additional +callback method that allows you to save information about the state of your activity and then +restore it when the the system recreates the activity.</p> + +<p>The callback method in which you can save information about the current state of your activity is +{@link android.app.Activity#onSaveInstanceState onSaveInstanceState()}. The system calls this method +before making the activity vulnerable to being destroyed and passes it +a {@link android.os.Bundle} object. The {@link android.os.Bundle} is where you can store +state information about the activity as name-value pairs, using methods such as {@link +android.os.Bundle#putString putString()}. Then, if the system kills your activity's +process and the user navigates back to your activity, the system passes the {@link +android.os.Bundle} to {@link android.app.Activity#onCreate onCreate()} so you can restore the +activity state you saved during {@link android.app.Activity#onSaveInstanceState +onSaveInstanceState()}. If there is no state information to restore, then the {@link +android.os.Bundle} passed to {@link android.app.Activity#onCreate onCreate()} is null.</p> + +<p class="note"><strong>Note:</strong> There's no guarantee that {@link +android.app.Activity#onSaveInstanceState onSaveInstanceState()} will be called before your +activity is destroyed, because there are cases in which it won't be necessary to save the state +(such as when the user leaves your activity using the BACK key, because the user is explicitly +closing the activity). If the method is called, it is always called before {@link +android.app.Activity#onStop onStop()} and possibly before {@link android.app.Activity#onPause +onPause()}.</p> + +<p>However, even if you do nothing and do not implement {@link +android.app.Activity#onSaveInstanceState onSaveInstanceState()}, some of the activity state is +restored by the {@link android.app.Activity} class's default implementation of {@link +android.app.Activity#onSaveInstanceState onSaveInstanceState()}. Specifically, the default +implementation calls {@link +android.view.View#onSaveInstanceState onSaveInstanceState()} for every {@link android.view.View} +in the layout, which allows each view to provide information about itself +that should be saved. Almost every widget in the Android framework implements this method as +appropriate, such that any visible changes to the UI are automatically saved and restored when your +activity is recreated. For example, the {@link android.widget.EditText} widget saves any text +entered by the user and the {@link android.widget.CheckBox} widget saves whether it's checked or +not. The only work required by you is to provide a unique ID (with the <a +href="{@docRoot}guide/topics/resources/layout-resource.html#idvalue">{@code android:id}</a> +attribute) for each widget you want to save its state. If a widget does not have an ID, then it +cannot save its state.</p> + +<div class="sidebox-wrapper"> +<div class="sidebox"> +<p>You can also explicitly stop a view in your layout from saving its state by setting the +{@link android.R.attr#saveEnabled android:saveEnabled} attribute to {@code "false"} or by calling +the {@link android.view.View#setSaveEnabled setSaveEnabled()} method. Usually, you should not +disable this, but you might if you want to restore the state of the activity UI differently.</p> +</div> +</div> + +<p>Although the default implementation of {@link +android.app.Activity#onSaveInstanceState onSaveInstanceState()} saves useful information about +your activity's UI, you still might need to override it to save additional information. +For example, you might need to save member values that changed during the activity's life (which +might correlate to values restored in the UI, but the members that hold those UI values are not +restored, by default).</p> + +<p>Because the default implementation of {@link +android.app.Activity#onSaveInstanceState onSaveInstanceState()} helps save the state of the UI, if +you override the method in order to save additional state information, you should always call the +superclass implementation of {@link android.app.Activity#onSaveInstanceState onSaveInstanceState()} +before doing any work.</p> + +<p class="note"><strong>Note:</strong> Because {@link android.app.Activity#onSaveInstanceState +onSaveInstanceState()} is not guaranteed +to be called, you should use it only to record the transient state of the activity (the state of +the UI)—you should never use it to store persistent data. Instead, you should use {@link +android.app.Activity#onPause onPause()} to store persistent data (such as data that should be saved +to a database) when the user leaves the activity.</p> + +<p>A good way to test your application's ability to restore its state is to simply rotate the +device so that the screen orientation changes. When the screen orientation changes, the system +destroys and recreates the activity in order to apply alternative resources that might be available +for the new orientation. For this reason alone, it's very important that your activity +completely restores its state when it is recreated, because users regularly rotate the screen while +using applications.</p> + + +<h3 id="ConfigurationChanges">Handling configuration changes</h3> + +<p>Some device configurations can change during runtime (such as screen orientation, keyboard +availability, and language). When such a change occurs, Android restarts the running Activity +({@link android.app.Activity#onDestroy} is called, followed immediately by {@link +android.app.Activity#onCreate onCreate()}). The restart behavior is +designed to help your application adapt to new configurations by automatically reloading your +application with alternative resources that you've provided. If you design your activity to +properly handle this event, it will be more resilient to unexpected events in the activity +lifecycle.</p> + +<p>The best way to handle a configuration change, such as a change in the screen orientation, is + to simply preserve the state of your application using {@link + android.app.Activity#onSaveInstanceState onSaveInstanceState()} and {@link +android.app.Activity#onRestoreInstanceState onRestoreInstanceState()} (or {@link +android.app.Activity#onCreate onCreate()}), as discussed in the previous section.</p> + +<p>For a detailed discussion about configuration changes that happen at runtime and how you should +handle them, read <a href="{@docRoot}guide/topics/resources/runtime-changes.html">Handling +Runtime Changes</a>.</p> + + + +<h3 id="CoordinatingActivities">Coordinating activities</h3> + + <p>When one activity starts another, they both experience lifecycle transitions. The first activity +pauses and stops (though, it won't stop if it's still visible in the background), while the other +activity is created. In case these activities share data saved to disc or elsewhere, it's important +to understand that the first activity is not completely stopped before the second one is created. +Rather, the process of starting the second one overlaps with the process of stopping the first +one.</p> + +<p>The order of lifecycle callbacks is well defined, particularly when the two activities are in the +same process and one is starting the other. Here's the order of operations that occur when Activity +A starts Acivity B: </p> + +<ol> +<li>Activity A's {@link android.app.Activity#onPause onPause()} method executes.</li> + +<li>Activity B's {@link android.app.Activity#onCreate onCreate()}, {@link +android.app.Activity#onStart onStart()}, and {@link android.app.Activity#onResume onResume()} +methods execute in sequence. (Activity B now has user focus.)</li> + +<li>Then, if Activity A is no longer visible on screen, its {@link +android.app.Activity#onStop onStop()} method executes.</li> +</ol> + + <p>This predictable sequence of lifecycle callbacks allows you to manage the transition of +information from one activity to another. For example, if you must write to a database when the +first activity stops so that the following activity can read it, then you should write to the +database during {@link android.app.Activity#onPause onPause()} instead of during {@link +android.app.Activity#onStop onStop()}.</p> + + +<h2>Beginner's Path</h2> + +<p>For more information about how Android maintains a history of activities and +enables user multitasking, continue with the <b><a +href="{@docRoot}guide/topics/fundamentals/tasks-and-back-stack.html">Tasks and Back +Stack</a></b> document.</p> diff --git a/docs/html/guide/topics/fundamentals/tasks-and-back-stack.jd b/docs/html/guide/topics/fundamentals/tasks-and-back-stack.jd new file mode 100644 index 0000000..47dc547 --- /dev/null +++ b/docs/html/guide/topics/fundamentals/tasks-and-back-stack.jd @@ -0,0 +1,568 @@ +page.title=Tasks and Back Stack +parent.title=Application Fundamentals +parent.link=index.html +@jd:body + +<div id="qv-wrapper"> +<div id="qv"> +<h2>Quickview</h2> +<ul> + <li>All activities belong to a task</li> + <li>A task contains a collection of activities in the order in which the user interacts with +them</li> + <li>Tasks can move to the background and retain the state of each activity in order for the user +to perform other tasks without loosing their work</li> +</ul> + +<h2>In this document</h2> +<ol> +<li><a href="#ActivityState">Saving Activity State</a></li></li> +<li><a href="#ManagingTasks">Managing Tasks</a> + <ol> + <li><a href="#TaskLaunchModes">Defining launch modes</a></li> + <li><a href="#Affinities">Handling affinities</a></li> + <li><a href="#Clearing">Clearing the back stack</a></li> + <li><a href="#Starting">Starting a task</a></li> + </ol> +</li> +</ol> + +<h2>See also</h2> +<ol> + <li><a><a href="{@docRoot}videos/index.html#v=fL6gSd4ugSI">Application Lifecycle video</a></li> + <li><a +href="{@docRoot}guide/topics/manifest/activity-element.html">{@code <activity>} manifest +element</a></li> +</ol> +</div> +</div> + + +<p>An application usually contains multiple <a +href="{@docRoot}guide/topics/fundamentals/activities.html">activities</a>. Each activity +should be designed around a specific kind of action the user can perform and can start other +activities. For example, an email application might have one activity to show a list of new email. +When the user selects an email, a new activity opens to view that email.</p> + +<p>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 <em>task</em>.</p> + +<p>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.</p> + +<!-- SAVE FOR WHEN THE FRAGMENT DOC IS ADDED +<div class="sidebox-wrapper"> +<div class="sidebox"> +<h3>Adding fragments to a task's back stack</h3> + +<p>Your activity can also include {@link android.app.Fragment}s to the back stack. For example, +suppose you have a two-pane layout using fragments, one of which is a list view (fragment A) and the +other being a layout to display an item from the list (fragment B). When the user selects an item +from the list, fragment B is replaced by a new fragment (fragment C). In this case, it might be +desireable for the user to navigate back to reveal fragment B, using the BACK key.</p> +<p>In order to add fragment B to the back stack so that this is possible, you must call {@link +android.app.FragmentTransaction#addToBackStack addToBackStack()} before you {@link +android.app.FragmentTransaction#commit()} the transaction that replaces fragment B with fragment +C.</p> +<p>For more information about using fragments and adding them to the back stack, see the {@link +android.app.Fragment} class documentation.</p> + +</div> +</div> +--> + +<p>The device Home screen is the starting place for most tasks. When the user touches an icon in the +application +launcher (or a shortcut on the Home screen), that application's task comes to the foreground. If no +task exists for the application (the application has not been used recently), then a new task +is created and the "main" activity for that application opens as the root activity in the stack.</p> + +<p>When the current activity starts another, the new activity is pushed on the top of the stack and +takes focus. The previous activity remains in the stack, but is stopped. When an activity +stops, the system retains the current state of its user interface. When the user presses the BACK +key, the current activity is popped from the top of the stack (the activity is destroyed) and the +previous activity resumes (the previous state of its UI is restored). Activities in the stack are +never rearranged, only pushed and popped from the stack—pushed onto the stack when started by +the current activity and popped off when the user leaves it using the BACK key. As such, the back +stack operates as a "last in, first out" object structure. Figure 1 visualizes +this behavior with a timeline showing the progress between activities along with the current back +stack at each point in time.</p> + +<img src="{@docRoot}images/fundamentals/diagram_backstack.png" alt="" /> +<p class="img-caption"><strong>Figure 1.</strong> A representation of how each new activity in a +task adds an item to the back stack. When the user presses the BACK key, the current activity is +destroyed and the previous activity resumes.</p> + + +<p>If the user continues to press BACK, then each activity in the stack is popped off to reveal the +previous one, until the user returns to the Home screen (or to whichever activity was running when +the task began). When all activities are removed from the stack, the task no longer exists.</p> + +<div class="figure" style="width:369px"> +<img src="{@docRoot}images/fundamentals/diagram_multitasking.png" alt="" /> <p +class="img-caption"><strong>Figure 2.</strong> Two tasks: Task A is in the background, waiting +to be resumed, while Task B receives user interaction in the foreground.</p> +</div> +<div class="figure" style="width:178px"> + <img src="{@docRoot}images/fundamentals/diagram_multiple_instances.png" alt="" /> <p +class="img-caption"><strong>Figure 3.</strong> A single activity is instantiated multiple times.</p> +</div> + +<p>A task is a cohesive unit that can move to the "background" when users begin a new task or go +to the Home screen, via the HOME key. While in the background, all the activities in the task are +stopped, but the back stack for the task remains intact—the task has simply lost focus while +another task takes place, as shown in figure 2. A task can then return to the "foreground" so users +can pick up where they left off. Suppose, for example, that the current task (Task A) has three +activities in its stack—two under the current activity. The user presses the HOME key, then +starts a new application from the application launcher. When the Home screen appears, Task A goes +into the background. When the new application starts, the system starts a task for that application +(Task B) with its own stack of activities. After interacting with +that application, the user returns Home again and selects the application that originally +started Task A. Now, Task A comes to the +foreground—all three activities in its stack are intact and the activity at the top of the +stack resumes. At +this point, the user can also switch back to Task B by going Home and selecting the application icon +that started that task (or by touching and holding the HOME key to reveal recent tasks and selecting +one). This is an example of multitasking on Android.</p> + +<p class="note"><strong>Note:</strong> Multiple tasks can be held in the background at once. +However, if the user is running many background tasks at the same time, the system might begin +destroying background activities in order to recover memory, causing the activity states to be lost. +See the following section about <a href="#ActivityState">Activity state</a>.</p> + +<p>Because the activities in the back stack are never rearranged, if your application allows +users to start a particular activity from more than one activity, a new instance of +that activity is created and popped onto the stack (rather than bringing any previous instance of +the activity to the top). As such, one activity in your application might be instantiated multiple +times (even from different tasks), as shown in figure 3. As such, if the user navigates backward +using the BACK key, each instance of the activity is revealed in the order they were opened (each +with their own UI state). However, you can modify this behavior if you do not want an activity to be +instantiated more than once. How to do so is discussed in the later section about <a +href="#ManagingTasks">Managing Tasks</a>.</p> + + +<p>To summarize the default behavior for activities and tasks:</p> + +<ul> + <li>When Activity A starts Activity B, Activity A is stopped, but the system retains its state +(such as scroll position and text entered into forms). +If the user presses the BACK key while in Activity B, Activity A resumes with its state +restored.</li> + <li>When the user leaves a task by pressing the HOME key, the current activity is stopped and +its task goes into the background. The system retains the state of every activity in the task. If +the user later resumes the task by selecting the launcher icon that began the task, the task comes +to the foreground and resumes the activity at the top of the stack.</li> + <li>If the user presses the BACK key, the current activity is popped from the stack and +destroyed. The previous activity in the stack is resumed. When an activity is destroyed, the system +<em>does not</em> retain the activity's state.</li> + <li>Activities can be instantiated multiple times, even from other tasks.</li> +</ul> + + +<h2 id="ActivityState">Saving Activity State</h2> + +<p>As discussed above, the system's default behavior preserves the state of an activity when it is +stopped. This way, when users navigate back to a previous activity, its user interface appears +the way they left it. However, you can—and <strong>should</strong>—proactively retain +the state of your activities using callback methods, in case the activity is destroyed and must +be recreated.</p> + +<p>When the system stops one of your activities (such as when a new activity starts or the task +moves to the background), the system might destroy that activity completely if it needs to recover +system memory. When this happens, information about the activity state is lost. If this happens, the +system still +knows that the activity has a place in the back stack, but when the activity is brought to the +top of the stack the system must recreate it (rather than resume it). In order to +avoid loosing the user's work, you should proactively retain it by implementing the {@link +android.app.Activity#onSaveInstanceState onSaveInstanceState()} callback +methods in your activity.</p> + +<p>For more information about how to save your activity state, see the <a +href="{@docRoot}guide/topics/fundamentals/activities.html#SavingActivityState">Activities</a> +document.</p> + + + +<h2 id="ManagingTasks">Managing Tasks</h2> + +<p>The way Android manages tasks and the back stack, as described above—by placing all +activities started in succession in the same task and in a "last in, first out" stack—works +great for most applications and you shouldn't have to worry about how your activities are associated +with tasks or how they exist in the back stack. However, you might decide that you want to interrupt +the normal behavior. Perhaps you want an activity in your application to begin a new task when it is +started (instead of being placed within the current task); or, when you start an activity, you want +to bring forward an existing instance of it (instead of creating a new +instance on top of the back stack); or, you want your back stack to be cleared of all +activitiesstart an activity except for the root activity when the user leaves the task.</p> + +<p>You can do these things and more, with attributes in the +<a href="{@docRoot}guide/topics/manifest/activity-element.html">{@code +<activity>}</a> manifest element and with flags in the intent that you pass to {@link +android.app.Activity#startActivity startActivity()}.</p> + +<p>In this regard, the the principal <a +href="{@docRoot}guide/topics/manifest/activity-element.html">{@code <activity>}</a> +attributes you can use are:</p> + +<ul class="nolist"> + <li><a href="{@docRoot}guide/topics/manifest/activity-element.html#aff">{@code +taskAffinity}</a></li> + <li><a href="{@docRoot}guide/topics/manifest/activity-element.html#lmode">{@code +launchMode}</a></li> + <li><a href="{@docRoot}guide/topics/manifest/activity-element.html#reparent">{@code +allowTaskReparenting}</a></li> + <li><a href="{@docRoot}guide/topics/manifest/activity-element.html#clear">{@code +clearTaskOnLaunch}</a></li> + <li><a href="{@docRoot}guide/topics/manifest/activity-element.html#always">{@code +alwaysRetainTaskState}</a></li> + <li><a href="{@docRoot}guide/topics/manifest/activity-element.html#finish">{@code +finishOnTaskLaunch}</a></li> +</ul> + +<p>And the principal intent flags you can use are:</p> + +<ul class="nolist"> + <li>{@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK}</li> + <li>{@link android.content.Intent#FLAG_ACTIVITY_CLEAR_TOP}</li> + <li>{@link android.content.Intent#FLAG_ACTIVITY_SINGLE_TOP}</li> +</ul> + +<p>In the following sections, you'll see how you can use these manifest attributes and intent +flags to define how activities are associated with tasks and how the behave in the back stack.</p> + + +<p class="caution"><strong>Caution:</strong> Most applications should not interrupt the default +behavior for activities and tasks. If you determine that it's necessary for your activity to modify +the default behaviors, use caution and be sure to test the usability of the activity during +launch and when navigating back to it from other activities and tasks with the BACK key. Be sure +to test for navigation behaviors that might conflict with the user's expected behavior.</p> + + +<h3 id="TaskLaunchModes">Defining launch modes</h3> + +<p>Launch modes allow you to define how a new instance of an activity is associated with the +current task. You can define different launch modes in two ways:</p> +<ul class="nolist"> + <li><a href="#ManifestForTasks">Using the manifest file</a> + <p>When you declare an activity in your manifest file, you can specify how the activity +should associate with tasks when it starts.</li> + <li><a href="#IntentFlagsForTasks">Using Intent flags</a> + <p>When you call {@link android.app.Activity#startActivity startActivity()}, +you can include a flag in the {@link android.content.Intent} that declares how (or +whether) the new activity should associate with the current task.</p></li> +</ul> + +<p>As such, if Activity A starts Activity B, Activity B can define in its manifest how it +should associate with the current task (if at all) and Activity A can also request how Activity +B should associate with current task. If both activities define how Activity B +should associate with a task, then Activity A's request (as defined in the intent) is honored +over Activity B's request (as defined in its manifest).</p> + +<p class="note"><strong>Note:</strong> Some the launch modes available in the manifest +are not available as flags for an intent and, likewise, some launch modes available as flags +for an intent cannot be defined in the manifest.</p> + + +<h4 id="ManifestForTasks">Using the manifest file</h4> + +<p>When declaring an activity in your manifest file, you can specify how the activity should +associate with a task using the <a +href="{@docRoot}guide/topics/manifest/activity-element.html">{@code <activity>}</a> +element's <a href="{@docRoot}guide/topics/manifest/activity-element.html#lmode">{@code +launchMode}</a> attribute.</p> + +<p>The <a href="{@docRoot}guide/topics/manifest/activity-element.html#lmode">{@code +launchMode}</a> attribute specifies an instruction on how the activity should be launched into a +task. There are four different launch modes you can assign to the +<code><a href="{@docRoot}guide/topics/manifest/activity-element.html#lmode">launchMode</a></code> +attribute:</p> + +<dl> +<dt>{@code "standard"} (the default mode)</dt> + <dd>Default. The system creates a new instance of the activity in the task from +which it was started and routes the intent to it. The activity can be instantiated multiple times, +each instance can belong to different tasks, and one task can have multiple instances.</dd> +<dt>{@code "singleTop"}</dt> + <dd>If an instance of the activity already exists at the top of the current task, the system +routes the intent to that instance through a call to its {@link +android.app.Activity#onNewIntent onNewIntent()} method, rather than creating a new instance of the +activity. The activity can be instantiated multiple times, each instance can +belong to different tasks, and one task can have multiple instances (but only if the the +activity at the top of the back stack is <em>not</em> an existing instance of the activity). + <p>For example, suppose a task's back stack consists of root activity A with activities B, C, +and D on top (the stack is A-B-C-D; D is on top). An intent arrives for an activity of type D. +If D has the default {@code "standard"} launch mode, a new instance of the class is launched and the +stack becomes A-B-C-D-D. However, if D's launch mode is {@code "singleTop"}, the existing instance +of D is deliverd the intent through {@link +android.app.Activity#onNewIntent onNewIntent()}, because it's at the top of the stack—the +stack remains A-B-C-D. However, if an intent arrives for an activity of type B, then a new +instance of B is added to the stack, even if its launch mode is {@code "singleTop"}.</p> + <p class="note"><strong>Note:</strong> When a new instance of an activity is created, +the user can press the BACK key to return to the previous activity. But when an existing instance of +an activity handles a new intent, the user cannot press the BACK key to return to the state of +the activity before the new intent arrived in {@link android.app.Activity#onNewIntent +onNewIntent()}.</p> +</dd> + +<dt>{@code "singleTask"}</dt> + <dd>The system creates a new task and instantiates the activity at the root of the new task. +However, if an instance of the activity already exists in a separate task, the system routes the +intent to the existing instance through a call to its {@link +android.app.Activity#onNewIntent onNewIntent()} method, rather than creating a new instance. Only +one instance of the activity can exist at a time. + <p class="note"><strong>Note:</strong> Although the activity starts in a new task, the +BACK key still returns the user to the previous activity.</p></dd> +<dt>{@code "singleInstance"}.</dt> + <dd>Same as {@code "singleTask"}, except that the system doesn't launch any other activities into +the task holding the instance. The activity is always the single and only member of its task; +any activities started by this one open in a separate task.</dd> +</dl> + + +<p>As another example, the Android Browser application declares that the web browser activity should +always open in its own task—by specifying the {@code singleTask} launch mode in the <a +href="{@docRoot}guide/topics/manifest/activity-element.html">{@code <activity>}</a> element. +This means that if your application issues an +intent to open the Android Browser, its activity is <em>not</em> placed in the same +task as your application. Instead, either a new task starts for the Browser or, if the Browser +already has a task running in the background, that task is brought forward to handle the new +intent.</p> + +<p>Regardless of whether an activity starts in a new task or in the same task as the activity that +started it, the BACK key always takes the user to the previous activity. However, if you +start an activity from your task (Task A) that specifies the {@code singleTask} launch mode, then +that activity might have an instance in the background that belongs to a task with its own back +stack (Task B). In this +case, when Task B is brought forward to handle a new intent, the BACK key first navigates +backward through the activities in Task B before returning to +the top-most activity in Task A. Figure 4 visualizes this type of scenario.</p> + +<img src="{@docRoot}images/fundamentals/diagram_backstack_singletask_multiactivity.png" alt="" /> +<p class="img-caption"><strong>Figure 4.</strong> A representation of how an activity with +launch mode "singleTask" is added to the back stack. If the activity is already a part of a +background task with its own back stack (Task B), then the entire back stack also comes +forward, on top of the current task (Task A).</p> + +<p>For more information about using launch modes in the manifest file, see the +<code><a href="{@docRoot}guide/topics/manifest/activity-element.html"><activity></a></code> +element documentation, where the {@code launchMode} attribute and the accepted values are +discussed more.</p> + +<p class="note"><strong>Note:</strong> The behaviors that you specify for your activity with the <a +href="{@docRoot}guide/topics/manifest/activity-element.html#lmode">{@code launchMode}</a> attribute +can be overriden by flags included with the intent that start your activity, as discussed in the +next section.</p> + + + +<h4 id="#IntentFlagsForTasks">Using Intent flags</h4> + +<p>When starting an activity, you can modify the default association of an activity to its task +by including flags in the intent that you deliver to {@link +android.app.Activity#startActivity startActivity()}. The flags you can use to modify the +default behavior are:</p> + +<p> + <dt>{@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK}</dt> + <dd>Start the activity in a new task. If a task is already running for the activity you are now +starting, that task is brought to the foreground with its last state restored and the activity +receives the new intent in {@link android.app.Activity#onNewIntent onNewIntent()}. + <p>This produces the same behavior as the {@code "singleTask"} <a +href="{@docRoot}guide/topics/manifest/activity-element.html#lmode">{@code launchMode}</a> value, +discussed in the previous section.</p></dd> + <dt>{@link android.content.Intent#FLAG_ACTIVITY_SINGLE_TOP}</dt> + <dd>If the activity being started is the current activity (at the top of the back stack), then +the existing instance receives a call to {@link android.app.Activity#onNewIntent onNewIntent()}, +instead of creating a new instance of the activity. + <p>This produces the same behavior as the {@code "singleTop"} <a +href="{@docRoot}guide/topics/manifest/activity-element.html#lmode">{@code launchMode}</a> value, +discussed in the previous section.</p></dd> + <dt>{@link android.content.Intent#FLAG_ACTIVITY_CLEAR_TOP}</dt> + <dd>If the activity being started is already running in the current task, then instead +of launching a new instance of that activity, all of the other activities on top of it are +destroyed and this intent is delivered to the resumed instance of the activity (now on top), +through {@link android.app.Activity#onNewIntent onNewIntent()}). + <p>There is no value for the <a +href="{@docRoot}guide/topics/manifest/activity-element.html#lmode">{@code launchMode}</a> +attribute that produces this behavior.</p> + <p>{@code FLAG_ACTIVITY_CLEAR_TOP} is most often used in conjunction with {@code +FLAG_ACTIVITY_NEW_TASK}. When used together, these flags are a way of locating an existing activity +in another task and putting it in a position where it can respond to the intent. </p> + <p class="note"><strong>Note:</strong> If the launch mode of the designated activity is {@code +"standard"}, it too is removed from the stack and a new instance is launched in its place to handle +the incoming intent. That's because a new instance is always created for a new intent when the +launch mode is {@code "standard"}. </p> +</dd> +</dl> + + + + + +<h3 id="Affinities">Handling affinities</h3> + +<p>The <em>affinity</em> indicates which task an activity prefers to belong to. By default, all the +activities from the same application have an affinity for each other. So, by default, all +activities in the same application prefer to be in the same task. However, you can modify +the default affinity for an activity. Activities defined in +different applications can share an affinity, or activities defined in the same application can be +assigned different task affinities.</p> + +<p>You can modify the affinity for any given activity with the <a +href="{@docRoot}guide/topics/manifest/activity-element.html#aff">{@code taskAffinity}</a> attribute +of the <a href="{@docRoot}guide/topics/manifest/activity-element.html">{@code <activity>}</a> +element.</p> + +<p>The <a +href="{@docRoot}guide/topics/manifest/activity-element.html#aff">{@code taskAffinity}</a> +attribute takes a string value, which must be unique from the default package name +declared in the <a href="{@docRoot}guide/topics/manifest/manifest-element.html">{@code +<manifest>}</a> element, because the system uses that name to identify the default task +affinity for the application.</p> + +<p>The affinity comes into play in two circumstances:</p> +<ul> + <li>When the intent that launches an activity contains the {@link +android.content.Intent#FLAG_ACTIVITY_NEW_TASK} flag. + +<p>A new activity is, by default, launched into the task of the activity +that called {@link android.app.Activity#startActivity startActivity()}. It's pushed onto the same +back stack as the caller. However, if the intent passed to {@link +android.app.Activity#startActivity startActivity()} contains the {@link +android.content.Intent#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.</p> + +<p>If this flag causes an activity to begin a new task and the user presses the HOME key to leave +it, there must be some way for the user to navigate back to the task. Some entities (such as the +notification manager) always start activities in an external task, never as part of their own, so +they always put {@code FLAG_ACTIVITY_NEW_TASK} in the intents they pass to {@link +android.app.Activity#startActivity startActivity()}. If you have an activity that can be invoked by +an external entity that might use this flag, take care that the user has a independent way to get +back to the task that's started, such as with a launcher icon (the root activity of the task +has a {@link android.content.Intent#CATEGORY_LAUNCHER} intent filter; see the <a +href="#Starting">Starting a task</a> section below).</p> +</li> + + <li>When an activity has its <a +href="{@docRoot}guide/topics/manifest/activity-element.html#reparent">{@code +allowTaskReparenting}</a> attribute set to {@code "true"}. + <p>In this case, the activity can move from the task it starts to the task it has an affinity +for, when that task comes to the foreground.</p> + <p>For example, 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.</p> +</li> +</ul> + +<p class="note"><strong>Tip:</strong> If an {@code .apk} file contains more than one "application" +from the user's point of view, you probably want to use the <a +href="{@docRoot}guide/topics/manifest/activity-element.html#aff">{@code taskAffinity}</a> +attribute to assign different affinities to the activities associated with each "application".</p> + + + +<h3 id="Clearing">Clearing the back stack</h3> + +<p>If the user leaves a task for a long time, the system clears the task of all activities except +the root activity. When the user returns to the task again, only the root activity is restored. +The system behaves this way, because, after an extended amount of time, users likely have abandoned +what they were doing before and are returning to the task to begin something new. </p> + +<p>There are some activity attributes that you can use to modify this behavior: </p> + +<dl> +<dt><code><a +href="{@docRoot}guide/topics/manifest/activity-element.html#always">alwaysRetainTaskState</a></code> +</dt> +<dd>If this attribute is set to {@code "true"} in the root activity of a task, +the default behavior just described does not happen. +The task retains all activities in its stack even after a long period.</dd> + +<dt><code><a +href="{@docRoot}guide/topics/manifest/activity-element.html#clear">clearTaskOnLaunch</a></code></dt> +<dd>If this attribute is set to {@code "true"} in the root activity of a task, +the stack is cleared down to the root activity whenever the user leaves the task +and returns to it. In other words, it's the opposite of <a +href="{@docRoot}guide/topics/manifest/activity-element.html#always">{@code +alwaysRetainTaskState}</a>. The user always returns to the task in its +initial state, even after a leaving the task for only a moment.</dd> + +<dt><code><a +href="{@docRoot}guide/topics/manifest/activity-element.html#finish">finishOnTaskLaunch</a></code> +</dt> +<dd>This attribute is like <a +href="{@docRoot}guide/topics/manifest/activity-element.html#clear">{@code clearTaskOnLaunch}</a>, +but it operates on a +single activity, not an entire task. It can also cause any activity to go +away, including the root activity. When it's set to {@code "true"}, the +activity remains part of the task only for the current session. If the user +leaves and then returns to the task, it is no longer present.</dd> +</dl> + + + + +<h3 id="Starting">Starting a task</h3> + +<p>You can set up an activity as the entry point for a task by giving it an intent filter with +{@code "android.intent.action.MAIN"} as the specified action and {@code +"android.intent.category.LAUNCHER"} as the specified category. For example:</p> + +<pre> +<activity ... > + <intent-filter ... > + <action android:name="android.intent.action.MAIN" /> + <category android:name="android.intent.category.LAUNCHER" /> + </intent-filter> + ... +</activity> +</pre> + +<p>An intent filter of this kind causes an icon and label for the +activity to be displayed in the application launcher, giving users a way to launch the activity and +to return to the task that it creates any time after it has been launched. +</p> + +<p>This second ability is important: Users must be able to leave a task and then come back to it +later using this activity launcher. For this reason, the two <a href="#LaunchModes">launch +modes</a> that mark activities as always initiating a task, {@code "singleTask"} and "{@code +"singleInstance"}, should be used only when the activity has an {@link +android.content.Intent#ACTION_MAIN} +and a {@link android.content.Intent#CATEGORY_LAUNCHER} +filter. Imagine, for example, what could happen if the filter is missing: An intent launches a +{@code "singleTask"} activity, initiating a new task, and the user spends some time working in +that task. The user then presses the HOME key. The task is now sent to the background and not +visible. Because it is not represented in the application launcher, the user has no way to return to +the task. +</p> + +<p>For those cases where you don't want the user to be able to return to an activity, set the + <code><a +href="{@docRoot}guide/topics/manifest/activity-element.html"><activity></a></code> element's +<a href="{@docRoot}guide/topics/manifest/activity-element.html#finish">{@code +finishOnTaskLaunch}</a> to {@code "true"} (see <a +href="#Clearing">Clearing the stack</a>).</p> + + + + +<h2>Beginner's Path</h2> + +<p>For more information about how to use intents to +activate other application components and publish the intents to which your components +respond, continue with the <b><a +href="{@docRoot}guide/topics/intents/intents-filters.html">Intents and Intent +Filters</a></b> document.</p> diff --git a/docs/html/guide/topics/resources/string-resource.jd b/docs/html/guide/topics/resources/string-resource.jd index 81c5d55..2db38f1 100644 --- a/docs/html/guide/topics/resources/string-resource.jd +++ b/docs/html/guide/topics/resources/string-resource.jd @@ -12,8 +12,8 @@ your application with strings:</p> <dd>XML resource that provides a single string.</dd> <dt><a href="#StringArray">String Array</a></dt> <dd>XML resource that provides an array of strings.</dd> - <dt><a href="#Plurals">Plurals</a></dt> - <dd>XML resource that carries different strings for different pluralizations + <dt><a href="#Plurals">Quantity Strings (Plurals)</a></dt> + <dd>XML resource that carries different strings for different quantities of the same word or phrase.</dd> </dl> @@ -218,13 +218,30 @@ getStringArray}(R.array.planets_array); -<h2 id="Plurals">Plurals</h2> +<h2 id="Plurals">Quantity Strings (Plurals)</h2> -<p>A pair of strings that each provide a different plural form of the same word or phrase, -which you can collectively reference from the application. When you request the plurals -resource using a method such as {@link android.content.res.Resources#getQuantityString(int,int) -getQuantityString()}, you must pass a "count", which will determine the plural form you -require and return that string to you.</p> +<p>Different languages have different rules for grammatical agreement with quantity. In English, +for example, the quantity 1 is a special case. We write "1 book", but for any other quantity we'd +write "<i>n</i> books". This distinction between singular and plural is very common, but other +languages make finer distinctions. The full set supported by Android is <code>zero</code>, +<code>one</code>, <code>two</code>, <code>few</code>, <code>many</code>, and <code>other</code>. + +<p>The rules for deciding which case to use for a given language and quantity can be very complex, +so Android provides you with methods such as +{@link android.content.res.Resources#getQuantityString(int,int) getQuantityString()} to select +the appropriate resource for you. + +<p>Note that the selection is made based on grammatical necessity. A string for <code>zero</code> +in English will be ignored even if the quantity is 0, because 0 isn't grammatically different +from 2, or any other number except 1 ("zero books", "one book", "two books", et cetera). +Don't be misled either by the fact that, say, <code>two</code> sounds like it could only apply to +the quantity 2: a language may require that 2, 12, 102 (et cetera) are all treated like one +another but differently to other quantities. Rely on your translator to know what distinctions +their language actually insists upon. + +<p>It's often possible to avoid quantity strings by using quantity-neutral formulations such as +"Books: 1". This will make your life and your translators' lives easier, if it's a style that's +in keeping with your application. <p class="note"><strong>Note:</strong> A plurals collection is a simple resource that is referenced using the value provided in the {@code name} attribute (not the name of the XML @@ -251,7 +268,7 @@ In Java: <code>R.plurals.<em>plural_name</em></code> <<a href="#plurals-element">plurals</a> name="<em>plural_name</em>"> <<a href="#plurals-item-element">item</a> - quantity=["one" | "other"] + quantity=["zero" | "one" | "two" | "few" | "many" | "other"] ><em>text_string</em></item> </plurals> </resources> @@ -285,16 +302,27 @@ Styling</a>, below, for information about to properly style and format your stri <p class="caps">attributes:</p> <dl class="atn-list"> <dt><code>quantity</code></dt> - <dd><em>Keyword</em>. A value indicating the case in which this string should be used. Valid -values: + <dd><em>Keyword</em>. A value indicating when this string should be used. Valid +values, with non-exhaustive examples in parentheses: <table> <tr><th>Value</th><th>Description</th></tr> <tr> - <td>{@code one}</td><td>When there is one (a singular string).</td> + <td>{@code zero}</td><td>When the language requires special treatment of the number 0 (as in Arabic).</td> + </tr> + <tr> + <td>{@code one}</td><td>When the language requires special treatment of numbers like one (as with the number 1 in English and most other languages; in Russian, any number ending in 1 but not ending in 11 is in this class).</td> + </tr> + <tr> + <td>{@code two}</td><td>When the language requires special treatment of numbers like two (as in Welsh).</td> + </tr> + <tr> + <td>{@code few}</td><td>When the language requires special treatment of "small" numbers (as with 2, 3, and 4 in Czech; or numbers ending 2, 3, or 4 but not 12, 13, or 14 in Polish).</td> </tr> <tr> - <td>{@code other}</td><td>When the quantity is anything other than one (a plural -string, but also used when the count is zero).</td> + <td>{@code many}</td><td>When the language requires special treatment of "large" numbers (as with numbers ending 11-99 in Maltese).</td> + </tr> + <tr> + <td>{@code other}</td><td>When the language does not require special treatment of the given quantity.</td> </tr> </table> </dd> @@ -315,6 +343,17 @@ string, but also used when the count is zero).</td> </plurals> </resources> </pre> + <p>XML file saved at {@code res/values-pl/strings.xml}:</p> +<pre> +<?xml version="1.0" encoding="utf-8"?> +<resources> + <plurals name="numberOfSongsAvailable"> + <item quantity="one">Znaleziono jedną piosenkę.</item> + <item quantity="few">Znaleziono %d piosenki.</item> + <item quantity="other">Znaleziono %d piosenek.</item> + </plurals> +</resources> +</pre> <p>Java code:</p> <pre> int count = getNumberOfsongsAvailable(); diff --git a/docs/html/guide/topics/ui/dialogs.jd b/docs/html/guide/topics/ui/dialogs.jd index 1a997f9..879eb8b 100644 --- a/docs/html/guide/topics/ui/dialogs.jd +++ b/docs/html/guide/topics/ui/dialogs.jd @@ -473,18 +473,25 @@ public class NotificationTest extends Activity { progressDialog = new ProgressDialog(NotificationTest.this); progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); progressDialog.setMessage("Loading..."); - progressThread = new ProgressThread(handler); - progressThread.start(); return progressDialog; default: return null; } } + @Override + protected void onPrepareDialog(int id, Dialog dialog) { + switch(id) { + case PROGRESS_DIALOG: + progressDialog.setProgress(0); + progressThread = new ProgressThread(handler); + progressThread.start(); + } + // Define the Handler that receives messages from the thread and update the progress final Handler handler = new Handler() { public void handleMessage(Message msg) { - int total = msg.getData().getInt("total"); + int total = msg.arg1; progressDialog.setProgress(total); if (total >= 100){ dismissDialog(PROGRESS_DIALOG); @@ -515,9 +522,7 @@ public class NotificationTest extends Activity { Log.e("ERROR", "Thread Interrupted"); } Message msg = mHandler.obtainMessage(); - Bundle b = new Bundle(); - b.putInt("total", total); - msg.setData(b); + msg.arg1 = total; mHandler.sendMessage(msg); total++; } diff --git a/docs/html/guide/tutorials/notepad/notepad-ex2.jd b/docs/html/guide/tutorials/notepad/notepad-ex2.jd index a945a62..854731f 100644 --- a/docs/html/guide/tutorials/notepad/notepad-ex2.jd +++ b/docs/html/guide/tutorials/notepad/notepad-ex2.jd @@ -87,8 +87,8 @@ Open the Notepadv2 class.</p> menu callback used for the options menu. Here, we add just one line, which will add a menu item to delete a note. Call <code>menu.add()</code> like so: <pre> -public boolean onCreateContextMenu(Menu menu, View v - ContextMenuInfo menuInfo) { +public void onCreateContextMenu(Menu menu, View v, + ContextMenu.ContextMenuInfo menuInfo) { super.onCreateContextMenu(menu, v, menuInfo); menu.add(0, DELETE_ID, 0, R.string.menu_delete); }</pre> |
