diff options
author | Scott Main <smain@google.com> | 2012-06-21 17:14:39 -0700 |
---|---|---|
committer | Scott Main <smain@google.com> | 2012-06-21 21:27:30 -0700 |
commit | 50e990c64fa23ce94efa76b9e72df7f8ec3cee6a (patch) | |
tree | 52605cd25e01763596477956963fabcd087054b0 /docs/html/guide/topics/fundamentals | |
parent | a2860267cad115659018d636bf9203a644c680a7 (diff) | |
download | frameworks_base-50e990c64fa23ce94efa76b9e72df7f8ec3cee6a.zip frameworks_base-50e990c64fa23ce94efa76b9e72df7f8ec3cee6a.tar.gz frameworks_base-50e990c64fa23ce94efa76b9e72df7f8ec3cee6a.tar.bz2 |
Massive clobber of all HTML files in developer docs for new site design
Change-Id: Idc55a0b368c1d2c1e7d4999601b739dd57f08eb3
Diffstat (limited to 'docs/html/guide/topics/fundamentals')
-rw-r--r-- | docs/html/guide/topics/fundamentals/activities.jd | 777 | ||||
-rw-r--r-- | docs/html/guide/topics/fundamentals/bound-services.jd | 675 | ||||
-rw-r--r-- | docs/html/guide/topics/fundamentals/fragments.jd | 836 | ||||
-rw-r--r-- | docs/html/guide/topics/fundamentals/loaders.jd | 500 | ||||
-rw-r--r-- | docs/html/guide/topics/fundamentals/processes-and-threads.jd | 486 | ||||
-rw-r--r-- | docs/html/guide/topics/fundamentals/services.jd | 874 | ||||
-rw-r--r-- | docs/html/guide/topics/fundamentals/tasks-and-back-stack.jd | 596 |
7 files changed, 0 insertions, 4744 deletions
diff --git a/docs/html/guide/topics/fundamentals/activities.jd b/docs/html/guide/topics/fundamentals/activities.jd deleted file mode 100644 index b79136c..0000000 --- a/docs/html/guide/topics/fundamentals/activities.jd +++ /dev/null @@ -1,777 +0,0 @@ -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}resources/tutorials/hello-world.html">Hello World Tutorial</a></li> - <li><a href="{@docRoot}guide/topics/fundamentals/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/topics/fundamentals/tasks-and-back-stack.html">Tasks -and Back Stack</a> document.)</p> - -<p>When an activity is stopped because a new activity starts, it is notified of this change in state -through the activity's lifecycle callback methods. -There are several callback methods that an activity might receive, due to a change in its -state—whether the system is creating it, stopping it, resuming it, or destroying it—and -each callback provides you the opportunity to perform specific work that's -appropriate to that state change. For instance, when stopped, your activity should release any -large objects, such as network or database connections. When the activity resumes, you can -reacquire the necessary resources and resume actions that were interrupted. These state transitions -are all part of the activity lifecycle.</p> - -<p>The rest of this document discusses the basics of how to build and use an activity, -including a complete discussion of how the activity lifecycle works, so you can properly manage -the transition between various activity states.</p> - - - -<h2 id="Creating">Creating an Activity</h2> - -<p>To create an activity, you must create a subclass of {@link android.app.Activity} (or -an existing subclass of it). In your subclass, you need to implement callback methods that the -system calls when the activity transitions between various states of its lifecycle, such as when -the activity is being created, stopped, resumed, or destroyed. The two most important callback -methods are:</p> - -<dl> - <dt>{@link android.app.Activity#onCreate onCreate()}</dt> - <dd>You must implement this method. The system calls this when creating your - activity. Within your implementation, you should initialize the essential components of your -activity. - Most importantly, this is where you must call {@link android.app.Activity#setContentView - setContentView()} to define the layout for the activity's user interface.</dd> - <dt>{@link android.app.Activity#onPause onPause()}</dt> - <dd>The system calls this method as the first indication that the user is leaving your -activity (though it does not always mean the activity is being destroyed). This is usually where you -should commit any changes that should be persisted beyond the current user session (because -the user might not come back).</dd> -</dl> - -<p>There are several other lifecycle callback methods that you should use in order to provide a -fluid user experience between activities and handle unexpected interuptions that cause your activity -to be stopped and even destroyed. All of the lifecycle callback methods are discussed later, in -the section about <a href="#Lifecycle">Managing the Activity Lifecycle</a>.</p> - - - -<h3 id="UI">Implementing a user interface</h3> - -<p> The user interface for an activity is provided by a hierarchy of views—objects derived -from the {@link android.view.View} class. Each view controls a particular rectangular space -within the activity's window and can respond to user interaction. For example, a view might be a -button that initiates an action when the user touches it.</p> - -<p>Android provides a number of ready-made views that you can use to design and organize your -layout. "Widgets" are views that provide a visual (and interactive) elements for the screen, such -as a button, text field, checkbox, or just an image. "Layouts" are views derived from {@link -android.view.ViewGroup} that provide a unique layout model for its child views, such as a linear -layout, a grid layout, or relative layout. You can also subclass the {@link android.view.View} and -{@link android.view.ViewGroup} classes (or existing subclasses) to create your own widgets and -layouts and apply them to your activity layout.</p> - -<p>The most common way to define a layout using views is with an XML layout file saved in your -application resources. This way, you can maintain the design of your user interface separately from -the source code that defines the activity's behavior. You can set the layout as the UI for your -activity with {@link android.app.Activity#setContentView(int) setContentView()}, passing the -resource ID for the layout. However, you can also create new {@link android.view.View}s in your -activity code and build a view hierarchy by inserting new {@link -android.view.View}s into a {@link android.view.ViewGroup}, then use that layout by passing the root -{@link android.view.ViewGroup} to {@link android.app.Activity#setContentView(View) -setContentView()}.</p> - -<p>For information about creating a user interface, see the <a -href="{@docRoot}guide/topics/ui/index.html">User Interface</a> documentation.</p> - - - -<h3 id="Declaring">Declaring the activity in the manifest</h3> - -<p>You must declare your activity in the manifest file in order for it to -be accessible to the system. To 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/topics/intents/intents-filters.html">Intents and Intent Filters</a> -document.</p> - - - -<h2 id="StartingAnActivity">Starting an Activity</h2> - -<p>You can start another activity by calling {@link android.app.Activity#startActivity - startActivity()}, passing it an {@link android.content.Intent} that describes the activity you - want to start. The intent specifies either the exact activity you want to start or describes the - type of action you want to perform (and the system selects the appropriate activity for you, -which - can even be from a different application). An intent can also carry small amounts of data to be - used by the activity that is started.</p> - -<p>When working within your own application, you'll often need to simply launch a known activity. - You can do so by creating an intent that explicitly defines the activity you want to start, -using the class name. For example, here's how one activity starts another activity named {@code -SignInActivity}:</p> - -<pre> -Intent intent = new Intent(this, SignInActivity.class); -startActivity(intent); -</pre> - -<p>However, your application might also want to perform some action, such as send an email, text - message, or status update, using data from your activity. In this case, your application might - not have its own activities to perform such actions, so you can instead leverage the activities - provided by other applications on the device, which can perform the actions for you. This is where -intents are really valuable—you can create an intent that describes an action you want to -perform and the system - launches the appropriate activity from another application. If there are - multiple activities that can handle the intent, then the user can select which one to use. For - example, if you want to allow the user to send an email message, you can create the - following intent:</p> - -<pre> -Intent intent = new Intent(Intent.ACTION_SEND); -intent.putExtra(Intent.EXTRA_EMAIL, recipientArray); -startActivity(intent); -</pre> - -<p>The {@link android.content.Intent#EXTRA_EMAIL} extra added to the intent is a string array of - email addresses to which the email should be sent. When an email application responds to this - intent, it reads the string array provided in the extra and places them in the "to" field of the - email composition form. In this situation, the email application's activity starts and when the - user is done, your activity resumes.</p> - - - - -<h3 id="StartingAnActivityForResult">Starting an activity for a result</h3> - -<p>Sometimes, you might want to receive a result from the activity that you start. In that case, - start the activity by calling {@link android.app.Activity#startActivityForResult - startActivityForResult()} (instead of {@link android.app.Activity#startActivity - startActivity()}). To then receive the result from the subsequent -activity, implement the {@link android.app.Activity#onActivityResult onActivityResult()} callback - method. When the subsequent activity is done, it returns a result in an {@link -android.content.Intent} to your {@link android.app.Activity#onActivityResult onActivityResult()} -method.</p> - -<p>For example, perhaps you want the user to pick one of their contacts, so your activity can -do something with the information in that contact. Here's how you can create such an intent and -handle the result:</p> - -<pre> -private void pickContact() { - // Create an intent to "pick" a contact, as defined by the content provider URI - Intent intent = new Intent(Intent.ACTION_PICK, Contacts.CONTENT_URI); - startActivityForResult(intent, PICK_CONTACT_REQUEST); -} - -@Override -protected void onActivityResult(int requestCode, int resultCode, Intent data) { - // If the request went well (OK) and the request was PICK_CONTACT_REQUEST - if (resultCode == Activity.RESULT_OK && requestCode == PICK_CONTACT_REQUEST) { - // Perform a query to the contact's content provider for the contact's name - Cursor cursor = getContentResolver().query(data.getData(), - new String[] {Contacts.DISPLAY_NAME}, null, null, null); - if (cursor.moveToFirst()) { // True if the cursor is not empty - int columnIndex = cursor.getColumnIndex(Contacts.DISPLAY_NAME); - String name = cursor.getString(columnIndex); - // Do something with the selected contact's name... - } - } -} -</pre> - -<p>This example shows the basic logic you should use in your {@link -android.app.Activity#onActivityResult onActivityResult()} method in order to handle an -activity result. The first condition checks whether the request was successful—if it was, then -the {@code resultCode} will be {@link android.app.Activity#RESULT_OK}—and whether the request -to which this result is responding is known—in this case, the {@code requestCode} matches the -second parameter sent with {@link android.app.Activity#startActivityForResult -startActivityForResult()}. From there, the code handles the activity result by querying the -data returned in an {@link android.content.Intent} (the {@code data} parameter).</p> - -<p>What happens is, a {@link -android.content.ContentResolver} performs a query against a content provider, which returns a -{@link android.database.Cursor} that allows the queried data to be read. For more information, see -the <a -href="{@docRoot}guide/topics/providers/content-providers.html">Content Providers</a> document.</p> - -<p>For more information about using intents, see the <a -href="{@docRoot}guide/topics/intents/intents-filters.html">Intents and Intent -Filters</a> document.</p> - - -<h2 id="ShuttingDown">Shutting Down an Activity</h2> - -<p>You can shut down an activity by calling its {@link android.app.Activity#finish -finish()} method. You can also shut down a separate activity that you previously started by calling -{@link android.app.Activity#finishActivity finishActivity()}.</p> - -<p class="note"><strong>Note:</strong> In most cases, you should not explicitly finish an activity -using these methods. As discussed in the following section about the activity lifecycle, the -Android system manages the life of an activity for you, so you do not need to finish your own -activities. Calling these methods could adversely affect the expected user -experience and should only be used when you absolutely do not want the user to return to this -instance of the activity.</p> - - -<h2 id="Lifecycle">Managing the Activity Lifecycle</h2> - -<p>Managing the lifecycle of your activities by implementing callback methods is -crucial to developing a strong -and flexible application. The lifecycle of an activity is directly affected by its association with -other activities, its task and back stack.</p> - -<p>An activity can exist in essentially three states:</p> - -<dl> - <dt><i>Resumed</i></dt> - <dd>The activity is in the foreground of the screen and has user focus. (This state is -also sometimes referred to as "running".)</dd> - - <dt><i>Paused</i></dt> - <dd>Another activity is in the foreground and has focus, but this one is still visible. That is, -another activity is visible on top of this one and that activity is partially transparent or doesn't -cover the entire screen. A paused activity is completely alive (the {@link android.app.Activity} -object is retained in memory, it maintains all state and member information, and remains attached to -the window manager), but can be killed by the system in extremely low memory situations.</dd> - - <dt><i>Stopped</i></dt> - <dd>The activity is completely obscured by another activity (the activity is now in the -"background"). A stopped activity is also still alive (the {@link android.app.Activity} -object is retained in memory, it maintains all state and member information, but is <em>not</em> -attached to the window manager). However, it is no longer visible to the user and it -can be killed by the system when memory is needed elsewhere.</dd> -</dl> - -<p>If an activity is paused or stopped, the system can drop it from memory either by asking it to -finish (calling its {@link android.app.Activity#finish finish()} method), or simply killing its -process. When the activity is opened again (after being finished or killed), it must be created all -over.</p> - - - -<h3 id="ImplementingLifecycleCallbacks">Implementing the lifecycle callbacks</h3> - -<p>When an activity transitions into and out of the different states described above, it is notified -through various callback methods. All of the callback methods are hooks that you -can override to do appropriate work when the state of your activity changes. The following skeleton -activity includes each of the fundamental lifecycle methods:</p> - - -<pre> -public class ExampleActivity extends Activity { - @Override - public void {@link android.app.Activity#onCreate onCreate}(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - // The activity is being created. - } - @Override - protected void {@link android.app.Activity#onStart onStart()} { - super.onStart(); - // The activity is about to become visible. - } - @Override - protected void {@link android.app.Activity#onResume onResume()} { - super.onResume(); - // The activity has become visible (it is now "resumed"). - } - @Override - protected void {@link android.app.Activity#onPause onPause()} { - super.onPause(); - // Another activity is taking focus (this activity is about to be "paused"). - } - @Override - protected void {@link android.app.Activity#onStop onStop()} { - super.onStop(); - // The activity is no longer visible (it is now "stopped") - } - @Override - protected void {@link android.app.Activity#onDestroy onDestroy()} { - super.onDestroy(); - // The activity is about to be destroyed. - } -} -</pre> - -<p class="note"><strong>Note:</strong> Your implementation of these lifecycle methods must -always call the superclass implementation before doing any work, as shown in the examples above.</p> - -<p>Taken together, these methods define the entire lifecycle of an activity. By implementing these -methods, you can monitor three nested loops in the activity lifecycle: </p> - -<ul> -<li>The <b>entire lifetime</b> of an activity happens between the call to {@link -android.app.Activity#onCreate onCreate()} and the call to {@link -android.app.Activity#onDestroy}. Your activity should perform setup of -"global" state (such as defining layout) in {@link android.app.Activity#onCreate onCreate()}, and -release all remaining resources in {@link android.app.Activity#onDestroy}. For example, if your -activity has a thread running in the background to download data from the network, it might create -that thread in {@link android.app.Activity#onCreate onCreate()} and then stop the thread in {@link -android.app.Activity#onDestroy}.</li> - -<li><p>The <b>visible lifetime</b> of an activity happens between the call to {@link -android.app.Activity#onStart onStart()} and the call to {@link -android.app.Activity#onStop onStop()}. During this time, the user can see the activity -on-screen and interact with it. For example, {@link android.app.Activity#onStop onStop()} is called -when a new activity starts and this one is no longer visible. Between these two methods, you can -maintain resources that are needed to show the activity to the user. For example, you can register a -{@link android.content.BroadcastReceiver} in {@link -android.app.Activity#onStart onStart()} to monitor changes that impact your UI, and unregister -it in {@link android.app.Activity#onStop onStop()} when the user can no longer see what you are -displaying. The system might call {@link android.app.Activity#onStart onStart()} and {@link -android.app.Activity#onStop onStop()} multiple times during the entire lifetime of the activity, as -the activity alternates between being visible and hidden to the user.</p></li> - -<li><p>The <b>foreground lifetime</b> of an activity happens between the call to {@link -android.app.Activity#onResume onResume()} and the call to {@link android.app.Activity#onPause -onPause()}. During this time, the activity is in front of all other activities on screen and has -user input focus. An activity can frequently transition in and out of the foreground—for -example, {@link android.app.Activity#onPause onPause()} is called when the device goes to sleep or -when a dialog appears. Because this state can transition often, the code in these two methods should -be fairly lightweight in order to avoid slow transitions that make the user wait.</p></li> -</ul> - -<p>Figure 1 illustrates these loops and the paths an activity might take between states. -The rectangles represent the callback methods you can implement to perform operations when -the activity transitions between states. <p> - -<img src="{@docRoot}images/activity_lifecycle.png" alt="" /> -<p class="img-caption"><strong>Figure 1.</strong> The activity lifecycle.</p> - -<p>The same lifecycle callback methods are listed in table 1, which describes each of the callback -methods in more detail and locates each one within the -activity's overall lifecycle, including whether the system can kill the activity after the -callback method completes.</p> - -<p class="table-caption"><strong>Table 1.</strong> A summary of the activity lifecycle's -callback methods.</p> - -<table border="2" width="85%" frame="hsides" rules="rows"> -<colgroup align="left" span="3"></colgroup> -<colgroup align="left"></colgroup> -<colgroup align="center"></colgroup> -<colgroup align="center"></colgroup> - -<thead> -<tr><th colspan="3">Method</th> <th>Description</th> <th>Killable after?</th> <th>Next</th></tr> -</thead> - -<tbody> -<tr> - <td colspan="3" align="left"><code>{@link android.app.Activity#onCreate onCreate()}</code></td> - <td>Called when the activity is first created. - This is where you should do all of your normal static set up — - create views, bind data to lists, and so on. This method is passed - a Bundle object containing the activity's previous state, if that - state was captured (see <a href="#actstate">Saving Activity State</a>, - later). - <p>Always followed by {@code onStart()}.</p></td> - <td align="center">No</td> - <td align="center">{@code onStart()}</td> -</tr> - -<tr> - <td rowspan="5" style="border-left: none; border-right: none;"> </td> - <td colspan="2" align="left"><code>{@link android.app.Activity#onRestart -onRestart()}</code></td> - <td>Called after the activity has been stopped, just prior to it being - started again. - <p>Always followed by {@code onStart()}</p></td> - <td align="center">No</td> - <td align="center">{@code onStart()}</td> -</tr> - -<tr> - <td colspan="2" align="left"><code>{@link android.app.Activity#onStart onStart()}</code></td> - <td>Called just before the activity becomes visible to the user. - <p>Followed by {@code onResume()} if the activity comes - to the foreground, or {@code onStop()} if it becomes hidden.</p></td> - <td align="center">No</td> - <td align="center">{@code onResume()} <br/>or<br/> {@code onStop()}</td> -</tr> - -<tr> - <td rowspan="2" style="border-left: none;"> </td> - <td align="left"><code>{@link android.app.Activity#onResume onResume()}</code></td> - <td>Called just before the activity starts - interacting with the user. At this point the activity is at - the top of the activity stack, with user input going to it. - <p>Always followed by {@code onPause()}.</p></td> - <td align="center">No</td> - <td align="center">{@code onPause()}</td> -</tr> - -<tr> - <td align="left"><code>{@link android.app.Activity#onPause onPause()}</code></td> - <td>Called when the system is about to start resuming another - activity. This method is typically used to commit unsaved changes to - persistent data, stop animations and other things that may be consuming - CPU, and so on. It should do whatever it does very quickly, because - the next activity will not be resumed until it returns. - <p>Followed either by {@code onResume()} if the activity - returns back to the front, or by {@code onStop()} if it becomes - invisible to the user.</td> - <td align="center"><strong style="color:#800000">Yes</strong></td> - <td align="center">{@code onResume()} <br/>or<br/> {@code onStop()}</td> -</tr> - -<tr> - <td colspan="2" align="left"><code>{@link android.app.Activity#onStop onStop()}</code></td> - <td>Called when the activity is no longer visible to the user. This - may happen because it is being destroyed, or because another activity - (either an existing one or a new one) has been resumed and is covering it. - <p>Followed either by {@code onRestart()} if - the activity is coming back to interact with the user, or by - {@code onDestroy()} if this activity is going away.</p></td> - <td align="center"><strong style="color:#800000">Yes</strong></td> - <td align="center">{@code onRestart()} <br/>or<br/> {@code onDestroy()}</td> -</tr> - -<tr> - <td colspan="3" align="left"><code>{@link android.app.Activity#onDestroy -onDestroy()}</code></td> - <td>Called before the activity is destroyed. This is the final call - that the activity will receive. It could be called either because the - activity is finishing (someone called <code>{@link android.app.Activity#finish - finish()}</code> on it), or because the system is temporarily destroying this - instance of the activity to save space. You can distinguish - between these two scenarios with the <code>{@link - android.app.Activity#isFinishing isFinishing()}</code> method.</td> - <td align="center"><strong style="color:#800000">Yes</strong></td> - <td align="center"><em>nothing</em></td> -</tr> -</tbody> -</table> - -<p>The column labeled "Killable after?" indicates whether or not the system can -kill the process hosting the activity at any time <em>after the method returns</em>, without -executing another line of the activity's code. Three methods are marked "yes": ({@link -android.app.Activity#onPause -onPause()}, {@link android.app.Activity#onStop onStop()}, and {@link android.app.Activity#onDestroy -onDestroy()}). Because {@link android.app.Activity#onPause onPause()} is the first -of the three, once the activity is created, {@link android.app.Activity#onPause onPause()} is the -last method that's guaranteed to be called before the process <em>can</em> be killed—if -the system must recover memory in an emergency, then {@link -android.app.Activity#onStop onStop()} and {@link android.app.Activity#onDestroy onDestroy()} might -not be called. Therefore, you should use {@link android.app.Activity#onPause onPause()} to write -crucial persistent data (such as user edits) to storage. However, you should be selective about -what information must be retained during {@link android.app.Activity#onPause onPause()}, because any -blocking procedures in this method block the transition to the next activity and slow the user -experience.</p> - -<p> Methods that are marked "No" in the <b>Killable</b> column protect the process hosting the -activity from being killed from the moment they are called. Thus, an activity is killable -from the time {@link android.app.Activity#onPause onPause()} returns to the time -{@link android.app.Activity#onResume onResume()} is called. It will not again be killable until -{@link android.app.Activity#onPause onPause()} is again called and returns. </p> - -<p class="note"><strong>Note:</strong> An activity that's not technically "killable" by this -definition in table 1 might still be killed by the system—but that would happen only in -extreme circumstances when there is no other recourse. When an activity might be killed is -discussed more in the <a -href="{@docRoot}guide/topics/fundamentals/processes-and-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/topics/fundamentals/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/topics/fundamentals/bound-services.jd b/docs/html/guide/topics/fundamentals/bound-services.jd deleted file mode 100644 index ec7d723..0000000 --- a/docs/html/guide/topics/fundamentals/bound-services.jd +++ /dev/null @@ -1,675 +0,0 @@ -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/topics/fundamentals/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/topics/fundamentals/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/topics/fundamentals/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}guide/developing/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}guide/developing/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/topics/fundamentals/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/topics/fundamentals/services.html#Lifecycle">Services</a> document.</p> - - - - diff --git a/docs/html/guide/topics/fundamentals/fragments.jd b/docs/html/guide/topics/fundamentals/fragments.jd deleted file mode 100644 index 2a22394..0000000 --- a/docs/html/guide/topics/fundamentals/fragments.jd +++ /dev/null @@ -1,836 +0,0 @@ -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/topics/fundamentals/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/topics/fundamentals/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/topics/fundamentals/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/topics/fundamentals/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/topics/fundamentals/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/topics/fundamentals/loaders.jd b/docs/html/guide/topics/fundamentals/loaders.jd deleted file mode 100644 index ddd513b..0000000 --- a/docs/html/guide/topics/fundamentals/loaders.jd +++ /dev/null @@ -1,500 +0,0 @@ -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/topics/fundamentals/processes-and-threads.jd b/docs/html/guide/topics/fundamentals/processes-and-threads.jd deleted file mode 100644 index 814d34e..0000000 --- a/docs/html/guide/topics/fundamentals/processes-and-threads.jd +++ /dev/null @@ -1,486 +0,0 @@ -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 process that should host that thread is not already -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 or Android has been -able to retain its previous process cached in the background), 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>The exact mapping of processes to importance and the management of these processes is -an implementation detail of the platform that changes over time. Broadly speaking, there -are five levels in the current implementation that are of most relevance to application -developers. The following list presents these 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 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> - - <li>Another foreground process has a dependency on this one: either bound - to a Service in this process, or using a Content Provider of the process.</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>Another visible process has a dependency on this one: either bound - to a Service in this process, or using a Content Provider of the process.</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>Perceptible process</b> - <p>A process that doesn't have any foreground or visible components, but is still - doing something that is directly perceptible by the user. A classic example of such - a process would be one doing background music playback. The main way applications - get into this state is through {@link android.app.Service#startForeground} or because - another perceptible process has a dependency on one of its services or content - providers. In addition, as of {@link android.os.Build.VERSION_CODES#HONEYCOMB}, - processes can go into this state when {@link android.app.Activity#onStop - Activity.onStop()} is executing, allowing the process to continue executing - critical code after no longer being visible to the user but before going - fully into the background.</p> - - <p>Like visible processes, a perceptible process is considered extremely important - and will not be killed unless doing so is required to keep all foreground and - visible 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 any of the -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 downloading a file the user has requested), -so the system keeps them running unless there's not enough memory to retain them along with all -foreground and visible processes. </p> - - <p>Even though Android tries to keep these processes running, it is considered normal - operation for them to temporarily be killed to support the needs of more important - processes. For example, if the user opens a very heavy-weight web page that needs - most of the device's RAM, background services may be temporarily killed to satisfy - those needs. Services in these processes thus must be prepared to deal gracefully - with being killed while doing their work and later restarted.</p> - - <p>In recent implementations of Android, there are actually a number of sub-divisions - in this area for processes that Android considers more important to the user and so - would like to try harder to keep around. For example, the process hosting the current - home app is generally kept in this area so that the user will not see long delays in - returning home because that process has been killed.</p> - </li> - - <li><b>Background (cached) process</b> - <p>The final importance level is for processes that are not of current significance. - This is basically any process that does not fall into one of the previous levels. - These processes have no direct impact on the user experience, and the system can kill - them at any time to reclaim memory for the other more important processes. - This includes everything from processes holding running activity objects that are not currently - visible to the user (the activity's {@link android.app.Activity#onStop onStop()} - method has been called) to processes that have no active code at all but may be - useful to keep around in case they are needed in the near future.</p> - - <p>Usually there are many background processes being maintained, so they are kept - in an LRU list to allow older processes to be killed before more recent ones. This - helps reduce the frequency that new processes need to be creating, facilitating things - like more rapid switching between the applications the user has recently visited. - However, processes in this state must deal correctly with being killed and later - restarted when needed. For example, 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/topics/fundamentals/activities.html#SavingActivityState">Activities</a> -document for information about saving and restoring state.</p> - - <p>Android may also employ other additional policies for killing background processes. For - example, there are typically restrictions on a maximum number of such processes to - keep around, and limits on the amount of time they can spend holding wake locks - or consuming CPU power until they will be removed.</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 not generally 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 has been bound to by a client 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 may sometimes start a <a -href="{@docRoot}guide/topics/fundamentals/services.html">service</a> for that operation, rather than -simply create a worker thread—but only when the operation is a specific task that needs -to be accomplished regardless of whether the user returns to the application. -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 not however an approach that should always -be used. It would not be appropriate when simply downloading the data for a web page, since -that can easily be restarted later if the user returns to the web browser. Allowing -such a process to be in the background (instead of running a service) gives Android better -information about how to manage that process in relation to others. - - <p>For a similar reason, broadcast receivers will often employ services rather than - simply put time-consuming operations in a thread.</p> - - <p>Some command line tools are available to help you understand how Android is managing - its processes. The most common command is <code>adb shell dumpsys activity</code> - which provides a summary of various key state, including at the end a list of the - process states, one per line (plus an optional second line for any key dependency - on that process), ordered from higher importance to lowest. The exact - contents of these lines has changed across different versions of Android, but the - typical state for one process in the list would be:</p> - <pre> -Proc # 2: adj=prcp /F trm= 0 848:com.google.android.inputmethod.latin/u0a32 (service) - com.google.android.inputmethod.latin/com.android.inputmethod.latin.LatinIME<=Proc{417:system/1000} -</pre> - - <p>This is a perceptible process (adj=prcp) that is running with the foreground - scheduling class (/F), and has not recently been told to trim any memory - (trm= 0). Its process id is 848; its name is com.google.android.inputmethod.latin; - its Linux uid is u0a32 (10032), and the key state contributing to its current - importance level is a service.</p> - - <p>The second line provides the name of the service that is important, because another - process has a dependency on it (here the system process).</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/design/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/topics/fundamentals/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/topics/fundamentals/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/topics/fundamentals/services.html">Services</a></b> document.</p> ---> diff --git a/docs/html/guide/topics/fundamentals/services.jd b/docs/html/guide/topics/fundamentals/services.jd deleted file mode 100644 index 9c38897..0000000 --- a/docs/html/guide/topics/fundamentals/services.jd +++ /dev/null @@ -1,874 +0,0 @@ -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/topics/fundamentals/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/topics/fundamentals/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/topics/fundamentals/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/topics/intents/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/topics/fundamentals/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/topics/fundamentals/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/topics/fundamentals/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/topics/fundamentals/tasks-and-back-stack.jd b/docs/html/guide/topics/fundamentals/tasks-and-back-stack.jd deleted file mode 100644 index 0880614..0000000 --- a/docs/html/guide/topics/fundamentals/tasks-and-back-stack.jd +++ /dev/null @@ -1,596 +0,0 @@ -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="{@docRoot}resources/articles/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}videos/index.html#v=fL6gSd4ugSI">Application Lifecycle video</a></li> - <li><a -href="{@docRoot}guide/topics/manifest/activity-element.html">{@code <activity>} manifest -element</a></li> -</ol> -</div> -</div> - - -<p>An application usually contains multiple <a -href="{@docRoot}guide/topics/fundamentals/activities.html">activities</a>. Each activity -should be designed around a specific kind of action the user can perform and can start other -activities. For example, an email application might have one activity to show a list of new email. -When the user selects an email, a new activity opens to view that email.</p> - -<p>An activity can even start activities that exist in other applications on the device. For -example, if your application wants to send an email, you can define an intent to perform a "send" -action and include some data, such as an email address and a message. An activity from another -application that declares itself to handle this kind of intent then opens. In this case, the intent -is to send an email, so an email application's "compose" activity starts (if multiple activities -support the same intent, then the system lets the user select which one to use). When the email is -sent, your activity resumes and it seems as if the email activity was part of your application. Even -though the activities may be from different applications, Android maintains this seamless user -experience by keeping both activities in the same <em>task</em>.</p> - -<p>A task is a collection of activities that users interact with -when performing a certain job. The activities are arranged in a stack (the "back stack"), in the -order in which each activity is opened.</p> - -<!-- SAVE FOR WHEN THE FRAGMENT DOC IS ADDED -<div class="sidebox-wrapper"> -<div class="sidebox"> -<h3>Adding fragments to a task's back stack</h3> - -<p>Your activity can also include {@link android.app.Fragment}s to the back stack. For example, -suppose you have a two-pane layout using fragments, one of which is a list view (fragment A) and the -other being a layout to display an item from the list (fragment B). When the user selects an item -from the list, fragment B is replaced by a new fragment (fragment C). In this case, it might be -desireable for the user to navigate back to reveal fragment B, using the <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/topics/fundamentals/activities.html#SavingActivityState">Activities</a> -document.</p> - - - -<h2 id="ManagingTasks">Managing Tasks</h2> - -<p>The way Android manages tasks and the back stack, as described above—by placing all -activities started in succession in the same task and in a "last in, first out" stack—works -great for most applications and you shouldn't have to worry about how your activities are associated -with tasks or how they exist in the back stack. However, you might decide that you want to interrupt -the normal behavior. Perhaps you want an activity in your application to begin a new task when it is -started (instead of being placed within the current task); or, when you start an activity, you want -to bring forward an existing instance of it (instead of creating a new -instance on top of the back stack); or, you want your back stack to be cleared of all -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/topics/intents/intents-filters.html">Intents and Intent -Filters</a></b> document.</p> ---> |