diff options
Diffstat (limited to 'docs/html/guide/components')
-rw-r--r-- | docs/html/guide/components/activities.jd | 776 | ||||
-rw-r--r-- | docs/html/guide/components/bound-services.jd | 675 | ||||
-rw-r--r-- | docs/html/guide/components/fragments.jd | 836 | ||||
-rw-r--r-- | docs/html/guide/components/fundamentals.jd | 518 | ||||
-rw-r--r-- | docs/html/guide/components/index.jd | 56 | ||||
-rw-r--r-- | docs/html/guide/components/intents-filters.jd | 1055 | ||||
-rw-r--r-- | docs/html/guide/components/loaders.jd | 500 | ||||
-rw-r--r-- | docs/html/guide/components/processes-and-threads.jd | 424 | ||||
-rw-r--r-- | docs/html/guide/components/services.jd | 874 | ||||
-rw-r--r-- | docs/html/guide/components/tasks-and-back-stack.jd | 595 |
10 files changed, 6309 insertions, 0 deletions
diff --git a/docs/html/guide/components/activities.jd b/docs/html/guide/components/activities.jd new file mode 100644 index 0000000..36f651f --- /dev/null +++ b/docs/html/guide/components/activities.jd @@ -0,0 +1,776 @@ +page.title=Activities +@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="#ShuttingDown">Shutting Down an Activity</a></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}guide/components/tasks-and-back-stack.html">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" stack mechanism, +so, when the user is done with the current activity and presses the <em>Back</em> button, 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/components/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 declare 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. The <a href="{@docRoot}guide/topics/manifest/activity-element.html#nm">{@code android:name}</a> +attribute is the only required attribute—it specifies the class name of the activity. Once +you publish your application, you should not change this name, because if you do, you might break +some functionality, such as application shortcuts (read the blog post, <a +href="http://android-developers.blogspot.com/2011/06/things-that-cannot-change.html">Things +That Cannot Change</a>).</p> + +<p>See the <a +href="{@docRoot}guide/topics/manifest/activity-element.html">{@code <activity>}</a> element +reference for more information about declaring your activity in the manifest.</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/components/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/components/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/components/processes-and-threads.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 so that when the activity returns to the +foreground (when it "resumes"), those changes are still there.</p> + +<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: {@link +android.app.Activity#onSaveInstanceState onSaveInstanceState()}.</p> + +<p>The system calls {@link android.app.Activity#onSaveInstanceState onSaveInstanceState()} +before making the activity vulnerable to destruction. The system passes this method +a {@link android.os.Bundle} in which you can save +state information about the activity as name-value pairs, using methods such as {@link +android.os.Bundle#putString putString()} and {@link +android.os.Bundle#putInt putInt()}. Then, if the system kills your application +process and the user navigates back to your activity, the system recreates the activity and passes +the {@link android.os.Bundle} to both {@link android.app.Activity#onCreate onCreate()} and {@link +android.app.Activity#onRestoreInstanceState onRestoreInstanceState()}. Using either of these +methods, you can extract your saved state from the {@link android.os.Bundle} and restore the +activity state. If there is no state information to restore, then the {@link +android.os.Bundle} passed to you is null (which is the case when the activity is created for +the first time).</p> + +<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 destroyed, then recreated and the activity must restore +the previously saved state, or the activity is stopped, then resumed and the activity state +remains intact.</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 <em>Back</em> button, because the user is +explicitly +closing the activity). If the system calls {@link android.app.Activity#onSaveInstanceState +onSaveInstanceState()}, it does so 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 the corresponding {@link +android.view.View#onSaveInstanceState onSaveInstanceState()} method 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 the +system 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. Likewise, you should also call the supercall implementation of {@link +android.app.Activity#onRestoreInstanceState onRestoreInstanceState()} if you override it, so the +default implementation can restore view states.</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 screen configuration. 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 recreates the running activity +(the system calls {@link android.app.Activity#onDestroy}, then immediately calls {@link +android.app.Activity#onCreate onCreate()}). This behavior is +designed to help your application adapt to new configurations by automatically reloading your +application with alternative resources that you've provided (such as different layouts for +different screen orientations and sizes).</p> + +<p>If you properly design your activity to handle a restart due to a screen orientation change and +restore the activity state as described above, your application will be more resilient to other +unexpected events in the activity lifecycle.</p> + +<p>The best way to handle such a restart is + to save and restore the state of your activity 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 more information about configuration changes that happen at runtime and how you can handle +them, read the guide to <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/components/tasks-and-back-stack.html">Tasks and Back +Stack</a></b> document.</p> +-->
\ No newline at end of file diff --git a/docs/html/guide/components/bound-services.jd b/docs/html/guide/components/bound-services.jd new file mode 100644 index 0000000..b6a2512 --- /dev/null +++ b/docs/html/guide/components/bound-services.jd @@ -0,0 +1,675 @@ +page.title=Bound Services +parent.title=Services +parent.link=services.html +@jd:body + + +<div id="qv-wrapper"> +<ol id="qv"> +<h2>Quickview</h2> +<ul> + <li>A bound service allows other components to bind to it, in order to interact with it and +perform interprocess communication</li> + <li>A bound service is destroyed once all clients unbind, unless the service was also started</li> +</ul> +<h2>In this document</h2> +<ol> + <li><a href="#Basics">The Basics</a></li> + <li><a href="#Creating">Creating a Bound Service</a> + <ol> + <li><a href="#Binder">Extending the Binder class</a></li> + <li><a href="#Messenger">Using a Messenger</a></li> + </ol> + </li> + <li><a href="#Binding">Binding to a Service</a></li> + <li><a href="#Lifecycle">Managing the Lifecycle of a Bound Service</a></li> +</ol> + +<h2>Key classes</h2> +<ol> + <li>{@link android.app.Service}</li> + <li>{@link android.content.ServiceConnection}</li> + <li>{@link android.os.IBinder}</li> +</ol> + +<h2>Samples</h2> +<ol> + <li><a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/RemoteService.html">{@code + RemoteService}</a></li> + <li><a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/LocalService.html">{@code + LocalService}</a></li> +</ol> + +<h2>See also</h2> +<ol> + <li><a href="{@docRoot}guide/components/services.html">Services</a></li> +</ol> +</div> + + +<p>A bound service is the server in a client-server interface. A bound service allows components +(such as activities) to bind to the service, send requests, receive responses, and even perform +interprocess communication (IPC). A bound service typically lives only while it serves another +application component and does not run in the background indefinitely.</p> + +<p>This document shows you how to create a bound service, including how to bind +to the service from other application components. However, you should also refer to the <a +href="{@docRoot}guide/components/services.html">Services</a> document for additional +information about services in general, such as how to deliver notifications from a service, set +the service to run in the foreground, and more.</p> + + +<h2 id="Basics">The Basics</h2> + +<p>A bound service is an implementation of the {@link android.app.Service} class that allows +other applications to bind to it and interact with it. To provide binding for a +service, you must implement the {@link android.app.Service#onBind onBind()} callback method. This +method returns an {@link android.os.IBinder} object that defines the programming interface that +clients can use to interact with the service.</p> + +<div class="sidebox-wrapper"> +<div class="sidebox"> + <h3>Binding to a Started Service</h3> + +<p>As discussed in the <a href="{@docRoot}guide/components/services.html">Services</a> +document, you can create a service that is both started and bound. That is, the service can be +started by calling {@link android.content.Context#startService startService()}, which allows the +service to run indefinitely, and also allow a client to bind to the service by calling {@link +android.content.Context#bindService bindService()}. + <p>If you do allow your service to be started and bound, then when the service has been +started, the system does <em>not</em> destroy the service when all clients unbind. Instead, you must +explicitly stop the service, by calling {@link android.app.Service#stopSelf stopSelf()} or {@link +android.content.Context#stopService stopService()}.</p> + +<p>Although you should usually implement either {@link android.app.Service#onBind onBind()} +<em>or</em> {@link android.app.Service#onStartCommand onStartCommand()}, it's sometimes necessary to +implement both. For example, a music player might find it useful to allow its service to run +indefinitely and also provide binding. This way, an activity can start the service to play some +music and the music continues to play even if the user leaves the application. Then, when the user +returns to the application, the activity can bind to the service to regain control of playback.</p> + +<p>Be sure to read the section about <a href="#Lifecycle">Managing the Lifecycle of a Bound +Service</a>, for more information about the service lifecycle when adding binding to a +started service.</p> +</div> +</div> + +<p>A client can bind to the service by calling {@link android.content.Context#bindService +bindService()}. When it does, it must provide an implementation of {@link +android.content.ServiceConnection}, which monitors the connection with the service. The {@link +android.content.Context#bindService bindService()} method returns immediately without a value, but +when the Android system creates the connection between the +client and service, it calls {@link +android.content.ServiceConnection#onServiceConnected onServiceConnected()} on the {@link +android.content.ServiceConnection}, to deliver the {@link android.os.IBinder} that +the client can use to communicate with the service.</p> + +<p>Multiple clients can connect to the service at once. However, the system calls your service's +{@link android.app.Service#onBind onBind()} method to retrieve the {@link android.os.IBinder} only +when the first client binds. The system then delivers the same {@link android.os.IBinder} to any +additional clients that bind, without calling {@link android.app.Service#onBind onBind()} again.</p> + +<p>When the last client unbinds from the service, the system destroys the service (unless the +service was also started by {@link android.content.Context#startService startService()}).</p> + +<p>When you implement your bound service, the most important part is defining the interface +that your {@link android.app.Service#onBind onBind()} callback method returns. There are a few +different ways you can define your service's {@link android.os.IBinder} interface and the following +section discusses each technique.</p> + + + +<h2 id="Creating">Creating a Bound Service</h2> + +<p>When creating a service that provides binding, you must provide an {@link android.os.IBinder} +that provides the programming interface that clients can use to interact with the service. There +are three ways you can define the interface:</p> + +<dl> + <dt><a href="#Binder">Extending the Binder class</a></dt> + <dd>If your service is private to your own application and runs in the same process as the client +(which is common), you should create your interface by extending the {@link android.os.Binder} class +and returning an instance of it from +{@link android.app.Service#onBind onBind()}. The client receives the {@link android.os.Binder} and +can use it to directly access public methods available in either the {@link android.os.Binder} +implementation or even the {@link android.app.Service}. + <p>This is the preferred technique when your service is merely a background worker for your own +application. The only reason you would not create your interface this way is because +your service is used by other applications or across separate processes.</dd> + + <dt><a href="#Messenger">Using a Messenger</a></dt> + <dd>If you need your interface to work across different processes, you can create +an interface for the service with a {@link android.os.Messenger}. In this manner, the service +defines a {@link android.os.Handler} that responds to different types of {@link +android.os.Message} objects. This {@link android.os.Handler} +is the basis for a {@link android.os.Messenger} that can then share an {@link android.os.IBinder} +with the client, allowing the client to send commands to the service using {@link +android.os.Message} objects. Additionally, the client can define a {@link android.os.Messenger} of +its own so the service can send messages back. + <p>This is the simplest way to perform interprocess communication (IPC), because the {@link +android.os.Messenger} queues all requests into a single thread so that you don't have to design +your service to be thread-safe.</p> + </dd> + + <dt>Using AIDL</dt> + <dd>AIDL (Android Interface Definition Language) performs all the work to decompose objects into +primitives that the operating system can understand and marshall them across processes to perform +IPC. The previous technique, using a {@link android.os.Messenger}, is actually based on AIDL as +its underlying structure. As mentioned above, the {@link android.os.Messenger} creates a queue of +all the client requests in a single thread, so the service receives requests one at a time. If, +however, you want your service to handle multiple requests simultaneously, then you can use AIDL +directly. In this case, your service must be capable of multi-threading and be built thread-safe. + <p>To use AIDL directly, you must +create an {@code .aidl} file that defines the programming interface. The Android SDK tools use +this file to generate an abstract class that implements the interface and handles IPC, which you +can then extend within your service.</p> + </dd> +</dl> + + <p class="note"><strong>Note:</strong> Most applications <strong>should not</strong> use AIDL to +create a bound service, because it may require multithreading capabilities and +can result in a more complicated implementation. As such, AIDL is not suitable for most applications +and this document does not discuss how to use it for your service. If you're certain that you need +to use AIDL directly, see the <a href="{@docRoot}tools/aidl.html">AIDL</a> +document.</p> + + + + +<h3 id="Binder">Extending the Binder class</h3> + +<p>If your service is used only by the local application and does not need to work across processes, +then you can implement your own {@link android.os.Binder} class that provides your client direct +access to public methods in the service.</p> + +<p class="note"><strong>Note:</strong> This works only if the client and service are in the same +application and process, which is most common. For example, this would work well for a music +application that needs to bind an activity to its own service that's playing music in the +background.</p> + +<p>Here's how to set it up:</p> +<ol> + <li>In your service, create an instance of {@link android.os.Binder} that either: + <ul> + <li>contains public methods that the client can call</li> + <li>returns the current {@link android.app.Service} instance, which has public methods the +client can call</li> + <li>or, returns an instance of another class hosted by the service with public methods the +client can call</li> + </ul> + <li>Return this instance of {@link android.os.Binder} from the {@link +android.app.Service#onBind onBind()} callback method.</li> + <li>In the client, receive the {@link android.os.Binder} from the {@link +android.content.ServiceConnection#onServiceConnected onServiceConnected()} callback method and +make calls to the bound service using the methods provided.</li> +</ol> + +<p class="note"><strong>Note:</strong> The reason the service and client must be in the same +application is so the client can cast the returned object and properly call its APIs. The service +and client must also be in the same process, because this technique does not perform any +marshalling across processes.</p> + +<p>For example, here's a service that provides clients access to methods in the service through +a {@link android.os.Binder} implementation:</p> + +<pre> +public class LocalService extends Service { + // Binder given to clients + private final IBinder mBinder = new LocalBinder(); + // Random number generator + private final Random mGenerator = new Random(); + + /** + * Class used for the client Binder. Because we know this service always + * runs in the same process as its clients, we don't need to deal with IPC. + */ + public class LocalBinder extends Binder { + LocalService getService() { + // Return this instance of LocalService so clients can call public methods + return LocalService.this; + } + } + + @Override + public IBinder onBind(Intent intent) { + return mBinder; + } + + /** method for clients */ + public int getRandomNumber() { + return mGenerator.nextInt(100); + } +} +</pre> + +<p>The {@code LocalBinder} provides the {@code getService()} method for clients to retrieve the +current instance of {@code LocalService}. This allows clients to call public methods in the +service. For example, clients can call {@code getRandomNumber()} from the service.</p> + +<p>Here's an activity that binds to {@code LocalService} and calls {@code getRandomNumber()} +when a button is clicked:</p> + +<pre> +public class BindingActivity extends Activity { + LocalService mService; + boolean mBound = false; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.main); + } + + @Override + protected void onStart() { + super.onStart(); + // Bind to LocalService + Intent intent = new Intent(this, LocalService.class); + bindService(intent, mConnection, Context.BIND_AUTO_CREATE); + } + + @Override + protected void onStop() { + super.onStop(); + // Unbind from the service + if (mBound) { + unbindService(mConnection); + mBound = false; + } + } + + /** Called when a button is clicked (the button in the layout file attaches to + * this method with the android:onClick attribute) */ + public void onButtonClick(View v) { + if (mBound) { + // Call a method from the LocalService. + // However, if this call were something that might hang, then this request should + // occur in a separate thread to avoid slowing down the activity performance. + int num = mService.getRandomNumber(); + Toast.makeText(this, "number: " + num, Toast.LENGTH_SHORT).show(); + } + } + + /** Defines callbacks for service binding, passed to bindService() */ + private ServiceConnection mConnection = new ServiceConnection() { + + @Override + public void onServiceConnected(ComponentName className, + IBinder service) { + // We've bound to LocalService, cast the IBinder and get LocalService instance + LocalBinder binder = (LocalBinder) service; + mService = binder.getService(); + mBound = true; + } + + @Override + public void onServiceDisconnected(ComponentName arg0) { + mBound = false; + } + }; +} +</pre> + +<p>The above sample shows how the client binds to the service using an implementation of +{@link android.content.ServiceConnection} and the {@link +android.content.ServiceConnection#onServiceConnected onServiceConnected()} callback. The next +section provides more information about this process of binding to the service.</p> + +<p class="note"><strong>Note:</strong> The example above doesn't explicitly unbind from the service, +but all clients should unbind at an appropriate time (such as when the activity pauses).</p> + +<p>For more sample code, see the <a +href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/LocalService.html">{@code +LocalService.java}</a> class and the <a +href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/LocalServiceActivities.html">{@code +LocalServiceActivities.java}</a> class in <a +href="{@docRoot}resources/samples/ApiDemos/index.html">ApiDemos</a>.</p> + + + + + +<h3 id="Messenger">Using a Messenger</h3> + +<div class="sidebox-wrapper"> +<div class="sidebox"> + <h4>Compared to AIDL</h4> + <p>When you need to perform IPC, using a {@link android.os.Messenger} for your interface is +simpler than implementing it with AIDL, because {@link android.os.Messenger} queues +all calls to the service, whereas, a pure AIDL interface sends simultaneous requests to the +service, which must then handle multi-threading.</p> + <p>For most applications, the service doesn't need to perform multi-threading, so using a {@link +android.os.Messenger} allows the service to handle one call at a time. If it's important +that your service be multi-threaded, then you should use <a +href="{@docRoot}tools/aidl.html">AIDL</a> to define your interface.</p> +</div> +</div> + +<p>If you need your service to communicate with remote processes, then you can use a +{@link android.os.Messenger} to provide the interface for your service. This technique allows +you to perform interprocess communication (IPC) without the need to use AIDL.</p> + +<p>Here's a summary of how to use a {@link android.os.Messenger}:</p> + +<ul> + <li>The service implements a {@link android.os.Handler} that receives a callback for each +call from a client.</li> + <li>The {@link android.os.Handler} is used to create a {@link android.os.Messenger} object +(which is a reference to the {@link android.os.Handler}).</li> + <li>The {@link android.os.Messenger} creates an {@link android.os.IBinder} that the service +returns to clients from {@link android.app.Service#onBind onBind()}.</li> + <li>Clients use the {@link android.os.IBinder} to instantiate the {@link android.os.Messenger} +(that references the service's {@link android.os.Handler}), which the client uses to send +{@link android.os.Message} objects to the service.</li> + <li>The service receives each {@link android.os.Message} in its {@link +android.os.Handler}—specifically, in the {@link android.os.Handler#handleMessage +handleMessage()} method.</li> +</ul> + + +<p>In this way, there are no "methods" for the client to call on the service. Instead, the +client delivers "messages" ({@link android.os.Message} objects) that the service receives in +its {@link android.os.Handler}.</p> + +<p>Here's a simple example service that uses a {@link android.os.Messenger} interface:</p> + +<pre> +public class MessengerService extends Service { + /** Command to the service to display a message */ + static final int MSG_SAY_HELLO = 1; + + /** + * Handler of incoming messages from clients. + */ + class IncomingHandler extends Handler { + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + case MSG_SAY_HELLO: + Toast.makeText(getApplicationContext(), "hello!", Toast.LENGTH_SHORT).show(); + break; + default: + super.handleMessage(msg); + } + } + } + + /** + * Target we publish for clients to send messages to IncomingHandler. + */ + final Messenger mMessenger = new Messenger(new IncomingHandler()); + + /** + * When binding to the service, we return an interface to our messenger + * for sending messages to the service. + */ + @Override + public IBinder onBind(Intent intent) { + Toast.makeText(getApplicationContext(), "binding", Toast.LENGTH_SHORT).show(); + return mMessenger.getBinder(); + } +} +</pre> + +<p>Notice that the {@link android.os.Handler#handleMessage handleMessage()} method in the +{@link android.os.Handler} is where the service receives the incoming {@link android.os.Message} +and decides what to do, based on the {@link android.os.Message#what} member.</p> + +<p>All that a client needs to do is create a {@link android.os.Messenger} based on the {@link +android.os.IBinder} returned by the service and send a message using {@link +android.os.Messenger#send send()}. For example, here's a simple activity that binds to the +service and delivers the {@code MSG_SAY_HELLO} message to the service:</p> + +<pre> +public class ActivityMessenger extends Activity { + /** Messenger for communicating with the service. */ + Messenger mService = null; + + /** Flag indicating whether we have called bind on the service. */ + boolean mBound; + + /** + * Class for interacting with the main interface of the service. + */ + private ServiceConnection mConnection = new ServiceConnection() { + public void onServiceConnected(ComponentName className, IBinder service) { + // This is called when the connection with the service has been + // established, giving us the object we can use to + // interact with the service. We are communicating with the + // service using a Messenger, so here we get a client-side + // representation of that from the raw IBinder object. + mService = new Messenger(service); + mBound = true; + } + + public void onServiceDisconnected(ComponentName className) { + // This is called when the connection with the service has been + // unexpectedly disconnected -- that is, its process crashed. + mService = null; + mBound = false; + } + }; + + public void sayHello(View v) { + if (!mBound) return; + // Create and send a message to the service, using a supported 'what' value + Message msg = Message.obtain(null, MessengerService.MSG_SAY_HELLO, 0, 0); + try { + mService.send(msg); + } catch (RemoteException e) { + e.printStackTrace(); + } + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.main); + } + + @Override + protected void onStart() { + super.onStart(); + // Bind to the service + bindService(new Intent(this, MessengerService.class), mConnection, + Context.BIND_AUTO_CREATE); + } + + @Override + protected void onStop() { + super.onStop(); + // Unbind from the service + if (mBound) { + unbindService(mConnection); + mBound = false; + } + } +} +</pre> + +<p>Notice that this example does not show how the service can respond to the client. If you want the +service to respond, then you need to also create a {@link android.os.Messenger} in the client. Then +when the client receives the {@link android.content.ServiceConnection#onServiceConnected +onServiceConnected()} callback, it sends a {@link android.os.Message} to the service that includes +the client's {@link android.os.Messenger} in the {@link android.os.Message#replyTo} parameter +of the {@link android.os.Messenger#send send()} method.</p> + +<p>You can see an example of how to provide two-way messaging in the <a +href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/MessengerService.html">{@code +MessengerService.java}</a> (service) and <a +href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/MessengerServiceActivities.html">{@code +MessengerServiceActivities.java}</a> (client) samples.</p> + + + + + +<h2 id="Binding">Binding to a Service</h2> + +<p>Application components (clients) can bind to a service by calling +{@link android.content.Context#bindService bindService()}. The Android +system then calls the service's {@link android.app.Service#onBind +onBind()} method, which returns an {@link android.os.IBinder} for interacting with the service.</p> + +<p>The binding is asynchronous. {@link android.content.Context#bindService +bindService()} returns immediately and does <em>not</em> return the {@link android.os.IBinder} to +the client. To receive the {@link android.os.IBinder}, the client must create an instance of {@link +android.content.ServiceConnection} and pass it to {@link android.content.Context#bindService +bindService()}. The {@link android.content.ServiceConnection} includes a callback method that the +system calls to deliver the {@link android.os.IBinder}.</p> + +<p class="note"><strong>Note:</strong> Only activities, services, and content providers can bind +to a service—you <strong>cannot</strong> bind to a service from a broadcast receiver.</p> + +<p>So, to bind to a service from your client, you must: </p> +<ol> + <li>Implement {@link android.content.ServiceConnection}. + <p>Your implementation must override two callback methods:</p> + <dl> + <dt>{@link android.content.ServiceConnection#onServiceConnected onServiceConnected()}</dt> + <dd>The system calls this to deliver the {@link android.os.IBinder} returned by +the service's {@link android.app.Service#onBind onBind()} method.</dd> + <dt>{@link android.content.ServiceConnection#onServiceDisconnected +onServiceDisconnected()}</dt> + <dd>The Android system calls this when the connection to the service is unexpectedly +lost, such as when the service has crashed or has been killed. This is <em>not</em> called when the +client unbinds.</dd> + </dl> + </li> + <li>Call {@link +android.content.Context#bindService bindService()}, passing the {@link +android.content.ServiceConnection} implementation. </li> + <li>When the system calls your {@link android.content.ServiceConnection#onServiceConnected +onServiceConnected()} callback method, you can begin making calls to the service, using +the methods defined by the interface.</li> + <li>To disconnect from the service, call {@link +android.content.Context#unbindService unbindService()}. + <p>When your client is destroyed, it will unbind from the service, but you should always unbind +when you're done interacting with the service or when your activity pauses so that the service can +shutdown while its not being used. (Appropriate times to bind and unbind is discussed +more below.)</p> + </li> +</ol> + +<p>For example, the following snippet connects the client to the service created above by +<a href="#Binder">extending the Binder class</a>, so all it must do is cast the returned +{@link android.os.IBinder} to the {@code LocalService} class and request the {@code +LocalService} instance:</p> + +<pre> +LocalService mService; +private ServiceConnection mConnection = new ServiceConnection() { + // Called when the connection with the service is established + public void onServiceConnected(ComponentName className, IBinder service) { + // Because we have bound to an explicit + // service that is running in our own process, we can + // cast its IBinder to a concrete class and directly access it. + LocalBinder binder = (LocalBinder) service; + mService = binder.getService(); + mBound = true; + } + + // Called when the connection with the service disconnects unexpectedly + public void onServiceDisconnected(ComponentName className) { + Log.e(TAG, "onServiceDisconnected"); + mBound = false; + } +}; +</pre> + +<p>With this {@link android.content.ServiceConnection}, the client can bind to a service by passing +this it to {@link android.content.Context#bindService bindService()}. For example:</p> + +<pre> +Intent intent = new Intent(this, LocalService.class); +bindService(intent, mConnection, Context.BIND_AUTO_CREATE); +</pre> + +<ul> + <li>The first parameter of {@link android.content.Context#bindService bindService()} is an +{@link android.content.Intent} that explicitly names the service to bind (thought the intent +could be implicit).</li> +<li>The second parameter is the {@link android.content.ServiceConnection} object.</li> +<li>The third parameter is a flag indicating options for the binding. It should usually be {@link +android.content.Context#BIND_AUTO_CREATE} in order to create the service if its not already alive. +Other possible values are {@link android.content.Context#BIND_DEBUG_UNBIND} +and {@link android.content.Context#BIND_NOT_FOREGROUND}, or {@code 0} for none.</li> +</ul> + + +<h3>Additional notes</h3> + +<p>Here are some important notes about binding to a service:</p> +<ul> + <li>You should always trap {@link android.os.DeadObjectException} exceptions, which are thrown +when the connection has broken. This is the only exception thrown by remote methods.</li> + <li>Objects are reference counted across processes. </li> + <li>You should usually pair the binding and unbinding during +matching bring-up and tear-down moments of the client's lifecycle. For example: + <ul> + <li>If you only need to interact with the service while your activity is visible, you +should bind during {@link android.app.Activity#onStart onStart()} and unbind during {@link +android.app.Activity#onStop onStop()}.</li> + <li>If you want your activity to receive responses even while it is stopped in the +background, then you can bind during {@link android.app.Activity#onCreate onCreate()} and unbind +during {@link android.app.Activity#onDestroy onDestroy()}. Beware that this implies that your +activity needs to use the service the entire time it's running (even in the background), so if +the service is in another process, then you increase the weight of the process and it becomes +more likely that the system will kill it.</li> + </ul> + <p class="note"><strong>Note:</strong> You should usually <strong>not</strong> bind and unbind +during your activity's {@link android.app.Activity#onResume onResume()} and {@link +android.app.Activity#onPause onPause()}, because these callbacks occur at every lifecycle transition +and you should keep the processing that occurs at these transitions to a minimum. Also, if +multiple activities in your application bind to the same service and there is a transition between +two of those activities, the service may be destroyed and recreated as the current activity unbinds +(during pause) before the next one binds (during resume). (This activity transition for how +activities coordinate their lifecycles is described in the <a +href="{@docRoot}guide/components/activities.html#CoordinatingActivities">Activities</a> +document.)</p> +</ul> + +<p>For more sample code, showing how to bind to a service, see the <a +href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/RemoteService.html">{@code +RemoteService.java}</a> class in <a +href="{@docRoot}resources/samples/ApiDemos/index.html">ApiDemos</a>.</p> + + + + + +<h2 id="Lifecycle">Managing the Lifecycle of a Bound Service</h2> + +<div class="figure" style="width:588px"> +<img src="{@docRoot}images/fundamentals/service_binding_tree_lifecycle.png" alt="" /> +<p class="img-caption"><strong>Figure 1.</strong> The lifecycle for a service that is started +and also allows binding.</p> +</div> + +<p>When a service is unbound from all clients, the Android system destroys it (unless it was also +started with {@link android.app.Service#onStartCommand onStartCommand()}). As such, you don't have +to manage the lifecycle of your service if it's purely a bound +service—the Android system manages it for you based on whether it is bound to any clients.</p> + +<p>However, if you choose to implement the {@link android.app.Service#onStartCommand +onStartCommand()} callback method, then you must explicitly stop the service, because the +service is now considered to be <em>started</em>. In this case, the service runs until the service +stops itself with {@link android.app.Service#stopSelf()} or another component calls {@link +android.content.Context#stopService stopService()}, regardless of whether it is bound to any +clients.</p> + +<p>Additionally, if your service is started and accepts binding, then when the system calls +your {@link android.app.Service#onUnbind onUnbind()} method, you can optionally return +{@code true} if you would like to receive a call to {@link android.app.Service#onRebind +onRebind()} the next time a client binds to the service (instead of receiving a call to {@link +android.app.Service#onBind onBind()}). {@link android.app.Service#onRebind +onRebind()} returns void, but the client still receives the {@link android.os.IBinder} in its +{@link android.content.ServiceConnection#onServiceConnected onServiceConnected()} callback. +Below, figure 1 illustrates the logic for this kind of lifecycle.</p> + +<p>For more information about the lifecycle of an started service, see the <a +href="{@docRoot}guide/components/services.html#Lifecycle">Services</a> document.</p> + + + + diff --git a/docs/html/guide/components/fragments.jd b/docs/html/guide/components/fragments.jd new file mode 100644 index 0000000..938e0ab --- /dev/null +++ b/docs/html/guide/components/fragments.jd @@ -0,0 +1,836 @@ +page.title=Fragments +parent.title=Activities +parent.link=activities.html +@jd:body + +<div id="qv-wrapper"> +<div id="qv"> + + <h2>Quickview</h2> + <ul> + <li>Fragments decompose application functionality and UI into reusable modules</li> + <li>Add multiple fragments to a screen to avoid switching activities</li> + <li>Fragments have their own lifecycle, state, and back stack</li> + <li>Fragments require API Level 11 or greater</li> + </ul> + + <h2>In this document</h2> + <ol> + <li><a href="#Design">Design Philosophy</a></li> + <li><a href="#Creating">Creating a Fragment</a> + <ol> + <li><a href="#UI">Adding a user interface</a></li> + <li><a href="#Adding">Adding a fragment to an activity</a></li> + </ol> + </li> + <li><a href="#Managing">Managing Fragments</a></li> + <li><a href="#Transactions">Performing Fragment Transactions</a></li> + <li><a href="#CommunicatingWithActivity">Communicating with the Activity</a> + <ol> + <li><a href="#EventCallbacks">Creating event callbacks to the activity</a></li> + <li><a href="#ActionBar">Adding items to the Action Bar</a></li> + </ol> + </li> + <li><a href="#Lifecycle">Handling the Fragment Lifecycle</a> + <ol> + <li><a href="#CoordinatingWithActivity">Coordinating with the activity lifecycle</a></li> + </ol> + </li> + <li><a href="#Example">Example</a></li> + </ol> + + <h2>Key classes</h2> + <ol> + <li>{@link android.app.Fragment}</li> + <li>{@link android.app.FragmentManager}</li> + <li>{@link android.app.FragmentTransaction}</li> + </ol> + + <h2>Related samples</h2> + <ol> + <li><a +href="{@docRoot}resources/samples/HoneycombGallery/index.html">Honeycomb Gallery</a></li> + <li><a +href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/index.html#Fragment">ApiDemos</a></li> + </ol> + + <h2>See also</h2> + <ol> + <li><a href="{@docRoot}guide/practices/tablets-and-handsets.html">Supporting Tablets +and Handsets</a></li> + </ol> +</div> +</div> + +<p>A {@link android.app.Fragment} represents a behavior or a portion of user interface in an +{@link android.app.Activity}. You can combine multiple fragments in a single activity to build a +multi-pane UI and reuse a fragment in multiple activities. You can think of a fragment as a +modular section of an activity, which has its own lifecycle, receives its own input events, and +which you can add or remove while the activity is running (sort of like a "sub activity" that +you can reuse in different activities).</p> + +<p>A fragment must always be embedded in an activity and the fragment's lifecycle is directly +affected by the host activity's lifecycle. For example, when the activity is paused, so are all +fragments in it, and when the activity is destroyed, so are all fragments. However, while an +activity is running (it is in the <em>resumed</em> <a +href="{@docRoot}guide/components/activities.html#Lifecycle">lifecycle state</a>), you can +manipulate each fragment independently, such as add or remove them. When you perform such a +fragment transaction, you can also add it to a back stack that's managed by the +activity—each back stack entry in the activity is a record of the fragment transaction that +occurred. The back stack allows the user to reverse a fragment transaction (navigate backwards), +by pressing the <em>Back</em> button.</p> + +<p>When you add a fragment as a part of your activity layout, it lives in a {@link +android.view.ViewGroup} inside the activity's view hierarchy and the fragment defines its own view +layout. +You can insert a fragment into your activity layout by declaring the fragment in the activity's +layout file, as a {@code <fragment>} element, or from your application code by adding it to an +existing {@link android.view.ViewGroup}. However, a fragment is not required to be a part of the +activity layout; you may also use a fragment without its own UI as an invisible worker for the +activity.</p> + +<p>This document describes how to build your application to use fragments, including +how fragments can maintain their state when added to the activity's back stack, share +events with the activity and other fragments in the activity, contribute to the activity's action +bar, and more.</p> + + +<h2 id="Design">Design Philosophy</h2> + +<p>Android introduced fragments in Android 3.0 (API level 11), primarily to support more +dynamic and flexible UI designs on large screens, such as tablets. Because a +tablet's screen is much larger than that of a handset, there's more room to combine and +interchange UI components. Fragments allow such designs without the need for you to manage complex +changes to the view hierarchy. By dividing the layout of an activity into fragments, you become able +to modify the activity's appearance at runtime and preserve those changes in a back stack +that's managed by the activity.</p> + +<p>For example, a news application can use one fragment to show a list of articles on the +left and another fragment to display an article on the right—both fragments appear in one +activity, side by side, and each fragment has its own set of lifecycle callback methods and handle +their own user input events. Thus, instead of using one activity to select an article and another +activity to read the article, the user can select an article and read it all within the same +activity, as illustrated in the tablet layout in figure 1.</p> + +<p>You should design each fragment as a modular and reusable activity component. That is, because +each fragment defines its own layout and its own behavior with its own lifecycle callbacks, you can +include one fragment in multiple activities, so you should design for reuse and avoid directly +manipulating one fragment from another fragment. This is especially important because a modular +fragment allows you to change your fragment combinations for different screen sizes. When designing +your application to support both tablets and handsets, you can reuse your fragments in different +layout configurations to optimize the user experience based on the available screen space. For +example, on a handset, it might be necessary to separate fragments to provide a single-pane UI when +more than one cannot fit within the same activity.</p> + +<img src="{@docRoot}images/fundamentals/fragments.png" alt="" /> +<p class="img-caption"><strong>Figure 1.</strong> An example of how two UI modules defined by +fragments can be combined into one activity for a tablet design, but separated for a +handset design.</p> + +<p>For example—to continue with the news application example—the application can embed +two fragments in <em>Activity A</em>, when running on a tablet-sized device. However, on a +handset-sized screen, there's not enough room for both fragments, so <em>Activity A</em> includes +only the fragment for the list of articles, and when the user selects an article, it starts +<em>Activity B</em>, which includes the second fragment to read the article. Thus, the application +supports both tablets and handsets by reusing fragments in different combinations, as illustrated in +figure 1.</p> + +<p>For more information about designing your application with different fragment combinations for +different screen configurations, see the guide to <a +href="{@docRoot}guide/practices/tablets-and-handsets.html">Supporting Tablets and Handsets</a>.</p> + + + +<h2 id="Creating">Creating a Fragment</h2> + +<div class="figure" style="width:327px"> +<img src="{@docRoot}images/fragment_lifecycle.png" alt="" /> +<p class="img-caption"><strong>Figure 2.</strong> The lifecycle of a fragment (while its +activity is running).</p> +</div> + +<p>To create a fragment, you must create a subclass of {@link android.app.Fragment} (or an existing +subclass of it). The {@link android.app.Fragment} class has code that looks a lot like +an {@link android.app.Activity}. It contains callback methods similar to an activity, such +as {@link android.app.Fragment#onCreate onCreate()}, {@link android.app.Fragment#onStart onStart()}, +{@link android.app.Fragment#onPause onPause()}, and {@link android.app.Fragment#onStop onStop()}. In +fact, if you're converting an existing Android application to use fragments, you might simply move +code from your activity's callback methods into the respective callback methods of your +fragment.</p> + +<p>Usually, you should implement at least the following lifecycle methods:</p> + +<dl> + <dt>{@link android.app.Fragment#onCreate onCreate()}</dt> + <dd>The system calls this when creating the fragment. Within your implementation, you should +initialize essential components of the fragment that you want to retain when the fragment is +paused or stopped, then resumed.</dd> + <dt>{@link android.app.Fragment#onCreateView onCreateView()}</dt> + <dd>The system calls this when it's time for the fragment to draw its user interface for the +first time. To draw a UI for your fragment, you must return a {@link android.view.View} from this +method that is the root of your fragment's layout. You can return null if the fragment does not +provide a UI.</dd> + <dt>{@link android.app.Activity#onPause onPause()}</dt> + <dd>The system calls this method as the first indication that the user is leaving the +fragment (though it does not always mean the fragment 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>Most applications should implement at least these three methods for every fragment, but there are +several other callback methods you should also use to handle various stages of the +fragment lifecycle. All the lifecycle callback methods are discussed more later, in the section +about <a href="#Lifecycle">Handling the Fragment Lifecycle</a>.</p> + + +<p>There are also a few subclasses that you might want to extend, instead of the base {@link +android.app.Fragment} class:</p> + +<dl> + <dt>{@link android.app.DialogFragment}</dt> + <dd>Displays a floating dialog. Using this class to create a dialog is a good alternative to using +the dialog helper methods in the {@link android.app.Activity} class, because you can +incorporate a fragment dialog into the back stack of fragments managed by the activity, +allowing the user to return to a dismissed fragment.</dd> + + <dt>{@link android.app.ListFragment}</dt> + <dd>Displays a list of items that are managed by an adapter (such as a {@link +android.widget.SimpleCursorAdapter}), similar to {@link android.app.ListActivity}. It provides +several methods for managing a list view, such as the {@link +android.app.ListFragment#onListItemClick(ListView,View,int,long) onListItemClick()} callback to +handle click events.</dd> + + <dt>{@link android.preference.PreferenceFragment}</dt> + <dd>Displays a hierarchy of {@link android.preference.Preference} objects as a list, similar to +{@link android.preference.PreferenceActivity}. This is useful when creating a "settings" +activity for your application.</dd> +</dl> + + +<h3 id="UI">Adding a user interface</h3> + +<p>A fragment is usually used as part of an activity's user interface and contributes its own +layout to the activity.</p> + +<p>To provide a layout for a fragment, you must implement the {@link +android.app.Fragment#onCreateView onCreateView()} callback method, which the Android system calls +when it's time for the fragment to draw its layout. Your implementation of this method must return a +{@link android.view.View} that is the root of your fragment's layout.</p> + +<p class="note"><strong>Note:</strong> If your fragment is a subclass of {@link +android.app.ListFragment}, the default implementation returns a {@link android.widget.ListView} from +{@link android.app.Fragment#onCreateView onCreateView()}, so you don't need to implement it.</p> + +<p>To return a layout from {@link +android.app.Fragment#onCreateView onCreateView()}, you can inflate it from a <a +href="{@docRoot}guide/topics/resources/layout-resource.html">layout resource</a> defined in XML. To +help you do so, {@link android.app.Fragment#onCreateView onCreateView()} provides a +{@link android.view.LayoutInflater} object.</p> + +<p>For example, here's a subclass of {@link android.app.Fragment} that loads a layout from the +{@code example_fragment.xml} file:</p> + +<pre> +public static class ExampleFragment extends Fragment { + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + // Inflate the layout for this fragment + return inflater.inflate(R.layout.example_fragment, container, false); + } +} +</pre> + +<div class="sidebox-wrapper"> +<div class="sidebox"> + <h3>Creating a layout</h3> + <p>In the sample above, {@code R.layout.example_fragment} is a reference to a layout resource +named {@code example_fragment.xml} saved in the application resources. For information about how to +create a layout in XML, see the <a href="{@docRoot}guide/topics/ui/index.html">User Interface</a> +documentation.</p> +</div> +</div> + +<p>The {@code container} parameter passed to {@link android.app.Fragment#onCreateView +onCreateView()} is the parent {@link android.view.ViewGroup} (from the activity's layout) in which +your fragment layout +will be inserted. The {@code savedInstanceState} parameter is a {@link android.os.Bundle} that +provides data about the previous instance of the fragment, if the fragment is being resumed +(restoring state is discussed more in the section about <a href="#Lifecycle">Handling the +Fragment Lifecycle</a>).</p> + +<p>The {@link android.view.LayoutInflater#inflate(int,ViewGroup,boolean) inflate()} method takes +three arguments:</p> +<ul> + <li>The resource ID of the layout you want to inflate.</li> + <li>The {@link android.view.ViewGroup} to be the parent of the inflated layout. Passing the {@code +container} is important in order for the system to apply layout parameters to the root view of the +inflated layout, specified by the parent view in which it's going.</li> + <li>A boolean indicating whether the inflated layout should be attached to the {@link +android.view.ViewGroup} (the second parameter) during inflation. (In this case, this +is false because the system is already inserting the inflated layout into the {@code +container}—passing true would create a redundant view group in the final layout.)</li> +</ul> + +<p>Now you've seen how to create a fragment that provides a layout. Next, you need to add +the fragment to your activity.</p> + + + +<h3 id="Adding">Adding a fragment to an activity</h3> + +<p>Usually, a fragment contributes a portion of UI to the host activity, which is embedded as a part +of the activity's overall view hierarchy. There are two ways you can add a fragment to the activity +layout:</p> + +<ul> + <li><b>Declare the fragment inside the activity's layout file.</b> +<p>In this case, you can +specify layout properties for the fragment as if it were a view. For example, here's the layout +file for an activity with two fragments:</p> +<pre> +<?xml version="1.0" encoding="utf-8"?> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:orientation="horizontal" + android:layout_width="match_parent" + android:layout_height="match_parent"> + <fragment android:name="com.example.news.ArticleListFragment" + android:id="@+id/list" + android:layout_weight="1" + android:layout_width="0dp" + android:layout_height="match_parent" /> + <fragment android:name="com.example.news.ArticleReaderFragment" + android:id="@+id/viewer" + android:layout_weight="2" + android:layout_width="0dp" + android:layout_height="match_parent" /> +</LinearLayout> +</pre> + <p>The {@code android:name} attribute in the {@code <fragment>} specifies the {@link +android.app.Fragment} class to instantiate in the layout.</p> + +<p>When the system creates this activity layout, it instantiates each fragment specified in the +layout and calls the {@link android.app.Fragment#onCreateView onCreateView()} method for each one, +to retrieve each fragment's layout. The system inserts the {@link android.view.View} returned by the +fragment directly in place of the {@code <fragment>} element.</p> + +<div class="note"> + <p><strong>Note:</strong> Each fragment requires a unique identifier that +the system can use to restore the fragment if the activity is restarted (and which you can use to +capture the fragment to perform transactions, such as remove it). There are three ways to provide an +ID for a fragment:</p> + <ul> + <li>Supply the {@code android:id} attribute with a unique ID.</li> + <li>Supply the {@code android:tag} attribute with a unique string.</li> + <li>If you provide neither of the previous two, the system uses the ID of the container +view.</li> + </ul> +</div> + </li> + + <li><b>Or, programmatically add the fragment to an existing {@link android.view.ViewGroup}.</b> +<p>At any time while your activity is running, you can add fragments to your activity layout. You +simply need to specify a {@link +android.view.ViewGroup} in which to place the fragment.</p> + <p>To make fragment transactions in your activity (such as add, remove, or replace a +fragment), you must use APIs from {@link android.app.FragmentTransaction}. You can get an instance +of {@link android.app.FragmentTransaction} from your {@link android.app.Activity} like this:</p> + +<pre> +FragmentManager fragmentManager = {@link android.app.Activity#getFragmentManager()} +FragmentTransaction fragmentTransaction = fragmentManager.{@link android.app.FragmentManager#beginTransaction()}; +</pre> + +<p>You can then add a fragment using the {@link +android.app.FragmentTransaction#add(int,Fragment) add()} method, specifying the fragment to add and +the view in which to insert it. For example:</p> + +<pre> +ExampleFragment fragment = new ExampleFragment(); +fragmentTransaction.add(R.id.fragment_container, fragment); +fragmentTransaction.commit(); +</pre> + + <p>The first argument passed to {@link android.app.FragmentTransaction#add(int,Fragment) add()} +is the {@link android.view.ViewGroup} in which the fragment should be placed, specified by +resource ID, and the second parameter is the fragment to add.</p> + <p>Once you've made your changes with +{@link android.app.FragmentTransaction}, you must +call {@link android.app.FragmentTransaction#commit} for the changes to take effect.</p> + </li> +</ul> + + +<h4 id="AddingWithoutUI">Adding a fragment without a UI</h4> + +<p>The examples above show how to add a fragment to your activity in order to provide a UI. However, +you can also use a fragment to provide a background behavior for the activity without presenting +additional UI.</p> + +<p>To add a fragment without a UI, add the fragment from the activity using {@link +android.app.FragmentTransaction#add(Fragment,String)} (supplying a unique string "tag" for the +fragment, rather than a view ID). This adds the fragment, but, because it's not associated with a +view in the activity layout, it does not receive a call to {@link +android.app.Fragment#onCreateView onCreateView()}. So you don't need to implement that method.</p> + +<p>Supplying a string tag for the fragment isn't strictly for non-UI fragments—you can also +supply string tags to fragments that do have a UI—but if the fragment does not have a +UI, then the string tag is the only way to identify it. If you want to get the fragment from the +activity later, you need to use {@link android.app.FragmentManager#findFragmentByTag +findFragmentByTag()}.</p> + +<p>For an example activity that uses a fragment as a background worker, without a UI, see the <a +href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/FragmentRetainInstance.html">{@code +FragmentRetainInstance.java}</a> sample.</p> + + + +<h2 id="Managing">Managing Fragments</h2> + +<p>To manage the fragments in your activity, you need to use {@link android.app.FragmentManager}. To +get it, call {@link android.app.Activity#getFragmentManager()} from your activity.</p> + +<p>Some things that you can do with {@link android.app.FragmentManager} include:</p> + +<ul> + <li>Get fragments that exist in the activity, with {@link +android.app.FragmentManager#findFragmentById findFragmentById()} (for fragments that provide a UI in +the activity layout) or {@link android.app.FragmentManager#findFragmentByTag +findFragmentByTag()} (for fragments that do or don't provide a UI).</li> + <li>Pop fragments off the back stack, with {@link +android.app.FragmentManager#popBackStack()} (simulating a <em>Back</em> command by the user).</li> + <li>Register a listener for changes to the back stack, with {@link +android.app.FragmentManager#addOnBackStackChangedListener addOnBackStackChangedListener()}.</li> +</ul> + +<p>For more information about these methods and others, refer to the {@link +android.app.FragmentManager} class documentation.</p> + +<p>As demonstrated in the previous section, you can also use {@link android.app.FragmentManager} +to open a {@link android.app.FragmentTransaction}, which allows you to perform transactions, such as +add and remove fragments.</p> + + +<h2 id="Transactions">Performing Fragment Transactions</h2> + +<p>A great feature about using fragments in your activity is the ability to add, remove, replace, +and perform other actions with them, in response to user interaction. Each set of changes that you +commit to the activity is called a transaction and you can perform one using APIs in {@link +android.app.FragmentTransaction}. You can also save each transaction to a back stack managed by the +activity, allowing the user to navigate backward through the fragment changes (similar to navigating +backward through activities).</p> + +<p>You can acquire an instance of {@link android.app.FragmentTransaction} from the {@link +android.app.FragmentManager} like this:</p> + +<pre> +FragmentManager fragmentManager = {@link android.app.Activity#getFragmentManager()}; +FragmentTransaction fragmentTransaction = fragmentManager.{@link android.app.FragmentManager#beginTransaction()}; +</pre> + +<p>Each transaction is a set of changes that you want to perform at the same time. You can set +up all the changes you want to perform for a given transaction using methods such as {@link +android.app.FragmentTransaction#add add()}, {@link android.app.FragmentTransaction#remove remove()}, +and {@link android.app.FragmentTransaction#replace replace()}. Then, to apply the transaction +to the activity, you must call {@link android.app.FragmentTransaction#commit()}.</p> +</dl> + +<p>Before you call {@link +android.app.FragmentTransaction#commit()}, however, you might want to call {@link +android.app.FragmentTransaction#addToBackStack addToBackStack()}, in order to add the transaction +to a back stack of fragment transactions. This back stack is managed by the activity and allows +the user to return to the previous fragment state, by pressing the <em>Back</em> button.</p> + +<p>For example, here's how you can replace one fragment with another, and preserve the previous +state in the back stack:</p> + +<pre> +// Create new fragment and transaction +Fragment newFragment = new ExampleFragment(); +FragmentTransaction transaction = getFragmentManager().beginTransaction(); + +// Replace whatever is in the fragment_container view with this fragment, +// and add the transaction to the back stack +transaction.replace(R.id.fragment_container, newFragment); +transaction.addToBackStack(null); + +// Commit the transaction +transaction.commit(); +</pre> + +<p>In this example, {@code newFragment} replaces whatever fragment (if any) is currently in the +layout container identified by the {@code R.id.fragment_container} ID. By calling {@link +android.app.FragmentTransaction#addToBackStack addToBackStack()}, the replace transaction is +saved to the back stack so the user can reverse the transaction and bring back the +previous fragment by pressing the <em>Back</em> button.</p> + +<p>If you add multiple changes to the transaction (such as another {@link +android.app.FragmentTransaction#add add()} or {@link android.app.FragmentTransaction#remove +remove()}) and call {@link +android.app.FragmentTransaction#addToBackStack addToBackStack()}, then all changes applied +before you call {@link android.app.FragmentTransaction#commit commit()} are added to the +back stack as a single transaction and the <em>Back</em> button will reverse them all together.</p> + +<p>The order in which you add changes to a {@link android.app.FragmentTransaction} doesn't matter, +except:</p> +<ul> + <li>You must call {@link android.app.FragmentTransaction#commit()} last</li> + <li>If you're adding multiple fragments to the same container, then the order in which +you add them determines the order they appear in the view hierarchy</li> +</ul> + +<p>If you do not call {@link android.app.FragmentTransaction#addToBackStack(String) +addToBackStack()} when you perform a transaction that removes a fragment, then that fragment is +destroyed when the transaction is committed and the user cannot navigate back to it. Whereas, if you +do call {@link android.app.FragmentTransaction#addToBackStack(String) addToBackStack()} when +removing a fragment, then the fragment is <em>stopped</em> and will be resumed if the user navigates +back.</p> + +<p class="note"><strong>Tip:</strong> For each fragment transaction, you can apply a transition +animation, by calling {@link android.app.FragmentTransaction#setTransition setTransition()} before +you commit.</p> + +<p>Calling {@link android.app.FragmentTransaction#commit()} does not perform the transaction +immediately. Rather, it schedules it to run on the activity's UI thread (the "main" thread) as soon +as the thread is able to do so. If necessary, however, you may call {@link +android.app.FragmentManager#executePendingTransactions()} from your UI thread to immediately execute +transactions submitted by {@link android.app.FragmentTransaction#commit()}. Doing so is +usually not necessary unless the transaction is a dependency for jobs in other threads.</p> + +<p class="caution"><strong>Caution:</strong> You can commit a transaction using {@link +android.app.FragmentTransaction#commit commit()} only prior to the activity <a +href="{@docRoot}guide/components/activities.html#SavingActivityState">saving its +state</a> (when the user leaves the activity). If you attempt to commit after that point, an +exception will be thrown. This is because the state after the commit can be lost if the activity +needs to be restored. For situations in which its okay that you lose the commit, use {@link +android.app.FragmentTransaction#commitAllowingStateLoss()}.</p> + + + + +<h2 id="CommunicatingWithActivity">Communicating with the Activity</h2> + +<p>Although a {@link android.app.Fragment} is implemented as an object that's independent from an +{@link android.app.Activity} and can be used inside multiple activities, a given instance of +a fragment is directly tied to the activity that contains it.</p> + +<p>Specifically, the fragment can access the {@link android.app.Activity} instance with {@link +android.app.Fragment#getActivity()} and easily perform tasks such as find a view in the +activity layout:</p> + +<pre> +View listView = {@link android.app.Fragment#getActivity()}.{@link android.app.Activity#findViewById findViewById}(R.id.list); +</pre> + +<p>Likewise, your activity can call methods in the fragment by acquiring a reference to the +{@link android.app.Fragment} from {@link android.app.FragmentManager}, using {@link +android.app.FragmentManager#findFragmentById findFragmentById()} or {@link +android.app.FragmentManager#findFragmentByTag findFragmentByTag()}. For example:</p> + +<pre> +ExampleFragment fragment = (ExampleFragment) getFragmentManager().findFragmentById(R.id.example_fragment); +</pre> + + +<h3 id="EventCallbacks">Creating event callbacks to the activity</h3> + +<p>In some cases, you might need a fragment to share events with the activity. A good way to do that +is to define a callback interface inside the fragment and require that the host activity implement +it. When the activity receives a callback through the interface, it can share the information with +other fragments in the layout as necessary.</p> + +<p>For example, if a news application has two fragments in an activity—one to show a list of +articles (fragment A) and another to display an article (fragment B)—then fragment A must tell +the activity when a list item is selected so that it can tell fragment B to display the article. In +this case, the {@code OnArticleSelectedListener} interface is declared inside fragment A:</p> + +<pre> +public static class FragmentA extends ListFragment { + ... + // Container Activity must implement this interface + public interface OnArticleSelectedListener { + public void onArticleSelected(Uri articleUri); + } + ... +} +</pre> + +<p>Then the activity that hosts the fragment implements the {@code OnArticleSelectedListener} +interface and +overrides {@code onArticleSelected()} to notify fragment B of the event from fragment A. To ensure +that the host activity implements this interface, fragment A's {@link +android.app.Fragment#onAttach onAttach()} callback method (which the system calls when adding +the fragment to the activity) instantiates an instance of {@code OnArticleSelectedListener} by +casting the {@link android.app.Activity} that is passed into {@link android.app.Fragment#onAttach +onAttach()}:</p> + +<pre> +public static class FragmentA extends ListFragment { + OnArticleSelectedListener mListener; + ... + @Override + public void onAttach(Activity activity) { + super.onAttach(activity); + try { + mListener = (OnArticleSelectedListener) activity; + } catch (ClassCastException e) { + throw new ClassCastException(activity.toString() + " must implement OnArticleSelectedListener"); + } + } + ... +} +</pre> + +<p>If the activity has not implemented the interface, then the fragment throws a +{@link java.lang.ClassCastException}. +On success, the {@code mListener} member holds a reference to activity's implementation of +{@code OnArticleSelectedListener}, so that fragment A can share events with the activity by calling +methods defined by the {@code OnArticleSelectedListener} interface. For example, if fragment A is an +extension of {@link android.app.ListFragment}, each time +the user clicks a list item, the system calls {@link android.app.ListFragment#onListItemClick +onListItemClick()} in the fragment, which then calls {@code onArticleSelected()} to share +the event with the activity:</p> + +<pre> +public static class FragmentA extends ListFragment { + OnArticleSelectedListener mListener; + ... + @Override + public void onListItemClick(ListView l, View v, int position, long id) { + // Append the clicked item's row ID with the content provider Uri + Uri noteUri = ContentUris.{@link android.content.ContentUris#withAppendedId withAppendedId}(ArticleColumns.CONTENT_URI, id); + // Send the event and Uri to the host activity + mListener.onArticleSelected(noteUri); + } + ... +} +</pre> + +<p>The {@code id} parameter passed to {@link +android.app.ListFragment#onListItemClick onListItemClick()} is the row ID of the clicked item, +which the activity (or other fragment) uses to fetch the article from the application's {@link +android.content.ContentProvider}.</p> + +<p><!--To see a complete implementation of this kind of callback interface, see the <a +href="{@docRoot}resources/samples/NotePad/index.html">NotePad sample</a>. -->More information about +using a content provider is available in the <a +href="{@docRoot}guide/topics/providers/content-providers.html">Content Providers</a> document.</p> + + + +<h3 id="ActionBar">Adding items to the Action Bar</h3> + +<p>Your fragments can contribute menu items to the activity's <a +href="{@docRoot}guide/topics/ui/menus.html#options-menu">Options Menu</a> (and, consequently, the <a +href="{@docRoot}guide/topics/ui/actionbar.html">Action Bar</a>) by implementing +{@link android.app.Fragment#onCreateOptionsMenu(Menu,MenuInflater) onCreateOptionsMenu()}. In order +for this method to receive calls, however, you must call {@link +android.app.Fragment#setHasOptionsMenu(boolean) setHasOptionsMenu()} during {@link +android.app.Fragment#onCreate(Bundle) onCreate()}, to indicate that the fragment +would like to add items to the Options Menu (otherwise, the fragment will not receive a call to +{@link android.app.Fragment#onCreateOptionsMenu onCreateOptionsMenu()}).</p> + +<p>Any items that you then add to the Options Menu from the fragment are appended to the existing +menu items. The fragment also receives callbacks to {@link +android.app.Fragment#onOptionsItemSelected(MenuItem) onOptionsItemSelected()} when a menu item +is selected.</p> + +<p>You can also register a view in your fragment layout to provide a context menu by calling {@link +android.app.Fragment#registerForContextMenu(View) registerForContextMenu()}. When the user opens +the context menu, the fragment receives a call to {@link +android.app.Fragment#onCreateContextMenu(ContextMenu,View,ContextMenu.ContextMenuInfo) +onCreateContextMenu()}. When the user selects an item, the fragment receives a call to {@link +android.app.Fragment#onContextItemSelected(MenuItem) onContextItemSelected()}.</p> + +<p class="note"><strong>Note:</strong> Although your fragment receives an on-item-selected callback +for each menu item it adds, the activity is first to receive the respective callback when the user +selects a menu item. If the activity's implementation of the on-item-selected callback does not +handle the selected item, then the event is passed to the fragment's callback. This is true for +the Options Menu and context menus.</p> + +<p>For more information about menus, see the <a +href="{@docRoot}guide/topics/ui/menus.html">Menus</a> and <a +href="{@docRoot}guide/topics/ui/actionbar.html">Action Bar</a> developer guides.</p> + + + + +<h2 id="Lifecycle">Handling the Fragment Lifecycle</h2> + +<div class="figure" style="width:350px"> +<img src="{@docRoot}images/activity_fragment_lifecycle.png" alt=""/> +<p class="img-caption"><strong>Figure 3.</strong> The effect of the activity lifecycle on the fragment +lifecycle.</p> +</div> + +<p>Managing the lifecycle of a fragment is a lot like managing the lifecycle of an activity. Like +an activity, a fragment can exist in three states:</p> + +<dl> + <dt><i>Resumed</i></dt> + <dd>The fragment is visible in the running activity.</dd> + + <dt><i>Paused</i></dt> + <dd>Another activity is in the foreground and has focus, but the activity in which this +fragment lives is still visible (the foreground activity is partially transparent or doesn't +cover the entire screen).</dd> + + <dt><i>Stopped</i></dt> + <dd>The fragment is not visible. Either the host activity has been stopped or the +fragment has been removed from the activity but added to the back stack. A stopped fragment is +still alive (all state and member information is retained by the system). However, it is no longer +visible to the user and will be killed if the activity is killed.</dd> +</dl> + +<p>Also like an activity, you can retain the state of a fragment using a {@link +android.os.Bundle}, in case the activity's process is killed and you need to restore the +fragment state when the activity is recreated. You can save the state during the fragment's {@link +android.app.Fragment#onSaveInstanceState onSaveInstanceState()} callback and restore it during +either {@link android.app.Fragment#onCreate onCreate()}, {@link +android.app.Fragment#onCreateView onCreateView()}, or {@link +android.app.Fragment#onActivityCreated onActivityCreated()}. For more information about saving +state, see the <a +href="{@docRoot}guide/components/activities.html#SavingActivityState">Activities</a> +document.</p> + +<p>The most significant difference in lifecycle between an activity and a fragment is how one is +stored in its respective back stack. An activity is placed into a back stack of activities +that's managed by the system when it's stopped, by default (so that the user can navigate back +to it with the <em>Back</em> button, as discussed in <a +href="{@docRoot}guide/components/tasks-and-back-stack.html">Tasks and Back Stack</a>). +However, a fragment is placed into a back stack managed by the host activity only when you +explicitly request that the instance be saved by calling {@link +android.app.FragmentTransaction#addToBackStack(String) addToBackStack()} during a transaction that +removes the fragment.</p> + +<p>Otherwise, managing the fragment lifecycle is very similar to managing the activity +lifecycle. So, the same practices for <a +href="{@docRoot}guide/components/activities.html#Lifecycle">managing the activity +lifecycle</a> also apply to fragments. What you also need to understand, though, is how the life +of the activity affects the life of the fragment.</p> + + +<h3 id="CoordinatingWithActivity">Coordinating with the activity lifecycle</h3> + +<p>The lifecycle of the activity in which the fragment lives directly affects the lifecycle of the +fragment, such that each lifecycle callback for the activity results in a similar callback for each +fragment. For example, when the activity receives {@link android.app.Activity#onPause}, each +fragment in the activity receives {@link android.app.Fragment#onPause}.</p> + +<p>Fragments have a few extra lifecycle callbacks, however, that handle unique interaction with the +activity in order to perform actions such as build and destroy the fragment's UI. These additional +callback methods are:</p> + +<dl> + <dt>{@link android.app.Fragment#onAttach onAttach()}</dt> + <dd>Called when the fragment has been associated with the activity (the {@link +android.app.Activity} is passed in here).</dd> + <dt>{@link android.app.Fragment#onCreateView onCreateView()}</dt> + <dd>Called to create the view hierarchy associated with the fragment.</dd> + <dt>{@link android.app.Fragment#onActivityCreated onActivityCreated()}</dt> + <dd>Called when the activity's {@link android.app.Activity#onCreate +onCreate()} method has returned.</dd> + <dt>{@link android.app.Fragment#onDestroyView onDestroyView()}</dt> + <dd>Called when the view hierarchy associated with the fragment is being removed.</dd> + <dt>{@link android.app.Fragment#onDetach onDetach()}</dt> + <dd>Called when the fragment is being disassociated from the activity.</dd> +</dl> + +<p>The flow of a fragment's lifecycle, as it is affected by its host activity, is illustrated +by figure 3. In this figure, you can see how each successive state of the activity determines which +callback methods a fragment may receive. For example, when the activity has received its {@link +android.app.Activity#onCreate onCreate()} callback, a fragment in the activity receives no more than +the {@link android.app.Fragment#onActivityCreated onActivityCreated()} callback.</p> + +<p>Once the activity reaches the resumed state, you can freely add and remove fragments to the +activity. Thus, only while the activity is in the resumed state can the lifecycle of a fragment +change independently.</p> + +<p>However, when the activity leaves the resumed state, the fragment again is pushed through its +lifecycle by the activity.</p> + + + + +<h2 id="Example">Example</h2> + +<p>To bring everything discussed in this document together, here's an example of an activity +using two fragments to create a two-pane layout. The activity below includes one fragment to +show a list of Shakespeare play titles and another to show a summary of the play when selected +from the list. It also demonstrates how to provide different configurations of the fragments, +based on the screen configuration.</p> + +<p class="note"><strong>Note:</strong> The complete source code for this activity is available in +<a +href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/FragmentLayout.html">{@code +FragmentLayout.java}</a>.</p> + +<p>The main activity applies a layout in the usual way, during {@link +android.app.Activity#onCreate onCreate()}:</p> + +{@sample development/samples/ApiDemos/src/com/example/android/apis/app/FragmentLayout.java main} + +<p>The layout applied is {@code fragment_layout.xml}:</p> + +{@sample development/samples/ApiDemos/res/layout-land/fragment_layout.xml layout} + +<p>Using this layout, the system instantiates the {@code TitlesFragment} (which lists the play +titles) as soon as the activity loads the layout, while the {@link android.widget.FrameLayout} +(where the fragment for showing the play summary will go) consumes space on the right side of the +screen, but remains empty at first. As you'll see below, it's not until the user selects an item +from the list that a fragment is placed into the {@link android.widget.FrameLayout}.</p> + +<p>However, not all screen configurations are wide enough to show both the list of +plays and the summary, side by side. So, the layout above is used only for the landscape +screen configuration, by saving it at {@code res/layout-land/fragment_layout.xml}.</p> + +<p>Thus, when the screen is in portrait orientation, the system applies the following layout, which +is saved at {@code res/layout/fragment_layout.xml}:</p> + +{@sample development/samples/ApiDemos/res/layout/fragment_layout.xml layout} + +<p>This layout includes only {@code TitlesFragment}. This means that, when the device is in +portrait orientation, only the list of play titles is visible. So, when the user clicks a list +item in this configuration, the application will start a new activity to show the summary, +instead of loading a second fragment.</p> + +<p>Next, you can see how this is accomplished in the fragment classes. First is {@code +TitlesFragment}, which shows the list of Shakespeare play titles. This fragment extends {@link +android.app.ListFragment} and relies on it to handle most of the list view work.</p> + +<p>As you inspect this code, notice that there are two possible behaviors when the user clicks a +list item: depending on which of the two layouts is active, it can either create and display a new +fragment to show the details in the same activity (adding the fragment to the {@link +android.widget.FrameLayout}), or start a new activity (where the fragment can be shown).</p> + +{@sample development/samples/ApiDemos/src/com/example/android/apis/app/FragmentLayout.java titles} + +<p>The second fragment, {@code DetailsFragment} shows the play summary for the item selected from +the list from {@code TitlesFragment}:</p> + +{@sample development/samples/ApiDemos/src/com/example/android/apis/app/FragmentLayout.java details} + +<p>Recall from the {@code TitlesFragment} class, that, if the user clicks a list item and the +current layout does <em>not</em> include the {@code R.id.details} view (which is where the +{@code DetailsFragment} belongs), then the application starts the {@code DetailsActivity} +activity to display the content of the item.</p> + +<p>Here is the {@code DetailsActivity}, which simply embeds the {@code DetailsFragment} to display +the selected play summary when the screen is in portrait orientation:</p> + +{@sample development/samples/ApiDemos/src/com/example/android/apis/app/FragmentLayout.java +details_activity} + +<p>Notice that this activity finishes itself if the configuration is landscape, so that the main +activity can take over and display the {@code DetailsFragment} alongside the {@code TitlesFragment}. +This can happen if the user begins the {@code DetailsActivity} while in portrait orientation, but +then rotates to landscape (which restarts the current activity).</p> + + +<p>For more samples using fragments (and complete source files for this example), +see the sample code available in <a +href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/index.html#Fragment"> +ApiDemos</a> (available for download from the <a +href="{@docRoot}resources/samples/get.html">Samples SDK component</a>).</p> + + diff --git a/docs/html/guide/components/fundamentals.jd b/docs/html/guide/components/fundamentals.jd new file mode 100644 index 0000000..1717782 --- /dev/null +++ b/docs/html/guide/components/fundamentals.jd @@ -0,0 +1,518 @@ +page.title=Application Fundamentals +@jd:body + +<div id="qv-wrapper"> +<div id="qv"> + +<h2>Quickview</h2> +<ul> + <li>Android applications are composed of one or more application components (activities, +services, content providers, and broadcast receivers)</li> + <li>Each component performs a different role in the overall application behavior, and each +one can be activated individually (even by other applications)</li> + <li>The manifest file must declare all components in the application and should also declare +all application requirements, such as the minimum version of Android required and any hardware +configurations required</li> + <li>Non-code application resources (images, strings, layout files, etc.) should include +alternatives for different device configurations (such as different strings for different +languages and different layouts for different screen sizes)</li> +</ul> + + +<h2>In this document</h2> +<ol> +<li><a href="#Components">Application Components</a> + <ol> + <li><a href="#ActivatingComponents">Activating components</a></li> + </ol> +</li> +<li><a href="#Manifest">The Manifest File</a> + <ol> + <li><a href="#DeclaringComponents">Declaring components</a></li> + <li><a href="#DeclaringRequirements">Declaring application requirements</a></li> + </ol> +</li> +<li><a href="#Resources">Application Resources</a></li> +</ol> +</div> +</div> + +<p>Android applications are written in the Java programming language. The Android SDK tools compile +the code—along with any data and resource files—into an <i>Android package</i>, an +archive file with an {@code .apk} suffix. All the code in a single {@code .apk} file is considered +to be one application and is the file that Android-powered devices use to install the +application.</p> + +<p>Once installed on a device, each Android application lives in its own security sandbox: </p> + +<ul> + <li>The Android operating system is a multi-user Linux system in which each application is a +different user.</li> + +<li>By default, the system assigns each application a unique Linux user ID (the ID is used only by +the system and is unknown to the application). The system sets permissions for all the files in an +application so that only the user ID assigned to that application can access them. </li> + +<li>Each process has its own virtual machine (VM), so an application's code runs in isolation from +other applications.</li> + +<li>By default, every application runs in its own Linux process. Android starts the process when any +of the application's components need to be executed, then shuts down the process when it's no longer +needed or when the system must recover memory for other applications.</li> +</ul> + +<p>In this way, the Android system implements the <em>principle of least privilege</em>. That is, +each application, by default, has access only to the components that it requires to do its work and +no more. This creates a very secure environment in which an application cannot access parts of +the system for which it is not given permission.</p> + +<p>However, there are ways for an application to share data with other applications and for an +application to access system services:</p> + +<ul> + <li>It's possible to arrange for two applications to share the same Linux user ID, in which case +they are able to access each other's files. To conserve system resources, applications with the +same user ID can also arrange to run in the same Linux process and share the same VM (the +applications must also be signed with the same certificate).</li> + <li>An application can request permission to access device data such as the user's +contacts, SMS messages, the mountable storage (SD card), camera, Bluetooth, and more. All +application permissions must be granted by the user at install time.</li> +</ul> + +<p>That covers the basics regarding how an Android application exists within the system. The rest of +this document introduces you to:</p> +<ul> + <li>The core framework components that define your application.</li> + <li>The manifest file in which you declare components and required device features for your +application.</li> + <li>Resources that are separate from the application code and allow your application to +gracefully optimize its behavior for a variety of device configurations.</li> +</ul> + +<!-- +<p class="note"><strong>Tip:</strong> If you're new to Android development, we suggest that you +follow the Beginner's Path link at the bottom of this page. For each document in the Application +Fundamentals, the Beginner's Path points you to the document we suggest you read next, in order +to get up to speed on the core Android concepts.</p> +--> + + +<h2 id="Components">Application Components</h2> + +<p>Application components are the essential building blocks of an Android application. Each +component is a different point through which the system can enter your application. Not all +components are actual entry points for the user and some depend on each other, but each one exists +as its own entity and plays a specific role—each one is a unique building block that +helps define your application's overall behavior.</p> + +<p>There are four different types of application components. Each type serves a distinct purpose +and has a distinct lifecycle that defines how the component is created and destroyed.</p> + +<p>Here are the four types of application components:</p> + +<dl> + +<dt><b>Activities</b></dt> + +<dd>An <i>activity</i> represents a single screen with a user interface. For example, +an email application might have one activity that shows a list of new +emails, another activity to compose an email, and another activity for reading emails. Although +the activities work together to form a cohesive user experience in the email application, each one +is independent of the others. As such, a different application can start any one of these +activities (if the email application allows it). For example, a camera application can start the +activity in the email application that composes new mail, in order for the user to share a picture. + +<p>An activity is implemented as a subclass of {@link android.app.Activity} and you can learn more +about it in the <a href="{@docRoot}guide/components/activities.html">Activities</a> +developer guide.</p> +</dd> + + +<dt><b>Services</b></dt> + +<dd>A <i>service</i> is a component that runs in the background to perform long-running +operations or to perform work for remote processes. A service +does not provide a user interface. For example, a service might play music in the background while +the user is in a different application, or it might fetch data over the network without +blocking user interaction with an activity. Another component, such as an activity, can start the +service and let it run or bind to it in order to interact with it. + +<p>A service is implemented as a subclass of {@link android.app.Service} and you can learn more +about it in the <a href="{@docRoot}guide/components/services.html">Services</a> developer +guide.</p> +</dd> + + +<dt><b>Content providers</b></dt> + +<dd>A <i>content provider</i> manages a shared set of application data. You can store the data in +the file system, an SQLite database, on the web, or any other persistent storage location your +application can access. Through the content provider, other applications can query or even modify +the data (if the content provider allows it). For example, the Android system provides a content +provider that manages the user's contact information. As such, any application with the proper +permissions can query part of the content provider (such as {@link +android.provider.ContactsContract.Data}) to read and write information about a particular person. + +<p>Content providers are also useful for reading and writing data that is private to your +application and not shared. For example, the <a +href="{@docRoot}resources/samples/NotePad/index.html">Note Pad</a> sample application uses a +content provider to save notes.</p> + +<p>A content provider is implemented as a subclass of {@link android.content.ContentProvider} +and must implement a standard set of APIs that enable other applications to perform +transactions. For more information, see the <a +href="{@docRoot}guide/topics/providers/content-providers.html">Content Providers</a> developer +guide.</p> +</dd> + + +<dt><b>Broadcast receivers</b></dt> + +<dd>A <i>broadcast receiver</i> is a component that responds to system-wide broadcast +announcements. Many broadcasts originate from the system—for example, a broadcast announcing +that the screen has turned off, the battery is low, or a picture was captured. +Applications can also initiate broadcasts—for example, to let other applications know that +some data has been downloaded to the device and is available for them to use. Although broadcast +receivers don't display a user interface, they may <a +href="{@docRoot}guide/topics/ui/notifiers/notifications.html">create a status bar notification</a> +to alert the user when a broadcast event occurs. More commonly, though, a broadcast receiver is +just a "gateway" to other components and is intended to do a very minimal amount of work. For +instance, it might initiate a service to perform some work based on the event. + +<p>A broadcast receiver is implemented as a subclass of {@link android.content.BroadcastReceiver} +and each broadcast is delivered as an {@link android.content.Intent} object. For more information, +see the {@link android.content.BroadcastReceiver} class.</p> +</dd> + +</dl> + + + +<p>A unique aspect of the Android system design is that any application can start another +application’s component. For example, if you want the user to capture a +photo with the device camera, there's probably another application that does that and your +application can use it, instead of developing an activity to capture a photo yourself. You don't +need to incorporate or even link to the code from the camera application. +Instead, you can simply start the activity in the camera application that captures a +photo. When complete, the photo is even returned to your application so you can use it. To the user, +it seems as if the camera is actually a part of your application.</p> + +<p>When the system starts a component, it starts the process for that application (if it's not +already running) and instantiates the classes needed for the component. For example, if your +application starts the activity in the camera application that captures a photo, that activity +runs in the process that belongs to the camera application, not in your application's process. +Therefore, unlike applications on most other systems, Android applications don't have a single entry +point (there's no {@code main()} function, for example).</p> + +<p>Because the system runs each application in a separate process with file permissions that +restrict access to other applications, your application cannot directly activate a component from +another application. The Android system, however, can. So, to activate a component in +another application, you must deliver a message to the system that specifies your <em>intent</em> to +start a particular component. The system then activates the component for you.</p> + + +<h3 id="ActivatingComponents">Activating Components</h3> + +<p>Three of the four component types—activities, services, and +broadcast receivers—are activated by an asynchronous message called an <em>intent</em>. +Intents bind individual components to each other at runtime (you can think of them +as the messengers that request an action from other components), whether the component belongs +to your application or another.</p> + +<p>An intent is created with an {@link android.content.Intent} object, which defines a message to +activate either a specific component or a specific <em>type</em> of component—an intent +can be either explicit or implicit, respectively.</p> + +<p>For activities and services, an intent defines the action to perform (for example, to "view" or +"send" something) and may specify the URI of the data to act on (among other things that the +component being started might need to know). For example, an intent might convey a request for an +activity to show an image or to open a web page. In some cases, you can start an +activity to receive a result, in which case, the activity also returns +the result in an {@link android.content.Intent} (for example, you can issue an intent to let +the user pick a personal contact and have it returned to you—the return intent includes a +URI pointing to the chosen contact).</p> + +<p>For broadcast receivers, the intent simply defines the +announcement being broadcast (for example, a broadcast to indicate the device battery is low +includes only a known action string that indicates "battery is low").</p> + +<p>The other component type, content provider, is not activated by intents. Rather, it is +activated when targeted by a request from a {@link android.content.ContentResolver}. The content +resolver handles all direct transactions with the content provider so that the component that's +performing transactions with the provider doesn't need to and instead calls methods on the {@link +android.content.ContentResolver} object. This leaves a layer of abstraction between the content +provider and the component requesting information (for security).</p> + +<p>There are separate methods for activating each type of component:</p> +<ul> + <li>You can start an activity (or give it something new to do) by +passing an {@link android.content.Intent} to {@link android.content.Context#startActivity +startActivity()} or {@link android.app.Activity#startActivityForResult startActivityForResult()} +(when you want the activity to return a result).</li> + <li>You can start a service (or give new instructions to an ongoing service) by +passing an {@link android.content.Intent} to {@link android.content.Context#startService +startService()}. Or you can bind to the service by passing an {@link android.content.Intent} to +{@link android.content.Context#bindService bindService()}.</li> + <li>You can initiate a broadcast by passing an {@link android.content.Intent} to methods like +{@link android.content.Context#sendBroadcast(Intent) sendBroadcast()}, {@link +android.content.Context#sendOrderedBroadcast(Intent, String) sendOrderedBroadcast()}, or {@link +android.content.Context#sendStickyBroadcast sendStickyBroadcast()}.</li> + <li>You can perform a query to a content provider by calling {@link +android.content.ContentProvider#query query()} on a {@link android.content.ContentResolver}.</li> +</ul> + +<p>For more information about using intents, see the <a +href="{@docRoot}guide/components/intents-filters.html">Intents and +Intent Filters</a> document. More information about activating specific components is also provided +in the following documents: <a +href="{@docRoot}guide/components/activities.html">Activities</a>, <a +href="{@docRoot}guide/components/services.html">Services</a>, {@link +android.content.BroadcastReceiver} and <a +href="{@docRoot}guide/topics/providers/content-providers.html">Content Providers</a>.</p> + + +<h2 id="Manifest">The Manifest File</h2> + +<p>Before the Android system can start an application component, the system must know that the +component exists by reading the application's {@code AndroidManifest.xml} file (the "manifest" +file). Your application must declare all its components in this file, which must be at the root of +the application project directory.</p> + +<p>The manifest does a number of things in addition to declaring the application's components, +such as:</p> +<ul> + <li>Identify any user permissions the application requires, such as Internet access or +read-access to the user's contacts.</li> + <li>Declare the minimum <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#ApiLevels">API Level</a> +required by the application, based on which APIs the application uses.</li> + <li>Declare hardware and software features used or required by the application, such as a camera, +bluetooth services, or a multitouch screen.</li> + <li>API libraries the application needs to be linked against (other than the Android framework +APIs), such as the <a +href="http://code.google.com/android/add-ons/google-apis/maps-overview.html">Google Maps +library</a>.</li> + <li>And more</li> +</ul> + + +<h3 id="DeclaringComponents">Declaring components</h3> + +<p>The primary task of the manifest is to inform the system about the application's components. For +example, a manifest file can declare an activity as follows: </p> + +<pre> +<?xml version="1.0" encoding="utf-8"?> +<manifest ... > + <application android:icon="@drawable/app_icon.png" ... > + <activity android:name="com.example.project.ExampleActivity" + android:label="@string/example_label" ... > + </activity> + ... + </application> +</manifest></pre> + +<p>In the <code><a +href="{@docRoot}guide/topics/manifest/application-element.html"><application></a></code> +element, the {@code android:icon} attribute points to resources for an icon that identifies the +application.</p> + +<p>In the <code><a +href="{@docRoot}guide/topics/manifest/activity-element.html"><activity></a></code> element, +the {@code android:name} attribute specifies the fully qualified class name of the {@link +android.app.Activity} subclass and the {@code android:label} attributes specifies a string +to use as the user-visible label for the activity.</p> + +<p>You must declare all application components this way:</p> +<ul> + <li><code><a +href="{@docRoot}guide/topics/manifest/activity-element.html"><activity></a></code> elements +for activities</li> + <li><code><a +href="{@docRoot}guide/topics/manifest/service-element.html"><service></a></code> elements for +services</li> + <li><code><a +href="{@docRoot}guide/topics/manifest/receiver-element.html"><receiver></a></code> elements +for broadcast receivers</li> + <li><code><a +href="{@docRoot}guide/topics/manifest/provider-element.html"><provider></a></code> elements +for content providers</li> +</ul> + +<p>Activities, services, and content providers that you include in your source but do not declare +in the manifest are not visible to the system and, consequently, can never run. However, +broadcast +receivers can be either declared in the manifest or created dynamically in code (as +{@link android.content.BroadcastReceiver} objects) and registered with the system by calling +{@link android.content.Context#registerReceiver registerReceiver()}.</p> + +<p>For more about how to structure the manifest file for your application, see the <a +href="{@docRoot}guide/topics/manifest/manifest-intro.html">The AndroidManifest.xml File</a> +documentation. </p> + + + +<h3 id="DeclaringComponentCapabilities">Declaring component capabilities</h3> + +<p>As discussed above, in <a href="#ActivatingComponents">Activating Components</a>, you can use an +{@link android.content.Intent} to start activities, services, and broadcast receivers. You can do so +by explicitly naming the target component (using the component class name) in the intent. However, +the real power of intents lies in the concept of intent actions. With intent actions, you simply +describe the type of action you want to perform (and optionally, the data upon which you’d like to +perform the action) and allow the system to find a component on the device that can perform the +action and start it. If there are multiple components that can perform the action described by the +intent, then the user selects which one to use.</p> + +<p>The way the system identifies the components that can respond to an intent is by comparing the +intent received to the <i>intent filters</i> provided in the manifest file of other applications on +the device.</p> + +<p>When you declare a component in your application's manifest, you can optionally include +intent filters that declare the capabilities of the component so it can respond to intents +from other applications. You can declare an intent filter for your component by +adding an <a href="{@docRoot}guide/topics/manifest/intent-filter-element.html">{@code +<intent-filter>}</a> element as a child of the component's declaration element.</p> + +<p>For example, an email application with an activity for composing a new email might declare an +intent filter in its manifest entry to respond to "send" intents (in order to send email). An +activity in your application can then create an intent with the “send” action ({@link +android.content.Intent#ACTION_SEND}), which the system matches to the email application’s “send” +activity and launches it when you invoke the intent with {@link android.app.Activity#startActivity +startActivity()}.</p> + +<p>For more about creating intent filters, see the <a +href="{@docRoot}guide/components/intents-filters.html">Intents and Intent Filters</a> document. +</p> + + + +<h3 id="DeclaringRequirements">Declaring application requirements</h3> + +<p>There are a variety of devices powered by Android and not all of them provide the +same features and capabilities. In order to prevent your application from being installed on devices +that lack features needed by your application, it's important that you clearly define a profile for +the types of devices your application supports by declaring device and software requirements in your +manifest file. Most of these declarations are informational only and the system does not read +them, but external services such as Google Play do read them in order to provide filtering +for users when they search for applications from their device.</p> + +<p>For example, if your application requires a camera and uses APIs introduced in Android 2.1 (<a +href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#ApiLevels">API Level</a> 7), you should declare these as +requirements in your manifest file. That way, devices that do <em>not</em> have a camera and have an +Android version <em>lower</em> than 2.1 cannot install your application from Google Play.</p> + +<p>However, you can also declare that your application uses the camera, but does not +<em>require</em> it. In that case, your application must perform a check at runtime to determine +if the device has a camera and disable any features that use the camera if one is not available.</p> + +<p>Here are some of the important device characteristics that you should consider as you design and +develop your application:</p> + +<dl> + <dt>Screen size and density</dt> + <dd>In order to categorize devices by their screen type, Android defines two characteristics for +each device: screen size (the physical dimensions of the screen) and screen density (the physical +density of the pixels on the screen, or dpi—dots per inch). To simplify all the different +types of screen configurations, the Android system generalizes them into select groups that make +them easier to target. +<p>The screen sizes are: small, normal, large, and extra large.<br/> +The screen densities are: low density, medium density, high density, and extra high density.</p> + +<p>By default, your application is compatible with all screen sizes and densities, +because the Android system makes the appropriate adjustments to your UI layout and image +resources. However, you should create specialized layouts for certain screen sizes and provide +specialized images for certain densities, using alternative layout resources, and by declaring in +your manifest exactly which screen sizes your application supports with the <a +href="{@docRoot}guide/topics/manifest/supports-screens-element.html">{@code +<supports-screens>}</a> element.</p> +<p>For more information, see the <a +href="{@docRoot}guide/practices/screens_support.html">Supporting Multiple Screens</a> +document.</p></dd> + + <dt>Input configurations</dt> + <dd>Many devices provide a different type of user input mechanism, such as a hardware keyboard, a +trackball, or a five-way navigation pad. If your application requires a particular kind of input +hardware, then you should declare it in your manifest with the <a +href="{@docRoot}guide/topics/manifest/uses-configuration-element.html">{@code +<uses-configuration>}</a> element. However, it is rare that an application should require +a certain input configuration.</dd> + + <dt>Device features</dt> + <dd>There are many hardware and software features that may or may not exist on a given +Android-powered device, such as a camera, a light sensor, bluetooth, a certain +version of OpenGL, or the fidelity of the touchscreen. You should never assume that a certain +feature is available on all Android-powered devices (other than the availability of the standard +Android library), so you should declare any features used by your application with the <a +href="{@docRoot}guide/topics/manifest/uses-feature-element.html">{@code <uses-feature>}</a> +element.</dd> + + <dt>Platform Version</dt> + <dd>Different Android-powered devices often run different versions of the Android platform, +such as Android 1.6 or Android 2.3. Each successive version often includes additional APIs not +available in the previous version. In order to indicate which set of APIs are available, each +platform version specifies an <a +href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#ApiLevels">API Level</a> (for example, Android 1.0 is API Level +1 and Android 2.3 is API Level 9). If you use any APIs that were added to the platform after +version 1.0, you should declare the minimum API Level in which those APIs were introduced using the +<a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html">{@code <uses-sdk>}</a> +element.</dd> +</dl> + +<p>It's important that you declare all such requirements for your application, because, when you +distribute your application on Google Play, the store uses these declarations to filter which +applications are available on each device. As such, your application should be available only to +devices that meet all your application requirements.</p> + +<p>For more information about how Google Play filters applications based on these (and other) +requirements, see the <a href="{@docRoot}guide/google/play/filters.html">Filters on Google Play</a> +document.</p> + + + +<h2 id="Resources">Application Resources</h2> + +<p>An Android application is composed of more than just code—it requires resources that are +separate from the source code, such as images, audio files, and anything relating to the visual +presentation of the application. For example, you should define animations, menus, styles, colors, +and the layout of activity user interfaces with XML files. Using application resources makes it easy +to update various characteristics of your application without modifying code and—by providing +sets of alternative resources—enables you to optimize your application for a variety of +device configurations (such as different languages and screen sizes).</p> + +<p>For every resource that you include in your Android project, the SDK build tools define a unique +integer ID, which you can use to reference the resource from your application code or from +other resources defined in XML. For example, if your application contains an image file named {@code +logo.png} (saved in the {@code res/drawable/} directory), the SDK tools generate a resource ID +named {@code R.drawable.logo}, which you can use to reference the image and insert it in your +user interface.</p> + +<p>One of the most important aspects of providing resources separate from your source code +is the ability for you to provide alternative resources for different device +configurations. For example, by defining UI strings in XML, you can translate the strings into other +languages and save those strings in separate files. Then, based on a language <em>qualifier</em> +that you append to the resource directory's name (such as {@code res/values-fr/} for French string +values) and the user's language setting, the Android system applies the appropriate language strings +to your UI.</p> + +<p>Android supports many different <em>qualifiers</em> for your alternative resources. The +qualifier is a short string that you include in the name of your resource directories in order to +define the device configuration for which those resources should be used. As another +example, you should often create different layouts for your activities, depending on the +device's screen orientation and size. For example, when the device screen is in portrait +orientation (tall), you might want a layout with buttons to be vertical, but when the screen is in +landscape orientation (wide), the buttons should be aligned horizontally. To change the layout +depending on the orientation, you can define two different layouts and apply the appropriate +qualifier to each layout's directory name. Then, the system automatically applies the appropriate +layout depending on the current device orientation.</p> + +<p>For more about the different kinds of resources you can include in your application and how +to create alternative resources for various device configurations, see the <a +href="{@docRoot}guide/topics/resources/index.html">Application Resources</a> developer guide.</p> + + +<!-- +<h2>Beginner's Path</h2> + +<p>For a close look at implementing activities—the components your users use to +interact with your application—continue with the <b><a +href="{@docRoot}guide/components/activities.html">Activities</a></b> document.</p> +--> diff --git a/docs/html/guide/components/index.jd b/docs/html/guide/components/index.jd new file mode 100644 index 0000000..87bae53 --- /dev/null +++ b/docs/html/guide/components/index.jd @@ -0,0 +1,56 @@ +page.title=App Components +page.landing=true +page.landing.intro=Android's application framework lets you create extremely rich and innovative apps using a set of reusable components. This section explains how Android apps work and how you use components to build them. +page.landing.image=images/develop/app_components.png + +@jd:body + +<div class="landing-docs"> + + <div class="col-6"> + <h3>Blog Articles</h3> + + <a href="http://android-developers.blogspot.com/2012/05/using-dialogfragments.html"> + <h4>Using DialogFragments</h4> + <p>In this post, I’ll show how to use DialogFragments with the v4 support library (for backward compatibility on pre-Honeycomb devices) to show a simple edit dialog and return a result to the calling Activity using an interface.</p> + </a> + + <a href="http://android-developers.blogspot.com/2011/03/fragments-for-all.html"> + <h4>Fragments For All</h4> + <p>Today we’ve released a static library that exposes the same Fragments API (as well as the new LoaderManager and a few other classes) so that applications compatible with Android 1.6 or later can use fragments to create tablet-compatible user interfaces. </p> + </a> + + <a +href="http://android-developers.blogspot.com/2010/07/multithreading-for-performance.html"> + <h4>Multithreading for Performance</h4> + <p>A good practice in creating responsive applications is to make sure your main UI thread +does the minimum amount of work. Any potentially long task that may hang your application should be +handled in a different thread.</p> + </a> + </div> + + <div class="col-6"> + <h3>Training</h3> + + <a href="http://developer.android.com/training/basics/activity-lifecycle/index.html"> + <h4>Managing the Activity Lifecycle</h4> + <p>This class explains important lifecycle callback methods that each Activity + instance receives and how you can use them so your activity does what the user expects and does not consume system + resources when your activity doesn't need them.</p> + </a> + + <a href="http://developer.android.com/training/basics/fragments/index.html"> + <h4>Building a Dynamic UI with Fragments</h4> + <p>This class shows you how to create a dynamic user experience with fragments and optimize +your app's user experience for devices with different screen sizes, all while continuing to support +devices running versions as old as Android 1.6.</p> + </a> + + <a href="http://developer.android.com/training/sharing/index.html"> + <h4>Sharing Content</h4> + <p>This class covers some common ways you can send and receive content between + applications using Intent APIs and the ActionProvider object.</p> + </a> + </div> + +</div> diff --git a/docs/html/guide/components/intents-filters.jd b/docs/html/guide/components/intents-filters.jd new file mode 100644 index 0000000..3ad3c93 --- /dev/null +++ b/docs/html/guide/components/intents-filters.jd @@ -0,0 +1,1055 @@ +page.title=Intents and Intent Filters +@jd:body + +<div id="qv-wrapper"> +<div id="qv"> + +<h2>In this document</h2> +<ol> +<li><a href="#iobjs">Intent Objects</a></li> +<li><a href="#ires">Intent Resolution</a></li> +<li style="margin-left: 2em"><a href="#ifs">Intent filters</a></li> +<li style="margin-left: 2em"><a href="#ccases">Common cases</a></li> +<li style="margin-left: 2em"><a href="#imatch">Using intent matching</a></li> +<li><a href="#npex">Note Pad Example</a></li> +</ol> + +<h2>Key classes</h2> +<ol> +<li>{@link android.content.Intent}</li> +<li>{@link android.content.IntentFilter}</li> +<li>{@link android.content.BroadcastReceiver}</li> +<li>{@link android.content.pm.PackageManager}</li> +</ol> + +</div> +</div> + + +<p> +Three of the core components of an application — activities, services, and +broadcast receivers — are activated through messages, called <i>intents</i>. +Intent messaging is a facility for late run-time binding between components in the same +or different applications. The intent itself, an {@link android.content.Intent} +object, is a passive data structure holding an abstract description of an operation +to be performed — or, often in the case of broadcasts, a description of something +that has happened and is being announced. There are separate mechanisms for +delivering intents to each type of component: +</p> + +<ul> +<li>An Intent object is passed to <code>{@link android.content.Context#startActivity +Context.startActivity()}</code> or <code>{@link android.app.Activity#startActivityForResult +Activity.startActivityForResult()}</code> to launch an activity or get an existing +activity to do something new. (It can also be passed to +<code>{@link android.app.Activity#setResult(int, Intent) Activity.setResult()}</code> +to return information to the activity that called {@code startActivityForResult()}.)</li> + +<li><p>An Intent object is passed to <code>{@link android.content.Context#startService +Context.startService()}</code> to initiate a service or deliver new instructions to an +ongoing service. Similarly, an intent can be passed to <code>{@link +android.content.Context#bindService Context.bindService()}</code> to establish a +connection between the calling component and a target service. It can optionally +initiate the service if it's not already running.</p></li> + +<li><p>Intent objects passed to any of the broadcast methods (such as <code>{@link +android.content.Context#sendBroadcast(Intent) Context.sendBroadcast()}</code>, +<code>{@link android.content.Context#sendOrderedBroadcast(Intent, String) +Context.sendOrderedBroadcast()}</code>, or <code>{@link +android.content.Context#sendStickyBroadcast Context.sendStickyBroadcast()}</code>) +are delivered to all interested broadcast receivers. Many kinds of broadcasts +originate in system code.</p></li> +</ul> + +<p> +In each case, the Android system finds the appropriate activity, service, or set +of broadcast receivers to respond to the intent, instantiating them if necessary. +There is no overlap within these messaging systems: Broadcast intents are delivered +only to broadcast receivers, never to activities or services. An intent passed to +{@code startActivity()} is delivered only to an activity, never to a service or +broadcast receiver, and so on. +</p> + +<p> +This document begins with a description of Intent objects. It then describes the +rules Android uses to map intents to components — how it resolves which +component should receive an intent message. For intents that don't explicitly +name a target component, this process involves testing the Intent object against +<i>intent filters</i> associated with potential targets. +</p> + + +<h2><a name="iobjs"></a>Intent Objects</h2> + +<p> +An {@link android.content.Intent} object is a bundle of information. It +contains information of interest to the component that receives the intent +(such as the action to be taken and the data to act on) plus information +of interest to the Android system (such as the category of component that +should handle the intent and instructions on how to launch a target activity). +Principally, it can contain the following: +</p> + +<dl> + +<dt><b>Component name</b><a name="cname"></a></dt> +<dd>The name of the component that should handle the intent. This field is +a {@link android.content.ComponentName} object — a combination of the +fully qualified class name of the target component (for example "{@code +com.example.project.app.FreneticActivity}") and the package name set +in the manifest file of the application where the component resides (for +example, "{@code com.example.project}"). The package part of the component +name and the package name set in the manifest do not necessarily have to match. + +<p> +The component name is optional. If it is set, the Intent object is +delivered to an instance of the designated class. If it is not set, +Android uses other information in the Intent object to locate a suitable +target — see <a href="#ires">Intent Resolution</a>, later in this +document. +</p> + +<p> +The component name is set by <code>{@link android.content.Intent#setComponent +setComponent()}</code>, <code>{@link android.content.Intent#setClass +setClass()}</code>, or <code>{@link android.content.Intent#setClassName(String, String) +setClassName()}</code> and read by <code>{@link android.content.Intent#getComponent +getComponent()}</code>. +</p> +</dd> + +<p><dt><b>Action</b></dt> +<dd>A string naming the action to be performed — or, in the case of broadcast +intents, the action that took place and is being reported. The Intent class defines +a number of action constants, including these: +</p> + +<table> +<tr> + <th>Constant</th> + <th>Target component</th> + <th>Action</th> +</tr><tr> + <td>{@code ACTION_CALL} + <td>activity + <td>Initiate a phone call. +</tr><tr> + <td>{@code ACTION_EDIT} + <td>activity + <td>Display data for the user to edit. +</tr><tr> + <td>{@code ACTION_MAIN} + <td>activity + <td>Start up as the initial activity of a task, with no data input and no returned output. +</tr><tr> + <td>{@code ACTION_SYNC} + <td>activity + <td>Synchronize data on a server with data on the mobile device. +</tr><tr> + <td>{@code ACTION_BATTERY_LOW} + <td>broadcast receiver + <td>A warning that the battery is low. +</tr><tr> + <td>{@code ACTION_HEADSET_PLUG} + <td>broadcast receiver + <td>A headset has been plugged into the device, or unplugged from it. +</tr><tr> + <td>{@code ACTION_SCREEN_ON} + <td>broadcast receiver + <td>The screen has been turned on. +</tr><tr> + <td>{@code ACTION_TIMEZONE_CHANGED} + <td>broadcast receiver + <td>The setting for the time zone has changed. +</tr> +</table> + +<p> +See the {@link android.content.Intent} class description for a list of +pre-defined constants for generic actions. Other actions are defined +elsewhere in the Android API. +You can also define your own action strings for activating the components +in your application. Those you invent should include the application +package as a prefix — for example: +"<code>com.example.project.SHOW_COLOR</code>". +</p> + +<p> +The action largely determines how the rest of the intent is structured +— particularly the <a href="#data">data</a> and +<a href="#extras">extras</a> fields — +much as a method name determines a set of arguments and a return value. +For this reason, it's a good idea to use action names that are +as specific as possible, and to couple them tightly to the other fields of +the intent. In other words, instead of defining an action in isolation, +define an entire protocol for the Intent objects your components can handle. +</p> + +<p> +The action in an Intent object is set by the +<code>{@link android.content.Intent#setAction setAction()}</code> +method and read by +<code>{@link android.content.Intent#getAction getAction()}</code>. +</p> +</dd> + +<p><dt><b>Data</b><a name="data"></a></dt> +<dd>The URI of the data to be acted on and the MIME type of that data. Different +actions are paired with different kinds of data specifications. For example, if +the action field is {@code ACTION_EDIT}, +the data field would contain the URI of the document to be displayed for editing. +If the action is {@code ACTION_CALL}, the data field would be a {@code tel:} URI +with the number to call. Similarly, if the action is {@code ACTION_VIEW} and the +data field is an {@code http:} URI, the receiving activity would be called upon +to download and display whatever data the URI refers to. + +<p> +When matching an intent to a component that is capable of handling the data, +it's often important to know the type of data (its MIME type) in addition to its URI. +For example, a component able to display image data should not be called +upon to play an audio file. +</p> + +<p> +In many cases, the data type can be inferred from the URI — particularly +{@code content:} URIs, which indicate that the data is located on the device and +controlled by a content provider (see the +<a href="{@docRoot}guide/topics/providers/content-providers.html">separate +discussion on content providers</a>). But the type can also be explicitly set +in the Intent object. +The <code>{@link android.content.Intent#setData setData()}</code> method specifies +data only as a URI, <code>{@link android.content.Intent#setType setType()}</code> +specifies it only as a MIME type, and <code>{@link +android.content.Intent#setDataAndType setDataAndType()}</code> specifies it as both +a URI and a MIME type. The URI is read by <code>{@link +android.content.Intent#getData getData()}</code> and the type by <code>{@link +android.content.Intent#getType getType()}</code>. +</p> +</dd> + +<p><dt><b>Category</b></dt> +<dd>A string containing additional information about the kind of component +that should handle the intent. Any number of category descriptions can be +placed in an Intent object. As it does for actions, the Intent class defines +several category constants, including these: + +<table> +<tr> + <th>Constant</th> + <th>Meaning</th> +</tr><tr> + <td>{@code CATEGORY_BROWSABLE} + <td>The target activity can be safely invoked by the browser to display data + referenced by a link — for example, an image or an e-mail message. +</tr><tr> + <td>{@code CATEGORY_GADGET} + <td>The activity can be embedded inside of another activity that hosts gadgets. +</tr><tr> + <td>{@code CATEGORY_HOME} + <td>The activity displays the home screen, the first screen the user sees when + the device is turned on or when the <em>Home</em> button is pressed. +</tr><tr> + <td>{@code CATEGORY_LAUNCHER} + <td>The activity can be the initial activity of a task and is listed in + the top-level application launcher. +</tr><tr> + <td>{@code CATEGORY_PREFERENCE} + <td>The target activity is a preference panel. +</tr> +</table> + +<p> +See the {@link android.content.Intent} class description for the full list of +categories. +</p> + +<p> +The <code>{@link android.content.Intent#addCategory addCategory()}</code> method +places a category in an Intent object, <code>{@link android.content.Intent#removeCategory +removeCategory()}</code> deletes a category previously added, and <code>{@link android.content.Intent#getCategories getCategories()}</code> gets the set of all +categories currently in the object. +</p> +</dd> + +<p><dt><b>Extras</b><a name="extras"></a></dt> +<dd>Key-value pairs for additional information that should be delivered to the +component handling the intent. Just as some actions are paired with particular +kinds of data URIs, some are paired with particular extras. For example, an +{@code ACTION_TIMEZONE_CHANGED} intent has a "{@code time-zone}" extra that +identifies the new time zone, and {@code ACTION_HEADSET_PLUG} has a +"{@code state}" extra indicating whether the headset is now plugged in or +unplugged, as well as a "{@code name}" extra for the type of headset. +If you were to invent a {@code SHOW_COLOR} action, the color value would +be set in an extra key-value pair. + +<p> +The Intent object has a series of {@code put...()} methods for inserting various +types of extra data and a similar set of {@code get...()} methods for reading +the data. These methods parallel those for {@link android.os.Bundle} objects. +In fact, the extras can be installed and read as a Bundle using the <code>{@link +android.content.Intent#putExtras putExtras()}</code> and <code>{@link +android.content.Intent#getExtras getExtras()}</code> methods. +</p> +</dd> + +<p><dt><b>Flags</b></dt> +<dd>Flags of various sorts. Many instruct the Android system how to launch an +activity (for example, which task the activity should belong to) and how to treat +it after it's launched (for example, whether it belongs in the list of recent +activities). All these flags are defined in the Intent class. +</dd> + +</dl> + +<p> +The Android system and the applications that come with the platform employ +Intent objects both to send out system-originated broadcasts and to activate +system-defined components. To see how to structure an intent to activate a +system component, consult the +<a href="{@docRoot}guide/appendix/g-app-intents.html">list of intents</a> +in the reference. +</p> + + +<h2><a name="ires"></a>Intent Resolution</h2> + +<p> +Intents can be divided into two groups: +</p> + +<ul> +<li><i>Explicit intents</i> designate the target component by its +name (the <a href="#cname">component name field</a>, mentioned earlier, +has a value set). Since component names would generally not be known to +developers of other applications, explicit intents are typically used +for application-internal messages — such as an activity starting +a subordinate service or launching a sister activity.</li> + +<li><p><i>Implicit intents</i> do not name a target (the field for +the component name is blank). Implicit intents are often used to +activate components in other applications.</p></li> +</ul> + +<p> +Android delivers an explicit intent to an instance of the designated +target class. Nothing in the Intent object other than the component +name matters for determining which component should get the intent. +</p> + +<p> +A different strategy is needed for implicit intents. In the absence of a +designated target, the Android system must find the best component (or +components) to handle the intent — a single activity or service to +perform the requested action or the set of broadcast receivers to respond +to the broadcast announcement. It does so by comparing the contents of +the Intent object to <i>intent filters</i>, structures associated with +components that can potentially receive intents. Filters advertise the +capabilities of a component and delimit the intents it can handle. They +open the component to the possibility of receiving implicit intents of +the advertised type. If a component does not have any intent filters, +it can receive only explicit intents. A component with filters can +receive both explicit and implicit intents. +</p> + +<p> +Only three aspects of an Intent object are consulted when the object +is tested against an intent filter: +</p> + +<p style="margin-left: 2em">action +<br/>data (both URI and data type) +<br/>category</p> + +<p> +The extras and flags play no part in resolving which component receives +an intent. +</p> + + +<h3><a name="ifs"></a>Intent filters</h3> + +<p> +To inform the system which implicit intents they can handle, activities, +services, and broadcast receivers can have one or more intent filters. +Each filter describes a capability of the component, a set of intents that +the component is willing to receive. It, in effect, filters in +intents of a desired type, while filtering out unwanted +intents — but only unwanted implicit intents (those that don't name +a target class). An explicit intent is always delivered to its target, +no matter what it contains; the filter is not consulted. But an implicit +intent is delivered to a component only if it can pass through one of the +component's filters. +</p> + +<p> +A component has separate filters for each job it can do, each face it can +present to the user. For example, the NoteEditor activity of the sample +Note Pad application has two filters — one for starting up with a +specific note that the user can view or edit, and another for starting +with a new, blank note that the user can fill in and save. (All of Note +Pad's filters are described in the <a href="#npex">Note Pad Example</a> +section, later.) +</p> + +<div class="sidebox-wrapper"> +<div class="sidebox"> +<h2>Filters and security</h2> +<p>An intent filter cannot be relied on for security. While it opens a +component to receiving only certain kinds of implicit intents, it does +nothing to prevent explicit intents from targeting the component. Even +though a filter restricts the intents a component will be asked to handle +to certain actions and data sources, someone could always put +together an explicit intent with a different action and data source, and +name the component as the target. +</p> +</div> +</div> + +<p> +An intent filter is an instance of the {@link android.content.IntentFilter} class. +However, since the Android system must know about the capabilities of a component +before it can launch that component, intent filters are generally not set up in +Java code, but in the application's manifest file (AndroidManifest.xml) as +<code><a href="{@docRoot}guide/topics/manifest/intent-filter-element.html"><intent-filter></a></code> +elements. (The one exception would be filters for +broadcast receivers that are registered dynamically by calling <code>{@link android.content.Context#registerReceiver(BroadcastReceiver, IntentFilter, String, +Handler) Context.registerReceiver()}</code>; they are directly created as +IntentFilter objects.) +</p> + +<p> +A filter has fields that parallel the action, data, and category fields of an +Intent object. An implicit intent is tested against the filter in all three areas. +To be delivered to the component that owns the filter, it must pass all three tests. +If it fails even one of them, the Android system won't deliver it to the +component — at least not on the basis of that filter. However, since a +component can have multiple intent filters, an intent that does not pass +through one of a component's filters might make it through on another. +</p> + +<p> +Each of the three tests is described in detail below: +</p> + +<dl> + +<dt><b>Action test</b></dt> +<dd>An +<code><a href="{@docRoot}guide/topics/manifest/intent-filter-element.html"><intent-filter></a></code> +element in the manifest file lists actions as +<code><a href="{@docRoot}guide/topics/manifest/action-element.html"><action></a></code> +subelements. For example: + +<pre><intent-filter . . . > + <action android:name="com.example.project.SHOW_CURRENT" /> + <action android:name="com.example.project.SHOW_RECENT" /> + <action android:name="com.example.project.SHOW_PENDING" /> + . . . +</intent-filter></pre> + +<p> +As the example shows, while an Intent object names just a single action, +a filter may list more than one. The list cannot be empty; a filter must +contain at least one {@code <action>} element, or it +will block all intents. +</p> + +<p> +To pass this test, the action specified in the Intent object must match +one of the actions listed in the filter. If the object or the filter +does not specify an action, the results are as follows: +</p> + +<ul> +<li>If the filter fails to list any actions, there is nothing for an +intent to match, so all intents fail the test. No intents can get +through the filter.</li> + +<li><p>On the other hand, an Intent object that doesn't specify an +action automatically passes the test — as long as the filter +contains at least one action.</p></li> +</ul +</dd> + +<dt><b>Category test</b></dt> +<dd>An +<code><a href="{@docRoot}guide/topics/manifest/intent-filter-element.html"><intent-filter></a></code> +element also lists categories as subelements. For example: + +<pre><intent-filter . . . > + <category android:name="android.intent.category.DEFAULT" /> + <category android:name="android.intent.category.BROWSABLE" /> + . . . +</intent-filter></pre> + +<p> +Note that the constants described earlier for actions and categories are not +used in the manifest file. The full string values are used instead. For +instance, the "{@code android.intent.category.BROWSABLE}" string in the example +above corresponds to the {@code CATEGORY_BROWSABLE} constant mentioned earlier +in this document. Similarly, the string "{@code android.intent.action.EDIT}" +corresponds to the {@code ACTION_EDIT} constant. +</p> + +<p> +For an intent to pass the category test, every category in the Intent object +must match a category in the filter. The filter can list additional categories, +but it cannot omit any that are in the intent. +</p> + +<p> +In principle, therefore, an Intent object with no categories should always pass +this test, regardless of what's in the filter. That's mostly true. However, +with one exception, Android treats all implicit intents passed to {@link +android.content.Context#startActivity startActivity()} as if they contained +at least one category: "{@code android.intent.category.DEFAULT}" (the +{@code CATEGORY_DEFAULT} constant). +Therefore, activities that are willing to receive implicit intents must +include "{@code android.intent.category.DEFAULT}" in their intent filters. +(Filters with "{@code android.intent.action.MAIN}" and +"{@code android.intent.category.LAUNCHER}" settings are the exception. +They mark activities that begin new tasks and that are represented on the +launcher screen. They can include "{@code android.intent.category.DEFAULT}" +in the list of categories, but don't need to.) See <a href="#imatch">Using +intent matching</a>, later, for more on these filters.) +</p> +<dd> + +<dt><b>Data test</b></dt> +<dd>Like the action and categories, the data specification for an intent filter +is contained in a subelement. And, as in those cases, the subelement can appear +multiple times, or not at all. For example: + +<pre><intent-filter . . . > + <data android:mimeType="video/mpeg" android:scheme="http" . . . /> + <data android:mimeType="audio/mpeg" android:scheme="http" . . . /> + . . . +</intent-filter></pre> + +<p> +Each +<code><a href="{@docRoot}guide/topics/manifest/data-element.html"><data></a></code> +element can specify a URI and a data type (MIME media type). There are separate +attributes — {@code scheme}, {@code host}, {@code port}, +and {@code path} — for each part of the URI: +</p> + +<p style="margin-left: 2em">{@code scheme://host:port/path}</p> + +<p> +For example, in the following URI, +</p> + +<p style="margin-left: 2em">{@code content://com.example.project:200/folder/subfolder/etc}</p> + +<p> the scheme is "{@code content}", the host is "{@code com.example.project}", +the port is "{@code 200}", and the path is "{@code folder/subfolder/etc}". +The host and port together constitute the URI <i>authority</i>; if a host is +not specified, the port is ignored. +</p> + +<p> +Each of these attributes is optional, but they are not independent of each other: +For an authority to be meaningful, a scheme must also be specified. +For a path to be meaningful, both a scheme and an authority must be specified. +</p> + +<p> +When the URI in an Intent object is compared to a URI specification in a filter, +it's compared only to the parts of the URI actually mentioned in the filter. +For example, if a filter specifies only a scheme, all URIs with that scheme match +the filter. If a filter specifies a scheme and an authority but no path, all URIs +with the same scheme and authority match, regardless of their paths. If a filter +specifies a scheme, an authority, and a path, only URIs with the same scheme, +authority, and path match. However, a path specification in the filter can +contain wildcards to require only a partial match of the path. +</p> + +<p> +The {@code type} attribute of a {@code <data>} element specifies the MIME type +of the data. It's more common in filters than a URI. Both the Intent object and +the filter can use a "*" wildcard for the subtype field — for example, +"{@code text/*}" or "{@code audio/*}" — indicating any subtype matches. +</p> + +<p> +The data test compares both the URI and the data type in the Intent object to a URI +and data type specified in the filter. The rules are as follows: +</p> + +<ol type="a"> +<li>An Intent object that contains neither a URI nor a data type passes the +test only if the filter likewise does not specify any URIs or data types.</li> + +<li><p>An Intent object that contains a URI but no data type (and a type cannot +be inferred from the URI) passes the test only if its URI matches a URI in the +filter and the filter likewise does not specify a type. This will be the case +only for URIs like {@code mailto:} and {@code tel:} that do not refer to actual data.</p></li> + +<li><p>An Intent object that contains a data type but not a URI passes the test +only if the filter lists the same data type and similarly does not specify a URI.</p></li> + +<li><p>An Intent object that contains both a URI and a data type (or a data type +can be inferred from the URI) passes the data type part of the test only if its +type matches a type listed in the filter. It passes the URI part of the test +either if its URI matches a URI in the filter or if it has a {@code content:} +or {@code file:} URI and the filter does not specify a URI. In other words, +a component is presumed to support {@code content:} and {@code file:} data if +its filter lists only a data type.</p></li> +</ol> +</dl> + +<p> +If an intent can pass through the filters of more than one activity or service, +the user may be asked which component to activate. An exception is raised if +no target can be found. +</p> + + +<h3><a name="ccases"></a>Common cases</h3> + +<p> +The last rule shown above for the data test, rule (d), reflects the expectation +that components are able to get local data from a file or content provider. +Therefore, their filters can list just a data type and do not need to explicitly +name the {@code content:} and {@code file:} schemes. +This is a typical case. A {@code <data>} element like the following, +for example, tells Android that the component can get image data from a content +provider and display it: +</p> + +<pre><data android:mimeType="image/*" /></pre> + +<p> +Since most available data is dispensed by content providers, filters that +specify a data type but not a URI are perhaps the most common. +</p> + +<p> +Another common configuration is filters with a scheme and a data type. For +example, a {@code <data>} element like the following tells Android that +the component can get video data from the network and display it: +</p> + +<pre><data android:scheme="http" android:type="video/*" /></pre> + +<p> +Consider, for example, what the browser application does when +the user follows a link on a web page. It first tries to display the data +(as it could if the link was to an HTML page). If it can't display the data, +it puts together an implicit intent with the scheme and data type and tries +to start an activity that can do the job. If there are no takers, it asks the +download manager to download the data. That puts it under the control +of a content provider, so a potentially larger pool of activities +(those with filters that just name a data type) can respond. +</p> + +<p> +Most applications also have a way to start fresh, without a reference +to any particular data. Activities that can initiate applications +have filters with "{@code android.intent.action.MAIN}" specified as +the action. If they are to be represented in the application launcher, +they also specify the "{@code android.intent.category.LAUNCHER}" +category: +</p> + +<pre><intent-filter . . . > + <action android:name="code android.intent.action.MAIN" /> + <category android:name="code android.intent.category.LAUNCHER" /> +</intent-filter></pre> + + +<h3><a name="imatch"></a>Using intent matching</h3> + +<p> +Intents are matched against intent filters not only to discover a target +component to activate, but also to discover something about the set of +components on the device. For example, the Android system populates the +application launcher, the top-level screen that shows the applications +that are available for the user to launch, by finding all the activities + with intent filters that specify the "{@code android.intent.action.MAIN}" +action and "{@code android.intent.category.LAUNCHER}" category +(as illustrated in the previous section). It then displays the icons and +labels of those activities in the launcher. Similarly, it discovers the +home screen by looking for the activity with +"{@code android.intent.category.HOME}" in its filter. +</p> + +<p> +Your application can use intent matching is a similar way. +The {@link android.content.pm.PackageManager} has a set of {@code query...()} +methods that return all components that can accept a particular intent, and +a similar series of {@code resolve...()} methods that determine the best +component to respond to an intent. For example, +{@link android.content.pm.PackageManager#queryIntentActivities +queryIntentActivities()} returns a list of all activities that can perform +the intent passed as an argument, and {@link +android.content.pm.PackageManager#queryIntentServices +queryIntentServices()} returns a similar list of services. +Neither method activates the components; they just list the ones that +can respond. There's a similar method, +{@link android.content.pm.PackageManager#queryBroadcastReceivers +queryBroadcastReceivers()}, for broadcast receivers. +</p> + +<h2 id="npex">Note Pad Example</h2> + +<p> +The Note Pad sample application enables users to browse through a list +of notes, view details about individual items in the list, edit the items, +and add a new item to the list. This section looks at the intent filters +declared in its manifest file. (If you're working offline in the SDK, you +can find all the source files for this sample application, including its +manifest file, at {@code <sdk>/samples/NotePad/index.html}. +If you're viewing the documentation online, the source files are in the +<a href="{@docRoot}resources/samples/index.html">Tutorials and Sample Code</a> +section <a href="{@docRoot}resources/samples/NotePad/index.html">here</a>.) +</p> + +<p> +In its manifest file, the Note Pad application declares three activities, +each with at least one intent filter. It also declares a content provider +that manages the note data. Here is the manifest file in its entirety: +</p> + +<pre><manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.example.android.notepad"> + <application android:icon="@drawable/app_notes" + android:label="@string/app_name" > + + <provider android:name="NotePadProvider" + android:authorities="com.google.provider.NotePad" /> + + <activity android:name="NotesList" android:label="@string/title_notes_list"> + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + <category android:name="android.intent.category.LAUNCHER" /> + </intent-filter> + <intent-filter> + <action android:name="android.intent.action.VIEW" /> + <action android:name="android.intent.action.EDIT" /> + <action android:name="android.intent.action.PICK" /> + <category android:name="android.intent.category.DEFAULT" /> + <data android:mimeType="vnd.android.cursor.dir/vnd.google.note" /> + </intent-filter> + <intent-filter> + <action android:name="android.intent.action.GET_CONTENT" /> + <category android:name="android.intent.category.DEFAULT" /> + <data android:mimeType="vnd.android.cursor.item/vnd.google.note" /> + </intent-filter> + </activity> + + <activity android:name="NoteEditor" + android:theme="@android:style/Theme.Light" + android:label="@string/title_note" > + <intent-filter android:label="@string/resolve_edit"> + <action android:name="android.intent.action.VIEW" /> + <action android:name="android.intent.action.EDIT" /> + <action android:name="com.android.notepad.action.EDIT_NOTE" /> + <category android:name="android.intent.category.DEFAULT" /> + <data android:mimeType="vnd.android.cursor.item/vnd.google.note" /> + </intent-filter> + <intent-filter> + <action android:name="android.intent.action.INSERT" /> + <category android:name="android.intent.category.DEFAULT" /> + <data android:mimeType="vnd.android.cursor.dir/vnd.google.note" /> + </intent-filter> + </activity> + + <activity android:name="TitleEditor" + android:label="@string/title_edit_title" + android:theme="@android:style/Theme.Dialog"> + <intent-filter android:label="@string/resolve_title"> + <action android:name="com.android.notepad.action.EDIT_TITLE" /> + <category android:name="android.intent.category.DEFAULT" /> + <category android:name="android.intent.category.ALTERNATIVE" /> + <category android:name="android.intent.category.SELECTED_ALTERNATIVE" /> + <data android:mimeType="vnd.android.cursor.item/vnd.google.note" /> + </intent-filter> + </activity> + + </application> +</manifest></pre> + +<p> +The first activity, NotesList, is +distinguished from the other activities by the fact that it operates +on a directory of notes (the note list) rather than on a single note. +It would generally serve as the initial user interface into the +application. It can do three things as described by its three intent +filters: +</p> + +<ol> +<li><pre><intent-filter> + <action android:name="android.intent.action.MAIN" /> + <category android:name="android.intent.category.LAUNCHER" /> +</intent-filter></pre> + +<p> +This filter declares the main entry point into the Note Pad application. +The standard {@code MAIN} action is an entry point that does not require +any other information in the Intent (no data specification, for example), +and the {@code LAUNCHER} category says that this entry point should be +listed in the application launcher. +</p></li> + +<li><pre><intent-filter> + <action android:name="android.intent.action.VIEW" /> + <action android:name="android.intent.action.EDIT" /> + <action android:name="android.intent.action.PICK" /> + <category android:name="android.intent.category.DEFAULT" /> + <data android:mimeType="vnd.android.cursor.dir/vnd.google.note" /> +</intent-filter></pre> + +<p> +This filter declares the things that the activity can do on a directory +of notes. It can allow the user to view or edit the directory (via +the {@code VIEW} and {@code EDIT} actions), or to pick a particular note +from the directory (via the {@code PICK} action). +</p> + +<p> +The {@code mimeType} attribute of the +<code><a href="{@docRoot}guide/topics/manifest/data-element.html"><data></a></code> +element specifies the kind of data that these actions operate on. It +indicates that the activity can get a Cursor over zero or more items +({@code vnd.android.cursor.dir}) from a content provider that holds +Note Pad data ({@code vnd.google.note}). The Intent object that launches +the activity would include a {@code content:} URI specifying the exact +data of this type that the activity should open. +</p> + +<p> +Note also the {@code DEFAULT} category supplied in this filter. It's +there because the <code>{@link android.content.Context#startActivity +Context.startActivity()}</code> and +<code>{@link android.app.Activity#startActivityForResult +Activity.startActivityForResult()}</code> methods treat all intents +as if they contained the {@code DEFAULT} category — with just +two exceptions: +</p> + +<ul> +<li>Intents that explicitly name the target activity</li> +<li>Intents consisting of the {@code MAIN} action and {@code LAUNCHER} +category</li> +</ul> + +<p> +Therefore, the {@code DEFAULT} category is <em>required</em> for all +filters — except for those with the {@code MAIN} action and +{@code LAUNCHER} category. (Intent filters are not consulted for +explicit intents.) +</p></li> + +<li><pre><intent-filter> + <action android:name="android.intent.action.GET_CONTENT" /> + <category android:name="android.intent.category.DEFAULT" /> + <data android:mimeType="vnd.android.cursor.item/vnd.google.note" /> +</intent-filter></pre> + +<p> +This filter describes the activity's ability to return a note selected by +the user without requiring any specification of the directory the user should +choose from. The {@code GET_CONTENT} action is similar to the {@code PICK} +action. In both cases, the activity returns the URI for a note selected by +the user. (In each case, it's returned to the activity that called +<code>{@link android.app.Activity#startActivityForResult +startActivityForResult()}</code> to start the NoteList activity.) Here, +however, the caller specifies the type of data desired instead of the +directory of data the user will be picking from. +</p> + +<p> +The data type, <code>vnd.android.cursor.item/vnd.google.note</code>, +indicates the type of data the activity can return — a URI for +a single note. From the returned URI, the caller can get a Cursor for +exactly one item ({@code vnd.android.cursor.item}) from the content +provider that holds Note Pad data ({@code vnd.google.note}). +</p> + +<p> +In other words, for the {@code PICK} action in the previous filter, +the data type indicates the type of data the activity could display to the +user. For the {@code GET_CONTENT} filter, it indicates the type of data +the activity can return to the caller. +</p></li> +</ol> + +<p> +Given these capabilities, the following intents will resolve to the +NotesList activity: +</p> + +<dl style="margin-left: 2em"> +<dt>action: <code>android.intent.action.MAIN</code></dt> +<dd>Launches the activity with no data specified.</dd> + +<dt>action: <code>android.intent.action.MAIN</code> +<br/>category: <code>android.intent.category.LAUNCHER</code></dt> +<dd> Launches the activity with no data selected specified. +This is the actual intent used by the Launcher to populate its top-level +list. All activities with filters that match this action and category +are added to the list.</dd> + +<dt>action: <code>android.intent.action.VIEW</code> +<br/>data: <code>content://com.google.provider.NotePad/notes</code></dt> +<dd>Asks the activity to display a list of all the notes under +<code>content://com.google.provider.NotePad/notes</code>. The user can then +browse through the list and get information about the items in it.</dd> + +<dt>action: <code>android.intent.action.PICK</code> +<br/>data: <code>content://com.google.provider.NotePad/notes</code></dt> +<dd>Asks the activity to display a list of the notes under +<code>content://com.google.provider.NotePad/notes</code>. +The user can then pick a note from the list, and the activity will return +the URI for that item back to the activity that started the NoteList activity.</dd> + +<dt>action: <code>android.intent.action.GET_CONTENT</code> +<br/>data type: <code>vnd.android.cursor.item/vnd.google.note</code></dt> +<dd>Asks the activity to supply a single item of Note Pad data.</dd> +</dl> + +<p> +The second activity, NoteEditor, shows +users a single note entry and allows them to edit it. It can do two things +as described by its two intent filters: + +<ol> +<li><pre><intent-filter android:label="@string/resolve_edit"> + <action android:name="android.intent.action.VIEW" /> + <action android:name="android.intent.action.EDIT" /> + <action android:name="com.android.notepad.action.EDIT_NOTE" /> + <category android:name="android.intent.category.DEFAULT" /> + <data android:mimeType="vnd.android.cursor.item/vnd.google.note" /> +</intent-filter></pre> + +<p> +The first, primary, purpose of this activity is to enable the user to +interact with a single note — to either {@code VIEW} the note or +{@code EDIT} it. (The {@code EDIT_NOTE} category is a synonym for +{@code EDIT}.) The intent would contain the URI for data matching the +MIME type <code>vnd.android.cursor.item/vnd.google.note</code> — +that is, the URI for a single, specific note. It would typically be a +URI that was returned by the {@code PICK} or {@code GET_CONTENT} +actions of the NoteList activity. +</p> + +<p> +As before, this filter lists the {@code DEFAULT} category so that the +activity can be launched by intents that don't explicitly specify the +NoteEditor class. +</p></li> + +<li><pre><intent-filter> + <action android:name="android.intent.action.INSERT" /> + <category android:name="android.intent.category.DEFAULT" /> + <data android:mimeType="vnd.android.cursor.dir/vnd.google.note" /> +</intent-filter></pre> + +<p> +The secondary purpose of this activity is to enable the user to create a new +note, which it will {@code INSERT} into an existing directory of notes. The +intent would contain the URI for data matching the MIME type +<code>vnd.android.cursor.dir/vnd.google.note</code> — that +is, the URI for the directory where the note should be placed. +</p></li> +</ol> + +<p> +Given these capabilities, the following intents will resolve to the +NoteEditor activity: +</p> + +<dl style:"margin-left: 2em"> +<dt>action: <code>android.intent.action.VIEW</code> +<br/>data: <code>content://com.google.provider.NotePad/notes/<var>ID</var></code></dt> +<dd>Asks the activity to display the content of the note identified +by {@code <var>ID</var>}. (For details on how {@code content:} URIs +specify individual members of a group, see +<a href="{@docRoot}guide/topics/providers/content-providers.html">Content Providers</a>.) + +<dt>action: <code>android.intent.action.EDIT</code> +<br/>data: <code>content://com.google.provider.NotePad/notes/<var>ID</var></code></dt> +<dd>Asks the activity to display the content of the note identified +by {@code <var>ID</var>}, and to let the user edit it. If the user +saves the changes, the activity updates the data for the note in the +content provider.</dd> + +<dt>action: <code>android.intent.action.INSERT</code> +<br/>data: <code>content://com.google.provider.NotePad/notes</code></dt> +<dd>Asks the activity to create a new, empty note in the notes list at +<code>content://com.google.provider.NotePad/notes</code> +and allow the user to edit it. If the user saves the note, its URI +is returned to the caller. +</dd> +</dl> + +<p>The last activity, TitleEditor, +enables the user to edit the title of a note. This could be implemented +by directly invoking the activity (by explicitly setting its component +name in the Intent), without using an intent filter. But here we take +the opportunity to show how to publish alternative operations on existing +data: +</p> + +<pre><intent-filter android:label="@string/resolve_title"> + <action android:name="com.android.notepad.action.EDIT_TITLE" /> + <category android:name="android.intent.category.DEFAULT" /> + <category android:name="android.intent.category.ALTERNATIVE" /> + <category android:name="android.intent.category.SELECTED_ALTERNATIVE" /> + <data android:mimeType="vnd.android.cursor.item/vnd.google.note" /> +</intent-filter></pre> + +<p> +The single intent filter for this activity uses a custom action called +"<code>com.android.notepad.action.EDIT_TITLE</code>". It must be invoked on +a specific note (data type <code>vnd.android.cursor.item/vnd.google.note</code>), +like the previous {@code VIEW} and {@code EDIT} actions. However, here the +activity displays the title contained in the note data, not the content of +the note itself. +</p> + +<p> +In addition to supporting the usual {@code DEFAULT} category, the title +editor also supports two other standard categories: +<code>{@link android.content.Intent#CATEGORY_ALTERNATIVE ALTERNATIVE}</code> +and <code>{@link android.content.Intent#CATEGORY_SELECTED_ALTERNATIVE +SELECTED_ALTERNATIVE}</code>. +These categories identify activities that can be presented to users in +a menu of options (much as the {@code LAUNCHER} category identifies +activities that should be presented to user in the application launcher). +Note that the filter also supplies an explicit label (via +<code>android:label="@string/resolve_title"</code>) to better control +what users see when presented with this activity as an alternative +action to the data they are currently viewing. (For more information +on these categories and building options menus, see the +<code>{@link android.content.pm.PackageManager#queryIntentActivityOptions +PackageManager.queryIntentActivityOptions()}</code> and +<code>{@link android.view.Menu#addIntentOptions Menu.addIntentOptions()}</code> +methods.) +</p> + +<p> +Given these capabilities, the following intent will resolve to the +TitleEditor activity: +</p> + +<dl style="margin-left: 2em"> +<dt>action: <code>com.android.notepad.action.EDIT_TITLE</code> +<br/>data: <code>content://com.google.provider.NotePad/notes/<var>ID</var></code></dt> +<dd>Asks the activity to display the title associated with note <var>ID</var>, and +allow the user to edit the title.</dd> +</dl> + + + + + + + + + + + diff --git a/docs/html/guide/components/loaders.jd b/docs/html/guide/components/loaders.jd new file mode 100644 index 0000000..ddd513b --- /dev/null +++ b/docs/html/guide/components/loaders.jd @@ -0,0 +1,500 @@ +page.title=Loaders +parent.title=Activities +parent.link=activities.html +@jd:body +<div id="qv-wrapper"> +<div id="qv"> + <h2>In this document</h2> + <ol> + <li><a href="#summary">Loader API Summary</a></li> + <li><a href="#app">Using Loaders in an Application</a> + <ol> + <li><a href="#requirements"></a></li> + <li><a href="#starting">Starting a Loader</a></li> + <li><a href="#restarting">Restarting a Loader</a></li> + <li><a href="#callback">Using the LoaderManager Callbacks</a></li> + </ol> + </li> + <li><a href="#example">Example</a> + <ol> + <li><a href="#more_examples">More Examples</a></li> + </ol> + </li> + </ol> + + <h2>Key classes</h2> + <ol> + <li>{@link android.app.LoaderManager}</li> + <li>{@link android.content.Loader}</li> + + </ol> + + <h2>Related samples</h2> + <ol> + <li> <a +href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/LoaderCursor.html"> +LoaderCursor</a></li> + <li> <a +href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/LoaderThrottle.html"> +LoaderThrottle</a></li> + </ol> + </div> +</div> + +<p>Introduced in Android 3.0, loaders make it easy to asynchronously load data +in an activity or fragment. Loaders have these characteristics:</p> + <ul> + <li>They are available to every {@link android.app.Activity} and {@link +android.app.Fragment}.</li> + <li>They provide asynchronous loading of data.</li> + <li>They monitor the source of their data and deliver new results when the +content changes.</li> + <li>They automatically reconnect to the last loader's cursor when being +recreated after a configuration change. Thus, they don't need to re-query their +data.</li> + </ul> + +<h2 id="summary">Loader API Summary</h2> + +<p>There are multiple classes and interfaces that may be involved in using +loaders in an application. They are summarized in this table:</p> + +<table> + <tr> + <th>Class/Interface</th> + <th>Description</th> + </tr> + <tr> + <td>{@link android.app.LoaderManager}</td> + <td>An abstract class associated with an {@link android.app.Activity} or +{@link android.app.Fragment} for managing one or more {@link +android.content.Loader} instances. This helps an application manage +longer-running operations in conjunction with the {@link android.app.Activity} +or {@link android.app.Fragment} lifecycle; the most common use of this is with a +{@link android.content.CursorLoader}, however applications are free to write +their own loaders for loading other types of data. + <br /> + <br /> + There is only one {@link android.app.LoaderManager} per activity or fragment. But a {@link android.app.LoaderManager} can have +multiple loaders.</td> + </tr> + <tr> + <td>{@link android.app.LoaderManager.LoaderCallbacks}</td> + <td>A callback interface for a client to interact with the {@link +android.app.LoaderManager}. For example, you use the {@link +android.app.LoaderManager.LoaderCallbacks#onCreateLoader onCreateLoader()} +callback method to create a new loader.</td> + </tr> + <tr> + <td>{@link android.content.Loader}</td> + <td>An abstract class that performs asynchronous loading of data. This is +the base class for a loader. You would typically use {@link +android.content.CursorLoader}, but you can implement your own subclass. While +loaders are active they should monitor the source of their data and deliver new +results when the contents change. </td> + </tr> + <tr> + <td>{@link android.content.AsyncTaskLoader}</td> + <td>Abstract loader that provides an {@link android.os.AsyncTask} to do the work.</td> + </tr> + <tr> + <td>{@link android.content.CursorLoader}</td> + <td>A subclass of {@link android.content.AsyncTaskLoader} that queries the +{@link android.content.ContentResolver} and returns a {@link +android.database.Cursor}. This class implements the {@link +android.content.Loader} protocol in a standard way for querying cursors, +building on {@link android.content.AsyncTaskLoader} to perform the cursor query +on a background thread so that it does not block the application's UI. Using +this loader is the best way to asynchronously load data from a {@link +android.content.ContentProvider}, instead of performing a managed query through +the fragment or activity's APIs.</td> + </tr> +</table> + +<p>The classes and interfaces in the above table are the essential components +you'll use to implement a loader in your application. You won't need all of them +for each loader you create, but you'll always need a reference to the {@link +android.app.LoaderManager} in order to initialize a loader and an implementation +of a {@link android.content.Loader} class such as {@link +android.content.CursorLoader}. The following sections show you how to use these +classes and interfaces in an application.</p> + +<h2 id ="app">Using Loaders in an Application</h2> +<p>This section describes how to use loaders in an Android application. An +application that uses loaders typically includes the following:</p> +<ul> + <li>An {@link android.app.Activity} or {@link android.app.Fragment}.</li> + <li>An instance of the {@link android.app.LoaderManager}.</li> + <li>A {@link android.content.CursorLoader} to load data backed by a {@link +android.content.ContentProvider}. Alternatively, you can implement your own subclass +of {@link android.content.Loader} or {@link android.content.AsyncTaskLoader} to +load data from some other source.</li> + <li>An implementation for {@link android.app.LoaderManager.LoaderCallbacks}. +This is where you create new loaders and manage your references to existing +loaders.</li> +<li>A way of displaying the loader's data, such as a {@link +android.widget.SimpleCursorAdapter}.</li> + <li>A data source, such as a {@link android.content.ContentProvider}, when using a +{@link android.content.CursorLoader}.</li> +</ul> +<h3 id="starting">Starting a Loader</h3> + +<p>The {@link android.app.LoaderManager} manages one or more {@link +android.content.Loader} instances within an {@link android.app.Activity} or +{@link android.app.Fragment}. There is only one {@link +android.app.LoaderManager} per activity or fragment.</p> + +<p>You typically +initialize a {@link android.content.Loader} within the activity's {@link +android.app.Activity#onCreate onCreate()} method, or within the fragment's +{@link android.app.Fragment#onActivityCreated onActivityCreated()} method. You +do this as follows:</p> + +<pre>// Prepare the loader. Either re-connect with an existing one, +// or start a new one. +getLoaderManager().initLoader(0, null, this);</pre> + +<p>The {@link android.app.LoaderManager#initLoader initLoader()} method takes +the following parameters:</p> +<ul> + <li>A unique ID that identifies the loader. In this example, the ID is 0.</li> +<li>Optional arguments to supply to the loader at +construction (<code>null</code> in this example).</li> + +<li>A {@link android.app.LoaderManager.LoaderCallbacks} implementation, which +the {@link android.app.LoaderManager} calls to report loader events. In this +example, the local class implements the {@link +android.app.LoaderManager.LoaderCallbacks} interface, so it passes a reference +to itself, {@code this}.</li> +</ul> +<p>The {@link android.app.LoaderManager#initLoader initLoader()} call ensures that a loader +is initialized and active. It has two possible outcomes:</p> +<ul> + <li>If the loader specified by the ID already exists, the last created loader +is reused.</li> + <li>If the loader specified by the ID does <em>not</em> exist, +{@link android.app.LoaderManager#initLoader initLoader()} triggers the +{@link android.app.LoaderManager.LoaderCallbacks} method {@link android.app.LoaderManager.LoaderCallbacks#onCreateLoader onCreateLoader()}. +This is where you implement the code to instantiate and return a new loader. +For more discussion, see the section <a +href="#onCreateLoader">onCreateLoader</a>.</li> +</ul> +<p>In either case, the given {@link android.app.LoaderManager.LoaderCallbacks} +implementation is associated with the loader, and will be called when the +loader state changes. If at the point of this call the caller is in its +started state, and the requested loader already exists and has generated its +data, then the system calls {@link +android.app.LoaderManager.LoaderCallbacks#onLoadFinished onLoadFinished()} +immediately (during {@link android.app.LoaderManager#initLoader initLoader()}), +so you must be prepared for this to happen. See <a href="#onLoadFinished"> +onLoadFinished</a> for more discussion of this callback</p> + +<p>Note that the {@link android.app.LoaderManager#initLoader initLoader()} +method returns the {@link android.content.Loader} that is created, but you don't +need to capture a reference to it. The {@link android.app.LoaderManager} manages +the life of the loader automatically. The {@link android.app.LoaderManager} +starts and stops loading when necessary, and maintains the state of the loader +and its associated content. As this implies, you rarely interact with loaders +directly (though for an example of using loader methods to fine-tune a loader's +behavior, see the <a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/LoaderThrottle.html"> LoaderThrottle</a> sample). +You most commonly use the {@link +android.app.LoaderManager.LoaderCallbacks} methods to intervene in the loading +process when particular events occur. For more discussion of this topic, see <a +href="#callback">Using the LoaderManager Callbacks</a>.</p> + +<h3 id="restarting">Restarting a Loader</h3> + +<p>When you use {@link android.app.LoaderManager#initLoader initLoader()}, as +shown above, it uses an existing loader with the specified ID if there is one. +If there isn't, it creates one. But sometimes you want to discard your old data +and start over.</p> + +<p>To discard your old data, you use {@link +android.app.LoaderManager#restartLoader restartLoader()}. For example, this +implementation of {@link android.widget.SearchView.OnQueryTextListener} restarts +the loader when the user's query changes. The loader needs to be restarted so +that it can use the revised search filter to do a new query:</p> + +<pre> +public boolean onQueryTextChanged(String newText) { + // Called when the action bar search text has changed. Update + // the search filter, and restart the loader to do a new query + // with this filter. + mCurFilter = !TextUtils.isEmpty(newText) ? newText : null; + getLoaderManager().restartLoader(0, null, this); + return true; +}</pre> + +<h3 id="callback">Using the LoaderManager Callbacks</h3> + +<p>{@link android.app.LoaderManager.LoaderCallbacks} is a callback interface +that lets a client interact with the {@link android.app.LoaderManager}. </p> +<p>Loaders, in particular {@link android.content.CursorLoader}, are expected to +retain their data after being stopped. This allows applications to keep their +data across the activity or fragment's {@link android.app.Activity#onStop +onStop()} and {@link android.app.Activity#onStart onStart()} methods, so that +when users return to an application, they don't have to wait for the data to +reload. You use the {@link android.app.LoaderManager.LoaderCallbacks} methods +when to know when to create a new loader, and to tell the application when it is + time to stop using a loader's data.</p> + +<p>{@link android.app.LoaderManager.LoaderCallbacks} includes these +methods:</p> +<ul> + <li>{@link android.app.LoaderManager.LoaderCallbacks#onCreateLoader onCreateLoader()} — +Instantiate and return a new {@link android.content.Loader} for the given ID. +</li></ul> +<ul> + <li> {@link android.app.LoaderManager.LoaderCallbacks#onLoadFinished onLoadFinished()} +— Called when a previously created loader has finished its load. +</li></ul> +<ul> + <li>{@link android.app.LoaderManager.LoaderCallbacks#onLoaderReset onLoaderReset()} + — Called when a previously created loader is being reset, thus making its +data unavailable. +</li> +</ul> +<p>These methods are described in more detail in the following sections.</p> + +<h4 id ="onCreateLoader">onCreateLoader</h4> + +<p>When you attempt to access a loader (for example, through {@link +android.app.LoaderManager#initLoader initLoader()}), it checks to see whether +the loader specified by the ID exists. If it doesn't, it triggers the {@link +android.app.LoaderManager.LoaderCallbacks} method {@link +android.app.LoaderManager.LoaderCallbacks#onCreateLoader onCreateLoader()}. This +is where you create a new loader. Typically this will be a {@link +android.content.CursorLoader}, but you can implement your own {@link +android.content.Loader} subclass. </p> + +<p>In this example, the {@link +android.app.LoaderManager.LoaderCallbacks#onCreateLoader onCreateLoader()} +callback method creates a {@link android.content.CursorLoader}. You must build +the {@link android.content.CursorLoader} using its constructor method, which +requires the complete set of information needed to perform a query to the {@link +android.content.ContentProvider}. Specifically, it needs:</p> +<ul> + <li><em>uri</em> — The URI for the content to retrieve. </li> + <li><em>projection</em> — A list of which columns to return. Passing +<code>null</code> will return all columns, which is inefficient. </li> + <li><em>selection</em> — A filter declaring which rows to return, +formatted as an SQL WHERE clause (excluding the WHERE itself). Passing +<code>null</code> will return all rows for the given URI. </li> + <li><em>selectionArgs</em> — You may include ?s in the selection, which will +be replaced by the values from <em>selectionArgs</em>, in the order that they appear in +the selection. The values will be bound as Strings. </li> + <li><em>sortOrder</em> — How to order the rows, formatted as an SQL +ORDER BY clause (excluding the ORDER BY itself). Passing <code>null</code> will +use the default sort order, which may be unordered.</li> +</ul> +<p>For example:</p> +<pre> + // If non-null, this is the current filter the user has provided. +String mCurFilter; +... +public Loader<Cursor> onCreateLoader(int id, Bundle args) { + // This is called when a new Loader needs to be created. This + // sample only has one Loader, so we don't care about the ID. + // First, pick the base URI to use depending on whether we are + // currently filtering. + Uri baseUri; + if (mCurFilter != null) { + baseUri = Uri.withAppendedPath(Contacts.CONTENT_FILTER_URI, + Uri.encode(mCurFilter)); + } else { + baseUri = Contacts.CONTENT_URI; + } + + // Now create and return a CursorLoader that will take care of + // creating a Cursor for the data being displayed. + String select = "((" + Contacts.DISPLAY_NAME + " NOTNULL) AND (" + + Contacts.HAS_PHONE_NUMBER + "=1) AND (" + + Contacts.DISPLAY_NAME + " != '' ))"; + return new CursorLoader(getActivity(), baseUri, + CONTACTS_SUMMARY_PROJECTION, select, null, + Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC"); +}</pre> +<h4 id="onLoadFinished">onLoadFinished</h4> + +<p>This method is called when a previously created loader has finished its load. +This method is guaranteed to be called prior to the release of the last data +that was supplied for this loader. At this point you should remove all use of +the old data (since it will be released soon), but should not do your own +release of the data since its loader owns it and will take care of that.</p> + + +<p>The loader will release the data once it knows the application is no longer +using it. For example, if the data is a cursor from a {@link +android.content.CursorLoader}, you should not call {@link +android.database.Cursor#close close()} on it yourself. If the cursor is being +placed in a {@link android.widget.CursorAdapter}, you should use the {@link +android.widget.SimpleCursorAdapter#swapCursor swapCursor()} method so that the +old {@link android.database.Cursor} is not closed. For example:</p> + +<pre> +// This is the Adapter being used to display the list's data.<br +/>SimpleCursorAdapter mAdapter; +... + +public void onLoadFinished(Loader<Cursor> loader, Cursor data) { + // Swap the new cursor in. (The framework will take care of closing the + // old cursor once we return.) + mAdapter.swapCursor(data); +}</pre> + +<h4 id="onLoaderReset">onLoaderReset</h4> + +<p>This method is called when a previously created loader is being reset, thus +making its data unavailable. This callback lets you find out when the data is +about to be released so you can remove your reference to it. </p> +<p>This implementation calls +{@link android.widget.SimpleCursorAdapter#swapCursor swapCursor()} +with a value of <code>null</code>:</p> + +<pre> +// This is the Adapter being used to display the list's data. +SimpleCursorAdapter mAdapter; +... + +public void onLoaderReset(Loader<Cursor> loader) { + // This is called when the last Cursor provided to onLoadFinished() + // above is about to be closed. We need to make sure we are no + // longer using it. + mAdapter.swapCursor(null); +}</pre> + + +<h2 id="example">Example</h2> + +<p>As an example, here is the full implementation of a {@link +android.app.Fragment} that displays a {@link android.widget.ListView} containing +the results of a query against the contacts content provider. It uses a {@link +android.content.CursorLoader} to manage the query on the provider.</p> + +<p>For an application to access a user's contacts, as shown in this example, its +manifest must include the permission +{@link android.Manifest.permission#READ_CONTACTS READ_CONTACTS}.</p> + +<pre> +public static class CursorLoaderListFragment extends ListFragment + implements OnQueryTextListener, LoaderManager.LoaderCallbacks<Cursor> { + + // This is the Adapter being used to display the list's data. + SimpleCursorAdapter mAdapter; + + // If non-null, this is the current filter the user has provided. + String mCurFilter; + + @Override public void onActivityCreated(Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + + // Give some text to display if there is no data. In a real + // application this would come from a resource. + setEmptyText("No phone numbers"); + + // We have a menu item to show in action bar. + setHasOptionsMenu(true); + + // Create an empty adapter we will use to display the loaded data. + mAdapter = new SimpleCursorAdapter(getActivity(), + android.R.layout.simple_list_item_2, null, + new String[] { Contacts.DISPLAY_NAME, Contacts.CONTACT_STATUS }, + new int[] { android.R.id.text1, android.R.id.text2 }, 0); + setListAdapter(mAdapter); + + // Prepare the loader. Either re-connect with an existing one, + // or start a new one. + getLoaderManager().initLoader(0, null, this); + } + + @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { + // Place an action bar item for searching. + MenuItem item = menu.add("Search"); + item.setIcon(android.R.drawable.ic_menu_search); + item.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM); + SearchView sv = new SearchView(getActivity()); + sv.setOnQueryTextListener(this); + item.setActionView(sv); + } + + public boolean onQueryTextChange(String newText) { + // Called when the action bar search text has changed. Update + // the search filter, and restart the loader to do a new query + // with this filter. + mCurFilter = !TextUtils.isEmpty(newText) ? newText : null; + getLoaderManager().restartLoader(0, null, this); + return true; + } + + @Override public boolean onQueryTextSubmit(String query) { + // Don't care about this. + return true; + } + + @Override public void onListItemClick(ListView l, View v, int position, long id) { + // Insert desired behavior here. + Log.i("FragmentComplexList", "Item clicked: " + id); + } + + // These are the Contacts rows that we will retrieve. + static final String[] CONTACTS_SUMMARY_PROJECTION = new String[] { + Contacts._ID, + Contacts.DISPLAY_NAME, + Contacts.CONTACT_STATUS, + Contacts.CONTACT_PRESENCE, + Contacts.PHOTO_ID, + Contacts.LOOKUP_KEY, + }; + public Loader<Cursor> onCreateLoader(int id, Bundle args) { + // This is called when a new Loader needs to be created. This + // sample only has one Loader, so we don't care about the ID. + // First, pick the base URI to use depending on whether we are + // currently filtering. + Uri baseUri; + if (mCurFilter != null) { + baseUri = Uri.withAppendedPath(Contacts.CONTENT_FILTER_URI, + Uri.encode(mCurFilter)); + } else { + baseUri = Contacts.CONTENT_URI; + } + + // Now create and return a CursorLoader that will take care of + // creating a Cursor for the data being displayed. + String select = "((" + Contacts.DISPLAY_NAME + " NOTNULL) AND (" + + Contacts.HAS_PHONE_NUMBER + "=1) AND (" + + Contacts.DISPLAY_NAME + " != '' ))"; + return new CursorLoader(getActivity(), baseUri, + CONTACTS_SUMMARY_PROJECTION, select, null, + Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC"); + } + + public void onLoadFinished(Loader<Cursor> loader, Cursor data) { + // Swap the new cursor in. (The framework will take care of closing the + // old cursor once we return.) + mAdapter.swapCursor(data); + } + + public void onLoaderReset(Loader<Cursor> loader) { + // This is called when the last Cursor provided to onLoadFinished() + // above is about to be closed. We need to make sure we are no + // longer using it. + mAdapter.swapCursor(null); + } +}</pre> +<h3 id="more_examples">More Examples</h3> + +<p>There are a few different samples in <strong>ApiDemos</strong> that +illustrate how to use loaders:</p> +<ul> + <li><a +href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/LoaderCursor.html"> +LoaderCursor</a> — A complete version of the +snippet shown above.</li> + <li><a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/LoaderThrottle.html"> LoaderThrottle</a> — An example of how to use throttling to +reduce the number of queries a content provider does when its data changes.</li> +</ul> + +<p>For information on downloading and installing the SDK samples, see <a +href="http://developer.android.com/resources/samples/get.html"> Getting the +Samples</a>. </p> + diff --git a/docs/html/guide/components/processes-and-threads.jd b/docs/html/guide/components/processes-and-threads.jd new file mode 100644 index 0000000..07a2667 --- /dev/null +++ b/docs/html/guide/components/processes-and-threads.jd @@ -0,0 +1,424 @@ +page.title=Processes and Threads +@jd:body + +<div id="qv-wrapper"> +<div id="qv"> +<h2>Quickview</h2> +<ul> + <li>Every application runs in its own process and all components of the application run in that +process, by default</li> + <li>Any slow, blocking operations in an activity should be done in a new thread, to avoid slowing +down the user interface</li> +</ul> + +<h2>In this document</h2> +<ol> +<li><a href="#Processes">Processes</a> + <ol> + <li><a href="#Lifecycle">Process lifecycle</a></li> + </ol> +</li> +<li><a href="#Threads">Threads</a> + <ol> + <li><a href="#WorkerThreads">Worker threads</a></li> + <li><a href="#ThreadSafe">Thread-safe methods</a></li> + </ol> +</li> +<li><a href="#IPC">Interprocess Communication</a></li> +</ol> + +</div> +</div> + +<p>When an application component starts and the application does not have any other components +running, the Android system starts a new Linux process for the application with a single thread of +execution. By default, all components of the same application run in the same process and thread +(called the "main" thread). If an application component starts and there already exists a process +for that application (because another component from the application exists), then the component is +started within that process and uses the same thread of execution. However, you can arrange for +different components in your application to run in separate processes, and you can create additional +threads for any process.</p> + +<p>This document discusses how processes and threads work in an Android application.</p> + + +<h2 id="Processes">Processes</h2> + +<p>By default, all components of the same application run in the same process and most applications +should not change this. However, if you find that you need to control which process a certain +component belongs to, you can do so in the manifest file.</p> + +<p>The manifest entry for each type of component element—<a +href="{@docRoot}guide/topics/manifest/activity-element.html">{@code +<activity>}</a>, <a href="{@docRoot}guide/topics/manifest/service-element.html">{@code +<service>}</a>, <a href="{@docRoot}guide/topics/manifest/receiver-element.html">{@code +<receiver>}</a>, and <a href="{@docRoot}guide/topics/manifest/provider-element.html">{@code +<provider>}</a>—supports an {@code android:process} attribute that can specify a +process in which that component should run. You can set this attribute so that each component runs +in its own process or so that some components share a process while others do not. You can also set +{@code android:process} so that components of different applications run in the same +process—provided that the applications share the same Linux user ID and are signed with the +same certificates.</p> + +<p>The <a href="{@docRoot}guide/topics/manifest/application-element.html">{@code +<application>}</a> element also supports an {@code android:process} attribute, to set a +default value that applies to all components.</p> + +<p>Android might decide to shut down a process at some point, when memory is low and required by +other processes that are more immediately serving the user. Application +components running in the process that's killed are consequently destroyed. A process is started +again for those components when there's again work for them to do.</p> + +<p>When deciding which processes to kill, the Android system weighs their relative importance to +the user. For example, it more readily shuts down a process hosting activities that are no longer +visible on screen, compared to a process hosting visible activities. The decision whether to +terminate a process, therefore, depends on the state of the components running in that process. The +rules used to decide which processes to terminate is discussed below. </p> + + +<h3 id="Lifecycle">Process lifecycle</h3> + +<p>The Android system tries to maintain an application process for as long as possible, but +eventually needs to remove old processes to reclaim memory for new or more important processes. To +determine which processes to keep +and which to kill, the system places each process into an "importance hierarchy" based on the +components running in the process and the state of those components. Processes with the lowest +importance are eliminated first, then those with the next lowest importance, and so on, as necessary +to recover system resources.</p> + +<p>There are five levels in the importance hierarchy. The following list presents the different +types of processes in order of importance (the first process is <em>most important</em> and is +<em>killed last</em>):</p> + +<ol> + <li><b>Foreground process</b> + <p>A process that is required for what the user is currently doing. A + process is considered to be in the foreground if any of the following conditions are true:</p> + + <ul> + <li>It hosts an {@link android.app.Activity} that the user is interacting with (the {@link +android.app.Activity}'s {@link android.app.Activity#onResume onResume()} method has been +called).</li> + + <li>It hosts a {@link android.app.Service} that's bound to the activity that the user is +interacting with.</li> + + <li>It hosts a {@link android.app.Service} that's running "in the foreground"—the +service has called {@link android.app.Service#startForeground startForeground()}. + + <li>It hosts a {@link android.app.Service} that's executing one of its lifecycle +callbacks ({@link android.app.Service#onCreate onCreate()}, {@link android.app.Service#onStart +onStart()}, or {@link android.app.Service#onDestroy onDestroy()}).</li> + + <li>It hosts a {@link android.content.BroadcastReceiver} that's executing its {@link + android.content.BroadcastReceiver#onReceive onReceive()} method.</li> + </ul> + + <p>Generally, only a few foreground processes exist at any given time. They are killed only as +a last resort—if memory is so low that they cannot all continue to run. Generally, at that +point, the device has reached a memory paging state, so killing some foreground processes is +required to keep the user interface responsive.</p></li> + + <li><b>Visible process</b> + <p>A process that doesn't have any foreground components, but still can + affect what the user sees on screen. A process is considered to be visible if either of the + following conditions are true:</p> + + <ul> + <li>It hosts an {@link android.app.Activity} that is not in the foreground, but is still +visible to the user (its {@link android.app.Activity#onPause onPause()} method has been called). +This might occur, for example, if the foreground activity started a dialog, which allows the +previous activity to be seen behind it.</li> + + <li>It hosts a {@link android.app.Service} that's bound to a visible (or foreground) +activity.</li> + </ul> + + <p>A visible process is considered extremely important and will not be killed unless doing so +is required to keep all foreground processes running. </p> + </li> + + <li><b>Service process</b> + <p>A process that is running a service that has been started with the {@link +android.content.Context#startService startService()} method and does not fall into either of the two +higher categories. Although service processes are not directly tied to anything the user sees, they +are generally doing things that the user cares about (such as playing music in the background or +downloading data on the network), so the system keeps them running unless there's not enough memory +to retain them along with all foreground and visible processes. </p> + </li> + + <li><b>Background process</b> + <p>A process holding an activity that's not currently visible to the user (the activity's +{@link android.app.Activity#onStop onStop()} method has been called). These processes have no direct +impact on the user experience, and the system can kill them at any time to reclaim memory for a +foreground, +visible, or service process. Usually there are many background processes running, so they are kept +in an LRU (least recently used) list to ensure that the process with the activity that was most +recently seen by the user is the last to be killed. If an activity implements its lifecycle methods +correctly, and saves its current state, killing its process will not have a visible effect on +the user experience, because when the user navigates back to the activity, the activity restores +all of its visible state. See the <a +href="{@docRoot}guide/components/activities.html#SavingActivityState">Activities</a> +document for information about saving and restoring state.</p> + </li> + + <li><b>Empty process</b> + <p>A process that doesn't hold any active application components. The only reason to keep this +kind of process alive is for caching purposes, to improve startup time the next time a component +needs to run in it. The system often kills these processes in order to balance overall system +resources between process caches and the underlying kernel caches.</p> + </li> +</ol> + + + <p>Android ranks a process at the highest level it can, based upon the importance of the +components currently active in the process. For example, if a process hosts a service and a visible +activity, the process is ranked as a visible process, not a service process.</p> + + <p>In addition, a process's ranking might be increased because other processes are dependent on +it—a process that is serving another process can never be ranked lower than the process it is +serving. For example, if a content provider in process A is serving a client in process B, or if a +service in process A is bound to a component in process B, process A is always considered at least +as important as process B.</p> + + <p>Because a process running a service is ranked higher than a process with background activities, +an activity that initiates a long-running operation might do well to start a <a +href="{@docRoot}guide/components/services.html">service</a> for that operation, rather than +simply create a worker thread—particularly if the operation will likely outlast the activity. +For example, an activity that's uploading a picture to a web site should start a service to perform +the upload so that the upload can continue in the background even if the user leaves the activity. +Using a service guarantees that the operation will have at least "service process" priority, +regardless of what happens to the activity. This is the same reason that broadcast receivers should +employ services rather than simply put time-consuming operations in a thread.</p> + + + + +<h2 id="Threads">Threads</h2> + +<p>When an application is launched, the system creates a thread of execution for the application, +called "main." This thread is very important because it is in charge of dispatching events to +the appropriate user interface widgets, including drawing events. It is also the thread in which +your application interacts with components from the Android UI toolkit (components from the {@link +android.widget} and {@link android.view} packages). As such, the main thread is also sometimes +called the UI thread.</p> + +<p>The system does <em>not</em> create a separate thread for each instance of a component. All +components that run in the same process are instantiated in the UI thread, and system calls to +each component are dispatched from that thread. Consequently, methods that respond to system +callbacks (such as {@link android.view.View#onKeyDown onKeyDown()} to report user actions +or a lifecycle callback method) always run in the UI thread of the process.</p> + +<p>For instance, when the user touches a button on the screen, your app's UI thread dispatches the +touch event to the widget, which in turn sets its pressed state and posts an invalidate request to +the event queue. The UI thread dequeues the request and notifies the widget that it should redraw +itself.</p> + +<p>When your app performs intensive work in response to user interaction, this single thread model +can yield poor performance unless you implement your application properly. Specifically, if +everything is happening in the UI thread, performing long operations such as network access or +database queries will block the whole UI. When the thread is blocked, no events can be dispatched, +including drawing events. From the user's perspective, the +application appears to hang. Even worse, if the UI thread is blocked for more than a few seconds +(about 5 seconds currently) the user is presented with the infamous "<a +href="http://developer.android.com/guide/practices/responsiveness.html">application not +responding</a>" (ANR) dialog. The user might then decide to quit your application and uninstall it +if they are unhappy.</p> + +<p>Additionally, the Andoid UI toolkit is <em>not</em> thread-safe. So, you must not manipulate +your UI from a worker thread—you must do all manipulation to your user interface from the UI +thread. Thus, there are simply two rules to Android's single thread model:</p> + +<ol> +<li>Do not block the UI thread +<li>Do not access the Android UI toolkit from outside the UI thread +</ol> + +<h3 id="WorkerThreads">Worker threads</h3> + +<p>Because of the single thread model described above, it's vital to the responsiveness of your +application's UI that you do not block the UI thread. If you have operations to perform +that are not instantaneous, you should make sure to do them in separate threads ("background" or +"worker" threads).</p> + +<p>For example, below is some code for a click listener that downloads an image from a separate +thread and displays it in an {@link android.widget.ImageView}:</p> + +<pre> +public void onClick(View v) { + new Thread(new Runnable() { + public void run() { + Bitmap b = loadImageFromNetwork("http://example.com/image.png"); + mImageView.setImageBitmap(b); + } + }).start(); +} +</pre> + +<p>At first, this seems to work fine, because it creates a new thread to handle the network +operation. However, it violates the second rule of the single-threaded model: <em>do not access the +Android UI toolkit from outside the UI thread</em>—this sample modifies the {@link +android.widget.ImageView} from the worker thread instead of the UI thread. This can result in +undefined and unexpected behavior, which can be difficult and time-consuming to track down.</p> + +<p>To fix this problem, Android offers several ways to access the UI thread from other +threads. Here is a list of methods that can help:</p> + +<ul> +<li>{@link android.app.Activity#runOnUiThread(java.lang.Runnable) +Activity.runOnUiThread(Runnable)}</li> +<li>{@link android.view.View#post(java.lang.Runnable) View.post(Runnable)}</li> +<li>{@link android.view.View#postDelayed(java.lang.Runnable, long) View.postDelayed(Runnable, +long)}</li> +</ul> + +<p>For example, you can fix the above code by using the {@link +android.view.View#post(java.lang.Runnable) View.post(Runnable)} method:</p> + +<pre> +public void onClick(View v) { + new Thread(new Runnable() { + public void run() { + final Bitmap bitmap = loadImageFromNetwork("http://example.com/image.png"); + mImageView.post(new Runnable() { + public void run() { + mImageView.setImageBitmap(bitmap); + } + }); + } + }).start(); +} +</pre> + +<p>Now this implementation is thread-safe: the network operation is done from a separate thread +while the {@link android.widget.ImageView} is manipulated from the UI thread.</p> + +<p>However, as the complexity of the operation grows, this kind of code can get complicated and +difficult to maintain. To handle more complex interactions with a worker thread, you might consider +using a {@link android.os.Handler} in your worker thread, to process messages delivered from the UI +thread. Perhaps the best solution, though, is to extend the {@link android.os.AsyncTask} class, +which simplifies the execution of worker thread tasks that need to interact with the UI.</p> + + +<h4 id="AsyncTask">Using AsyncTask</h4> + +<p>{@link android.os.AsyncTask} allows you to perform asynchronous work on your user +interface. It performs the blocking operations in a worker thread and then publishes the results on +the UI thread, without requiring you to handle threads and/or handlers yourself.</p> + +<p>To use it, you must subclass {@link android.os.AsyncTask} and implement the {@link +android.os.AsyncTask#doInBackground doInBackground()} callback method, which runs in a pool of +background threads. To update your UI, you should implement {@link +android.os.AsyncTask#onPostExecute onPostExecute()}, which delivers the result from {@link +android.os.AsyncTask#doInBackground doInBackground()} and runs in the UI thread, so you can safely +update your UI. You can then run the task by calling {@link android.os.AsyncTask#execute execute()} +from the UI thread.</p> + +<p>For example, you can implement the previous example using {@link android.os.AsyncTask} this +way:</p> + +<pre> +public void onClick(View v) { + new DownloadImageTask().execute("http://example.com/image.png"); +} + +private class DownloadImageTask extends AsyncTask<String, Void, Bitmap> { + /** The system calls this to perform work in a worker thread and + * delivers it the parameters given to AsyncTask.execute() */ + protected Bitmap doInBackground(String... urls) { + return loadImageFromNetwork(urls[0]); + } + + /** The system calls this to perform work in the UI thread and delivers + * the result from doInBackground() */ + protected void onPostExecute(Bitmap result) { + mImageView.setImageBitmap(result); + } +} +</pre> + +<p>Now the UI is safe and the code is simpler, because it separates the work into the +part that should be done on a worker thread and the part that should be done on the UI thread.</p> + +<p>You should read the {@link android.os.AsyncTask} reference for a full understanding on +how to use this class, but here is a quick overview of how it works:</p> + +<ul> +<li>You can specify the type of the parameters, the progress values, and the final +value of the task, using generics</li> +<li>The method {@link android.os.AsyncTask#doInBackground doInBackground()} executes automatically +on a worker thread</li> +<li>{@link android.os.AsyncTask#onPreExecute onPreExecute()}, {@link +android.os.AsyncTask#onPostExecute onPostExecute()}, and {@link +android.os.AsyncTask#onProgressUpdate onProgressUpdate()} are all invoked on the UI thread</li> +<li>The value returned by {@link android.os.AsyncTask#doInBackground doInBackground()} is sent to +{@link android.os.AsyncTask#onPostExecute onPostExecute()}</li> +<li>You can call {@link android.os.AsyncTask#publishProgress publishProgress()} at anytime in {@link +android.os.AsyncTask#doInBackground doInBackground()} to execute {@link +android.os.AsyncTask#onProgressUpdate onProgressUpdate()} on the UI thread</li> +<li>You can cancel the task at any time, from any thread</li> +</ul> + +<p class="caution"><strong>Caution:</strong> Another problem you might encounter when using a worker +thread is unexpected restarts in your activity due to a <a +href="{@docRoot}guide/topics/resources/runtime-changes.html">runtime configuration change</a> +(such as when the user changes the screen orientation), which may destroy your worker thread. To +see how you can persist your task during one of these restarts and how to properly cancel the task +when the activity is destroyed, see the source code for the <a +href="http://code.google.com/p/shelves/">Shelves</a> sample application.</p> + + +<h3 id="ThreadSafe">Thread-safe methods</h3> + +<p> In some situations, the methods you implement might be called from more than one thread, and +therefore must be written to be thread-safe. </p> + +<p>This is primarily true for methods that can be called remotely—such as methods in a <a +href="{@docRoot}guide/components/bound-services.html">bound service</a>. When a call on a +method implemented in an {@link android.os.IBinder} originates in the same process in which the +{@link android.os.IBinder IBinder} is running, the method is executed in the caller's thread. +However, when the call originates in another process, the method is executed in a thread chosen from +a pool of threads that the system maintains in the same process as the {@link android.os.IBinder +IBinder} (it's not executed in the UI thread of the process). For example, whereas a service's +{@link android.app.Service#onBind onBind()} method would be called from the UI thread of the +service's process, methods implemented in the object that {@link android.app.Service#onBind +onBind()} returns (for example, a subclass that implements RPC methods) would be called from threads +in the pool. Because a service can have more than one client, more than one pool thread can engage +the same {@link android.os.IBinder IBinder} method at the same time. {@link android.os.IBinder +IBinder} methods must, therefore, be implemented to be thread-safe.</p> + +<p> Similarly, a content provider can receive data requests that originate in other processes. +Although the {@link android.content.ContentResolver} and {@link android.content.ContentProvider} +classes hide the details of how the interprocess communication is managed, {@link +android.content.ContentProvider} methods that respond to those requests—the methods {@link +android.content.ContentProvider#query query()}, {@link android.content.ContentProvider#insert +insert()}, {@link android.content.ContentProvider#delete delete()}, {@link +android.content.ContentProvider#update update()}, and {@link android.content.ContentProvider#getType +getType()}—are called from a pool of threads in the content provider's process, not the UI +thread for the process. Because these methods might be called from any number of threads at the +same time, they too must be implemented to be thread-safe. </p> + + +<h2 id="IPC">Interprocess Communication</h2> + +<p>Android offers a mechanism for interprocess communication (IPC) using remote procedure calls +(RPCs), in which a method is called by an activity or other application component, but executed +remotely (in another process), with any result returned back to the +caller. This entails decomposing a method call and its data to a level the operating system can +understand, transmitting it from the local process and address space to the remote process and +address space, then reassembling and reenacting the call there. Return values are then +transmitted in the opposite direction. Android provides all the code to perform these IPC +transactions, so you can focus on defining and implementing the RPC programming interface. </p> + +<p>To perform IPC, your application must bind to a service, using {@link +android.content.Context#bindService bindService()}. For more information, see the <a +href="{@docRoot}guide/components/services.html">Services</a> developer guide.</p> + + +<!-- +<h2>Beginner's Path</h2> + +<p>For information about how to perform work in the background for an indefinite period of time +(without a user interface), continue with the <b><a +href="{@docRoot}guide/components/services.html">Services</a></b> document.</p> +--> diff --git a/docs/html/guide/components/services.jd b/docs/html/guide/components/services.jd new file mode 100644 index 0000000..ba5e1f0 --- /dev/null +++ b/docs/html/guide/components/services.jd @@ -0,0 +1,874 @@ +page.title=Services +@jd:body + +<div id="qv-wrapper"> +<ol id="qv"> +<h2>Quickview</h2> +<ul> + <li>A service can run in the background to perform work even while the user is in a different +application</li> + <li>A service can allow other components to bind to it, in order to interact with it and +perform interprocess communication</li> + <li>A service runs in the main thread of the application that hosts it, by default</li> +</ul> +<h2>In this document</h2> +<ol> +<li><a href="#Basics">The Basics</a></li> +<ol> + <li><a href="#Declaring">Declaring a service in the manifest</a></li> +</ol> +<li><a href="#CreatingAService">Creating a Started Service</a> + <ol> + <li><a href="#ExtendingIntentService">Extending the IntentService class</a></li> + <li><a href="#ExtendingService">Extending the Service class</a></li> + <li><a href="#StartingAService">Starting a service</a></li> + <li><a href="#Stopping">Stopping a service</a></li> + </ol> +</li> +<li><a href="#CreatingBoundService">Creating a Bound Service</a></li> +<li><a href="#Notifications">Sending Notifications to the User</a></li> +<li><a href="#Foreground">Running a Service in the Foreground</a></li> +<li><a href="#Lifecycle">Managing the Lifecycle of a Service</a> +<ol> + <li><a href="#LifecycleCallbacks">Implementing the lifecycle callbacks</a></li> +</ol> +</li> +</ol> + +<h2>Key classes</h2> +<ol> + <li>{@link android.app.Service}</li> + <li>{@link android.app.IntentService}</li> +</ol> + +<h2>Samples</h2> +<ol> + <li><a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/ServiceStartArguments.html">{@code + ServiceStartArguments}</a></li> + <li><a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/LocalService.html">{@code + LocalService}</a></li> +</ol> + +<h2>Articles</h2> +<ol> + <li><a href="{@docRoot}resources/articles/multitasking-android-way.html">Multitasking the Android Way</a></li> + <li><a href="{@docRoot}resources/articles/service-api-changes-starting-with.html">Service API changes starting + with Android 2.0</a></li> +</ol> + +<h2>See also</h2> +<ol> +<li><a href="{@docRoot}guide/components/bound-services.html">Bound Services</a></li> +</ol> + +</div> + + +<p>A {@link android.app.Service} is an application component that can perform +long-running operations in the background and does not provide a user interface. Another +application component can start a service and it will continue to run in the background even if the +user switches to another application. Additionally, a component can bind to a service to +interact with it and even perform interprocess communication (IPC). For example, a service might +handle network transactions, play music, perform file I/O, or interact with a content provider, all +from the background.</p> + +<p>A service can essentially take two forms:</p> + +<dl> + <dt>Started</dt> + <dd>A service is "started" when an application component (such as an activity) starts it by +calling {@link android.content.Context#startService startService()}. Once started, a service +can run in the background indefinitely, even if the component that started it is destroyed. Usually, +a started service performs a single operation and does not return a result to the caller. +For example, it might download or upload a file over the network. When the operation is done, the +service should stop itself.</dd> + <dt>Bound</dt> + <dd>A service is "bound" when an application component binds to it by calling {@link +android.content.Context#bindService bindService()}. A bound service offers a client-server +interface that allows components to interact with the service, send requests, get results, and even +do so across processes with interprocess communication (IPC). A bound service runs only as long as +another application component is bound to it. Multiple components can bind to the service at once, +but when all of them unbind, the service is destroyed.</dd> +</dl> + +<p>Although this documentation generally discusses these two types of services separately, your +service can work both ways—it can be started (to run indefinitely) and also allow binding. +It's simply a matter of whether you implement a couple callback methods: {@link +android.app.Service#onStartCommand onStartCommand()} to allow components to start it and {@link +android.app.Service#onBind onBind()} to allow binding.</p> + +<p>Regardless of whether your application is started, bound, or both, any application component +can use the service (even from a separate application), in the same way that any component can use +an activity—by starting it with an {@link android.content.Intent}. However, you can declare +the service as private, in the manifest file, and block access from other applications. This is +discussed more in the section about <a href="#Declaring">Declaring the service in the +manifest</a>.</p> + +<p class="caution"><strong>Caution:</strong> A service runs in the +main thread of its hosting process—the service does <strong>not</strong> create its own thread +and does <strong>not</strong> run in a separate process (unless you specify otherwise). This means +that, if your service is going to do any CPU intensive work or blocking operations (such as MP3 +playback or networking), you should create a new thread within the service to do that work. By using +a separate thread, you will reduce the risk of Application Not Responding (ANR) errors and the +application's main thread can remain dedicated to user interaction with your activities.</p> + + +<h2 id="Basics">The Basics</h2> + +<div class="sidebox-wrapper"> +<div class="sidebox"> + <h3>Should you use a service or a thread?</h3> + <p>A service is simply a component that can run in the background even when the user is not +interacting with your application. Thus, you should create a service only if that is what you +need.</p> + <p>If you need to perform work outside your main thread, but only while the user is interacting +with your application, then you should probably instead create a new thread and not a service. For +example, if you want to play some music, but only while your activity is running, you might create +a thread in {@link android.app.Activity#onCreate onCreate()}, start running it in {@link +android.app.Activity#onStart onStart()}, then stop it in {@link android.app.Activity#onStop +onStop()}. Also consider using {@link android.os.AsyncTask} or {@link android.os.HandlerThread}, +instead of the traditional {@link java.lang.Thread} class. See the <a +href="{@docRoot}guide/components/processes-and-threads.html#Threads">Processes and +Threading</a> document for more information about threads.</p> + <p>Remember that if you do use a service, it still runs in your application's main thread by +default, so you should still create a new thread within the service if it performs intensive or +blocking operations.</p> +</div> +</div> + +<p>To create a service, you must create a subclass of {@link android.app.Service} (or one +of its existing subclasses). In your implementation, you need to override some callback methods that +handle key aspects of the service lifecycle and provide a mechanism for components to bind to +the service, if appropriate. The most important callback methods you should override are:</p> + +<dl> + <dt>{@link android.app.Service#onStartCommand onStartCommand()}</dt> + <dd>The system calls this method when another component, such as an activity, +requests that the service be started, by calling {@link android.content.Context#startService +startService()}. Once this method executes, the service is started and can run in the +background indefinitely. If you implement this, it is your responsibility to stop the service when +its work is done, by calling {@link android.app.Service#stopSelf stopSelf()} or {@link +android.content.Context#stopService stopService()}. (If you only want to provide binding, you don't +need to implement this method.)</dd> + <dt>{@link android.app.Service#onBind onBind()}</dt> + <dd>The system calls this method when another component wants to bind with the +service (such as to perform RPC), by calling {@link android.content.Context#bindService +bindService()}. In your implementation of this method, you must provide an interface that clients +use to communicate with the service, by returning an {@link android.os.IBinder}. You must always +implement this method, but if you don't want to allow binding, then you should return null.</dd> + <dt>{@link android.app.Service#onCreate()}</dt> + <dd>The system calls this method when the service is first created, to perform one-time setup +procedures (before it calls either {@link android.app.Service#onStartCommand onStartCommand()} or +{@link android.app.Service#onBind onBind()}). If the service is already running, this method is not +called.</dd> + <dt>{@link android.app.Service#onDestroy()}</dt> + <dd>The system calls this method when the service is no longer used and is being destroyed. +Your service should implement this to clean up any resources such as threads, registered +listeners, receivers, etc. This is the last call the service receives.</dd> +</dl> + +<p>If a component starts the service by calling {@link +android.content.Context#startService startService()} (which results in a call to {@link +android.app.Service#onStartCommand onStartCommand()}), then the service +remains running until it stops itself with {@link android.app.Service#stopSelf()} or another +component stops it by calling {@link android.content.Context#stopService stopService()}.</p> + +<p>If a component calls +{@link android.content.Context#bindService bindService()} to create the service (and {@link +android.app.Service#onStartCommand onStartCommand()} is <em>not</em> called), then the service runs +only as long as the component is bound to it. Once the service is unbound from all clients, the +system destroys it.</p> + +<p>The Android system will force-stop a service only when memory is low and it must recover system +resources for the activity that has user focus. If the service is bound to an activity that has user +focus, then it's less likely to be killed, and if the service is declared to <a +href="#Foreground">run in the foreground</a> (discussed later), then it will almost never be killed. +Otherwise, if the service was started and is long-running, then the system will lower its position +in the list of background tasks over time and the service will become highly susceptible to +killing—if your service is started, then you must design it to gracefully handle restarts +by the system. If the system kills your service, it restarts it as soon as resources become +available again (though this also depends on the value you return from {@link +android.app.Service#onStartCommand onStartCommand()}, as discussed later). For more information +about when the system might destroy a service, see the <a +href="{@docRoot}guide/components/processes-and-threads.html">Processes and Threading</a> +document.</p> + +<p>In the following sections, you'll see how you can create each type of service and how to use +it from other application components.</p> + + + +<h3 id="Declaring">Declaring a service in the manifest</h3> + +<p>Like activities (and other components), you must declare all services in your application's +manifest file.</p> + +<p>To declare your service, add a <a +href="{@docRoot}guide/topics/manifest/service-element.html">{@code <service>}</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 ... > + <service android:name=".ExampleService" /> + ... + </application> +</manifest> +</pre> + +<p>There are other attributes you can include in the <a +href="{@docRoot}guide/topics/manifest/service-element.html">{@code <service>}</a> element to +define properties such as permissions required to start the service and the process in +which the service should run. The <a +href="{@docRoot}guide/topics/manifest/service-element.html#nm">{@code android:name}</a> +attribute is the only required attribute—it specifies the class name of the service. Once +you publish your application, you should not change this name, because if you do, you might break +some functionality where explicit intents are used to reference your service (read the blog post, <a +href="http://android-developers.blogspot.com/2011/06/things-that-cannot-change.html">Things +That Cannot Change</a>). + +<p>See the <a +href="{@docRoot}guide/topics/manifest/service-element.html">{@code <service>}</a> element +reference for more information about declaring your service in the manifest.</p> + +<p>Just like an activity, a service can define intent filters that allow other components to +invoke the service using implicit intents. By declaring intent filters, components +from any application installed on the user's device can potentially start your service if your +service declares an intent filter that matches the intent another application passes to {@link +android.content.Context#startService startService()}.</p> + +<p>If you plan on using your service only locally (other applications do not use it), then you +don't need to (and should not) supply any intent filters. Without any intent filters, you must +start the service using an intent that explicitly names the service class. More information +about <a href="#StartingAService">starting a service</a> is discussed below.</p> + +<p>Additionally, you can ensure that your service is private to your application only if +you include the <a +href="{@docRoot}guide/topics/manifest/service-element.html#exported">{@code android:exported}</a> +attribute and set it to {@code "false"}. This is effective even if your service supplies intent +filters.</p> + +<p>For more information about creating intent filters for your service, see the <a +href="{@docRoot}guide/components/intents-filters.html">Intents and Intent Filters</a> +document.</p> + + + +<h2 id="CreatingStartedService">Creating a Started Service</h2> + +<div class="sidebox-wrapper"> +<div class="sidebox"> + <h2>Targeting Android 1.6 or lower</h2> + <p>If you're building an application for Android 1.6 or lower, you need +to implement {@link android.app.Service#onStart onStart()}, instead of {@link +android.app.Service#onStartCommand onStartCommand()} (in Android 2.0, +{@link android.app.Service#onStart onStart()} was deprecated in favor of {@link +android.app.Service#onStartCommand onStartCommand()}).</p> + <p>For more information about providing compatibility with versions of Android older than 2.0, see +the {@link android.app.Service#onStartCommand onStartCommand()} documentation.</p> +</div> +</div> + +<p>A started service is one that another component starts by calling {@link +android.content.Context#startService startService()}, resulting in a call to the service's +{@link android.app.Service#onStartCommand onStartCommand()} method.</p> + +<p>When a service is started, it has a lifecycle that's independent of the +component that started it and the service can run in the background indefinitely, even if +the component that started it is destroyed. As such, the service should stop itself when its job +is done by calling {@link android.app.Service#stopSelf stopSelf()}, or another component can stop it +by calling {@link android.content.Context#stopService stopService()}.</p> + +<p>An application component such as an activity can start the service by calling {@link +android.content.Context#startService startService()} and passing an {@link android.content.Intent} +that specifies the service and includes any data for the service to use. The service receives +this {@link android.content.Intent} in the {@link android.app.Service#onStartCommand +onStartCommand()} method.</p> + +<p>For instance, suppose an activity needs to save some data to an online database. The activity can +start a companion service and deliver it the data to save by passing an intent to {@link +android.content.Context#startService startService()}. The service receives the intent in {@link +android.app.Service#onStartCommand onStartCommand()}, connects to the Internet and performs the +database transaction. When the transaction is done, the service stops itself and it is +destroyed.</p> + +<p class="caution"><strong>Caution:</strong> A services runs in the same process as the application +in which it is declared and in the main thread of that application, by default. So, if your service +performs intensive or blocking operations while the user interacts with an activity from the same +application, the service will slow down activity performance. To avoid impacting application +performance, you should start a new thread inside the service.</p> + +<p>Traditionally, there are two classes you can extend to create a started service:</p> +<dl> + <dt>{@link android.app.Service}</dt> + <dd>This is the base class for all services. When you extend this class, it's important that +you create a new thread in which to do all the service's work, because the service uses your +application's main thread, by default, which could slow the performance of any activity your +application is running.</dd> + <dt>{@link android.app.IntentService}</dt> + <dd>This is a subclass of {@link android.app.Service} that uses a worker thread to handle all +start requests, one at a time. This is the best option if you don't require that your service +handle multiple requests simultaneously. All you need to do is implement {@link +android.app.IntentService#onHandleIntent onHandleIntent()}, which receives the intent for each +start request so you can do the background work.</dd> +</dl> + +<p>The following sections describe how you can implement your service using either one for these +classes.</p> + + +<h3 id="ExtendingIntentService">Extending the IntentService class</h3> + +<p>Because most started services don't need to handle multiple requests simultaneously +(which can actually be a dangerous multi-threading scenario), it's probably best if you +implement your service using the {@link android.app.IntentService} class.</p> + +<p>The {@link android.app.IntentService} does the following:</p> + +<ul> + <li>Creates a default worker thread that executes all intents delivered to {@link +android.app.Service#onStartCommand onStartCommand()} separate from your application's main +thread.</li> + <li>Creates a work queue that passes one intent at a time to your {@link +android.app.IntentService#onHandleIntent onHandleIntent()} implementation, so you never have to +worry about multi-threading.</li> + <li>Stops the service after all start requests have been handled, so you never have to call +{@link android.app.Service#stopSelf}.</li> + <li>Provides default implementation of {@link android.app.IntentService#onBind onBind()} that +returns null.</li> + <li>Provides a default implementation of {@link android.app.IntentService#onStartCommand +onStartCommand()} that sends the intent to the work queue and then to your {@link +android.app.IntentService#onHandleIntent onHandleIntent()} implementation.</li> +</ul> + +<p>All this adds up to the fact that all you need to do is implement {@link +android.app.IntentService#onHandleIntent onHandleIntent()} to do the work provided by the +client. (Though, you also need to provide a small constructor for the service.)</p> + +<p>Here's an example implementation of {@link android.app.IntentService}:</p> + +<pre> +public class HelloIntentService extends IntentService { + + /** + * A constructor is required, and must call the super {@link android.app.IntentService#IntentService} + * constructor with a name for the worker thread. + */ + public HelloIntentService() { + super("HelloIntentService"); + } + + /** + * The IntentService calls this method from the default worker thread with + * the intent that started the service. When this method returns, IntentService + * stops the service, as appropriate. + */ + @Override + protected void onHandleIntent(Intent intent) { + // Normally we would do some work here, like download a file. + // For our sample, we just sleep for 5 seconds. + long endTime = System.currentTimeMillis() + 5*1000; + while (System.currentTimeMillis() < endTime) { + synchronized (this) { + try { + wait(endTime - System.currentTimeMillis()); + } catch (Exception e) { + } + } + } + } +} +</pre> + +<p>That's all you need: a constructor and an implementation of {@link +android.app.IntentService#onHandleIntent onHandleIntent()}.</p> + +<p>If you decide to also override other callback methods, such as {@link +android.app.IntentService#onCreate onCreate()}, {@link +android.app.IntentService#onStartCommand onStartCommand()}, or {@link +android.app.IntentService#onDestroy onDestroy()}, be sure to call the super implementation, so +that the {@link android.app.IntentService} can properly handle the life of the worker thread.</p> + +<p>For example, {@link android.app.IntentService#onStartCommand onStartCommand()} must return +the default implementation (which is how the intent gets delivered to {@link +android.app.IntentService#onHandleIntent onHandleIntent()}):</p> + +<pre> +@Override +public int onStartCommand(Intent intent, int flags, int startId) { + Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show(); + return super.onStartCommand(intent,flags,startId); +} +</pre> + +<p>Besides {@link android.app.IntentService#onHandleIntent onHandleIntent()}, the only method +from which you don't need to call the super class is {@link android.app.IntentService#onBind +onBind()} (but you only need to implement that if your service allows binding).</p> + +<p>In the next section, you'll see how the same kind of service is implemented when extending +the base {@link android.app.Service} class, which is a lot more code, but which might be +appropriate if you need to handle simultaneous start requests.</p> + + +<h3 id="ExtendingService">Extending the Service class</h3> + +<p>As you saw in the previous section, using {@link android.app.IntentService} makes your +implementation of a started service very simple. If, however, you require your service to +perform multi-threading (instead of processing start requests through a work queue), then you +can extend the {@link android.app.Service} class to handle each intent.</p> + +<p>For comparison, the following example code is an implementation of the {@link +android.app.Service} class that performs the exact same work as the example above using {@link +android.app.IntentService}. That is, for each start request, it uses a worker thread to perform the +job and processes only one request at a time.</p> + +<pre> +public class HelloService extends Service { + private Looper mServiceLooper; + private ServiceHandler mServiceHandler; + + // Handler that receives messages from the thread + private final class ServiceHandler extends Handler { + public ServiceHandler(Looper looper) { + super(looper); + } + @Override + public void handleMessage(Message msg) { + // Normally we would do some work here, like download a file. + // For our sample, we just sleep for 5 seconds. + long endTime = System.currentTimeMillis() + 5*1000; + while (System.currentTimeMillis() < endTime) { + synchronized (this) { + try { + wait(endTime - System.currentTimeMillis()); + } catch (Exception e) { + } + } + } + // Stop the service using the startId, so that we don't stop + // the service in the middle of handling another job + stopSelf(msg.arg1); + } + } + + @Override + public void onCreate() { + // Start up the thread running the service. Note that we create a + // separate thread because the service normally runs in the process's + // main thread, which we don't want to block. We also make it + // background priority so CPU-intensive work will not disrupt our UI. + HandlerThread thread = new HandlerThread("ServiceStartArguments", + Process.THREAD_PRIORITY_BACKGROUND); + thread.start(); + + // Get the HandlerThread's Looper and use it for our Handler + mServiceLooper = thread.getLooper(); + mServiceHandler = new ServiceHandler(mServiceLooper); + } + + @Override + public int onStartCommand(Intent intent, int flags, int startId) { + Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show(); + + // For each start request, send a message to start a job and deliver the + // start ID so we know which request we're stopping when we finish the job + Message msg = mServiceHandler.obtainMessage(); + msg.arg1 = startId; + mServiceHandler.sendMessage(msg); + + // If we get killed, after returning from here, restart + return START_STICKY; + } + + @Override + public IBinder onBind(Intent intent) { + // We don't provide binding, so return null + return null; + } + + @Override + public void onDestroy() { + Toast.makeText(this, "service done", Toast.LENGTH_SHORT).show(); + } +} +</pre> + +<p>As you can see, it's a lot more work than using {@link android.app.IntentService}.</p> + +<p>However, because you handle each call to {@link android.app.Service#onStartCommand +onStartCommand()} yourself, you can perform multiple requests simultaneously. That's not what +this example does, but if that's what you want, then you can create a new thread for each +request and run them right away (instead of waiting for the previous request to finish).</p> + +<p>Notice that the {@link android.app.Service#onStartCommand onStartCommand()} method must return an +integer. The integer is a value that describes how the system should continue the service in the +event that the system kills it (as discussed above, the default implementation for {@link +android.app.IntentService} handles this for you, though you are able to modify it). The return value +from {@link android.app.Service#onStartCommand onStartCommand()} must be one of the following +constants:</p> + +<dl> + <dt>{@link android.app.Service#START_NOT_STICKY}</dt> + <dd>If the system kills the service after {@link android.app.Service#onStartCommand +onStartCommand()} returns, <em>do not</em> recreate the service, unless there are pending +intents to deliver. This is the safest option to avoid running your service when not necessary +and when your application can simply restart any unfinished jobs.</dd> + <dt>{@link android.app.Service#START_STICKY}</dt> + <dd>If the system kills the service after {@link android.app.Service#onStartCommand +onStartCommand()} returns, recreate the service and call {@link +android.app.Service#onStartCommand onStartCommand()}, but <em>do not</em> redeliver the last intent. +Instead, the system calls {@link android.app.Service#onStartCommand onStartCommand()} with a +null intent, unless there were pending intents to start the service, in which case, +those intents are delivered. This is suitable for media players (or similar services) that are not +executing commands, but running indefinitely and waiting for a job.</dd> + <dt>{@link android.app.Service#START_REDELIVER_INTENT}</dt> + <dd>If the system kills the service after {@link android.app.Service#onStartCommand +onStartCommand()} returns, recreate the service and call {@link +android.app.Service#onStartCommand onStartCommand()} with the last intent that was delivered to the +service. Any pending intents are delivered in turn. This is suitable for services that are +actively performing a job that should be immediately resumed, such as downloading a file.</dd> +</dl> +<p>For more details about these return values, see the linked reference documentation for each +constant.</p> + + + +<h3 id="StartingAService">Starting a Service</h3> + +<p>You can start a service from an activity or other application component by passing an +{@link android.content.Intent} (specifying the service to start) to {@link +android.content.Context#startService startService()}. The Android system calls the service's {@link +android.app.Service#onStartCommand onStartCommand()} method and passes it the {@link +android.content.Intent}. (You should never call {@link android.app.Service#onStartCommand +onStartCommand()} directly.)</p> + +<p>For example, an activity can start the example service in the previous section ({@code +HelloSevice}) using an explicit intent with {@link android.content.Context#startService +startService()}:</p> + +<pre> +Intent intent = new Intent(this, HelloService.class); +startService(intent); +</pre> + +<p>The {@link android.content.Context#startService startService()} method returns immediately and +the Android system calls the service's {@link android.app.Service#onStartCommand +onStartCommand()} method. If the service is not already running, the system first calls {@link +android.app.Service#onCreate onCreate()}, then calls {@link android.app.Service#onStartCommand +onStartCommand()}.</p> + +<p>If the service does not also provide binding, the intent delivered with {@link +android.content.Context#startService startService()} is the only mode of communication between the +application component and the service. However, if you want the service to send a result back, then +the client that starts the service can create a {@link android.app.PendingIntent} for a broadcast +(with {@link android.app.PendingIntent#getBroadcast getBroadcast()}) and deliver it to the service +in the {@link android.content.Intent} that starts the service. The service can then use the +broadcast to deliver a result.</p> + +<p>Multiple requests to start the service result in multiple corresponding calls to the service's +{@link android.app.Service#onStartCommand onStartCommand()}. However, only one request to stop +the service (with {@link android.app.Service#stopSelf stopSelf()} or {@link +android.content.Context#stopService stopService()}) is required to stop it.</p> + + +<h3 id="Stopping">Stopping a service</h3> + +<p>A started service must manage its own lifecycle. That is, the system does not stop or +destroy the service unless it must recover system memory and the service +continues to run after {@link android.app.Service#onStartCommand onStartCommand()} returns. So, +the service must stop itself by calling {@link android.app.Service#stopSelf stopSelf()} or another +component can stop it by calling {@link android.content.Context#stopService stopService()}.</p> + +<p>Once requested to stop with {@link android.app.Service#stopSelf stopSelf()} or {@link +android.content.Context#stopService stopService()}, the system destroys the service as soon as +possible.</p> + +<p>However, if your service handles multiple requests to {@link +android.app.Service#onStartCommand onStartCommand()} concurrently, then you shouldn't stop the +service when you're done processing a start request, because you might have since received a new +start request (stopping at the end of the first request would terminate the second one). To avoid +this problem, you can use {@link android.app.Service#stopSelf(int)} to ensure that your request to +stop the service is always based on the most recent start request. That is, when you call {@link +android.app.Service#stopSelf(int)}, you pass the ID of the start request (the <code>startId</code> +delivered to {@link android.app.Service#onStartCommand onStartCommand()}) to which your stop request +corresponds. Then if the service received a new start request before you were able to call {@link +android.app.Service#stopSelf(int)}, then the ID will not match and the service will not stop.</p> + +<p class="caution"><strong>Caution:</strong> It's important that your application stops its services +when it's done working, to avoid wasting system resources and consuming battery power. If necessary, +other components can stop the service by calling {@link +android.content.Context#stopService stopService()}. Even if you enable binding for the service, +you must always stop the service yourself if it ever received a call to {@link +android.app.Service#onStartCommand onStartCommand()}.</p> + +<p>For more information about the lifecycle of a service, see the section below about <a +href="#Lifecycle">Managing the Lifecycle of a Service</a>.</p> + + + +<h2 id="CreatingBoundService">Creating a Bound Service</h2> + +<p>A bound service is one that allows application components to bind to it by calling {@link +android.content.Context#bindService bindService()} in order to create a long-standing connection +(and generally does not allow components to <em>start</em> it by calling {@link +android.content.Context#startService startService()}).</p> + +<p>You should create a bound service when you want to interact with the service from activities +and other components in your application or to expose some of your application's functionality to +other applications, through interprocess communication (IPC).</p> + +<p>To create a bound service, you must implement the {@link +android.app.Service#onBind onBind()} callback method to return an {@link android.os.IBinder} that +defines the interface for communication with the service. Other application components can then call +{@link android.content.Context#bindService bindService()} to retrieve the interface and +begin calling methods on the service. The service lives only to serve the application component that +is bound to it, so when there are no components bound to the service, the system destroys it +(you do <em>not</em> need to stop a bound service in the way you must when the service is started +through {@link android.app.Service#onStartCommand onStartCommand()}).</p> + +<p>To create a bound service, the first thing you must do is define the interface that specifies +how a client can communicate with the service. This interface between the service +and a client must be an implementation of {@link android.os.IBinder} and is what your service must +return from the {@link android.app.Service#onBind +onBind()} callback method. Once the client receives the {@link android.os.IBinder}, it can begin +interacting with the service through that interface.</p> + +<p>Multiple clients can bind to the service at once. When a client is done interacting with the +service, it calls {@link android.content.Context#unbindService unbindService()} to unbind. Once +there are no clients bound to the service, the system destroys the service.</p> + +<p>There are multiple ways to implement a bound service and the implementation is more +complicated than a started service, so the bound service discussion appears in a separate +document about <a +href="{@docRoot}guide/components/bound-services.html">Bound Services</a>.</p> + + + +<h2 id="Notifications">Sending Notifications to the User</h2> + +<p>Once running, a service can notify the user of events using <a +href="{@docRoot}guide/topics/ui/notifiers/toasts.html">Toast Notifications</a> or <a +href="{@docRoot}guide/topics/ui/notifiers/notifications.html">Status Bar Notifications</a>.</p> + +<p>A toast notification is a message that appears on the surface of the current window for a +moment then disappears, while a status bar notification provides an icon in the status bar with a +message, which the user can select in order to take an action (such as start an activity).</p> + +<p>Usually, a status bar notification is the best technique when some background work has completed +(such as a file completed +downloading) and the user can now act on it. When the user selects the notification from the +expanded view, the notification can start an activity (such as to view the downloaded file).</p> + +<p>See the <a +href="{@docRoot}guide/topics/ui/notifiers/toasts.html">Toast Notifications</a> or <a +href="{@docRoot}guide/topics/ui/notifiers/notifications.html">Status Bar Notifications</a> +developer guides for more information.</p> + + + +<h2 id="Foreground">Running a Service in the Foreground</h2> + +<p>A foreground service is a service that's considered to be something the +user is actively aware of and thus not a candidate for the system to kill when low on memory. A +foreground service must provide a notification for the status bar, which is placed under the +"Ongoing" heading, which means that the notification cannot be dismissed unless the service is +either stopped or removed from the foreground.</p> + +<p>For example, a music player that plays music from a service should be set to run in the +foreground, because the user is explicitly aware +of its operation. The notification in the status bar might indicate the current song and allow +the user to launch an activity to interact with the music player.</p> + +<p>To request that your service run in the foreground, call {@link +android.app.Service#startForeground startForeground()}. This method takes two parameters: an integer +that uniquely identifies the notification and the {@link +android.app.Notification} for the status bar. For example:</p> + +<pre> +Notification notification = new Notification(R.drawable.icon, getText(R.string.ticker_text), + System.currentTimeMillis()); +Intent notificationIntent = new Intent(this, ExampleActivity.class); +PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0); +notification.setLatestEventInfo(this, getText(R.string.notification_title), + getText(R.string.notification_message), pendingIntent); +startForeground(ONGOING_NOTIFICATION, notification); +</pre> + + +<p>To remove the service from the foreground, call {@link +android.app.Service#stopForeground stopForeground()}. This method takes a boolean, indicating +whether to remove the status bar notification as well. This method does <em>not</em> stop the +service. However, if you stop the service while it's still running in the foreground, then the +notification is also removed.</p> + +<p class="note"><strong>Note:</strong> The methods {@link +android.app.Service#startForeground startForeground()} and {@link +android.app.Service#stopForeground stopForeground()} were introduced in Android 2.0 (API Level +5). In order to run your service in the foreground on older versions of the platform, you must +use the previous {@code setForeground()} method—see the {@link +android.app.Service#startForeground startForeground()} documentation for information about how +to provide backward compatibility.</p> + +<p>For more information about notifications, see <a +href="{@docRoot}guide/topics/ui/notifiers/notifications.html">Creating Status Bar +Notifications</a>.</p> + + + +<h2 id="Lifecycle">Managing the Lifecycle of a Service</h2> + +<p>The lifecycle of a service is much simpler than that of an activity. However, it's even more important +that you pay close attention to how your service is created and destroyed, because a service +can run in the background without the user being aware.</p> + +<p>The service lifecycle—from when it's created to when it's destroyed—can follow two +different paths:</p> + +<ul> +<li>A started service + <p>The service is created when another component calls {@link +android.content.Context#startService startService()}. The service then runs indefinitely and must +stop itself by calling {@link +android.app.Service#stopSelf() stopSelf()}. Another component can also stop the +service by calling {@link android.content.Context#stopService +stopService()}. When the service is stopped, the system destroys it..</p></li> + +<li>A bound service + <p>The service is created when another component (a client) calls {@link +android.content.Context#bindService bindService()}. The client then communicates with the service +through an {@link android.os.IBinder} interface. The client can close the connection by calling +{@link android.content.Context#unbindService unbindService()}. Multiple clients can bind to +the same service and when all of them unbind, the system destroys the service. (The service +does <em>not</em> need to stop itself.)</p></li> +</ul> + +<p>These two paths are not entirely separate. That is, you can bind to a service that was already +started with {@link android.content.Context#startService startService()}. For example, a background +music service could be started by calling {@link android.content.Context#startService +startService()} with an {@link android.content.Intent} that identifies the music to play. Later, +possibly when the user wants to exercise some control over the player or get information about the +current song, an activity can bind to the service by calling {@link +android.content.Context#bindService bindService()}. In cases like this, {@link +android.content.Context#stopService stopService()} or {@link android.app.Service#stopSelf +stopSelf()} does not actually stop the service until all clients unbind. </p> + + +<h3 id="LifecycleCallbacks">Implementing the lifecycle callbacks</h3> + +<p>Like an activity, a service has lifecycle callback methods that you can implement to monitor +changes in the service's state and perform work at the appropriate times. The following skeleton +service demonstrates each of the lifecycle methods:</p> + + +<div class="figure" style="width:432px"> +<img src="{@docRoot}images/service_lifecycle.png" alt="" /> +<p class="img-caption"><strong>Figure 2.</strong> The service lifecycle. The diagram on the left +shows the lifecycle when the service is created with {@link android.content.Context#startService +startService()} and the diagram on the right shows the lifecycle when the service is created +with {@link android.content.Context#bindService bindService()}.</p> +</div> + +<pre> +public class ExampleService extends Service { + int mStartMode; // indicates how to behave if the service is killed + IBinder mBinder; // interface for clients that bind + boolean mAllowRebind; // indicates whether onRebind should be used + + @Override + public void {@link android.app.Service#onCreate onCreate}() { + // The service is being created + } + @Override + public int {@link android.app.Service#onStartCommand onStartCommand}(Intent intent, int flags, int startId) { + // The service is starting, due to a call to {@link android.content.Context#startService startService()} + return <em>mStartMode</em>; + } + @Override + public IBinder {@link android.app.Service#onBind onBind}(Intent intent) { + // A client is binding to the service with {@link android.content.Context#bindService bindService()} + return <em>mBinder</em>; + } + @Override + public boolean {@link android.app.Service#onUnbind onUnbind}(Intent intent) { + // All clients have unbound with {@link android.content.Context#unbindService unbindService()} + return <em>mAllowRebind</em>; + } + @Override + public void {@link android.app.Service#onRebind onRebind}(Intent intent) { + // A client is binding to the service with {@link android.content.Context#bindService bindService()}, + // after onUnbind() has already been called + } + @Override + public void {@link android.app.Service#onDestroy onDestroy}() { + // The service is no longer used and is being destroyed + } +} +</pre> + +<p class="note"><strong>Note:</strong> Unlike the activity lifecycle callback methods, you are +<em>not</em> required to call the superclass implementation of these callback methods.</p> + +<p>By implementing these methods, you can monitor two nested loops of the service's lifecycle: </p> + +<ul> +<li>The <strong>entire lifetime</strong> of a service happens between the time {@link +android.app.Service#onCreate onCreate()} is called and the time {@link +android.app.Service#onDestroy} returns. Like an activity, a service does its initial setup in +{@link android.app.Service#onCreate onCreate()} and releases all remaining resources in {@link +android.app.Service#onDestroy onDestroy()}. For example, a +music playback service could create the thread where the music will be played in {@link +android.app.Service#onCreate onCreate()}, then stop the thread in {@link +android.app.Service#onDestroy onDestroy()}. + +<p>The {@link android.app.Service#onCreate onCreate()} and {@link android.app.Service#onDestroy +onDestroy()} methods are called for all services, whether +they're created by {@link android.content.Context#startService startService()} or {@link +android.content.Context#bindService bindService()}.</p></li> + +<li>The <strong>active lifetime</strong> of a service begins with a call to either {@link +android.app.Service#onStartCommand onStartCommand()} or {@link android.app.Service#onBind onBind()}. +Each method is handed the {@link +android.content.Intent} that was passed to either {@link android.content.Context#startService +startService()} or {@link android.content.Context#bindService bindService()}, respectively. +<p>If the service is started, the active lifetime ends the same time that the entire lifetime +ends (the service is still active even after {@link android.app.Service#onStartCommand +onStartCommand()} returns). If the service is bound, the active lifetime ends when {@link +android.app.Service#onUnbind onUnbind()} returns.</p> +</li> +</ul> + +<p class="note"><strong>Note:</strong> Although a started service is stopped by a call to +either {@link android.app.Service#stopSelf stopSelf()} or {@link +android.content.Context#stopService stopService()}, there is not a respective callback for the +service (there's no {@code onStop()} callback). So, unless the service is bound to a client, +the system destroys it when the service is stopped—{@link +android.app.Service#onDestroy onDestroy()} is the only callback received.</p> + +<p>Figure 2 illustrates the typical callback methods for a service. Although the figure separates +services that are created by {@link android.content.Context#startService startService()} from those +created by {@link android.content.Context#bindService bindService()}, keep +in mind that any service, no matter how it's started, can potentially allow clients to bind to it. +So, a service that was initially started with {@link android.app.Service#onStartCommand +onStartCommand()} (by a client calling {@link android.content.Context#startService startService()}) +can still receive a call to {@link android.app.Service#onBind onBind()} (when a client calls +{@link android.content.Context#bindService bindService()}).</p> + +<p>For more information about creating a service that provides binding, see the <a +href="{@docRoot}guide/components/bound-services.html">Bound Services</a> document, +which includes more information about the {@link android.app.Service#onRebind onRebind()} +callback method in the section about <a +href="{@docRoot}guide/components/bound-services.html#Lifecycle">Managing the Lifecycle of +a Bound Service</a>.</p> + + +<!-- +<h2>Beginner's Path</h2> + +<p>To learn how to query data from the system or other applications (such as contacts or media +stored on the device), continue with the <b><a +href="{@docRoot}guide/topics/providers/content-providers.html">Content Providers</a></b> +document.</p> +--> diff --git a/docs/html/guide/components/tasks-and-back-stack.jd b/docs/html/guide/components/tasks-and-back-stack.jd new file mode 100644 index 0000000..8b7041c --- /dev/null +++ b/docs/html/guide/components/tasks-and-back-stack.jd @@ -0,0 +1,595 @@ +page.title=Tasks and Back Stack +parent.title=Activities +parent.link=activities.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 users +to perform other tasks without losing 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>Articles</h2> +<ol> + <li><a href="http://android-developers.blogspot.com/2010/04/multitasking-android-way.html">Multitasking the Android Way</a></li> +</ol> + +<h2>See also</h2> +<ol> + <li><a href="{@docRoot}design/patterns/navigation.html">Android Design: +Navigation</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/components/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 <em>Back</em> button.</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 +<em>Back</em> +button, 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 <em>Back</em> button. 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 <em>Back</em> button, the current +activity is +destroyed and the previous activity resumes.</p> + + +<p>If the user continues to press <em>Back</em>, 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:287px"> +<img src="{@docRoot}images/fundamentals/diagram_multitasking.png" alt="" /> <p +class="img-caption"><strong>Figure 2.</strong> Two tasks: Task B receives user interaction +in the foreground, while Task A is in the background, waiting to be resumed.</p> +</div> +<div class="figure" style="width:215px"> + <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 <em>Home</em> button. 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 <em>Home</em> +button, 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 <em>Home</em> button 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 pushed 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 <em>Back</em> button, 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 <em>Back</em> button while in Activity B, Activity A resumes with its state +restored.</li> + <li>When the user leaves a task by pressing the <em>Home</em> button, 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 <em>Back</em> button, 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> + + +<div class="design-announce"> +<p><strong>Navigation Design</strong></p> + <p>For more about how app navigation works on Android, read Android Design's <a +href="{@docRoot}design/patterns/navigation.html">Navigation</a> guide.</p> +</div> + + +<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 losing 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/components/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 +activities 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 <em>Back</em> button. +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 launch modes available for the manifest file +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 receives 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 <em>Back</em> button to return to the previous activity. But when an existing +instance of +an activity handles a new intent, the user cannot press the <em>Back</em> button 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 +<em>Back</em> button 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 <em>Back</em> button always takes the user to the previous activity. However, if you +start an activity that specifies the {@code singleTask} launch mode, then if an instance of +that activity exists in a background task, that whole task is brought to the foreground. At this +point, the back stack now includes all activities from the task brought forward, at the top of the +stack. Figure 4 illustrates 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, then the entire back stack also comes +forward, on top of the current task.</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 overridden 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 <em>Home</em> button +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 <em>Home</em> button. The task is now sent to the background +and is +not visible. Now the user has no way to return to the task, because it is not represented in the +application launcher. +</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/components/intents-filters.html">Intents and Intent +Filters</a></b> document.</p> +--> |