summaryrefslogtreecommitdiffstats
path: root/docs/html/guide
diff options
context:
space:
mode:
Diffstat (limited to 'docs/html/guide')
-rw-r--r--docs/html/guide/appendix/media-formats.jd31
-rw-r--r--docs/html/guide/faq/security.jd4
-rw-r--r--docs/html/guide/google/gcm/adv.jd8
-rw-r--r--docs/html/guide/google/gcm/gcm.jd39
-rw-r--r--docs/html/guide/google/gcm/gs.jd12
-rw-r--r--docs/html/guide/google/gcm/server-javadoc/allclasses-frame.html4
-rw-r--r--docs/html/guide/google/gcm/server-javadoc/allclasses-noframe.html4
-rw-r--r--docs/html/guide/google/gcm/server-javadoc/com/google/android/gcm/server/Constants.html4
-rw-r--r--docs/html/guide/google/gcm/server-javadoc/com/google/android/gcm/server/InvalidRequestException.html4
-rw-r--r--docs/html/guide/google/gcm/server-javadoc/com/google/android/gcm/server/Message.Builder.html4
-rw-r--r--docs/html/guide/google/gcm/server-javadoc/com/google/android/gcm/server/Message.html4
-rw-r--r--docs/html/guide/google/gcm/server-javadoc/com/google/android/gcm/server/MulticastResult.html4
-rw-r--r--docs/html/guide/google/gcm/server-javadoc/com/google/android/gcm/server/Result.html4
-rw-r--r--docs/html/guide/google/gcm/server-javadoc/com/google/android/gcm/server/Sender.html6
-rw-r--r--docs/html/guide/google/gcm/server-javadoc/com/google/android/gcm/server/package-frame.html4
-rw-r--r--docs/html/guide/google/gcm/server-javadoc/com/google/android/gcm/server/package-summary.html4
-rw-r--r--docs/html/guide/google/gcm/server-javadoc/com/google/android/gcm/server/package-tree.html4
-rw-r--r--docs/html/guide/google/gcm/server-javadoc/constant-values.html4
-rw-r--r--docs/html/guide/google/gcm/server-javadoc/default.css243
-rw-r--r--docs/html/guide/google/gcm/server-javadoc/deprecated-list.html4
-rw-r--r--docs/html/guide/google/gcm/server-javadoc/help-doc.html4
-rw-r--r--docs/html/guide/google/gcm/server-javadoc/index-all.html4
-rw-r--r--docs/html/guide/google/gcm/server-javadoc/index.html2
-rw-r--r--docs/html/guide/google/gcm/server-javadoc/overview-tree.html4
-rw-r--r--docs/html/guide/google/gcm/server-javadoc/serialized-form.html4
-rw-r--r--docs/html/guide/google/play/billing/billing_subscriptions.jd43
-rw-r--r--docs/html/guide/google/play/billing/index.jd6
-rw-r--r--docs/html/guide/google/play/expansion-files.jd6
-rw-r--r--docs/html/guide/google/play/publishing/multiple-apks.jd68
-rw-r--r--docs/html/guide/google/play/services.jd37
-rw-r--r--docs/html/guide/guide_toc.cs68
-rw-r--r--docs/html/guide/practices/security.jd4
-rw-r--r--docs/html/guide/topics/appwidgets/index.jd31
-rw-r--r--docs/html/guide/topics/connectivity/nfc/nfc.jd103
-rw-r--r--docs/html/guide/topics/data/data-storage.jd7
-rw-r--r--docs/html/guide/topics/manifest/activity-element.jd10
-rw-r--r--docs/html/guide/topics/manifest/application-element.jd18
-rw-r--r--docs/html/guide/topics/manifest/permission-element.jd2
-rw-r--r--docs/html/guide/topics/manifest/provider-element.jd161
-rw-r--r--docs/html/guide/topics/manifest/uses-feature-element.jd8
-rw-r--r--docs/html/guide/topics/providers/content-provider-basics.jd147
-rw-r--r--docs/html/guide/topics/resources/providing-resources.jd37
-rw-r--r--docs/html/guide/topics/resources/string-resource.jd24
-rw-r--r--docs/html/guide/topics/ui/accessibility/apps.jd420
-rw-r--r--docs/html/guide/topics/ui/accessibility/calendar.pngbin0 -> 17811 bytes
-rw-r--r--docs/html/guide/topics/ui/accessibility/checklist.jd173
-rw-r--r--docs/html/guide/topics/ui/accessibility/index.jd60
-rw-r--r--docs/html/guide/topics/ui/accessibility/services.jd263
-rw-r--r--docs/html/guide/topics/ui/controls.jd2
-rw-r--r--docs/html/guide/topics/ui/dialogs.jd1229
-rw-r--r--docs/html/guide/topics/ui/notifiers/notifications.jd1558
-rw-r--r--docs/html/guide/topics/ui/notifiers/toasts.jd52
-rw-r--r--docs/html/guide/topics/ui/themes.jd9
53 files changed, 3142 insertions, 1817 deletions
diff --git a/docs/html/guide/appendix/media-formats.jd b/docs/html/guide/appendix/media-formats.jd
index 93e8136..feacdc6 100644
--- a/docs/html/guide/appendix/media-formats.jd
+++ b/docs/html/guide/appendix/media-formats.jd
@@ -57,7 +57,7 @@ page.title=Android Supported Media Formats
<p class="table-caption" id="formats-table"><strong>Table 1.</strong> Core media format and codec support.</p>
-<table>
+<table style="font-size:12px">
<tbody>
<tr>
@@ -70,22 +70,22 @@ page.title=Android Supported Media Formats
</tr>
<tr>
-<td rowspan="10">Audio</td>
-<td>AAC LC/LTP</td>
+<td rowspan="11">Audio</td>
+<td>AAC LC</td>
<td style="text-align: center;"><big>&bull;</big></td>
<td style="text-align: center;"><big>&bull;</big></td>
-<td rowspan="3">Mono/Stereo content in any combination of standard bit
-rates up to 160 kbps and sampling rates from 8 to 48kHz</td>
-<td rowspan="3">
+<td rowspan="2">Support for mono/stereo/5.0/5.1
+content with standard sampling rates from 8 to 48 kHz.</td>
+<td rowspan="4">
&bull; 3GPP (.3gp)<br>
- &bull; MPEG-4 (.mp4, .m4a)<br>
+ <nobr>&bull; MPEG-4 (.mp4, .m4a)</nobr><br>
&bull; ADTS raw AAC (.aac, decode in Android 3.1+, encode in Android 4.0+, ADIF not supported)<br>
&bull; MPEG-TS (.ts, not seekable, Android 3.0+)</td>
</tr>
<tr>
<td>HE-AACv1 (AAC+)</td>
-<td>&nbsp;</td>
+<td style="text-align: center;"><big>&bull;</big><br><small>(Android 4.1+)</small></td>
<td style="text-align: center;"><big>&bull;</big></td>
</tr>
@@ -93,6 +93,16 @@ rates up to 160 kbps and sampling rates from 8 to 48kHz</td>
<td>HE-AACv2 (enhanced AAC+)</td>
<td>&nbsp;</td>
<td style="text-align: center;"><big>&bull;</big></td>
+<td>Support for stereo/5.0/5.1
+content with standard sampling rates from 8 to 48 kHz.</td>
+</tr>
+
+<tr>
+<td>AAC ELD (enhanced low delay AAC)</td>
+<td style="text-align: center;"><big>&bull;</big><br><small>(Android 4.1+)</small></td>
+<td style="text-align: center;"><big>&bull;</big><br><small>(Android 4.1+)</small></td>
+<td>Support for mono/stereo content
+with standard sampling rates from 16 to 48 kHz</td>
</tr>
<tr>
@@ -160,9 +170,10 @@ no dither applied for 24-bit.
<tr>
<td>PCM/WAVE</td>
-<td>&nbsp;</td>
+<td style="text-align: center;"><big>&bull;</big><br><small>(Android 4.1+)</small></td>
<td style="text-align: center;"><big>&bull;</big></td>
-<td>8- and 16-bit linear PCM (rates up to limit of hardware)</td>
+<td>8- and 16-bit linear PCM (rates up to limit of hardware). Sampling
+rates for raw PCM recordings at 8000, 16000 and 44100 Hz.</td>
<td>
WAVE (.wav)</td>
</tr>
diff --git a/docs/html/guide/faq/security.jd b/docs/html/guide/faq/security.jd
index 52ee0d9..a6e07c8 100644
--- a/docs/html/guide/faq/security.jd
+++ b/docs/html/guide/faq/security.jd
@@ -57,9 +57,7 @@ key</a>.</p>
<p>We appreciate researchers practicing responsible disclosure by emailing us
with a detailed summary of the issue and keeping the issue confidential while
users are at risk. In return, we will make sure to keep the researcher informed
-of our progress in issuing a fix and will properly credit the reporter(s) when
-we provide the patch. We will always move swiftly to mitigate or fix an
-externally-reported flaw and provide updates to users. </p>
+of our progress in issuing a fix. </p>
<a name="informed" id="informed"></a><h2>How can I stay informed about Android security?</h2>
diff --git a/docs/html/guide/google/gcm/adv.jd b/docs/html/guide/google/gcm/adv.jd
index 2174128..356ee1d 100644
--- a/docs/html/guide/google/gcm/adv.jd
+++ b/docs/html/guide/google/gcm/adv.jd
@@ -51,7 +51,6 @@ delivered right away unless the <code>delay_while_idle</code> flag is set to tru
<p>If the device is not connected to GCM, the message will be stored until a connection is established (again respecting the collapse key rules). When a connection is established, GCM will deliver all pending messages to the device, regardless of the <code>delay_while_idle</code> flag. If the device never gets connected again (for instance, if it was factory reset), the message will eventually time out and be discarded from GCM storage. The default timeout is 4 weeks, unless the <code>time_to_live</code> flag is set.</p>
-<p class="note"><strong>Note:</strong> When you set the <code>time_to_live</code> flag, you must also set <code>collapse_key</code>. Otherwise the message will be rejected as a bad request.</p>
<p>Finally, when GCM attempts to deliver a message to the device and the application was uninstalled, GCM will discard that message right away and invalidate the registration ID. Future attempts to send a message to that device will get a <code>NotRegistered</code> error. See <a href="#unreg">How Unregistration Works</a> for more information.</p>
<p>Although is not possible to track the status of each individual message, the Google APIs Console stats are broken down by messages sent to device, messages collapsed, and messages waiting for delivery.</p>
@@ -164,7 +163,7 @@ registerReceiver(mRetryReceiver, filter);
<p>There are two ways to unregister a device from GCM: manually and automatically.</p>
<p>An Android application can manually unregister itself by issuing a <code>com.google.android.c2dm.intent.UNREGISTER</code> intent, which is useful when the application offers a logoff feature (so it can unregister on logoff and register again on logon). See the <a href="gcm.html#unregistering">Architectural Overview</a> for more discussion of this topic. This is the sequence of events when an application unregisters itself:</p>
<ol>
- <li> The application issues a <code>com.google.android.c2dm.intent.UNREGISTER</code> intent, passing the registration ID (the application should have saved its registration ID when it received the proper <code>com.google.android.c2dm.intent.REGISTRATION</code> intent).</li>
+ <li> The application issues a <code>com.google.android.c2dm.intent.UNREGISTER</code> intent, passing the package name as an extra.</li>
<li>When the GCM server is done with the unregistration, it sends a <code>com.google.android.c2dm.intent.REGISTRATION</code> intent with the <code>unregistered</code> extra set.</li>
<li>The application then must contact the 3rd-party server so it can remove the registration ID.</li>
<li>The application should also clear its registration ID.
@@ -175,7 +174,7 @@ registerReceiver(mRetryReceiver, filter);
<li>The end user uninstalls the application.</li>
<li>The 3rd-party server sends a message to GCM server.</li>
<li>The GCM server sends the message to the device.</li>
- <li>The GCM client receives the message and queries Package Manager about whether there are broadcast receivers configured to receive it, which returns <code>false</code>.
+ <li>The GCM client receives the message and queries Package Manager about whether there are broadcast receivers configured to receive it, which returns <code>false</code>.
</li>
<li>The GCM client informs the GCM server that the application was uninstalled.</li>
<li>The GCM server marks the registration ID for deletion.</li>
@@ -184,6 +183,9 @@ registerReceiver(mRetryReceiver, filter);
<li>The 3rd-party deletes the registration ID.
</li>
</ol>
+
+<p class ="note"><strong>Note:</strong> The GCM client is the Google Cloud Messaging framework present on the device.</p>
+
<p>Note that it might take a while for the registration ID be completely removed from GCM. Thus it is possible that messages sent during step 7 above gets a valid message ID as response, even though the message will not be delivered to the device. Eventually, the registration ID will be removed and the server will get a <code>NotRegistered</code> error, without any further action being required from the 3rd-party server (this scenario happens frequently while an application is being developed and tested).</p>
<h2 id="collapsible">Send-to-Sync vs. Messages with Payload</h2>
diff --git a/docs/html/guide/google/gcm/gcm.jd b/docs/html/guide/google/gcm/gcm.jd
index 5515f31..a47ceb9 100644
--- a/docs/html/guide/google/gcm/gcm.jd
+++ b/docs/html/guide/google/gcm/gcm.jd
@@ -57,9 +57,15 @@ page.title=GCM Architectural Overview
</div>
<p>Google Cloud Messaging for Android (GCM) is a free service that helps
-developers send data from servers to their Android applications on Android devices. This could be a lightweight message telling the Android application that there is new data to be fetched from the server (for instance, a movie uploaded by a friend), or it could be a message containing up to 4kb of payload data (so apps like instant messaging can consume the message directly). The GCM service handles all aspects of queueing of
- messages and delivery to the target Android application running on the target
- device.</p>
+developers send data from servers to their Android applications on Android
+devices. This could be a lightweight message telling the Android application
+that there is new data to be fetched from the server (for instance, a movie
+uploaded by a friend), or it could be a message containing up to 4kb of payload
+data (so apps like instant messaging can consume the message directly). The GCM
+service handles all aspects of queueing of messages and delivery to the target
+Android application running on the target device.</p>
+
+
<p class="note"> To jump right into using GCM with your Android
applications, see the instructions in <a href="gs.html">Getting Started</a>.</p>
@@ -647,14 +653,16 @@ when the device is offline, so that only the last message gets sent to the
client. This is intended to avoid sending too many messages to the phone when it
comes back online. Note that since there is no guarantee of the order in which
messages get sent, the &quot;last&quot; message may not actually be the last
-message sent by the application server. See <a href="adv.html#collapsible">Advanced Topics</a> for more discussion of this topic. Optional, unless you are using the <code>time_to_live</code> parameter&mdash;in that case, you must also specify a <code>collapse_key</code>.</td>
+message sent by the application server. See <a href="adv.html#collapsible">Advanced Topics</a> for more discussion of this topic. Optional.</td>
</tr>
<tr>
<td><code>data</code></td>
<td>A JSON object whose fields represents the key-value pairs of the message's payload data. If present, the payload data it will be
included in the Intent as application data, with the key being the extra's name. For instance, <code>"data":{"score":"3x1"}</code> would result in an intent extra named <code>score</code> whose value is the string <code>3x1</code>.
+
There is no limit on the number of key/value pairs, though there is a limit on the total size of the message (4kb). The values could be any JSON object, but we recommend using strings, since the values will be converted to strings in the GCM server anyway. If you want to include objects or other non-string data types (such as integers or booleans), you have to do the conversion to string yourself. Also note that the key cannot be a reserved word (<code>from</code> or any word starting with <code>google.</code>). To complicate things slightly, there are some reserved words (such as <code>collapse_key</code>) that are technically allowed in payload data. However, if the request also contains the word, the value in the request will overwrite the value in the payload data. Hence using words that are defined as field names in this table is not recommended, even in cases where they are technically allowed. Optional.</td>
+
</tr>
<tr>
<td><code>delay_while_idle</code></td>
@@ -665,7 +673,7 @@ sent. Optional. The default value is <code>false</code>, and must be a JSON bool
</tr>
<tr>
<td><code>time_to_live</code></td>
- <td>How long (in seconds) the message should be kept on GCM storage if the device is offline. Optional (default time-to-live is 4 weeks, and must be set as a JSON number). If you use this parameter, you must also specify a <code>collapse_key</code>.</td>
+ <td>How long (in seconds) the message should be kept on GCM storage if the device is offline. Optional (default time-to-live is 4 weeks, and must be set as a JSON number).</td>
</tr>
</table>
@@ -685,8 +693,10 @@ sent. Optional. The default value is <code>false</code>, and must be a JSON bool
</tr>
<tr>
<td><code>data.&lt;key&gt;</code></td>
+
<td>Payload data, expressed as parameters prefixed with <code>data.</code> and suffixed as the key. For instance, a parameter of <code>data.score=3x1</code> would result in an intent extra named <code>score</code> whose value is the string <code>3x1</code>. There is no limit on the number of key/value parameters, though there is a limit on the total size of the message. Also note that the key cannot be a reserved word (<code>from</code> or any word starting with
<code>google.</code>). To complicate things slightly, there are some reserved words (such as <code>collapse_key</code>) that are technically allowed in payload data. However, if the request also contains the word, the value in the request will overwrite the value in the payload data. Hence using words that are defined as field names in this table is not recommended, even in cases where they are technically allowed. Optional.</td>
+
</tr>
<tr>
<td><code>delay_while_idle</code></td>
@@ -698,7 +708,7 @@ sent. Optional. The default value is <code>false</code>, and must be a JSON bool
</tr>
</table>
-<p>If you want to test your request (either JSON or plain text) without delivering the message to the devices, you can set an optional HTTP parameter called <code>dry_run</code> with the value <code>true</code>. The result will be almost identical to running the request without this parameter, except that the message will not be delivered to the devices. Consequently, the response will contain fake IDs for the message and multicast fields (see <a href="#response">Response format</a>).</p>
+
<h4 id="example-requests">Example requests</h4>
<p>Here is the smallest possible request (a message without any parameters and just one recipient) using JSON:</p>
@@ -763,13 +773,8 @@ the HTTP response contains a non-200 status code (such as 400, 401, or 503).</p>
<td>There was an error authenticating the sender account. <a href="#auth_error">Troubleshoot</a></td>
</tr>
<tr>
- <td>500</td>
- <td>There was an internal error in the GCM server while trying to process the request. <a href="#internal_error">Troubleshoot</a></td>
- </tr>
- <tr>
- <td>503</td>
- <td>Indicates that the server is temporarily unavailable (i.e., because of timeouts, etc ). Sender must retry later, honoring any <code>Retry-After</code> header
- included in the response. Application servers must implement exponential back-off. The GCM server took too long to process the request. <a href="#internal_error">Troubleshoot</a></td>
+ <td>5xx</td>
+ <td>Errors in the 500-599 range (such as 500 or 503) indicate that there was an internal error in the GCM server while trying to process the request, or that the server is temporarily unavailable (for example, because of timeouts). Sender must retry later, honoring any <code>Retry-After</code> header included in the response. Application servers must implement exponential back-off. <a href="#internal_error">Troubleshoot</a></td>
</tr>
</table>
@@ -891,13 +896,11 @@ Happens when the error code is <code>InvalidDataKey</code>.</dd>
</ul>
Check that the token you're sending inside the <code>Authorization</code> header is the correct API key associated with your project. You can check the validity of your API key by running the following command:<br/>
-
<pre># api_key=YOUR_API_KEY
# curl --header "Authorization: key=$api_key" --header Content-Type:"application/json" https://android.googleapis.com/gcm/send -d "{\"registration_ids\":[\"ABC\"]}"</pre>
-
If you receive a 401 HTTP status code, your API key is not valid. Otherwise you should see something like this:<br/>
<pre>
@@ -927,17 +930,15 @@ all messages at the same time.</li>
Senders that cause problems risk being blacklisted.
<br />
-Happens when the HTTP status code is 503, or when the <code>error</code> field of a JSON object in the results array is <code>Unavailable</code>.
+Happens when the HTTP status code is between 501 and 599, or when the <code>error</code> field of a JSON object in the results array is <code>Unavailable</code>.
</dd>
<dt id="internal_error"><strong>Internal Server Error</strong></dt>
<dd>
The server encountered an error while trying to process the request. You
-could retry the same request (obeying the requirements listed in the <strong>Timeout</strong>
+could retry the same request (obeying the requirements listed in the <a href="#timeout">Timeout</a>
section), but if the error persists, please report the problem in the <a href="https://groups.google.com/forum/?fromgroups#!forum/android-gcm">android-gcm group</a>.
-<br />
-Senders that cause problems risk being blacklisted.
<br />
Happens when the HTTP status code is 500, or when the <code>error</code> field of a JSON
object in the results array is <code>InternalServerError</code>.
diff --git a/docs/html/guide/google/gcm/gs.jd b/docs/html/guide/google/gcm/gs.jd
index 6f8598f..8d132d8 100644
--- a/docs/html/guide/google/gcm/gs.jd
+++ b/docs/html/guide/google/gcm/gs.jd
@@ -138,8 +138,16 @@ page.title=GCM: Getting Started
</ol>
<p>This intent service will be called by the <code>GCMBroadcastReceiver</code> (which is is provided by GCM library), as shown in the next step. It must be a subclass of <code>com.google.android.gcm.GCMBaseIntentService</code>, must contain a public constructor, and should be named <code>my_app_package.GCMIntentService</code> (unless you use a subclass of <code>GCMBroadcastReceiver</code> that overrides the method used to name the service).</p>
-<h4><br>
- Step 3: Write the my_app_package.GCMIntentService class</h4>
+
+<p>The intent service must also define its sender ID(s). It does this as follows:</p>
+<ul>
+ <li>If the value is static, the service's default constructor should call <code>super(senderIds)</code>.</li>
+ <li>If the value is dynamic, the service should override the <code>getSenderIds()</code> method.</li>
+</ul>
+
+
+<h4>Step 3: Write the my_app_package.GCMIntentService class</h4>
+
<p>Next write the <code>my_app_package.GCMIntentService</code> class, overriding the following callback methods (which are called by <code>GCMBroadcastReceiver</code>):<br>
</p>
<ul>
diff --git a/docs/html/guide/google/gcm/server-javadoc/allclasses-frame.html b/docs/html/guide/google/gcm/server-javadoc/allclasses-frame.html
index cf7dc28..80ee784 100644
--- a/docs/html/guide/google/gcm/server-javadoc/allclasses-frame.html
+++ b/docs/html/guide/google/gcm/server-javadoc/allclasses-frame.html
@@ -2,12 +2,12 @@
<!--NewPage-->
<HTML>
<HEAD>
-<!-- Generated by javadoc (build 1.6.0_26) on Mon Jul 16 14:12:10 PDT 2012 -->
+<!-- Generated by javadoc (build 1.6.0_26) on Wed Aug 29 14:55:34 PDT 2012 -->
<TITLE>
All Classes
</TITLE>
-<META NAME="date" CONTENT="2012-07-16">
+<META NAME="date" CONTENT="2012-08-29">
<LINK REL ="stylesheet" TYPE="text/css" HREF="default.css" TITLE="Style">
diff --git a/docs/html/guide/google/gcm/server-javadoc/allclasses-noframe.html b/docs/html/guide/google/gcm/server-javadoc/allclasses-noframe.html
index 299085c..966598d 100644
--- a/docs/html/guide/google/gcm/server-javadoc/allclasses-noframe.html
+++ b/docs/html/guide/google/gcm/server-javadoc/allclasses-noframe.html
@@ -2,12 +2,12 @@
<!--NewPage-->
<HTML>
<HEAD>
-<!-- Generated by javadoc (build 1.6.0_26) on Mon Jul 16 14:12:10 PDT 2012 -->
+<!-- Generated by javadoc (build 1.6.0_26) on Wed Aug 29 14:55:34 PDT 2012 -->
<TITLE>
All Classes
</TITLE>
-<META NAME="date" CONTENT="2012-07-16">
+<META NAME="date" CONTENT="2012-08-29">
<LINK REL ="stylesheet" TYPE="text/css" HREF="default.css" TITLE="Style">
diff --git a/docs/html/guide/google/gcm/server-javadoc/com/google/android/gcm/server/Constants.html b/docs/html/guide/google/gcm/server-javadoc/com/google/android/gcm/server/Constants.html
index 7384dfd..515bba4 100644
--- a/docs/html/guide/google/gcm/server-javadoc/com/google/android/gcm/server/Constants.html
+++ b/docs/html/guide/google/gcm/server-javadoc/com/google/android/gcm/server/Constants.html
@@ -2,12 +2,12 @@
<!--NewPage-->
<HTML>
<HEAD>
-<!-- Generated by javadoc (build 1.6.0_26) on Mon Jul 16 14:12:09 PDT 2012 -->
+<!-- Generated by javadoc (build 1.6.0_26) on Wed Aug 29 14:55:34 PDT 2012 -->
<TITLE>
Constants
</TITLE>
-<META NAME="date" CONTENT="2012-07-16">
+<META NAME="date" CONTENT="2012-08-29">
<LINK REL ="stylesheet" TYPE="text/css" HREF="../../../../../default.css" TITLE="Style">
diff --git a/docs/html/guide/google/gcm/server-javadoc/com/google/android/gcm/server/InvalidRequestException.html b/docs/html/guide/google/gcm/server-javadoc/com/google/android/gcm/server/InvalidRequestException.html
index 56de783..bb0974c 100644
--- a/docs/html/guide/google/gcm/server-javadoc/com/google/android/gcm/server/InvalidRequestException.html
+++ b/docs/html/guide/google/gcm/server-javadoc/com/google/android/gcm/server/InvalidRequestException.html
@@ -2,12 +2,12 @@
<!--NewPage-->
<HTML>
<HEAD>
-<!-- Generated by javadoc (build 1.6.0_26) on Mon Jul 16 14:12:10 PDT 2012 -->
+<!-- Generated by javadoc (build 1.6.0_26) on Wed Aug 29 14:55:34 PDT 2012 -->
<TITLE>
InvalidRequestException
</TITLE>
-<META NAME="date" CONTENT="2012-07-16">
+<META NAME="date" CONTENT="2012-08-29">
<LINK REL ="stylesheet" TYPE="text/css" HREF="../../../../../default.css" TITLE="Style">
diff --git a/docs/html/guide/google/gcm/server-javadoc/com/google/android/gcm/server/Message.Builder.html b/docs/html/guide/google/gcm/server-javadoc/com/google/android/gcm/server/Message.Builder.html
index 7d5110c..c2ee648 100644
--- a/docs/html/guide/google/gcm/server-javadoc/com/google/android/gcm/server/Message.Builder.html
+++ b/docs/html/guide/google/gcm/server-javadoc/com/google/android/gcm/server/Message.Builder.html
@@ -2,12 +2,12 @@
<!--NewPage-->
<HTML>
<HEAD>
-<!-- Generated by javadoc (build 1.6.0_26) on Mon Jul 16 14:12:10 PDT 2012 -->
+<!-- Generated by javadoc (build 1.6.0_26) on Wed Aug 29 14:55:34 PDT 2012 -->
<TITLE>
Message.Builder
</TITLE>
-<META NAME="date" CONTENT="2012-07-16">
+<META NAME="date" CONTENT="2012-08-29">
<LINK REL ="stylesheet" TYPE="text/css" HREF="../../../../../default.css" TITLE="Style">
diff --git a/docs/html/guide/google/gcm/server-javadoc/com/google/android/gcm/server/Message.html b/docs/html/guide/google/gcm/server-javadoc/com/google/android/gcm/server/Message.html
index 37a8a74..5dbd262 100644
--- a/docs/html/guide/google/gcm/server-javadoc/com/google/android/gcm/server/Message.html
+++ b/docs/html/guide/google/gcm/server-javadoc/com/google/android/gcm/server/Message.html
@@ -2,12 +2,12 @@
<!--NewPage-->
<HTML>
<HEAD>
-<!-- Generated by javadoc (build 1.6.0_26) on Mon Jul 16 14:12:10 PDT 2012 -->
+<!-- Generated by javadoc (build 1.6.0_26) on Wed Aug 29 14:55:34 PDT 2012 -->
<TITLE>
Message
</TITLE>
-<META NAME="date" CONTENT="2012-07-16">
+<META NAME="date" CONTENT="2012-08-29">
<LINK REL ="stylesheet" TYPE="text/css" HREF="../../../../../default.css" TITLE="Style">
diff --git a/docs/html/guide/google/gcm/server-javadoc/com/google/android/gcm/server/MulticastResult.html b/docs/html/guide/google/gcm/server-javadoc/com/google/android/gcm/server/MulticastResult.html
index 21752ca..0721488 100644
--- a/docs/html/guide/google/gcm/server-javadoc/com/google/android/gcm/server/MulticastResult.html
+++ b/docs/html/guide/google/gcm/server-javadoc/com/google/android/gcm/server/MulticastResult.html
@@ -2,12 +2,12 @@
<!--NewPage-->
<HTML>
<HEAD>
-<!-- Generated by javadoc (build 1.6.0_26) on Mon Jul 16 14:12:10 PDT 2012 -->
+<!-- Generated by javadoc (build 1.6.0_26) on Wed Aug 29 14:55:34 PDT 2012 -->
<TITLE>
MulticastResult
</TITLE>
-<META NAME="date" CONTENT="2012-07-16">
+<META NAME="date" CONTENT="2012-08-29">
<LINK REL ="stylesheet" TYPE="text/css" HREF="../../../../../default.css" TITLE="Style">
diff --git a/docs/html/guide/google/gcm/server-javadoc/com/google/android/gcm/server/Result.html b/docs/html/guide/google/gcm/server-javadoc/com/google/android/gcm/server/Result.html
index 512b8f5..a4aad29 100644
--- a/docs/html/guide/google/gcm/server-javadoc/com/google/android/gcm/server/Result.html
+++ b/docs/html/guide/google/gcm/server-javadoc/com/google/android/gcm/server/Result.html
@@ -2,12 +2,12 @@
<!--NewPage-->
<HTML>
<HEAD>
-<!-- Generated by javadoc (build 1.6.0_26) on Mon Jul 16 14:12:10 PDT 2012 -->
+<!-- Generated by javadoc (build 1.6.0_26) on Wed Aug 29 14:55:34 PDT 2012 -->
<TITLE>
Result
</TITLE>
-<META NAME="date" CONTENT="2012-07-16">
+<META NAME="date" CONTENT="2012-08-29">
<LINK REL ="stylesheet" TYPE="text/css" HREF="../../../../../default.css" TITLE="Style">
diff --git a/docs/html/guide/google/gcm/server-javadoc/com/google/android/gcm/server/Sender.html b/docs/html/guide/google/gcm/server-javadoc/com/google/android/gcm/server/Sender.html
index 5224e15..fabda98 100644
--- a/docs/html/guide/google/gcm/server-javadoc/com/google/android/gcm/server/Sender.html
+++ b/docs/html/guide/google/gcm/server-javadoc/com/google/android/gcm/server/Sender.html
@@ -2,12 +2,12 @@
<!--NewPage-->
<HTML>
<HEAD>
-<!-- Generated by javadoc (build 1.6.0_26) on Mon Jul 16 14:12:10 PDT 2012 -->
+<!-- Generated by javadoc (build 1.6.0_26) on Wed Aug 29 14:55:34 PDT 2012 -->
<TITLE>
Sender
</TITLE>
-<META NAME="date" CONTENT="2012-07-16">
+<META NAME="date" CONTENT="2012-08-29">
<LINK REL ="stylesheet" TYPE="text/css" HREF="../../../../../default.css" TITLE="Style">
@@ -591,6 +591,8 @@ protected static java.lang.String <B>getString</B>(java.io.InputStream&nbsp;stre
<p>
If the stream ends in a newline character, it will be stripped.
+ <p>
+ If the stream is null, returns an empty string.
<P>
<DD><DL>
diff --git a/docs/html/guide/google/gcm/server-javadoc/com/google/android/gcm/server/package-frame.html b/docs/html/guide/google/gcm/server-javadoc/com/google/android/gcm/server/package-frame.html
index 9f099b3..1bc4fd9 100644
--- a/docs/html/guide/google/gcm/server-javadoc/com/google/android/gcm/server/package-frame.html
+++ b/docs/html/guide/google/gcm/server-javadoc/com/google/android/gcm/server/package-frame.html
@@ -2,12 +2,12 @@
<!--NewPage-->
<HTML>
<HEAD>
-<!-- Generated by javadoc (build 1.6.0_26) on Mon Jul 16 14:12:10 PDT 2012 -->
+<!-- Generated by javadoc (build 1.6.0_26) on Wed Aug 29 14:55:34 PDT 2012 -->
<TITLE>
com.google.android.gcm.server
</TITLE>
-<META NAME="date" CONTENT="2012-07-16">
+<META NAME="date" CONTENT="2012-08-29">
<LINK REL ="stylesheet" TYPE="text/css" HREF="../../../../../default.css" TITLE="Style">
diff --git a/docs/html/guide/google/gcm/server-javadoc/com/google/android/gcm/server/package-summary.html b/docs/html/guide/google/gcm/server-javadoc/com/google/android/gcm/server/package-summary.html
index eddcca1..de791c7 100644
--- a/docs/html/guide/google/gcm/server-javadoc/com/google/android/gcm/server/package-summary.html
+++ b/docs/html/guide/google/gcm/server-javadoc/com/google/android/gcm/server/package-summary.html
@@ -2,12 +2,12 @@
<!--NewPage-->
<HTML>
<HEAD>
-<!-- Generated by javadoc (build 1.6.0_26) on Mon Jul 16 14:12:10 PDT 2012 -->
+<!-- Generated by javadoc (build 1.6.0_26) on Wed Aug 29 14:55:34 PDT 2012 -->
<TITLE>
com.google.android.gcm.server
</TITLE>
-<META NAME="date" CONTENT="2012-07-16">
+<META NAME="date" CONTENT="2012-08-29">
<LINK REL ="stylesheet" TYPE="text/css" HREF="../../../../../default.css" TITLE="Style">
diff --git a/docs/html/guide/google/gcm/server-javadoc/com/google/android/gcm/server/package-tree.html b/docs/html/guide/google/gcm/server-javadoc/com/google/android/gcm/server/package-tree.html
index d3d1c43..d509312 100644
--- a/docs/html/guide/google/gcm/server-javadoc/com/google/android/gcm/server/package-tree.html
+++ b/docs/html/guide/google/gcm/server-javadoc/com/google/android/gcm/server/package-tree.html
@@ -2,12 +2,12 @@
<!--NewPage-->
<HTML>
<HEAD>
-<!-- Generated by javadoc (build 1.6.0_26) on Mon Jul 16 14:12:10 PDT 2012 -->
+<!-- Generated by javadoc (build 1.6.0_26) on Wed Aug 29 14:55:34 PDT 2012 -->
<TITLE>
com.google.android.gcm.server Class Hierarchy
</TITLE>
-<META NAME="date" CONTENT="2012-07-16">
+<META NAME="date" CONTENT="2012-08-29">
<LINK REL ="stylesheet" TYPE="text/css" HREF="../../../../../default.css" TITLE="Style">
diff --git a/docs/html/guide/google/gcm/server-javadoc/constant-values.html b/docs/html/guide/google/gcm/server-javadoc/constant-values.html
index 66df664..68db1cb 100644
--- a/docs/html/guide/google/gcm/server-javadoc/constant-values.html
+++ b/docs/html/guide/google/gcm/server-javadoc/constant-values.html
@@ -2,12 +2,12 @@
<!--NewPage-->
<HTML>
<HEAD>
-<!-- Generated by javadoc (build 1.6.0_26) on Mon Jul 16 14:12:10 PDT 2012 -->
+<!-- Generated by javadoc (build 1.6.0_26) on Wed Aug 29 14:55:34 PDT 2012 -->
<TITLE>
Constant Field Values
</TITLE>
-<META NAME="date" CONTENT="2012-07-16">
+<META NAME="date" CONTENT="2012-08-29">
<LINK REL ="stylesheet" TYPE="text/css" HREF="default.css" TITLE="Style">
diff --git a/docs/html/guide/google/gcm/server-javadoc/default.css b/docs/html/guide/google/gcm/server-javadoc/default.css
index 2513e69..7c395c7 100644
--- a/docs/html/guide/google/gcm/server-javadoc/default.css
+++ b/docs/html/guide/google/gcm/server-javadoc/default.css
@@ -530,12 +530,12 @@ h3:target {
}
.design ol {
counter-reset: item; }
- .design ol li {
+ .design ol>li {
font-size: 14px;
line-height: 20px;
list-style-type: none;
position: relative; }
- .design ol li:before {
+ .design ol>li:before {
content: counter(item) ". ";
counter-increment: item;
position: absolute;
@@ -561,16 +561,18 @@ h3:target {
content: "9. "; }
.design ol li.value-10:before {
content: "10. "; }
-.design .with-callouts ol li {
+.design .with-callouts ol>li {
list-style-position: inside;
margin-left: 0; }
- .design .with-callouts ol li:before {
+ .design .with-callouts ol>li:before {
display: inline;
left: -20px;
float: left;
width: 17px;
color: #33b5e5;
font-weight: 500; }
+.design .with-callouts ul>li {
+ list-style-position: outside; }
/* special list items */
li.no-bullet {
@@ -1079,22 +1081,71 @@ color-stop(50%, #acbc00), color-stop(50%, #bdde00), color-stop(100%, #bdde00));
Print Only
========================================================================== */
@media print {
-a {
- color: inherit;
-}
-.nav-x, .nav-y {
- display: none;
-}
-.str { color: #060; }
-.kwd { color: #006; font-weight: bold; }
-.com { color: #600; font-style: italic; }
-.typ { color: #404; font-weight: bold; }
-.lit { color: #044; }
-.pun { color: #440; }
-.pln { color: #000; }
-.tag { color: #006; font-weight: bold; }
-.atn { color: #404; }
-.atv { color: #060; }
+ /* configure printed page */
+ @page {
+ margin: 0.75in 1in;
+ widows: 4;
+ orphans: 4;
+ }
+
+ /* reset spacing metrics */
+ html, body, .wrap {
+ margin: 0 !important;
+ padding: 0 !important;
+ width: auto !important;
+ }
+
+ /* leave enough space on the left for bullets */
+ body {
+ padding-left: 20px !important;
+ }
+ #doc-col {
+ margin-left: 0;
+ }
+
+ /* hide a bunch of non-content elements */
+ #header, #footer, #nav-x, #side-nav,
+ .training-nav-top, .training-nav-bottom,
+ #doc-col .content-footer,
+ .nav-x, .nav-y,
+ .paging-links,
+ a.totop {
+ display: none !important;
+ }
+
+ /* remove extra space above page titles */
+ #doc-col .content-header {
+ margin-top: 0;
+ }
+
+ /* bump up spacing above subheadings */
+ h2 {
+ margin-top: 40px !important;
+ }
+
+ /* print link URLs where possible and give links default text color */
+ p a:after {
+ content: " (" attr(href) ")";
+ font-size: 80%;
+ }
+ p a {
+ word-wrap: break-word;
+ }
+ a {
+ color: inherit;
+ }
+
+ /* syntax highlighting rules */
+ .str { color: #060; }
+ .kwd { color: #006; font-weight: bold; }
+ .com { color: #600; font-style: italic; }
+ .typ { color: #404; font-weight: bold; }
+ .lit { color: #044; }
+ .pun { color: #440; }
+ .pln { color: #000; }
+ .tag { color: #006; font-weight: bold; }
+ .atn { color: #404; }
+ .atv { color: #060; }
}
/* =============================================================================
@@ -2033,8 +2084,11 @@ div.toggle-content.closed .toggle-content-toggleme {
#jd-content img.toggle-content-img {
margin:0 5px 5px 0;
}
-div.toggle-content > p {
- padding:0 0 5px;
+div.toggle-content p {
+ margin:10px 0 0;
+}
+div.toggle-content-toggleme {
+ padding:0 0 0 15px;
}
@@ -2145,14 +2199,9 @@ table.blank th, table.blank td {
.nolist {
list-style:none;
- padding:0;
- margin:0 0 1em 1em;
+ margin-left:0;
}
-.nolist li {
- padding:0 0 2px;
- margin:0;
-}
pre.classic {
background-color:transparent;
@@ -2180,6 +2229,12 @@ p.table-caption {
color:#666;
}
+div.note,
+div.caution,
+div.warning {
+ margin: 0 0 15px;
+}
+
p.note, div.note,
p.caution, div.caution,
p.warning, div.warning {
@@ -2898,10 +2953,6 @@ ul#search_filtered {
/* SEARCH RESULTS */
-/* disable twiddle and size selectors for left column */
-#leftSearchControl div {
- padding:0;
-}
#leftSearchControl .gsc-twiddle {
background-image : none;
@@ -3475,7 +3526,7 @@ EndColorStr='#ececec');
.morehover:hover {
opacity:1;
- height:345px;
+ height:385px;
width:268px;
-webkit-transition-property:height, -webkit-opacity;
}
@@ -3489,7 +3540,7 @@ EndColorStr='#ececec');
.morehover .mid {
width:228px;
background:url(../images/more_mid.png) repeat-y;
- padding:10px 20px 10px 20px;
+ padding:10px 20px 0 20px;
}
.morehover .mid .header {
@@ -3598,15 +3649,19 @@ a.download-sdk {
padding-top: 14px;
}
+#nav-x .wrap {
+ min-height:34px;
+}
+
#nav-x .wrap,
#searchResults.wrap {
max-width:940px;
border-bottom:1px solid #CCC;
- min-height:34px;
-
}
-
+#searchResults.wrap #leftSearchControl {
+ min-height:700px
+}
.nav-x {
margin-left:0;
margin-bottom:0;
@@ -3762,7 +3817,8 @@ a.download-sdk {
height: 300px;
}
.slideshow-develop img.play {
- width:350px;
+ max-width:350px;
+ max-height:240px;
margin:20px 0 0 90px;
-webkit-transform: perspective(800px ) rotateY( 35deg );
box-shadow: -16px 20px 40px rgba(0, 0, 0, 0.3);
@@ -3817,6 +3873,7 @@ a.download-sdk {
.feed .feed-nav li {
list-style: none;
float: left;
+ height: 21px; /* +4px bottom border = 25px; same as .feed-nav */
margin-right: 25px;
cursor: pointer;
}
@@ -3969,21 +4026,24 @@ a.download-sdk {
.landing-docs {
margin:20px 0 0;
}
-.landing-banner {
- height:280px;
-}
.landing-banner .col-6:first-child,
-.landing-docs .col-6:first-child {
+.landing-docs .col-6:first-child,
+.landing-docs .col-12 {
margin-left:0;
+ min-height:280px;
}
.landing-banner .col-6:last-child,
-.landing-docs .col-6:last-child {
+.landing-docs .col-6:last-child,
+.landing-docs .col-12 {
margin-right:0;
}
.landing-banner h1 {
margin-top:0;
}
+.landing-docs {
+ clear:left;
+}
.landing-docs h3 {
font-size:14px;
line-height:21px;
@@ -4002,4 +4062,99 @@ a.download-sdk {
.plusone {
float:right;
-} \ No newline at end of file
+}
+
+
+
+/************* HOME/LANDING PAGE *****************/
+
+.slideshow-home {
+ height: 500px;
+ width: 940px;
+ border-bottom: 1px solid #CCC;
+ position: relative;
+ margin: 0;
+}
+.slideshow-home .frame {
+ width: 940px;
+ height: 500px;
+}
+.slideshow-home .content-left {
+ float: left;
+ text-align: center;
+ vertical-align: center;
+ margin: 0 0 0 35px;
+}
+.slideshow-home .content-right {
+ margin: 80px 0 0 0;
+}
+.slideshow-home .content-right p {
+ margin-bottom: 10px;
+}
+.slideshow-home .content-right p:last-child {
+ margin-top: 15px;
+}
+.slideshow-home .content-right h1 {
+ padding:0;
+}
+.slideshow-home .item {
+ height: 500px;
+ width: 940px;
+}
+.home-sections {
+ padding: 30px 20px 20px;
+ margin: 20px 0;
+ background: -webkit-linear-gradient(top, #F6F6F6,#F9F9F9);
+}
+.home-sections ul {
+ margin: 0;
+}
+.home-sections ul li {
+ float: left;
+ display: block;
+ list-style: none;
+ width: 170px;
+ height: 35px;
+ border: 1px solid #ccc;
+ background: white;
+ margin-right: 10px;
+ border-radius: 1px;
+ -webkit-border-radius: 1px;
+ -moz-border-radius: 1px;
+ box-shadow: 1px 1px 5px #EEE;
+ -webkit-box-shadow: 1px 1px 5px #EEE;
+ -moz-box-shadow: 1px 1px 5px #EEE;
+ background: white;
+}
+.home-sections ul li:hover {
+ background: #F9F9F9;
+ border: 1px solid #CCC;
+}
+.home-sections ul li a,
+.home-sections ul li a:hover {
+ font-weight: bold;
+ margin-top: 8px;
+ line-height: 18px;
+ float: left;
+ width: 100%;
+ text-align: center;
+ color: #09c !important;
+}
+.home-sections ul li a {
+ font-weight: bold;
+ margin-top: 8px;
+ line-height: 18px;
+ float: left;
+ width:100%;
+ text-align:center;
+}
+.home-sections ul li img {
+ float: left;
+ margin: -8px 0 0 10px;
+}
+.home-sections ul li.last {
+ margin-right: 0px;
+}
+.fullpage #footer {
+ margin-top: -40px;
+}
diff --git a/docs/html/guide/google/gcm/server-javadoc/deprecated-list.html b/docs/html/guide/google/gcm/server-javadoc/deprecated-list.html
index 729b2bf..04b9aa5 100644
--- a/docs/html/guide/google/gcm/server-javadoc/deprecated-list.html
+++ b/docs/html/guide/google/gcm/server-javadoc/deprecated-list.html
@@ -2,12 +2,12 @@
<!--NewPage-->
<HTML>
<HEAD>
-<!-- Generated by javadoc (build 1.6.0_26) on Mon Jul 16 14:12:10 PDT 2012 -->
+<!-- Generated by javadoc (build 1.6.0_26) on Wed Aug 29 14:55:34 PDT 2012 -->
<TITLE>
Deprecated List
</TITLE>
-<META NAME="date" CONTENT="2012-07-16">
+<META NAME="date" CONTENT="2012-08-29">
<LINK REL ="stylesheet" TYPE="text/css" HREF="default.css" TITLE="Style">
diff --git a/docs/html/guide/google/gcm/server-javadoc/help-doc.html b/docs/html/guide/google/gcm/server-javadoc/help-doc.html
index 7f5286c..c479cff 100644
--- a/docs/html/guide/google/gcm/server-javadoc/help-doc.html
+++ b/docs/html/guide/google/gcm/server-javadoc/help-doc.html
@@ -2,12 +2,12 @@
<!--NewPage-->
<HTML>
<HEAD>
-<!-- Generated by javadoc (build 1.6.0_26) on Mon Jul 16 14:12:10 PDT 2012 -->
+<!-- Generated by javadoc (build 1.6.0_26) on Wed Aug 29 14:55:34 PDT 2012 -->
<TITLE>
API Help
</TITLE>
-<META NAME="date" CONTENT="2012-07-16">
+<META NAME="date" CONTENT="2012-08-29">
<LINK REL ="stylesheet" TYPE="text/css" HREF="default.css" TITLE="Style">
diff --git a/docs/html/guide/google/gcm/server-javadoc/index-all.html b/docs/html/guide/google/gcm/server-javadoc/index-all.html
index 0b095ec..97aa300 100644
--- a/docs/html/guide/google/gcm/server-javadoc/index-all.html
+++ b/docs/html/guide/google/gcm/server-javadoc/index-all.html
@@ -2,12 +2,12 @@
<!--NewPage-->
<HTML>
<HEAD>
-<!-- Generated by javadoc (build 1.6.0_26) on Mon Jul 16 14:12:10 PDT 2012 -->
+<!-- Generated by javadoc (build 1.6.0_26) on Wed Aug 29 14:55:34 PDT 2012 -->
<TITLE>
Index
</TITLE>
-<META NAME="date" CONTENT="2012-07-16">
+<META NAME="date" CONTENT="2012-08-29">
<LINK REL ="stylesheet" TYPE="text/css" HREF="./default.css" TITLE="Style">
diff --git a/docs/html/guide/google/gcm/server-javadoc/index.html b/docs/html/guide/google/gcm/server-javadoc/index.html
index d8ba0ef..d3c3821 100644
--- a/docs/html/guide/google/gcm/server-javadoc/index.html
+++ b/docs/html/guide/google/gcm/server-javadoc/index.html
@@ -2,7 +2,7 @@
<!--NewPage-->
<HTML>
<HEAD>
-<!-- Generated by javadoc on Mon Jul 16 14:12:10 PDT 2012-->
+<!-- Generated by javadoc on Wed Aug 29 14:55:34 PDT 2012-->
<TITLE>
Generated Documentation (Untitled)
</TITLE>
diff --git a/docs/html/guide/google/gcm/server-javadoc/overview-tree.html b/docs/html/guide/google/gcm/server-javadoc/overview-tree.html
index b8e28ad..c9afea6 100644
--- a/docs/html/guide/google/gcm/server-javadoc/overview-tree.html
+++ b/docs/html/guide/google/gcm/server-javadoc/overview-tree.html
@@ -2,12 +2,12 @@
<!--NewPage-->
<HTML>
<HEAD>
-<!-- Generated by javadoc (build 1.6.0_26) on Mon Jul 16 14:12:10 PDT 2012 -->
+<!-- Generated by javadoc (build 1.6.0_26) on Wed Aug 29 14:55:34 PDT 2012 -->
<TITLE>
Class Hierarchy
</TITLE>
-<META NAME="date" CONTENT="2012-07-16">
+<META NAME="date" CONTENT="2012-08-29">
<LINK REL ="stylesheet" TYPE="text/css" HREF="default.css" TITLE="Style">
diff --git a/docs/html/guide/google/gcm/server-javadoc/serialized-form.html b/docs/html/guide/google/gcm/server-javadoc/serialized-form.html
index 7a1378f..ab99e41 100644
--- a/docs/html/guide/google/gcm/server-javadoc/serialized-form.html
+++ b/docs/html/guide/google/gcm/server-javadoc/serialized-form.html
@@ -2,12 +2,12 @@
<!--NewPage-->
<HTML>
<HEAD>
-<!-- Generated by javadoc (build 1.6.0_26) on Mon Jul 16 14:12:10 PDT 2012 -->
+<!-- Generated by javadoc (build 1.6.0_26) on Wed Aug 29 14:55:34 PDT 2012 -->
<TITLE>
Serialized Form
</TITLE>
-<META NAME="date" CONTENT="2012-07-16">
+<META NAME="date" CONTENT="2012-08-29">
<LINK REL ="stylesheet" TYPE="text/css" HREF="default.css" TITLE="Style">
diff --git a/docs/html/guide/google/play/billing/billing_subscriptions.jd b/docs/html/guide/google/play/billing/billing_subscriptions.jd
index ae12951..68eda19 100644
--- a/docs/html/guide/google/play/billing/billing_subscriptions.jd
+++ b/docs/html/guide/google/play/billing/billing_subscriptions.jd
@@ -12,6 +12,7 @@ parent.link=index.html
<li><a href="#publishing">Subscription publishing and unpublishing</a></li>
<li><a href="#pricing">Subscription pricing</a></li>
<li><a href="#user-billing">User billing</a></li>
+ <li><a href="#trials">Free trial period</a></li>
<li><a href="#cancellation">Subscription cancellation</a></li>
<li><a href="#uninstallation">App uninstallation</a></li>
<li><a href="#refunds">Refunds</a></li>
@@ -94,8 +95,10 @@ digital content, from any type of app or game.</p>
<p>As with other in-app products, you configure and publish subscriptions using
the Developer Console and then sell them from inside apps installed on an
Android-powered devices. In the Developer console, you create subscription
-products and add them to a product list, setting a price for each, choosing a
-billing interval of monthly or annually, and then publishing. In your apps, it’s
+products and add them to a product list, then set a price and optional trial
+period for each, choose a billing interval (monthly or annual), and then publish.</p>
+
+<p>In your apps, it’s
straightforward to add support for subscription purchases. The implementation
extends the standard In-app Billing API to support a new product type but uses
the same communication model, data structures, and user interactions as for
@@ -145,6 +148,7 @@ subscription and if so, allow access to your content. </p>
<li>You can set up subscriptions with either monthly or annual billing</li>
<li>You can sell multiple subscription items in an app with various billing
intervals or prices, such as for promotions</li>
+ <li>You can offer a configurable trial period for any subscription. <span class="new" style="font-size:.78em;">New!</span></li>
<li>Users purchase your subscriptions from inside your apps, rather than
directly from Google Play</li>
<li>Users manage their purchased subscriptions from the My Apps screen in
@@ -251,6 +255,41 @@ notify your backend servers of subscription purchases, tokens, and any billing
errors that may occur. Your backend servers can use the server-side API to query
and update your records and follow up with customers directly, if needed.</p>
+<h3 id="trials">Free Trial Period</h3>
+
+<p>For any subscription, you can set up a free trial period that lets users
+try your subscription content before buying it. The trial period
+runs for the period of time that you set and then automatically converts to a full subscription
+managed according to the subscription's billing interval and price.</p>
+
+<p>To take advantage of a free trial, a user must "purchase" the full
+subscription through the standard In-app Billing flow, providing a valid form of
+payment to use for billing and completing the normal purchase transaction.
+However, the user is not charged any money, since the initial period corresponds
+to the free trial. Instead, Google Play records a transaction of $0.00 and the
+subscription is marked as purchased for the duration of the trial period or
+until cancellation. When the transaction is complete, Google Play notifies users
+by email that they have purchased a subscription that includes a free trial
+period and that the initial charge was $0.00. </p>
+
+<p>When the trial period ends, Google Play automatically initiates billing
+against the credit card that the user provided during the initial purchase, at the amount set
+for the full subscription, and continuing at the subscription interval. If
+necessary, the user can cancel the subscription at any time during the trial
+period. In this case, Google Play <em>marks the subscription as expired immediately</em>,
+rather than waiting until the end of the trial period. The user has not
+paid for the trial period and so is not entitled to continued access after
+cancellation.</p>
+
+<p>You can set up a trial period for a subscription in the Developer Console,
+without needing to modify or update your APK. Just locate and edit the
+subscription in your product list, set a valid number of days for the trial
+(must be 7 days or longer), and publish. You can change the period any time,
+although note that Google Play does not apply the change to users who have
+already "purchased" a trial period for the subscription. Only new subscription
+purchases will use the updated trial period. You can create one free trial
+period per subscription product.</p>
+
<h3 id="cancellation">Subscription cancellation</h3>
<p>Users can view the status of all of their subscriptions and cancel them if
diff --git a/docs/html/guide/google/play/billing/index.jd b/docs/html/guide/google/play/billing/index.jd
index a33b199..134140d 100644
--- a/docs/html/guide/google/play/billing/index.jd
+++ b/docs/html/guide/google/play/billing/index.jd
@@ -42,10 +42,8 @@ and features, and more. You can use In-app Billing to sell products as</p>
<div class="sidebox-wrapper">
<div class="sidebox">
- <h2>Support for subscriptions <span class="new">New!</span></h2>
- <p>In-app Billing now lets you sell subscriptions in your apps, as well as standard in-app products.
- For details on how to sell subscriptions to content, services, and features, see the
- <a href="{@docRoot}guide/google/play/billing/billing_subscriptions.html">Subscriptions</a> documentation.</p>
+ <p><strong>Free trials for subscriptions</strong> <span class="new" style="font-size:.78em;">New!</span></p>
+ <p>You can now offer users a configurable <a href="{@docRoot}guide/google/play/billing/billing_subscriptions.html#trials">free trial period</a> for your in-app subscriptions. You can set up trials with a simple change in the Developer Console&mdash;no change to your app code is needed.
</div>
</div>
diff --git a/docs/html/guide/google/play/expansion-files.jd b/docs/html/guide/google/play/expansion-files.jd
index 750e958..f5cda06 100644
--- a/docs/html/guide/google/play/expansion-files.jd
+++ b/docs/html/guide/google/play/expansion-files.jd
@@ -421,7 +421,7 @@ policy, which captures the expansion file names, sizes, and URLs from the licens
<p>To use APK expansion files with your application and provide the best user experience with
minimal effort on your behalf, we recommend you use the Downloader Library that's included in the
-Google Market Apk Expansion package. This library downloads your expansion files in a
+Google Play APK Expansion Library package. This library downloads your expansion files in a
background service, shows a user notification with the download status, handles network
connectivity loss, resumes the download when possible, and more.</p>
@@ -450,8 +450,8 @@ application.</p>
<p>First, open the <a href="{@docRoot}sdk/exploring.html">Android SDK Manager</a>, expand
<em>Extras</em> and download:</p>
<ul>
- <li><em>Google Market Licensing package</em></li>
- <li><em>Google Market Apk Expansion package</em></li>
+ <li><em>Google Play Licensing Library package</em></li>
+ <li><em>Google Play APK Expansion Library package</em></li>
</ul>
<p>If you're using Eclipse, create a project for each library and add it to your app:</p>
diff --git a/docs/html/guide/google/play/publishing/multiple-apks.jd b/docs/html/guide/google/play/publishing/multiple-apks.jd
index e41817e..0619dfc 100644
--- a/docs/html/guide/google/play/publishing/multiple-apks.jd
+++ b/docs/html/guide/google/play/publishing/multiple-apks.jd
@@ -9,9 +9,7 @@ page.title=Multiple APK Support
<ul>
<li>Simultaneously publish different APKs for different
device configurations</li>
- <li>Different APKs are distributed to different devices based on filters declared in the
-manifest file</li>
- <li>You should publish multiple APKs only when it's not possible or reasonable to
+ <li>You should publish multiple APKs only when it's not possible to
support all desired devices with a single APK</li>
</ul>
@@ -39,16 +37,17 @@ support all desired devices with a single APK</li>
<li><a href="#TextureOptions">Supporting multiple GL textures</a></li>
<li><a href="#ScreenOptions">Supporting multiple screens</a></li>
<li><a href="#ApiLevelOptions">Supporting multiple API levels</a></li>
+ <li><a href="#CpuArchOptions">Supporting multiple CPU architectures</a></li>
</ol>
</li>
</ol>
<h2>See also</h2>
<ol>
+ <li><a href="{@docRoot}guide/google/play/expansion-files.html">APK Expansion Files</a></li>
<li><a href="{@docRoot}guide/google/play/filters.html">Filters on Google Play</a></li>
<li><a href="{@docRoot}guide/practices/screens_support.html">Supporting Multiple Screens</a></li>
- <li><a href="{@docRoot}tools/extras/support-library.html">Compatibility
-Package</a></li>
+ <li><a href="{@docRoot}tools/extras/support-library.html">Support Library</a></li>
<li><a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#ApiLevels">Android API Levels</a></li>
</ol>
@@ -76,14 +75,16 @@ many device configurations as possible, doing so is sometimes not possible. To h
you publish your application for as many devices as possible, Google Play allows you to
publish multiple APKs under the same application listing. Google Play then supplies each APK to
the appropriate devices based on configuration support you've declared in the manifest file of each
-APK.</p>
+APK. </p>
<p>By publishing your application with multiple APKs, you can:</p>
<ul>
<li>Support different OpenGL texture compression formats with each APK.</li>
- <li>Support different screen configurations with each APK.</li>
+ <li>Support different screen sizes and densities with each APK.</li>
<li>Support different platform versions with each APK.</li>
+ <li>Support different CPU architectures with each APK (such as for ARM, x86, and MIPS, when your
+ app uses the <a href="{@docRoot}tools/sdk/ndk/index.html">Android NDK</a>).</li>
</ul>
<p>Currently, these are the only device characteristics that Google Play supports for publishing
@@ -91,7 +92,8 @@ multiple APKs as the same application.</p>
<p class="note"><strong>Note:</strong> You should generally use multiple APKs to support
different device configurations <strong>only when your APK is too large</strong> (greater than
-50MB). Using a single APK to support different configurations is always the best practice,
+50MB) due to the alternative resources needed for different device configurations.
+Using a single APK to support different configurations is always the best practice,
because it makes the path for application updates simple and clear for users (and also makes
your life simpler by avoiding development and publishing complexity). Read the section below about
<a href="#SingleAPK">Using a Single APK Instead</a> to
@@ -283,14 +285,19 @@ higher, as per the previous note).</li>
</ul>
</div>
</li>
+
+ <li><strong>CPU architecture (ABI)</strong>
+ <p>This is based on the native libraries included in each APK (which are
+ determined by the architectures you declare in the {@code Application.mk}
+ file) when using the Android NDK.</p></li>
</ul>
<p>Other manifest elements that enable <a
href="{@docRoot}guide/google/play/filters.html">Google Play filters</a>&mdash;but are not
listed above&mdash;are still applied for each APK as usual. However, Google Play does not allow
-you to publish multiple APKs based on variations of them. Thus, you cannot publish
-multiple APKs if the above listed filters are the same for each APK (but the APKs differ based on
-other characteristics in the manifest file). For
+you to publish separate APKs based on variations of those device characteristics. Thus, you cannot
+publish multiple APKs if the above listed filters are the same for each APK (but the APKs differ
+based on other characteristics in the manifest or APK). For
example, you cannot provide different APKs that differ purely on the <a
href="{@docRoot}guide/topics/manifest/uses-configuration-element.html">{@code
&lt;uses-configuration&gt;}</a> characteristics.</p>
@@ -349,7 +356,8 @@ greater. In this case, the API level is the only supported filter used, so the v
get an update when they receive a system update.</li>
<li>If you have one APK that's for API level 4 (and above) <em>and</em> small -
large screens, and another APK for API level 8 (and above) <em>and</em> large - xlarge screens, then
-the version codes <strong>must increase</strong>. In this case, the API level filter is used to
+the version codes <strong>must increase</strong> in correlation with the API levels.
+In this case, the API level filter is used to
distinguish each APK, but so is the screen size. Because the screen sizes overlap (both APKs
support large screens), the version codes must still be in order. This ensures that a large screen
device that receives a system update to API level 8 will receive an update for the second
@@ -360,6 +368,21 @@ screens, then the version codes <strong>do not need to increase</strong> in corr
levels. Because there is no overlap within the screen size filter, there are no devices that
could potentially move between these two APKs, so there's no need for the version codes to
increase from the lower API level to the higher API level.</li>
+ <li>If you have one APK that's for API level 4 (and above) <em>and</em> ARMv7 CPUs,
+and another APK for API level 8 (and above) <em>and</em> ARMv5TE CPUs,
+then the version codes <strong>must increase</strong> in correlation with the API levels.
+In this case, the API level filter is used to
+distinguish each APK, but so is the CPU architecture. Because an APK with ARMv5TE libraries is
+compatible with devices that have an ARMv7 CPU, the APKs overlap on this characteristic.
+As such, the version code for the APK that supports API level 8 and above must be higher.
+This ensures that a device with an ARMv7 CPU that receives a system update to API level 8
+will receive an update for the second APK that's designed for API level 8.
+However, because this kind of update results in the ARMv7 device using an APK that's not
+fully optimized for that device's CPU, you should provide an
+APK for both the ARMv5TE and the ARMv7 architecture at each API level in order to optimize
+the app performance on each CPU.
+<strong>Note:</strong> This applies <em>only</em> when comparing APKs with the ARMv5TE and
+ARMv7 libraries, and not when comparing other native libraries.</li>
</ul>
</li>
@@ -384,7 +407,12 @@ screens so that all previously-supported devices are still supported.</li>
sizes small, normal, and large, while another APK supports sizes large and xlarge, there is an
overlap, because both APKs support large screens. If you do not resolve this, then devices that
qualify for both APKs (large screen devices in the example) will receive whichever APK has the
-highest version code.</li>
+highest version code.
+ <p class="note"><strong>Note:</strong> If you're creating separate APKs for different CPU
+ architectures, be aware that an APK for ARMv5TE will overlap with an APK for ARMv7. That is,
+ an APK designed for ARMv5TE is compatible with an ARMv7 device,
+but the reverse is not true (an APK with only the ARMv7 libraries is
+<em>not</em> compatible with an ARMv5TE device).</li>
</ul>
<p>When such conflicts occur, you will see a warning message, but you can still publish your
@@ -641,3 +669,17 @@ if (android.os.Build.VERSION.SDK_INT >= 11) {
}
</pre>
+
+<h3 id="CpuArchOptions">Supporting multiple CPU architectures</h3>
+
+<p>When using the Android NDK, you can create a single APK that supports multiple CPU architectures
+by declaring each of the desired architectures with the {@code APP_ABI} variable in the
+<code>Application.mk</code> file.</p>
+
+<p>For example, here's an <code>Application.mk</code> file that declares support for three
+different CPU architectures:</p>
+
+<pre>
+APP_ABI := armeabi armeabi-v7a mips
+APP_PLATFORM := android-9
+</pre>
diff --git a/docs/html/guide/google/play/services.jd b/docs/html/guide/google/play/services.jd
index 519d78b..092642c 100644
--- a/docs/html/guide/google/play/services.jd
+++ b/docs/html/guide/google/play/services.jd
@@ -1,24 +1,25 @@
page.title=Google Play Services
-
@jd:body
-
-<p>Google Play services is a platform that is delivered through the Google Play Store that
+<p>
+ Google Play services is a platform that is delivered through the Google Play Store that
offers integration with Google products, such as Google+, into Android apps.
The Google Play services framework consists of a services component
- that runs on the device and a thin client library that you package with your app. </p>
-
-
+ that runs on the device and a thin client library that you package with your app.
+</p>
<div class="distribute-features col-13">
- <ul>
- <li style="border-top: 1px solid #F80;"><h5>Easy Authentication</h5> Your app can leverage the user's
- existing Google account on the device without having to go through
- tedious authentication flows. A few clicks from the user and you're set!
- <br /> <a href="https://developers.google.com/android/google-play-services">Learn more &raquo;</a>
+<ul>
+ <li style="border-top: 1px solid #F80;"><h5>Easy Authentication</h5>
+ Your app can leverage the user's existing Google account on the device without having to go
+ through tedious authentication flows. A few clicks from the user and you're set!
+ <br/>
+ <a href="https://developers.google.com/android/google-play-services">Learn more &raquo;</a>
</li>
- <li style="border-top: 1px solid #F80;"><h5>Google+ Integration</h5> Google Play services makes it
- easy for your app to integrate with Sign in with Google+, +1 button, and Google+ history.
- <br /> <a href="https://developers.google.com/android/google-play-services">Learn more &raquo;</a>
- </li>
- </ul>
-
-</div> \ No newline at end of file
+ <li style="border-top: 1px solid #F80;"><h5>Google+ Integration</h5>
+ Google Play services makes it easy for your app to integrate with Google+ sign-in and the +1
+ button.
+ <br/>
+ <a href="https://developers.google.com/android/google-play-services">Learn more &raquo;</a>
+ </li>
+</ul>
+
+</div>
diff --git a/docs/html/guide/guide_toc.cs b/docs/html/guide/guide_toc.cs
index 9465f18..46c4398 100644
--- a/docs/html/guide/guide_toc.cs
+++ b/docs/html/guide/guide_toc.cs
@@ -8,7 +8,7 @@
<ul id="nav">
<!-- Walkthrough for Developers -- quick overview of what it's like to develop on Android -->
<!--<li style="color:red">Overview</li> -->
-
+
<li class="nav-section">
<div class="nav-section-header"><a href="<?cs var:toroot ?>guide/components/index.html">
<span class="en">App Components</span>
@@ -191,28 +191,21 @@
<li><a href="<?cs var:toroot ?>guide/topics/ui/menus.html">
<span class="en">Menus</span></span>
</a></li>
- <li><a href="<?cs var:toroot ?>guide/topics/ui/dialogs.html">
- <span class="en">Dialogs</span>
- </a></li>
<li><a href="<?cs var:toroot ?>guide/topics/ui/actionbar.html">
<span class="en">Action Bar</span>
</a></li>
<li><a href="<?cs var:toroot ?>guide/topics/ui/settings.html">
<span class="en">Settings</span>
</a></li>
- <li class="nav-section">
- <div class="nav-section-header"><a href="<?cs var:toroot ?>guide/topics/ui/notifiers/index.html">
- <span class="en">Notifications</span>
- </a></div>
- <ul>
- <li><a href="<?cs var:toroot ?>guide/topics/ui/notifiers/toasts.html">
- <span class="en">Toast Notifications</span>
- </a></li>
- <li><a href="<?cs var:toroot ?>guide/topics/ui/notifiers/notifications.html">
- <span class="en">Status Notifications</span>
- </a></li>
- </ul>
- </li>
+ <li><a href="<?cs var:toroot ?>guide/topics/ui/dialogs.html">
+ <span class="en">Dialogs</span>
+ </a></li>
+ <li><a href="<?cs var:toroot ?>guide/topics/ui/notifiers/notifications.html">
+ <span class="en">Notifications</span>
+ </a></li>
+ <li><a href="<?cs var:toroot ?>guide/topics/ui/notifiers/toasts.html">
+ <span class="en">Toasts</span>
+ </a></li>
<li class="nav-section">
<div class="nav-section-header"><a href="<?cs var:toroot ?>guide/topics/search/index.html">
<span class="en">Search</span>
@@ -223,7 +216,7 @@
<li><a href="<?cs var:toroot ?>guide/topics/search/adding-custom-suggestions.html">Adding Custom Suggestions</a></li>
<li><a href="<?cs var:toroot ?>guide/topics/search/searchable-config.html">Searchable Configuration</a></li>
</ul>
- </li>
+ </li>
<li><a href="<?cs var:toroot ?>guide/topics/ui/drag-drop.html">
<span class="en">Drag and Drop</span>
</a></li>
@@ -235,6 +228,9 @@
<li><a href="<?cs var:toroot ?>guide/topics/ui/accessibility/apps.html">
<span class="en">Making Applications Accessible</span>
</a></li>
+ <li><a href="<?cs var:toroot ?>guide/topics/ui/accessibility/checklist.html">
+ <span class="en">Accessibility Developer Checklist</span>
+ </a></li>
<li><a href="<?cs var:toroot ?>guide/topics/ui/accessibility/services.html">
<span class="en">Building Accessibility Services</span>
</a></li>
@@ -382,9 +378,9 @@
</a></li>
</ul>
</li><!-- end of location and sensors -->
-
-
+
+
<li class="nav-section">
<div class="nav-section-header"><a href="<?cs var:toroot ?>guide/topics/connectivity/index.html">
<span class="en">Connectivity</span>
@@ -419,10 +415,10 @@
<span class="en">SIP</span>
</a>
</li>
-
+
</ul>
</li><!-- end of connectivity -->
-
+
<li class="nav-section">
<div class="nav-section-header"><a href="<?cs var:toroot ?>guide/topics/text/index.html">
<span class="en">Text and Input</span>
@@ -439,7 +435,7 @@
</a></li>
</ul>
</li><!-- end of text and input -->
-
+
<li class="nav-section">
<div class="nav-section-header"><a href="<?cs var:toroot ?>guide/topics/data/index.html">
<span class="en">Data Storage</span>
@@ -457,7 +453,7 @@
</ul>
</li><!-- end of data storage -->
-
+
<li class="nav-section">
<div class="nav-section-header"><a href="<?cs var:toroot?>guide/topics/admin/index.html">
<span class="en">Administration</span>
@@ -475,7 +471,7 @@
-->
</ul>
</li><!-- end of administration -->
-
+
<li class="nav-section">
<div class="nav-section-header"><a href="<?cs var:toroot ?>guide/webapps/index.html">
<span class="en">Web Apps</span>
@@ -498,7 +494,7 @@
</a></li>
</ul>
</li><!-- end of web apps -->
-
+
<li class="nav-section">
<div class="nav-section-header"><a href="<?cs var:toroot ?>guide/practices/index.html">
<span class="en">Best Practices</span>
@@ -555,13 +551,13 @@
</ul>
</li>
-
-
+
+
<li class="nav-section">
<div class="nav-section-header"><a href="<?cs var:toroot ?>guide/google/index.html">
<span class="en">Google Services</span>
</a></div>
- <ul>
+ <ul>
<li class="nav-section">
<div class="nav-section-header"><a href="<?cs var:toroot?>guide/google/play/billing/index.html">
@@ -623,7 +619,7 @@
<li><a href="<?cs var:toroot ?>guide/google/play/expansion-files.html">
<span class="en">APK Expansion Files</span></a>
</li>
-
+
<li class="nav-section">
<div class="nav-section-header"><a href="<?cs var:toroot ?>guide/google/gcm/index.html">
<span class="en">Google Cloud Messaging</span></a>
@@ -649,9 +645,9 @@
</ul>
</li><!-- end Google Play -->
-
-
-
+
+
+
<!-- this needs to move
<li class="nav-section">
<div class="nav-section-header"><a href="<?cs var:toroot ?>guide/practices/ui_guidelines/index.html">
@@ -691,9 +687,9 @@
</a></div>
</li>
</ul>
- </li>
+ </li>
</ul> -->
-
+
<!-- Remove
<li class="nav-section">
<div class="nav-section-header"><a href="<?cs var:toroot ?>guide/appendix/index.html">
@@ -710,7 +706,7 @@
<li><a href="<?cs var:toroot ?>guide/appendix/g-app-intents.html">
<span class="en">Intents List: Google Apps</span>
</a></li>
-
+
<li><a href="<?cs var:toroot ?>guide/appendix/glossary.html">
<span class="en">Glossary</span>
diff --git a/docs/html/guide/practices/security.jd b/docs/html/guide/practices/security.jd
index ce59a9d..36eeff8 100644
--- a/docs/html/guide/practices/security.jd
+++ b/docs/html/guide/practices/security.jd
@@ -1,11 +1,11 @@
-page.title=Designing for Security
+page.title=Designing for Security
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>In this document</h2>
<ol>
-<li><a href="#Dalvik">Using Davlik Code</a></li>
+<li><a href="#Dalvik">Using Dalvik Code</a></li>
<li><a href="#Native">Using Native Code</a></li>
<li><a href="#Data">Storing Data</a></li>
<li><a href="#IPC">Using IPC</a></li>
diff --git a/docs/html/guide/topics/appwidgets/index.jd b/docs/html/guide/topics/appwidgets/index.jd
index a46f9a7..7e031d9 100644
--- a/docs/html/guide/topics/appwidgets/index.jd
+++ b/docs/html/guide/topics/appwidgets/index.jd
@@ -117,7 +117,7 @@ to modify App Widget settings at create-time.</p>
application's
<code>AndroidManifest.xml</code> file. For example:</p>
-<pre>
+<pre style="clear:right">
&lt;receiver android:name="ExampleAppWidgetProvider" >
&lt;intent-filter>
&lt;action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
@@ -307,6 +307,7 @@ following layout classes:</p>
<li>{@link android.widget.FrameLayout}</li>
<li>{@link android.widget.LinearLayout}</li>
<li>{@link android.widget.RelativeLayout}</li>
+ <li>{@link android.widget.GridLayout}</li>
</ul>
<p>And the following widget classes:</p>
@@ -327,6 +328,9 @@ following layout classes:</p>
<p>Descendants of these classes are not supported.</p>
+<p>RemoteViews also supports {@link android.view.ViewStub}, which is an invisible, zero-sized View you can use
+to lazily inflate layout resources at runtime.</p>
+
<h3 id="AddingMargins">Adding margins to App Widgets</h3>
@@ -410,6 +414,25 @@ App Widget,
done.
(See <a href="#Configuring">Creating an App Widget Configuration
Activity</a> below.)</dd>
+
+<dt>
+ {@link android.appwidget.AppWidgetProvider#onAppWidgetOptionsChanged onAppWidgetOptionsChanged()}
+</dt>
+<dd>
+This is called when the widget is first placed and any time the widget is resized. You can use this callback to show or hide content based on the widget's size ranges. You get the size ranges by calling {@link android.appwidget.AppWidgetManager#getAppWidgetOptions getAppWidgetOptions()}, which returns a {@link android.os.Bundle} that includes the following:<br /><br />
+<ul>
+ <li>{@link android.appwidget.AppWidgetManager#OPTION_APPWIDGET_MIN_WIDTH}&mdash;Contains
+the lower bound on the current width, in dp units, of a widget instance.</li>
+ <li>{@link android.appwidget.AppWidgetManager#OPTION_APPWIDGET_MIN_HEIGHT}&mdash;Contains
+the lower bound on the current height, in dp units, of a widget instance.</li>
+ <li>{@link android.appwidget.AppWidgetManager#OPTION_APPWIDGET_MAX_WIDTH}&mdash;Contains
+ the upper bound on the current width, in dp units, of a widget instance.</li>
+ <li>{@link android.appwidget.AppWidgetManager#OPTION_APPWIDGET_MAX_HEIGHT}&mdash;Contains
+the upper bound on the current width, in dp units, of a widget instance.</li>
+</ul>
+
+This callback was introduced in API Level 16 (Android 4.1). If you implement this callback, make sure that your app doesn't depend on it since it won't be called on older devices.
+</dd>
<dt>{@link android.appwidget.AppWidgetProvider#onDeleted(Context,int[])}</dt>
<dd>This is called every time an App Widget is deleted from the App Widget
host.</dd>
@@ -533,12 +556,13 @@ you would like
to receive the App Widget broadcasts directly, you can implement your own
{@link android.content.BroadcastReceiver} or override the
{@link android.appwidget.AppWidgetProvider#onReceive(Context,Intent)} callback.
-The four Intents you need to care about are:</p>
+The Intents you need to care about are as follows:</p>
<ul>
<li>{@link android.appwidget.AppWidgetManager#ACTION_APPWIDGET_UPDATE}</li>
<li>{@link android.appwidget.AppWidgetManager#ACTION_APPWIDGET_DELETED}</li>
<li>{@link android.appwidget.AppWidgetManager#ACTION_APPWIDGET_ENABLED}</li>
<li>{@link android.appwidget.AppWidgetManager#ACTION_APPWIDGET_DISABLED}</li>
+ <li>{@link android.appwidget.AppWidgetManager#ACTION_APPWIDGET_OPTIONS_CHANGED}</li>
</ul>
@@ -791,8 +815,7 @@ href="{@docRoot}resources/samples/StackWidget/index.html">StackView Widget
sample</a>:</p>
<p>
-<img src="{@docRoot}resources/samples/images/StackWidget.png" alt="StackView
-Widget" />
+<img src="{@docRoot}resources/images/StackWidget.png" alt="" />
</p>
<p>This sample consists of a stack of 10 views, which display the values
diff --git a/docs/html/guide/topics/connectivity/nfc/nfc.jd b/docs/html/guide/topics/connectivity/nfc/nfc.jd
index 51c7bee..5011872 100644
--- a/docs/html/guide/topics/connectivity/nfc/nfc.jd
+++ b/docs/html/guide/topics/connectivity/nfc/nfc.jd
@@ -318,8 +318,8 @@ other two intents, giving the user a better experience.</p>
</pre>
</li>
- <li>The <code>uses-feature</code> element so that your application shows up in Google
-Play only for devices that have NFC hardware:
+ <li>The <code>uses-feature</code> element so that your application shows up in Google Play
+ only for devices that have NFC hardware:
<pre>
&lt;uses-feature android:name="android.hardware.nfc" android:required="true" /&gt;
</pre>
@@ -511,13 +511,24 @@ contain the payload and allow you to enumerate the tag's technologies:</p>
<h2 id="creating-records">Creating Common Types of NDEF Records</h2>
<p>This section describes how to create common types of NDEF records to help you when writing to
-NFC tags or sending data with Android Beam. It also describes how to create the corresponding
+NFC tags or sending data with Android Beam. Starting with Android 4.0 (API level 14), the
+{@link android.nfc.NdefRecord#createUri createUri()} method is available to help you create
+URI records automatically. Starting in Android 4.1 (API level 16), {@link android.nfc.NdefRecord#createExternal createExternal()}
+and {@link android.nfc.NdefRecord#createMime createMime()} are available to help you create
+MIME and external type NDEF records. Use these helper methods whenever possible to avoid mistakes
+when manually creating NDEF records.</p>
+
+<p>
+This section also describes how to create the corresponding
intent filter for the record. All of these NDEF record examples should be in the first NDEF
record of the NDEF message that you are writing to a tag or beaming.</p>
<h3 id="abs-uri">TNF_ABSOLUTE_URI</h3>
-<p>Given the following {@link android.nfc.NdefRecord#TNF_ABSOLUTE_URI} NDEF record, which is
-stored as the first record inside of an {@link android.nfc.NdefMessage}:</p>
+<p class="note"><strong>Note:</strong> We recommend that you use the
+ <a href="#well-known-uri"><code>RTD_URI</code></a> type instead
+ of {@link android.nfc.NdefRecord#TNF_ABSOLUTE_URI}, because it is more efficient.</p>
+
+<p>You can create a {@link android.nfc.NdefRecord#TNF_ABSOLUTE_URI} NDEF record in the following way:</p>
<pre>
NdefRecord uriRecord = new NdefRecord(
@@ -526,7 +537,7 @@ NdefRecord uriRecord = new NdefRecord(
new byte[0], new byte[0]);
</pre>
-<p>the intent filter would look like this:</p>
+<p>The intent filter for the previous NDEF record would look like this:</p>
<pre>
&lt;intent-filter&gt;
&lt;action android:name="android.nfc.action.NDEF_DISCOVERED" /&gt;
@@ -537,32 +548,35 @@ NdefRecord uriRecord = new NdefRecord(
&lt;/intent-filter&gt;
</pre>
-
<h3 id="mime">TNF_MIME_MEDIA</h3>
-<p>Given the following {@link android.nfc.NdefRecord#TNF_MIME_MEDIA} NDEF record, which is stored as
-the first record inside
-of an {@link android.nfc.NdefMessage}:</p>
+<p>You can create a {@link android.nfc.NdefRecord#TNF_MIME_MEDIA} NDEF record in the following ways.</p>
+
+<p>Using the {@link android.nfc.NdefRecord#createMime createMime()} method:</p>
+<pre>
+NdefRecord mimeRecord = NdefRecord.createMime("application/vnd.com.example.android.beam",
+ "Beam me up, Android".getBytes(Charset.forName("US-ASCII")));
+</pre>
+
+<p>Creating the {@link android.nfc.NdefRecord} manually:</p>
<pre>
NdefRecord mimeRecord = new NdefRecord(
NdefRecord.TNF_MIME_MEDIA ,
- "application/com.example.android.beam".getBytes(Charset.forName("US-ASCII")),
+ "application/vnd.com.example.android.beam".getBytes(Charset.forName("US-ASCII")),
new byte[0], "Beam me up, Android!".getBytes(Charset.forName("US-ASCII")));
</pre>
-<p>the intent filter would look like this:</p>
+<p>The intent filter for the previous NDEF records would look like this:</p>
<pre>
&lt;intent-filter&gt;
&lt;action android:name="android.nfc.action.NDEF_DISCOVERED" /&gt;
&lt;category android:name="android.intent.category.DEFAULT" /&gt;
- &lt;data android:mimeType="application/com.example.android.beam" /&gt;
+ &lt;data android:mimeType="application/vnd.com.example.android.beam" /&gt;
&lt;/intent-filter&gt;
</pre>
-
<h3 id="well-known-text">TNF_WELL_KNOWN with RTD_TEXT</h3>
-<p>Given the following {@link android.nfc.NdefRecord#TNF_WELL_KNOWN} NDEF record, which is stored as
-the first record inside of an {@link android.nfc.NdefMessage}:</p>
+<p>You can create a {@link android.nfc.NdefRecord#TNF_WELL_KNOWN} NDEF record in the following way:</p>
<pre>
public NdefRecord createTextRecord(String payload, Locale locale, boolean encodeInUtf8) {
byte[] langBytes = locale.getLanguage().getBytes(Charset.forName("US-ASCII"));
@@ -592,9 +606,20 @@ public NdefRecord createTextRecord(String payload, Locale locale, boolean encode
<h3 id="well-known-uri">TNF_WELL_KNOWN with RTD_URI</h3>
-<p>Given the following {@link android.nfc.NdefRecord#TNF_WELL_KNOWN} NDEF record, which is stored as
-the first record inside of an {@link android.nfc.NdefMessage}:</p>
+<p>You can create a {@link android.nfc.NdefRecord#TNF_WELL_KNOWN} NDEF record in the following ways.</p>
+
+<p>Using the {@link android.nfc.NdefRecord#createUri(String)} method:</p>
+<pre>
+NdefRecord rtdUriRecord1 = NdefRecord.createUri("http://example.com");
+</pre>
+<p>Using the {@link android.nfc.NdefRecord#createUri(Uri)} method:</p>
+<pre>
+Uri uri = new Uri("http://example.com");
+NdefRecord rtdUriRecord2 = NdefRecord.createUri(uri);
+</pre>
+
+<p>Creating the {@link android.nfc.NdefRecord} manually:</p>
<pre>
byte[] uriField = "example.com".getBytes(Charset.forName("US-ASCII"));
byte[] payload = new byte[uriField.length + 1]; //add 1 for the URI Prefix
@@ -604,7 +629,7 @@ NdefRecord rtdUriRecord = new NdefRecord(
NdefRecord.TNF_WELL_KNOWN, NdefRecord.RTD_URI, new byte[0], payload);
</pre>
-<p>the intent filter would look like this:</p>
+<p>The intent filter for the previous NDEF records would look like this:</p>
<pre>
&lt;intent-filter&gt;
@@ -617,24 +642,32 @@ NdefRecord rtdUriRecord = new NdefRecord(
</pre>
<h3 id="ext-type">TNF_EXTERNAL_TYPE</h3>
-<p>Given the following {@link android.nfc.NdefRecord#TNF_EXTERNAL_TYPE} NDEF record, which is stored
-as the first record inside of an {@link android.nfc.NdefMessage}:</p>
+<p>You can create a {@link android.nfc.NdefRecord#TNF_EXTERNAL_TYPE} NDEF record in the following ways:</p>
+
+<p>Using the {@link android.nfc.NdefRecord#createExternal createExternal()} method:
+<pre>
+byte[] payload; //assign to your data
+String domain = "com.example"; //usually your app's package name
+String type = "externalType";
+NdefRecord extRecord = NdefRecord.createExternal(domain, type, payload);
+</pre>
+<p>Creating the {@link android.nfc.NdefRecord} manually:</p>
<pre>
byte[] payload;
...
-NdefRecord mimeRecord = new NdefRecord(
- NdefRecord.TNF_EXTERNAL_TYPE, "example.com:externalType", new byte[0], payload);
+NdefRecord extRecord = new NdefRecord(
+ NdefRecord.TNF_EXTERNAL_TYPE, "com.example:externalType", new byte[0], payload);
</pre>
-<p>the intent filter would look like this:</p>
+<p>The intent filter for the previous NDEF records would look like this:</p>
<pre>
&lt;intent-filter&gt;
&lt;action android:name="android.nfc.action.NDEF_DISCOVERED" /&gt;
&lt;category android:name="android.intent.category.DEFAULT" /&gt;
&lt;data android:scheme="vnd.android.nfc"
android:host="ext"
- android:pathPrefix="/example.com:externalType"/&gt;
+ android:pathPrefix="/com.example:externalType"/&gt;
&lt;/intent-filter&gt;
</pre>
@@ -840,8 +873,8 @@ public class Beam extends Activity implements CreateNdefMessageCallback {
String text = ("Beam me up, Android!\n\n" +
"Beam Time: " + System.currentTimeMillis());
NdefMessage msg = new NdefMessage(
- new NdefRecord[] { createMimeRecord(
- "application/com.example.android.beam", text.getBytes())
+ new NdefRecord[] { createMime(
+ "application/vnd.com.example.android.beam", text.getBytes())
/**
* The Android Application Record (AAR) is commented out. When a device
* receives a push with an AAR in it, the application specified in the AAR
@@ -882,22 +915,12 @@ public class Beam extends Activity implements CreateNdefMessageCallback {
// record 0 contains the MIME type, record 1 is the AAR, if present
textView.setText(new String(msg.getRecords()[0].getPayload()));
}
-
- /**
- * Creates a custom MIME type encapsulated in an NDEF record
- */
- public NdefRecord createMimeRecord(String mimeType, byte[] payload) {
- byte[] mimeBytes = mimeType.getBytes(Charset.forName("US-ASCII"));
- NdefRecord mimeRecord = new NdefRecord(
- NdefRecord.TNF_MIME_MEDIA, mimeBytes, new byte[0], payload);
- return mimeRecord;
- }
}
</pre>
<p>Note that this code comments out an AAR, which you can remove. If you enable the AAR, the
application specified in the AAR always receives the Android Beam message. If the application is not
-present, Google Play launches to download the application. Therefore, the following intent
+present, Google Play is started to download the application. Therefore, the following intent
filter is not technically necessary for Android 4.0 devices or later if the AAR is used:
</p>
@@ -905,13 +928,13 @@ filter is not technically necessary for Android 4.0 devices or later if the AAR
&lt;intent-filter&gt;
&lt;action android:name="android.nfc.action.NDEF_DISCOVERED"/&gt;
&lt;category android:name="android.intent.category.DEFAULT"/&gt;
- &lt;data android:mimeType="application/com.example.android.beam"/&gt;
+ &lt;data android:mimeType="application/vnd.com.example.android.beam"/&gt;
&lt;/intent-filter&gt;
</pre>
<p>With this intent filter, the <code>com.example.android.beam</code> application now can be started
when it scans an NFC tag or receives an Android Beam with an AAR of
type <code>com.example.android.beam</code>, or when an NDEF formatted message contains a MIME record
-of type <code>application/com.example.android.beam</code>.</p>
+of type <code>application/vnd.com.example.android.beam</code>.</p>
<p>Even though AARs guarantee an application is started or downloaded, intent filters are
recommended, because they let you start an Activity of your choice in your
diff --git a/docs/html/guide/topics/data/data-storage.jd b/docs/html/guide/topics/data/data-storage.jd
index e9d2d25..2603a06 100644
--- a/docs/html/guide/topics/data/data-storage.jd
+++ b/docs/html/guide/topics/data/data-storage.jd
@@ -232,7 +232,12 @@ save files. This can be a removable storage media (such as an SD card) or an int
(non-removable) storage. Files saved to the external storage are world-readable and can
be modified by the user when they enable USB mass storage to transfer files on a computer.</p>
-<p class="caution"><strong>Caution:</strong> External files can disappear if the user mounts the
+<p>It's possible that a device using a partition of the
+internal storage for the external storage may also offer an SD card slot. In this case,
+the SD card is <em>not</em> part of the external storage and your app cannot access it (the extra
+storage is intended only for user-provided media that the system scans).</p>
+
+<p class="caution"><strong>Caution:</strong> External storage can become unavailable if the user mounts the
external storage on a computer or removes the media, and there's no security enforced upon files you
save to the external storage. All applications can read and write files placed on the external
storage and the user can remove them.</p>
diff --git a/docs/html/guide/topics/manifest/activity-element.jd b/docs/html/guide/topics/manifest/activity-element.jd
index 844be11..2aedaec 100644
--- a/docs/html/guide/topics/manifest/activity-element.jd
+++ b/docs/html/guide/topics/manifest/activity-element.jd
@@ -218,7 +218,8 @@ separated by '{@code |}' &mdash; for example, "{@code locale|navigation|orientat
<td>"{@code uiMode}"</td>
<td>The user interface mode has changed &mdash; this can be caused when the user places the
device into a desk/car dock or when the the night mode changes. See {@link
-android.app.UiModeManager}. <em>Introduced in API Level 8</em>.</td>
+android.app.UiModeManager}.
+ <em>Added in API level 8</em>.</td>
</tr><tr>
<td>"{@code orientation}"</td>
<td>The screen orientation has changed &mdash; the user has rotated the device.
@@ -246,7 +247,12 @@ smallestWidth configuration</a>. However, if your application targets API level
your activity always handles this configuration change itself (this configuration change does not
restart your activity, even when running on an Android 3.2 or higher device).
<p><em>Added in API level 13.</em></p></td>
- </tr>
+ </tr><tr>
+ <td>"{@code layoutDirection}"</td>
+ <td>The layout direction has changed. For example, changing from left-to-right (LTR)
+ to right-to-left (RTL).
+ <em>Added in API level 17.</em></td>
+ </tr>
</table>
<p>
diff --git a/docs/html/guide/topics/manifest/application-element.jd b/docs/html/guide/topics/manifest/application-element.jd
index 2105a50..42cfdd5 100644
--- a/docs/html/guide/topics/manifest/application-element.jd
+++ b/docs/html/guide/topics/manifest/application-element.jd
@@ -23,6 +23,7 @@ parent.link=manifest-intro.html
android:<a href="#persistent">persistent</a>=["true" | "false"]
android:<a href="#proc">process</a>="<i>string</i>"
android:<a href="#restoreany">restoreAnyVersion</a>=["true" | "false"]
+ android:<a href="#supportsrtl">supportsRtl</a>=["true" | "false"]
android:<a href="#aff">taskAffinity</a>="<i>string</i>"
android:<a href="#theme">theme</a>="<i>resource or theme</i>"
android:<a href="#uioptions">uiOptions</a>=["none" | "splitActionBarWhenNarrow"] &gt;
@@ -271,7 +272,7 @@ applications, reducing resource usage.
</p></dd>
<dt><a name="restoreany"></a>{@code android:restoreAnyVersion}</dt>
-<dd>Indicate that the application is prepared to attempt a restore of any
+<dd>Indicates that the application is prepared to attempt a restore of any
backed-up data set, even if the backup was stored by a newer version
of the application than is currently installed on the device. Setting
this attribute to {@code true} will permit the Backup Manager to
@@ -281,6 +282,21 @@ incompatible. <em>Use with caution!</em>
<p>The default value of this attribute is {@code false}.
</p></dd>
+<dt><a name="supportsrtl"></a>{@code android:supportsRtl}</dt>
+<dd>Declares whether your application is willing to support right-to-left (RTL) layouts.
+<p>If set to {@code true} and <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target"
+>{@code targetSdkVersion}</a> is set to 17 or higher, various RTL APIs will be
+activated and used by the system so your app can display RTL layouts.
+If set to {@code false} or if <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target"
+>{@code targetSdkVersion}</a> is set to 16 or lower, the RTL APIs will be ignored
+or will have no effect and your app will behave the same regardless of the layout
+direction associated to the user's Locale choice (your layouts will always be left-to-right).
+
+<p>The default value of this attribute is {@code false}.</p>
+
+<p>This attribute was added in API level 17.</p>
+</dd>
+
<dt><a name="aff"></a>{@code android:taskAffinity}</dt>
<dd>An affinity name that applies to all activities within the application,
except for those that set a different affinity with their own
diff --git a/docs/html/guide/topics/manifest/permission-element.jd b/docs/html/guide/topics/manifest/permission-element.jd
index c256fb1..a23fb4b 100644
--- a/docs/html/guide/topics/manifest/permission-element.jd
+++ b/docs/html/guide/topics/manifest/permission-element.jd
@@ -111,7 +111,7 @@ The value can be set to one of the following strings:
<td>"{@code signatureOrSystem}"</td>
<td>A permission that the system grants only to applications that are
in the Android system image <em>or</em> that are signed with the same
- certificates as those in the system image. Please avoid using this
+ certificate as the application that declared the permission. Please avoid using this
option, as the {@code signature} protection level should be sufficient
for most needs and works regardless of exactly where applications are
installed. The "{@code signatureOrSystem}"
diff --git a/docs/html/guide/topics/manifest/provider-element.jd b/docs/html/guide/topics/manifest/provider-element.jd
index 4558800..6cf6843 100644
--- a/docs/html/guide/topics/manifest/provider-element.jd
+++ b/docs/html/guide/topics/manifest/provider-element.jd
@@ -5,7 +5,9 @@ parent.link=manifest-intro.html
<dl class="xml">
<dt>syntax:</dt>
-<dd><pre class="stx">&lt;provider android:<a href="#auth">authorities</a>="<i>list</i>"
+<dd>
+<pre class="stx">
+&lt;provider android:<a href="#auth">authorities</a>="<i>list</i>"
android:<a href="#enabled">enabled</a>=["true" | "false"]
android:<a href="#exported">exported</a>=["true" | "false"]
android:<a href="#gprmsn">grantUriPermissions</a>=["true" | "false"]
@@ -20,10 +22,13 @@ parent.link=manifest-intro.html
android:<a href="#sync">syncable</a>=["true" | "false"]
android:<a href="#wprmsn">writePermission</a>="<i>string</i>" &gt;
. . .
-&lt;/provider&gt;</pre></dd>
+&lt;/provider&gt;</pre>
+</dd>
<dt>contained in:</dt>
-<dd><code><a href="{@docRoot}guide/topics/manifest/application-element.html">&lt;application&gt;</a></code></dd>
+<dd>
+ <code><a href="{@docRoot}guide/topics/manifest/application-element.html">&lt;application&gt;</a></code>
+</dd>
<dt>can contain:</dt>
<dd><code><a href="{@docRoot}guide/topics/manifest/meta-data-element.html">&lt;meta-data&gt;</a></code>
@@ -31,58 +36,67 @@ parent.link=manifest-intro.html
<br/><code><a href="{@docRoot}guide/topics/manifest/path-permission-element.html">&lt;path-permission&gt;</a></code></dd>
<dt>description:</dt>
-<dd>Declares a content provider &mdash; a subclass of
-{@link android.content.ContentProvider} &mdash; that supplies structured
-access to data managed by the application. All content providers that
-are part of the application must be represented by {@code &lt;provider&gt;}
-elements in the manifest file. The system cannot see, and therefore will
-not run, any that are not declared. (You need to declare only
-those content providers that you develop as part of your application,
-not those developed by others that your application uses.)
-
-<p>
-The Android system identifies content providers by the authority part
- of a {@code content:} URI. For example, suppose that the following URI
-is passed to <code>{@link android.content.ContentResolver#query
-ContentResolver.query()}</code>:
-
-<p style="margin-left: 2em">{@code content://com.example.project.healthcareprovider/nurses/rn}</p>
-
-<p>
-The {@code content:} scheme identifies the data as belonging to a content
-provider and the authority ({@code com.example.project.healthcareprovider})
-identifies the particular provider. The authority therefore must be unique.
-Typically, as in this example, it's the fully qualified name of a
-ContentProvider subclass. The path part of a URI may be used by a content
-provider to identify particular data subsets, but those paths are not
-declared in the manifest.
-</p>
-
-<p>
-For information on using and developing content providers, see a separate document,
-<a href="{@docRoot}guide/topics/providers/content-providers.html">Content Providers</a>.
-</p></dd>
+<dd>
+ Declares a content provider component. A content provider is a subclass of
+ {@link android.content.ContentProvider} that supplies structured access to data managed by the
+ application. All content providers in your application must be defined in a
+ {@code &lt;provider&gt;} element in the manifest file; otherwise, the system is unaware of them
+ and doesn't run them.
+ <p>
+ You only declare content providers that are part of your application. Content providers in
+ other applications that you use in your application should not be declared.
+ </p>
+ <p>
+ The Android system stores references to content providers according to an <b>authority</b>
+ string, part of the provider's <b>content URI</b>. For example, suppose you want to
+ access a content provider that stores information about health care professionals. To do
+ this, you call the method
+ {@link android.content.ContentResolver#query ContentResolver.query()}, which among other
+ arguments takes a URI that identifies the provider:
+ </p>
+<pre>
+content://com.example.project.healthcareprovider/nurses/rn
+</pre>
+ <p>
+ The <code>content:</code> <b>scheme</b> identifies the URI as a content URI pointing to
+ an Android content provider. The authority
+ <code>com.example.project.healthcareprovider</code> identifies the provider itself; the
+ Android system looks up the authority in its list of known providers and their authorities.
+ The substring <code>nurses/rn</code> is a <b>path</b>, which the content provider can use
+ to identify subsets of the provider data.
+ </p>
+ <p>
+ Notice that when you define your provider in the <code>&lt;provider&gt;</code> element, you
+ don't include the scheme or the path in the <code>android:name</code> argument, only the
+ authority.
+ </p>
+ <p>
+ For information on using and developing content providers, see the API Guide,
+ <a href="{@docRoot}guide/topics/providers/content-providers.html">Content Providers</a>.
+ </p>
+</dd>
<dt>attributes:</dt>
-<dd><dl class="attr">
-<dt><a name="auth"></a>{@code android:authorities}</dt>
-<dd>A list of one or more URI authorities that identify data under the purview
-of the content provider.
-Multiple authorities are listed by separating their names with a semicolon.
-To avoid conflicts, authority names should use a Java-style naming convention
-(such as {@code com.example.provider.cartoonprovider}). Typically, it's the name
-of the ContentProvider subclass.
-
-<p>
-There is no default. At least one authority must be specified.
-</p></dd>
-
-<dt><a name="enabled"></a>{@code android:enabled}</dt>
-<dd>Whether or not the content provider can be instantiated by the system &mdash;
-"{@code true}" if it can be, and "{@code false}" if not. The default value
-is "{@code true}".
-
-<p>
+<dd>
+ <dl class="attr">
+ <dt><a name="auth"></a>{@code android:authorities}</dt>
+ <dd>
+ A list of one or more URI authorities that identify data offered by the content provider.
+ Multiple authorities are listed by separating their names with a semicolon.
+ To avoid conflicts, authority names should use a Java-style naming convention
+ (such as {@code com.example.provider.cartoonprovider}). Typically, it's the name
+ of the {@link android.content.ContentProvider} subclass that implements the provider
+ <p>
+ There is no default. At least one authority must be specified.
+ </p>
+ </dd>
+
+ <dt><a name="enabled"></a>{@code android:enabled}</dt>
+ <dd>Whether or not the content provider can be instantiated by the system &mdash;
+ "{@code true}" if it can be, and "{@code false}" if not. The default value
+ is "{@code true}".
+
+ <p>
The <code><a href="{@docRoot}guide/topics/manifest/application-element.html">&lt;application&gt;</a></code> element has its own
<code><a href="{@docRoot}guide/topics/manifest/application-element.html#enabled">enabled</a></code> attribute that applies to all
application components, including content providers. The
@@ -93,16 +107,37 @@ are by default) for the content provider to be enabled. If either is
</p></dd>
<dt><a name="exported"></a>{@code android:exported}</dt>
-<dd>Whether or not the content provider can be used by components of other
-applications &mdash; "{@code true}" if it can be, and "{@code false}" if not.
-If "{@code false}", the provider is available only to components of the
-same application or applications with the same user ID. The default value
-is "{@code true}".
-
-<p>
-You can export a content provider but still limit access to it with the
-<code><a href="{@docRoot}guide/topics/manifest/provider-element.html#prmsn">permission</a></code> attribute.
-</p></dd>
+<dd>
+ Whether the content provider is available for other applications to use:
+ <ul>
+ <li>
+ <code>true</code>: The provider is available to other applications. Any application can
+ use the provider's content URI to access it, subject to the permissions specified for
+ the provider.
+ </li>
+ <li>
+ <code>false</code>: The provider is not available to other applications. Set
+ <code>android:exported="false"</code> to limit access to the provider to your
+ applications. Only applications that have the same user ID (UID) as the provider will
+ have access to it.
+ </li>
+ </ul>
+ <p>
+ The default value is <code>"true"</code> for applications that set either
+<code><a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">android:minSdkVersion</a></code>
+ or
+<code><a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">android:targetSdkVersion</a></code> to
+ <code>"16"</code> or lower. For applications that
+ set either of these attributes to <code>"17"</code> or higher, the default is
+ <code>"false"</code>.
+ </p>
+ <p>
+ You can set <code>android:exported="false"</code> and still limit access to your
+ provider by setting permissions with the
+ <code><a href="{@docRoot}guide/topics/manifest/provider-element.html#prmsn">permission</a></code>
+ attribute.
+ </p>
+</dd>
<dt><a name="gprmsn"></a>{@code android:grantUriPermissions}</dt>
<dd>Whether or not those who ordinarily would not have permission to
diff --git a/docs/html/guide/topics/manifest/uses-feature-element.jd b/docs/html/guide/topics/manifest/uses-feature-element.jd
index a111356..10b5a33 100644
--- a/docs/html/guide/topics/manifest/uses-feature-element.jd
+++ b/docs/html/guide/topics/manifest/uses-feature-element.jd
@@ -561,7 +561,7 @@ is sensitive to delays or lag in sound input or output.</td>
</td>
</tr>
<tr>
- <td rowspan="4">Camera</td>
+ <td rowspan="5">Camera</td>
<td><code>android.hardware.camera</code></td>
<td>The application uses the device's camera. If the device supports
multiple cameras, the application uses the camera that facing
@@ -583,6 +583,12 @@ is sensitive to delays or lag in sound input or output.</td>
<td><code>android.hardware.camera.front</code></td>
<td>Subfeature. The application uses a front-facing camera on the device.</td>
</tr>
+<tr>
+ <td><code>android.hardware.camera.any</code></td>
+ <td>The application uses at least one camera facing in any direction. Use this
+in preference to <code>android.hardware.camera</code> if a back-facing camera is
+not required.</td>
+</tr>
<tr>
<td rowspan="3">Location</td>
diff --git a/docs/html/guide/topics/providers/content-provider-basics.jd b/docs/html/guide/topics/providers/content-provider-basics.jd
index 8c47ad7..527e713 100644
--- a/docs/html/guide/topics/providers/content-provider-basics.jd
+++ b/docs/html/guide/topics/providers/content-provider-basics.jd
@@ -2,9 +2,7 @@ page.title=Content Provider Basics
@jd:body
<div id="qv-wrapper">
<div id="qv">
-
-
- <!-- In this document -->
+<!-- In this document -->
<h2>In this document</h2>
<ol>
<li>
@@ -238,15 +236,11 @@ page.title=Content Provider Basics
</p>
<p>
For example, to get a list of the words and their locales from the User Dictionary Provider,
- you call {@link android.content.ContentResolver#query(Uri, String[], String, String[], String)
- ContentResolver.query()}.
- The {@link android.content.ContentResolver#query(Uri, String[], String, String[], String)
- query()} method calls the
- {@link android.content.ContentProvider#query(Uri, String[], String, String[], String)
- ContentProvider.query()} method defined by the User Dictionary Provider. The following lines
- of code show a
- {@link android.content.ContentResolver#query(Uri, String[], String, String[], String)
- ContentResolver.query()} call:
+ you call {@link android.content.ContentResolver#query ContentResolver.query()}.
+ The {@link android.content.ContentResolver#query query()} method calls the
+ {@link android.content.ContentProvider#query ContentProvider.query()} method defined by the
+ User Dictionary Provider. The following lines of code show a
+ {@link android.content.ContentResolver#query ContentResolver.query()} call:
<p>
<pre>
// Queries the user dictionary and returns results
@@ -259,7 +253,7 @@ mCursor = getContentResolver().query(
</pre>
<p>
Table 2 shows how the arguments to
- {@link android.content.ContentResolver#query(Uri, String[], String, String[], String)
+ {@link android.content.ContentResolver#query
query(Uri,projection,selection,selectionArgs,sortOrder)} match an SQL SELECT statement:
</p>
<p class="table-caption">
@@ -344,7 +338,7 @@ content://user_dictionary/words
<code>4</code> from user dictionary, you can use this content URI:
</p>
<pre>
-Uri singleUri = ContentUri.withAppendedId(UserDictionary.Words.CONTENT_URI,4);
+Uri singleUri = ContentUris.withAppendedId(UserDictionary.Words.CONTENT_URI,4);
</pre>
<p>
You often use id values when you've retrieved a set of rows and then want to update or delete
@@ -354,7 +348,7 @@ Uri singleUri = ContentUri.withAppendedId(UserDictionary.Words.CONTENT_URI,4);
<strong>Note:</strong> The {@link android.net.Uri} and {@link android.net.Uri.Builder} classes
contain convenience methods for constructing well-formed Uri objects from strings. The
{@link android.content.ContentUris} contains convenience methods for appending id values to
- a URI. The previous snippet uses {@link android.content.ContentUris#withAppendedId(Uri, long)
+ a URI. The previous snippet uses {@link android.content.ContentUris#withAppendedId
withAppendedId()} to append an id to the UserDictionary content URI.
</p>
@@ -367,10 +361,9 @@ Uri singleUri = ContentUri.withAppendedId(UserDictionary.Words.CONTENT_URI,4);
</p>
<p class="note">
For the sake of clarity, the code snippets in this section call
- {@link android.content.ContentResolver#query(Uri, String[], String, String[], String)
- ContentResolver.query()} on the "UI thread"". In actual code, however, you should
- do queries asynchronously on a separate thread. One way to do this is to use the
- {@link android.content.CursorLoader} class, which is described
+ {@link android.content.ContentResolver#query ContentResolver.query()} on the "UI thread"". In
+ actual code, however, you should do queries asynchronously on a separate thread. One way to do
+ this is to use the {@link android.content.CursorLoader} class, which is described
in more detail in the <a href="{@docRoot}guide/components/loaders.html">
Loaders</a> guide. Also, the lines of code are snippets only; they don't show a complete
application.
@@ -391,8 +384,8 @@ Uri singleUri = ContentUri.withAppendedId(UserDictionary.Words.CONTENT_URI,4);
To retrieve data from a provider, your application needs "read access permission" for the
provider. You can't request this permission at run-time; instead, you have to specify that
you need this permission in your manifest, using the
- <code><a href="{@docRoot}guide/topics/manifest/uses-permission-element.html">
- &lt;uses-permission&gt;</a></code> element and the exact permission name defined by the
+<code><a href="{@docRoot}guide/topics/manifest/uses-permission-element.html">&lt;uses-permission&gt;</a></code>
+ element and the exact permission name defined by the
provider. When you specify this element in your manifest, you are in effect "requesting" this
permission for your application. When users install your application, they implicitly grant
this request.
@@ -436,10 +429,9 @@ String[] mSelectionArgs = {""};
</pre>
<p>
The next snippet shows how to use
- {@link android.content.ContentResolver#query(Uri, String[], String, String[], String)
- ContentResolver.query()}, using the User Dictionary Provider as an example.
- A provider client query is similar to an SQL query, and it contains a set of columns to return,
- a set of selection criteria, and a sort order.
+ {@link android.content.ContentResolver#query ContentResolver.query()}, using the User Dictionary
+ Provider as an example. A provider client query is similar to an SQL query, and it contains a
+ set of columns to return, a set of selection criteria, and a sort order.
</p>
<p>
The set of columns that the query should return is called a <strong>projection</strong>
@@ -448,9 +440,9 @@ String[] mSelectionArgs = {""};
<p>
The expression that specifies the rows to retrieve is split into a selection clause and
selection arguments. The selection clause is a combination of logical and Boolean expressions,
- column names, and values (the variable <code>mSelection</code>). If you specify the replaceable
- parameter <code>?</code> instead of a value, the query method retrieves the value from the
- selection arguments array (the variable <code>mSelectionArgs</code>).
+ column names, and values (the variable <code>mSelectionClause</code>). If you specify the
+ replaceable parameter <code>?</code> instead of a value, the query method retrieves the value
+ from the selection arguments array (the variable <code>mSelectionArgs</code>).
</p>
<p>
In the next snippet, if the user doesn't enter a word, the selection clause is set to
@@ -517,7 +509,7 @@ if (null == mCursor) {
This query is analogous to the SQL statement:
</p>
<pre>
-SELECT _ID, word, frequency, locale FROM words WHERE word = &lt;userinput&gt; ORDER BY word ASC;
+SELECT _ID, word, locale FROM words WHERE word = &lt;userinput&gt; ORDER BY word ASC;
</pre>
<p>
In this SQL statement, the actual column names are used instead of contract class constants.
@@ -575,16 +567,15 @@ selectionArgs[0] = mUserInput;
<!-- Displaying the results -->
<h3 id="DisplayResults">Displaying query results</h3>
<p>
- The {@link android.content.ContentResolver#query(Uri, String[], String, String[], String)
- ContentResolver.query()} client method always returns a {@link android.database.Cursor}
- containing the columns specified by the query's projection for the rows that match the query's
- selection criteria. A {@link android.database.Cursor} object provides random read access to the
- rows and columns it contains. Using {@link android.database.Cursor} methods,
- you can iterate over the rows in the results, determine the data type of each column, get the
- data out of a column, and examine other properties of the results. Some
- {@link android.database.Cursor} implementations automatically update the object when the
- provider's data changes, or trigger methods in an observer object when the
- {@link android.database.Cursor} changes, or both.
+ The {@link android.content.ContentResolver#query ContentResolver.query()} client method always
+ returns a {@link android.database.Cursor} containing the columns specified by the query's
+ projection for the rows that match the query's selection criteria. A
+ {@link android.database.Cursor} object provides random read access to the rows and columns it
+ contains. Using {@link android.database.Cursor} methods, you can iterate over the rows in the
+ results, determine the data type of each column, get the data out of a column, and examine other
+ properties of the results. Some {@link android.database.Cursor} implementations automatically
+ update the object when the provider's data changes, or trigger methods in an observer object
+ when the {@link android.database.Cursor} changes, or both.
</p>
<p class="note">
<strong>Note:</strong> A provider may restrict access to columns based on the nature of the
@@ -594,7 +585,7 @@ selectionArgs[0] = mUserInput;
<p>
If no rows match the selection criteria, the provider
returns a {@link android.database.Cursor} object for which
- {@link android.database.Cursor#getCount() Cursor.getCount()} is 0 (an empty cursor).
+ {@link android.database.Cursor#getCount Cursor.getCount()} is 0 (an empty cursor).
</p>
<p>
If an internal error occurs, the results of the query depend on the particular provider. It may
@@ -685,8 +676,8 @@ if (mCursor != null) {
<p>
{@link android.database.Cursor} implementations contain several "get" methods for
retrieving different types of data from the object. For example, the previous snippet
- uses {@link android.database.Cursor#getString(int) getString()}. They also have a
- {@link android.database.Cursor#getType(int) getType()} method that returns a value indicating
+ uses {@link android.database.Cursor#getString getString()}. They also have a
+ {@link android.database.Cursor#getType getType()} method that returns a value indicating
the data type of the column.
</p>
@@ -713,17 +704,16 @@ if (mCursor != null) {
</p>
<p>
To get the permissions needed to access a provider, an application requests them with a
- <code><a href="{@docRoot}guide/topics/manifest/uses-permission-element.html">
- &lt;uses-permission&gt;</a></code> element in its manifest file.
- When the Android Package Manager installs the application, a user must approve all of the
- permissions the application requests. If the user approves all of them, Package Manager
- continues the installation; if the user doesn't approve them, Package Manager
+<code><a href="{@docRoot}guide/topics/manifest/uses-permission-element.html">&lt;uses-permission&gt;</a></code>
+ element in its manifest file. When the Android Package Manager installs the application, a user
+ must approve all of the permissions the application requests. If the user approves all of them,
+ Package Manager continues the installation; if the user doesn't approve them, Package Manager
aborts the installation.
</p>
<p>
The following
- <code><a href="{@docRoot}guide/topics/manifest/uses-permission-element.html">
- &lt;uses-permission&gt;</a></code> element requests read access to the User Dictionary Provider:
+<code><a href="{@docRoot}guide/topics/manifest/uses-permission-element.html">&lt;uses-permission&gt;</a></code>
+ element requests read access to the User Dictionary Provider:
</p>
<pre>
&lt;uses-permission android:name="android.permission.READ_USER_DICTIONARY"&gt;
@@ -746,7 +736,7 @@ if (mCursor != null) {
<h3 id="Inserting">Inserting data</h3>
<p>
To insert data into a provider, you call the
- {@link android.content.ContentResolver#insert(Uri,ContentValues) ContentResolver.insert()}
+ {@link android.content.ContentResolver#insert ContentResolver.insert()}
method. This method inserts a new row into the provider and returns a content URI for that row.
This snippet shows how to insert a new word into the User Dictionary Provider:
</p>
@@ -777,8 +767,7 @@ mNewUri = getContentResolver().insert(
The data for the new row goes into a single {@link android.content.ContentValues} object, which
is similar in form to a one-row cursor. The columns in this object don't need to have the
same data type, and if you don't want to specify a value at all, you can set a column
- to <code>null</code> using {@link android.content.ContentValues#putNull(String)
- ContentValues.putNull()}.
+ to <code>null</code> using {@link android.content.ContentValues#putNull ContentValues.putNull()}.
</p>
<p>
The snippet doesn't add the <code>_ID</code> column, because this column is maintained
@@ -799,17 +788,16 @@ content://user_dictionary/words/&lt;id_value&gt;
</p>
<p>
To get the value of <code>_ID</code> from the returned {@link android.net.Uri}, call
- {@link android.content.ContentUris#parseId(Uri) ContentUris.parseId()}.
+ {@link android.content.ContentUris#parseId ContentUris.parseId()}.
</p>
<h3 id="Updating">Updating data</h3>
<p>
To update a row, you use a {@link android.content.ContentValues} object with the updated
values just as you do with an insertion, and selection criteria just as you do with a query.
The client method you use is
- {@link android.content.ContentResolver#update(Uri, ContentValues, String, String[])
- ContentResolver.update()}. You only need to add values to the
- {@link android.content.ContentValues} object for columns you're updating. If you want to clear
- the contents of a column, set the value to <code>null</code>.
+ {@link android.content.ContentResolver#update ContentResolver.update()}. You only need to add
+ values to the {@link android.content.ContentValues} object for columns you're updating. If you
+ want to clear the contents of a column, set the value to <code>null</code>.
</p>
<p>
The following snippet changes all the rows whose locale has the language "en" to a
@@ -842,9 +830,8 @@ mRowsUpdated = getContentResolver().update(
</pre>
<p>
You should also sanitize user input when you call
- {@link android.content.ContentResolver#update(Uri, ContentValues, String, String[])
- ContentResolver.update()}. To learn more about this, read the section
- <a href="#Injection">Protecting against malicious input</a>.
+ {@link android.content.ContentResolver#update ContentResolver.update()}. To learn more about
+ this, read the section <a href="#Injection">Protecting against malicious input</a>.
</p>
<h3 id="Deleting">Deleting data</h3>
<p>
@@ -873,9 +860,8 @@ mRowsDeleted = getContentResolver().delete(
</pre>
<p>
You should also sanitize user input when you call
- {@link android.content.ContentResolver#delete(Uri, String, String[])
- ContentResolver.delete()}. To learn more about this, read the section
- <a href="#Injection">Protecting against malicious input</a>.
+ {@link android.content.ContentResolver#delete ContentResolver.delete()}. To learn more about
+ this, read the section <a href="#Injection">Protecting against malicious input</a>.
</p>
<!-- Provider Data Types -->
<h2 id="DataTypes">Provider Data Types</h2>
@@ -907,7 +893,7 @@ mRowsDeleted = getContentResolver().delete(
The data types for the User Dictionary Provider are listed in the reference documentation
for its contract class {@link android.provider.UserDictionary.Words} (contract classes are
described in the section <a href="#ContractClasses">Contract Classes</a>).
- You can also determine the data type by calling {@link android.database.Cursor#getType(int)
+ You can also determine the data type by calling {@link android.database.Cursor#getType
Cursor.getType()}.
</p>
<p>
@@ -918,7 +904,7 @@ mRowsDeleted = getContentResolver().delete(
data structures or files. For example, the {@link android.provider.ContactsContract.Data}
table in the Contacts Provider uses MIME types to label the type of contact data stored in each
row. To get the MIME type corresponding to a content URI, call
- {@link android.content.ContentResolver#getType(Uri) ContentResolver.getType()}.
+ {@link android.content.ContentResolver#getType ContentResolver.getType()}.
</p>
<p>
The section <a href="#MIMETypeReference">MIME Type Reference</a> describes the
@@ -935,8 +921,7 @@ mRowsDeleted = getContentResolver().delete(
<li>
<a href="#Batch">Batch access</a>: You can create a batch of access calls with methods in
the {@link android.content.ContentProviderOperation} class, and then apply them with
- {@link android.content.ContentResolver#applyBatch(String, ArrayList)
- ContentResolver.applyBatch()}.
+ {@link android.content.ContentResolver#applyBatch ContentResolver.applyBatch()}.
</li>
<li>
Asynchronous queries: You should do queries in a separate thread. One way to do this is to
@@ -963,11 +948,10 @@ mRowsDeleted = getContentResolver().delete(
To access a provider in "batch mode",
you create an array of {@link android.content.ContentProviderOperation} objects and then
dispatch them to a content provider with
- {@link android.content.ContentResolver#applyBatch(String, ArrayList)
- ContentResolver.applyBatch()}. You pass the content provider's <em>authority</em> to this
- method, rather than a particular content URI, which allows each
- {@link android.content.ContentProviderOperation} object in the array to work against a
- different table. A call to {@link android.content.ContentResolver#applyBatch(String, ArrayList)
+ {@link android.content.ContentResolver#applyBatch ContentResolver.applyBatch()}. You pass the
+ content provider's <em>authority</em> to this method, rather than a particular content URI.
+ This allows each {@link android.content.ContentProviderOperation} object in the array to work
+ against a different table. A call to {@link android.content.ContentResolver#applyBatch
ContentResolver.applyBatch()} returns an array of results.
</p>
<p>
@@ -1028,14 +1012,13 @@ mRowsDeleted = getContentResolver().delete(
</p>
<p>
A provider defines URI permissions for content URIs in its manifest, using the
- <code><a href="{@docRoot}guide/topics/manifest/provider-element.html#gprmsn">
- android:grantUriPermission</a></code>
- attribute of the <a href="{@docRoot}guide/topics/manifest/provider-element.html">
- {@code &lt;provider&gt;}</a>
+<code><a href="{@docRoot}guide/topics/manifest/provider-element.html#gprmsn">android:grantUriPermission</a></code>
+ attribute of the
+<code><a href="{@docRoot}guide/topics/manifest/provider-element.html">&lt;provider&gt;</a></code>
element, as well as the
- <a href="{@docRoot}guide/topics/manifest/grant-uri-permission-element.html">{@code
- &lt;grant-uri-permission&gt;}</a> child element of the
- <a href="{@docRoot}guide/topics/manifest/provider-element.html">{@code &lt;provider&gt;}</a>
+<code><a href="{@docRoot}guide/topics/manifest/grant-uri-permission-element.html">&lt;grant-uri-permission&gt;</a></code>
+ child element of the
+<code><a href="{@docRoot}guide/topics/manifest/provider-element.html">&lt;provider&gt;</a></code>
element. The URI permissions mechanism is explained in more detail in the
<a href="{@docRoot}guide/topics/security/security.html">Security and Permissions</a> guide,
in the section "URI Permissions".
@@ -1053,7 +1036,7 @@ mRowsDeleted = getContentResolver().delete(
Your application sends an intent containing the action
{@link android.content.Intent#ACTION_PICK} and the "contacts" MIME type
{@link android.provider.ContactsContract.RawContacts#CONTENT_ITEM_TYPE}, using the
- method {@link android.app.Activity#startActivityForResult(Intent, int)
+ method {@link android.app.Activity#startActivityForResult
startActivityForResult()}.
</li>
<li>
@@ -1063,7 +1046,7 @@ mRowsDeleted = getContentResolver().delete(
<li>
In the selection activity, the user selects a
contact to update. When this happens, the selection activity calls
- {@link android.app.Activity#setResult(int, Intent) setResult(resultcode, intent)}
+ {@link android.app.Activity#setResult setResult(resultcode, intent)}
to set up a intent to give back to your application. The intent contains the content URI
of the contact the user selected, and the "extras" flags
{@link android.content.Intent#FLAG_GRANT_READ_URI_PERMISSION}. These flags grant URI
@@ -1073,7 +1056,7 @@ mRowsDeleted = getContentResolver().delete(
</li>
<li>
Your activity returns to the foreground, and the system calls your activity's
- {@link android.app.Activity#onActivityResult(int, int, Intent) onActivityResult()}
+ {@link android.app.Activity#onActivityResult onActivityResult()}
method. This method receives the result intent created by the selection activity in
the People app.
</li>
diff --git a/docs/html/guide/topics/resources/providing-resources.jd b/docs/html/guide/topics/resources/providing-resources.jd
index b0d5d6f..b311b7f 100644
--- a/docs/html/guide/topics/resources/providing-resources.jd
+++ b/docs/html/guide/topics/resources/providing-resources.jd
@@ -329,6 +329,39 @@ your application for other languages.</p>
indicates the current locale.</p>
</td>
</tr>
+ <tr id="LayoutDirectionQualifier">
+ <td>Layout Direction</td>
+ <td><code>ldrtl</code><br/>
+ <code>ldltr</code><br/>
+ </td>
+ <td><p>The layout direction of your application. {@code ldrtl} means "layout-direction-right-to-left".
+ {@code ldltr} means "layout-direction-left-to-right" and is the default implicit value.
+ </p>
+ <p>This can apply to any resource such as layouts, drawables, or values.
+ </p>
+ <p>For example, if you want to provide some specific layout for the Arabic language and some
+ generic layout for any other "right-to-left" language (like Persian or Hebrew) then you would have:
+ </p>
+<pre class="classic no-pretty-print">
+res/
+ layout/ <span style="color:black">
+ main.xml </span>(Default layout)
+ layout-ar/ <span style="color:black">
+ main.xml </span>(Specific layout for Arabic)
+ layout-ldrtl/ <span style="color:black">
+ main.xml </span>(Any "right-to-left" language, except
+ for Arabic, because the "ar" language qualifier
+ has a higher precedence.)
+</pre>
+ <p class="note"><strong>Note:</strong> To enable right-to-left layout features
+ for your app, you must set <a
+ href="{@docRoot}guide/topics/manifest/application-element.html#supportsrtl">{@code
+ supportsRtl}</a> to {@code "true"} and set <a
+ href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target"
+ >{@code targetSdkVersion}</a> to 17 or higher.</p>
+ <p><em>Added in API level 17.</em></p>
+ </td>
+ </tr>
<tr id="SmallestScreenWidthQualifier">
<td>smallestWidth</td>
<td><code>sw&lt;N&gt;dp</code><br/><br/>
@@ -548,6 +581,10 @@ which indicates the current device orientation.</p>
no display</li>
</ul>
<p><em>Added in API level 8, television added in API 13.</em></p>
+ <p>For information about how your app can respond when the device is inserted into or
+ removed from a dock, read <a
+ href="{@docRoot}training/monitoring-device-state/docking-monitoring.html">Determining
+and Monitoring the Docking State and Type</a>.</p>
<p>This can change during the life of your application if the user places the device in a
dock. You can enable or disable some of these modes using {@link
android.app.UiModeManager}. See <a href="runtime-changes.html">Handling Runtime Changes</a> for
diff --git a/docs/html/guide/topics/resources/string-resource.jd b/docs/html/guide/topics/resources/string-resource.jd
index 5f5484e..da410a4 100644
--- a/docs/html/guide/topics/resources/string-resource.jd
+++ b/docs/html/guide/topics/resources/string-resource.jd
@@ -13,8 +13,7 @@ your application with strings:</p>
<dt><a href="#StringArray">String Array</a></dt>
<dd>XML resource that provides an array of strings.</dd>
<dt><a href="#Plurals">Quantity Strings (Plurals)</a></dt>
- <dd>XML resource that carries different strings for different quantities
- of the same word or phrase.</dd>
+ <dd>XML resource that carries different strings for pluralization.</dd>
</dl>
<p>All strings are capable of applying some styling markup and formatting arguments. For
@@ -231,10 +230,19 @@ so Android provides you with methods such as
{@link android.content.res.Resources#getQuantityString(int,int) getQuantityString()} to select
the appropriate resource for you.
-<p>Note that the selection is made based on grammatical necessity. A string for <code>zero</code>
-in English will be ignored even if the quantity is 0, because 0 isn't grammatically different
-from 2, or any other number except 1 ("zero books", "one book", "two books", and so on).
-Don't be misled either by the fact that, say, <code>two</code> sounds like it could only apply to
+<p>Although historically called "quantity strings" (and still called that in API), quantity
+strings should <i>only</i> be used for plurals. It would be a mistake to use quantity strings to
+implement something like Gmail's "Inbox" versus "Inbox (12)" when there are unread messages, for
+example. It might seem convenient to use quantity strings instead of an {@code if} statement,
+but it's important to note that some languages (such as Chinese) don't make these grammatical
+distinctions at all, so you'll always get the <code>other</code> string.
+
+<p>The selection of which string to use is made solely based on grammatical <i>necessity</i>.
+In English, a string for <code>zero</code> will be ignored even if the quantity is 0, because 0
+isn't grammatically different from 2, or any other number except 1 ("zero books", "one book",
+"two books", and so on).
+
+<p>Don't be misled either by the fact that, say, <code>two</code> sounds like it could only apply to
the quantity 2: a language may require that 2, 12, 102 (and so on) are all treated like one
another but differently to other quantities. Rely on your translator to know what distinctions
their language actually insists upon.
@@ -313,7 +321,7 @@ values, with non-exhaustive examples in parentheses:
<td>{@code one}</td><td>When the language requires special treatment of numbers like one (as with the number 1 in English and most other languages; in Russian, any number ending in 1 but not ending in 11 is in this class).</td>
</tr>
<tr>
- <td>{@code two}</td><td>When the language requires special treatment of numbers like two (as in Welsh).</td>
+ <td>{@code two}</td><td>When the language requires special treatment of numbers like two (as with 2 in Welsh, or 102 in Slovenian).</td>
</tr>
<tr>
<td>{@code few}</td><td>When the language requires special treatment of "small" numbers (as with 2, 3, and 4 in Czech; or numbers ending 2, 3, or 4 but not 12, 13, or 14 in Polish).</td>
@@ -322,7 +330,7 @@ values, with non-exhaustive examples in parentheses:
<td>{@code many}</td><td>When the language requires special treatment of "large" numbers (as with numbers ending 11-99 in Maltese).</td>
</tr>
<tr>
- <td>{@code other}</td><td>When the language does not require special treatment of the given quantity.</td>
+ <td>{@code other}</td><td>When the language does not require special treatment of the given quantity (as with all numbers in Chinese, or 42 in English).</td>
</tr>
</table>
</dd>
diff --git a/docs/html/guide/topics/ui/accessibility/apps.jd b/docs/html/guide/topics/ui/accessibility/apps.jd
index d23512b..13b4538 100644
--- a/docs/html/guide/topics/ui/accessibility/apps.jd
+++ b/docs/html/guide/topics/ui/accessibility/apps.jd
@@ -21,14 +21,11 @@ parent.link=index.html
<li><a href="#accessibility-methods">Implementing accessibility API methods</a></li>
<li><a href="#send-events">Sending accessibility events</a></li>
<li><a href="#populate-events">Populating accessibility events</a></li>
+ <li><a href="#virtual-hierarchy">Providing a customized accessibility context</a></li>
+ <li><a href="#custom-touch-events">Handling custom touch events</a></li>
</ol>
</li>
- <li><a href="#test">Testing Accessibility</a>
- <ol>
- <li><a href="#test-audibles">Testing audible feedback</a></li>
- <li><a href="#test-navigation">Testing focus navigation</a></li>
- </ol>
- </li>
+ <li><a href="#test">Testing Accessibility</a></li>
</ol>
<h2>Key classes</h2>
@@ -42,60 +39,79 @@ parent.link=index.html
<h2>See also</h2>
<ol>
- <li><a href="{@docRoot}training/accessibility/index.html">Implementing Accessibility</a></li>
- <li><a href="{@docRoot}training/design-navigation/index.html">Designing Effective Navigation</a>
- </li>
- <li><a href="{@docRoot}design/index.html">Android Design</a></li>
+ <li><a href="checklist.html">Accessibility Developer Checklist</a><li>
+ <li><a href="{@docRoot}tools/testing/testing_accessibility.html">Accessibility Testing Checklist</a><li>
+ <li><a href="{@docRoot}design/patterns/accessibility.html">Android Design: Accessibility</a></li>
+ <li><a href="{@docRoot}training/design-navigation/index.html">Designing Effective Navigation</a></li>
+ <li><a href="{@docRoot}training/accessibility/index.html">Training: Implementing Accessibility</a></li>
</ol>
</div>
</div>
-<p>Applications built for Android are accessible to users with visual, physical or age-related
-disabilities when they activate accessibility features and services on a device. By default,
-these services make your application more accessible. However, there are further steps you should
-take to optimize the accessibility of your application and ensure a pleasant experience for all your
-users.</p>
+<p>Applications built for Android are more accessible to users with visual, physical or age-related
+limitations when those users activate accessibility services and features on a device. These
+services make your application more accessible even if you do not make any accessibility changes
+to your code. However, there are steps you should take to optimize the accessibility of your
+application and ensure a pleasant experience for all your users.</p>
-<p>Making sure your application is accessible to all users is relatively easy, particularly when you
-use framework-provided user interface components. If you only use these standard components for your
-application, there are just a few steps required to ensure your application is accessible:</p>
+<p>Making sure your application is accessible to all users requires only a few steps, particularly
+when you create your user interface with the components provided by the Android framework. If you
+use only the standard components for your application, the steps are:</p>
<ol>
- <li>Label your {@link android.widget.ImageButton}, {@link android.widget.ImageView}, {@link
-android.widget.EditText}, {@link android.widget.CheckBox} and other user interface controls using
-the <a href="{@docRoot}reference/android/view/View.html#attr_android:contentDescription">
- {@code android:contentDescription}</a> attribute.</li>
- <li>Make all of your user interface elements accessible with a directional controller,
- such as a trackball or D-pad.</li>
- <li>Test your application by turning on accessibility services like TalkBack and Explore by
- Touch, and try using your application using only directional controls.</li>
+ <li>Add descriptive text to user interface controls in your application using the
+ <a href="{@docRoot}reference/android/view/View.html#attr_android:contentDescription">
+ {@code android:contentDescription}</a> attribute. Pay particular attention to
+ {@link android.widget.ImageButton}, {@link android.widget.ImageView}
+ and {@link android.widget.CheckBox}.</li>
+ <li>Make sure that all user interface elements that can accept input (touches or typing) can be
+ reached with a directional controller, such as a trackball, D-pad (physical or virtual) or
+ navigation <a href="http://support.google.com/android/bin/topic.py?hl=en&topic=2492346">gestures
+ </a>.</li>
+ <li>Make sure that audio prompts are always accompanied by another visual prompt or notification,
+ to assist users who are deaf or hard of hearing.</li>
+ <li>Test your application using only accessibility navigation services and features. Turn on
+ <a href="{@docRoot}tools/testing/testing_accessibility.html#testing-talkback">TalkBack</a> and
+ <a href="{@docRoot}tools/testing/testing_accessibility.html#testing-ebt">Explore by Touch</a>,
+ and then try using your application using only directional controls. For more information on
+ testing for accessibility, see the <a href="{@docRoot}tools/testing/testing_accessibility.html">
+ Accessibility Testing Checklist</a>.</li>
</ol>
-<p>Developers who create custom controls that extend from the {@link android.view.View} class have
-some additional responsibilities for making sure their components are accessible for users. This
-document also discusses how to make custom view controls compatible with accessibility services.</p>
+<p>If you build custom controls that extend the {@link android.view.View} class, you must complete
+some additional work to make sure your components are accessible. This document discusses how to
+make custom view controls compatible with accessibility services.</p>
+<p class="note">
+<strong>Note:</strong> The implementation steps in this document describe the requirements for
+making your application accessible for users with blindness or low-vision. Be sure to review the
+requirements for serving users who are deaf and hard of hearing in the
+<a href="{@docRoot}guide/topics/ui/accessibility/checklist.html">Accessibility Developer
+Checklist</a></p>.
-<h2 id="label-ui">Labeling User Interface Elements</h2>
-<p>Many user interface controls rely on visual cues to inform users of their meaning. For
-example, a note-taking application might use an {@link android.widget.ImageButton} with a
-picture of a plus sign to indicate that the user can add a new note. Or, an {@link
-android.widget.EditText} component may have a label near it that indicates its purpose. When a user
-with impaired vision accesses your application, these visual cues are often useless.</p>
-<p>To provide textual information about interface controls (as an alternative to the visual cues),
-use the <a href="{@docRoot}reference/android/view/View.html#attr_android:contentDescription">
-{@code android:contentDescription}</a> attribute. The text you provide in this attribute is not
-visible on the screen, but if a user has enabled accessibility services that provide audible
-prompts, then the description in this attribute is read aloud to the user.</p>
+<h2 id="label-ui">Labeling User Interface Elements</h2>
-<p>Set the <a href="{@docRoot}reference/android/view/View.html#attr_android:contentDescription">
+<p>Many user interface controls depend on visual cues to indicate their meaning and usage. For
+example, a note-taking application might use an {@link android.widget.ImageButton} with a
+picture of a plus sign to indicate that the user can add a new note. An {@link
+android.widget.EditText} component may have a label near it that indicates its purpose. A user
+with impaired vision can't see these cues well enough to follow them, which makes them useless.</p>
+
+<p>You can make these controls more accessible with the
+<a href="{@docRoot}reference/android/view/View.html#attr_android:contentDescription">
+{@code android:contentDescription}</a> XML layout attribute. The text in this attribute does not
+appear on screen, but if the user enables accessibility services that provide audible prompts, then
+when the user navigates to that control, the text is spoken.</p>
+
+<p>For this reason, set the
+<a href="{@docRoot}reference/android/view/View.html#attr_android:contentDescription">
{@code android:contentDescription}</a> attribute for every {@link android.widget.ImageButton},
-{@link android.widget.ImageView}, {@link android.widget.EditText}, {@link android.widget.CheckBox}
-in your application's user interface, and on any other input controls that might require additional
-information for users who are not able to see it.</p>
+{@link android.widget.ImageView}, {@link android.widget.CheckBox}
+in your application's user interface, and add descriptions to any other input controls that might
+require additional information for users who are not able to see it.</p>
<p>For example, the following {@link android.widget.ImageButton} sets the content description for
the plus button to the {@code add_note} string resource, which could be defined as “Add note" for an
@@ -108,32 +124,38 @@ English language interface:</p>
android:contentDescription=”@string/add_note”/&gt;
</pre>
-<p>By including the description, speech-based accessibility services can announce "Add note" when a
-user moves focus to this button or hovers over it.</p>
+<p>By including the description, an accessibility service that provides spoken feedback can announce
+"Add note" when a user moves focus to this button or hovers over it.</p>
<p class="note"><strong>Note:</strong> For {@link android.widget.EditText} fields, provide an
<a href="{@docRoot}reference/android/widget/TextView.html#attr_android:hint">android:hint</a>
-attribute to help users understand what content is expected.</p>
+attribute <em>instead</em> of a content description, to help users understand what content is
+expected when the text field is empty. When the field is filled, TalkBack reads the entered
+content to the user, instead of the hint text.</p>
+
<h2 id="focus-nav">Enabling Focus Navigation</h2>
<p>Focus navigation allows users with disabilities to step through user interface controls using a
-directional controller. Directional controllers can be physical, such as a clickable trackball,
-directional pad (D-pad) or arrow keys, tab key navigation with an attached keyboard or a software
-application, such as the
+directional controller. Directional controllers can be physical, such as a trackball, directional
+pad (D-pad) or arrow keys, or virtual, such as the
<a href="https://play.google.com/store/apps/details?id=com.googlecode.eyesfree.inputmethod.latin">
-Eyes-Free Keyboard</a>, that provides an on-screen directional control.</p>
+Eyes-Free Keyboard</a>, or the gestures navigation mode available in Android 4.1 and higher.
+Directional controllers are a primary means of navigation for many Android users.
+</p>
+
+<p>To ensure that users can navigate your application using only a directional controller, verify
+that all user interface (UI) input controls in your application can be reached and activated
+without using the touchscreen. You should also verify that clicking with the center button (or OK
+button) of a directional controller has the same effect as touching a control that already has
+focus. For information on testing directional controls, see
+<a href="{@docRoot}tools/testing/testing_accessibility.html#test-navigation">Testing
+focus navigation</a>.</p>
-<p>A directional controller is a primary means of navigation for many users.
-Verify that all user interface (UI) controls in your application are accessible
-without using the touchscreen and that clicking with the center button (or OK button) of a
-directional controller has the same effect as touching the controls on the touchscreen. For
-information on testing directional controls, see <a href="#test-navigation">Testing focus
-navigation</a>.</p>
<h3 id="focus-enable">Enabling view focus</h3>
-<p>A user interface element is accessible using directional controls when its
+<p>A user interface element is reachable using directional controls when its
<a href="{@docRoot}reference/android/view/View.html#attr_android:focusable">
{@code android:focusable}</a> attribute is set to {@code true}. This setting allows users to focus
on the element using the directional controls and then interact with it. The user interface controls
@@ -149,44 +171,44 @@ and even request that a control be given focus:</p>
<li>{@link android.view.View#requestFocus requestFocus()}</li>
</ul>
-<p>When working with a view that is not focusable by default, you can make it focusable from the XML
-layout file by setting the
-<a href="{@docRoot}reference/android/view/View.html#attr_android:focusable">
-{@code android:focusable}</a> attribute to {@code true} or by using the {@link
+<p>If a view is not focusable by default, you can make it focusable in your layout file by setting
+the <a href="{@docRoot}reference/android/view/View.html#attr_android:focusable">
+{@code android:focusable}</a> attribute to {@code true} or by calling the its {@link
android.view.View#setFocusable setFocusable()} method.</p>
+
<h3 id="focus-order">Controlling focus order</h3>
<p>When users navigate in any direction using directional controls, focus is passed from one
-user interface element (View) to another, as determined by the focus ordering. The ordering of the
-focus movement is based on an algorithm that finds the nearest neighbor in a given direction. In
-rare cases, the default algorithm may not match the order that you intended for your UI. In these
-situations, you can provide explicit overrides to the ordering using the following XML attributes in
-the layout file:</p>
+user interface element (view) to another, as determined by the focus order. This order is based on
+an algorithm that finds the nearest neighbor in a given direction. In rare cases, the algorithm may
+not match the order that you intended or may not be logical for users. In these situations, you can
+provide explicit overrides to the ordering using the following XML attributes in your layout file:
+</p>
<dl>
- <dt><a href="{@docRoot}reference/android/view/View.html#attr_android:nextFocusDown"
->{@code android:nextFocusDown}</a></dt>
- <dd>Defines the next view to receive focus when the user navigates down.</dd>
- <a><a href="{@docRoot}reference/android/view/View.html#attr_android:nextFocusLeft"
->{@code android:nextFocusLeft}</a></dt>
- <dd>Defines the next view to receive focus when the user navigates left.</dd>
- <dt><a href="{@docRoot}reference/android/view/View.html#attr_android:nextFocusRight"
->{@code android:nextFocusRight}</a></dt>
- <dd>Defines the next view to receive focus when the user navigates right.</dd>
- <dt><a href="{@docRoot}reference/android/view/View.html#attr_android:nextFocusUp"
->{@code android:nextFocusUp}</a></dt>
- <dd>Defines the next view to receive focus when the user navigates up.</dd>
+ <dt><a href="{@docRoot}reference/android/view/View.html#attr_android:nextFocusDown">
+ {@code android:nextFocusDown}</a></dt>
+ <dd>Defines the next view to receive focus when the user navigates down.</dd>
+ <dt><a href="{@docRoot}reference/android/view/View.html#attr_android:nextFocusLeft">
+ {@code android:nextFocusLeft}</a></dt>
+ <dd>Defines the next view to receive focus when the user navigates left.</dd>
+ <dt><a href="{@docRoot}reference/android/view/View.html#attr_android:nextFocusRight">
+ {@code android:nextFocusRight}</a></dt>
+ <dd>Defines the next view to receive focus when the user navigates right.</dd>
+ <dt><a href="{@docRoot}reference/android/view/View.html#attr_android:nextFocusUp">
+ {@code android:nextFocusUp}</a></dt>
+ <dd>Defines the next view to receive focus when the user navigates up.</dd>
</dl>
-<p>The following example XML layout shows two focusable user interface elements where the <a
-href="{@docRoot}reference/android/view/View.html#attr_android:nextFocusDown"
->{@code android:nextFocusDown}</a> and <a
-href="{@docRoot}reference/android/view/View.html#attr_android:nextFocusUp"
->{@code android:nextFocusUp}</a> attributes have been explicitly set. The {@link android.widget.TextView} is
+<p>The following example XML layout shows two focusable user interface elements where the
+<a href="{@docRoot}reference/android/view/View.html#attr_android:nextFocusDown">{@code
+android:nextFocusDown}</a> and
+<a href="{@docRoot}reference/android/view/View.html#attr_android:nextFocusUp">{@code
+android:nextFocusUp}</a> attributes have been explicitly set. The {@link android.widget.TextView} is
located to the right of the {@link android.widget.EditText}. However, since these properties have
been set, the {@link android.widget.TextView} element can now be reached by pressing the down arrow
-when focus is on the {@link android.widget.EditText} element: </p>
+when focus is on the {@link android.widget.EditText} element:</p>
<pre>
&lt;LinearLayout android:orientation="horizontal"
@@ -218,8 +240,9 @@ These are the main tasks for ensuring the accessibility of your view:</p>
<ul>
<li>Handle directional controller clicks</li>
- <li>Implement Accessibility API methods</li>
- <li>Send {@link android.view.accessibility.AccessibilityEvent} objects specific to your custom view</li>
+ <li>Implement accessibility API methods</li>
+ <li>Send {@link android.view.accessibility.AccessibilityEvent} objects specific to your custom
+ view</li>
<li>Populate {@link android.view.accessibility.AccessibilityEvent} and {@link
android.view.accessibility.AccessibilityNodeInfo} for your view</li>
</ul>
@@ -243,9 +266,9 @@ full keyboard much easier for users.</p>
<p>Accessibility events are messages about users interaction with visual interface components in
your application. These messages are handled by <a href="services.html">Accessibility Services</a>,
-which use the information in these events to produce supplemental feedback and prompts when users
-have enabled accessibility services. As of Android 4.0 (API Level 14) and higher, the methods for
-generating accessibility events have been expanded to provide more detailed information beyond the
+which use the information in these events to produce supplemental feedback and prompts. In
+Android 4.0 (API Level 14) and higher, the methods for
+generating accessibility events have been expanded to provide more detailed information than the
{@link android.view.accessibility.AccessibilityEventSource} interface introduced in Android 1.6 (API
Level 4). The expanded accessibility methods are part of the {@link android.view.View} class as well
as the {@link android.view.View.AccessibilityDelegate} class. The methods are as follows:</p>
@@ -262,12 +285,12 @@ sendAccessibilityEventUnchecked()}</dt>
<dd>(API Level 4) This method is used when the calling code needs to directly control the check
for accessibility being enabled on the device ({@link
android.view.accessibility.AccessibilityManager#isEnabled AccessibilityManager.isEnabled()}). If
-you do implement this method, you must assume that the calling method has already checked that
-accessibility is enabled and the result is {@code true}. You typically do not need to implement this
-method for a custom view.</dd>
+you do implement this method, you must perform the call as if accessibility is enabled, regardless
+of the actual system setting. You typically do not need to implement this method for a custom view.
+</dd>
<dt>{@link android.view.View#dispatchPopulateAccessibilityEvent
-dispatchPopulateAccessibilityEvent()} </dt>
+dispatchPopulateAccessibilityEvent()}</dt>
<dd>(API Level 4) The system calls this method when your custom view generates an
accessibility event. As of API Level 14, the default implementation of this method calls {@link
android.view.View#onPopulateAccessibilityEvent onPopulateAccessibilityEvent()} for this view and
@@ -276,21 +299,21 @@ dispatchPopulateAccessibilityEvent()} method for each child of this view. In ord
accessibility services on revisions of Android <em>prior</em> to 4.0 (API Level 14) you
<em>must</em> override this method and populate {@link
android.view.accessibility.AccessibilityEvent#getText} with descriptive text for your custom
-view.</dd>
+view, which is spoken by accessibility services, such as TalkBack.</dd>
<dt>{@link android.view.View#onPopulateAccessibilityEvent onPopulateAccessibilityEvent()}</dt>
- <dd>(API Level 14) This method sets the text output of an {@link
+ <dd>(API Level 14) This method sets the spoken text prompt of the {@link
android.view.accessibility.AccessibilityEvent} for your view. This method is also called if the
view is a child of a view which generates an accessibility event.
<p class="note"><strong>Note:</strong> Modifying additional attributes beyond the text within
-this method potentially overwrites properties set by other methods. So, while you are able modify
+this method potentially overwrites properties set by other methods. While you can modify
attributes of the accessibility event with this method, you should limit these changes
-to text content only and use the {@link android.view.View#onInitializeAccessibilityEvent
+to text content, and use the {@link android.view.View#onInitializeAccessibilityEvent
onInitializeAccessibilityEvent()} method to modify other properties of the event.</p>
- <p class="note"><strong>Note:</strong> If your implementation of this event calls for completely
-overiding the output text without allowing other parts of your layout to modify its content, then
+ <p class="note"><strong>Note:</strong> If your implementation of this event completely
+overrides the output text without allowing other parts of your layout to modify its content, then
do not call the super implementation of this method in your code.</p>
</dd>
@@ -306,7 +329,7 @@ that have not been set by the super class.</dd>
<dt>{@link android.view.View#onInitializeAccessibilityNodeInfo
onInitializeAccessibilityNodeInfo()}</dt>
<dd>(API Level 14) This method provides accessibility services with information about the state of
-the view. The default {@link android.view.View} implementation sets a standard set of view
+the view. The default {@link android.view.View} implementation has a standard set of view
properties, but if your custom view provides interactive control beyond a simple {@link
android.widget.TextView} or {@link android.widget.Button}, you should override this method and set
the additional information about your view into the {@link
@@ -315,7 +338,7 @@ android.view.accessibility.AccessibilityNodeInfo} object handled by this method.
<dt>{@link android.view.ViewGroup#onRequestSendAccessibilityEvent
onRequestSendAccessibilityEvent()}</dt>
<dd>(API Level 14) The system calls this method when a child of your view has generated an
-{@link android.view.accessibility.AccessibilityEvent}. This step allows the the parent view to amend
+{@link android.view.accessibility.AccessibilityEvent}. This step allows the parent view to amend
the accessibility event with additional information. You should implement this method only if your
custom view can have child views and if the parent view can provide context information to the
accessibility event that would be useful to accessibility services.</dd>
@@ -333,7 +356,7 @@ higher, to your project. Then, within your custom view class, call the
{@link android.support.v4.view.ViewCompat#setAccessibilityDelegate
ViewCompat.setAccessibilityDelegate()} method to implement the accessibility methods
above. For an example of this approach, see the Android Support Library (revision 5 or higher)
-sample {@code AccessibilityDelegateSupportActivity} in
+sample {@code AccessibilityDelegateSupportActivity} in
({@code &lt;sdk&gt;/extras/android/support/v4/samples/Support4Demos/})
</li>
</ul>
@@ -446,20 +469,20 @@ public void dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
}
</pre>
-<p>On Android 4.0 (API Level 14) and higher, the {@link
+<p>For Android 4.0 (API Level 14) and higher, use the {@link
android.view.View#onPopulateAccessibilityEvent onPopulateAccessibilityEvent()} and
{@link android.view.View#onInitializeAccessibilityEvent onInitializeAccessibilityEvent()}
-methods are the recommended way to populate or modify the information in an {@link
-android.view.accessibility.AccessibilityEvent}. Use the
+methods to populate or modify the information in an {@link
+android.view.accessibility.AccessibilityEvent}. Use the
{@link android.view.View#onPopulateAccessibilityEvent onPopulateAccessibilityEvent()} method
specifically for adding or modifying the text content of the event, which is turned into audible
prompts by accessibility services such as TalkBack. Use the
{@link android.view.View#onInitializeAccessibilityEvent onInitializeAccessibilityEvent()} method for
populating additional information about the event, such as the selection state of the view.</p>
-<p>In addition, you should also implement the
+<p>In addition, implement the
{@link android.view.View#onInitializeAccessibilityNodeInfo onInitializeAccessibilityNodeInfo()}
-method. {@link android.view.accessibility.AccessibilityNodeInfo} objects populated by this method
+method. The {@link android.view.accessibility.AccessibilityNodeInfo} objects populated by this method
are used by accessibility services to investigate the view hierarchy that generated an accessibility
event after receiving that event, to obtain a more detailed context information and provide
appropriate feedback to users.</p>
@@ -467,8 +490,8 @@ appropriate feedback to users.</p>
<p>The example code below shows how override these three methods by using
{@link android.support.v4.view.ViewCompat#setAccessibilityDelegate
ViewCompat.setAccessibilityDelegate()}. Note that this sample code requires that the Android
-<a href="{@docRoot}tools/extras/support-library.html">Support Library</a> for API Level 4 (revision 5
-or higher) is added to your project.</p>
+<a href="{@docRoot}tools/extras/support-library.html">Support Library</a> for API Level 4 (revision
+5 or higher) is added to your project.</p>
<pre>
ViewCompat.setAccessibilityDelegate(new AccessibilityDelegateCompat() {
@@ -509,10 +532,10 @@ ViewCompat.setAccessibilityDelegate(new AccessibilityDelegateCompat() {
}
</pre>
-<p>On applications targeting Android 4.0 (API Level 14) and higher, these methods can be implemented
+<p>In applications targeting Android 4.0 (API Level 14) and higher, you can implement these methods
directly in your custom view class. For another example of this approach, see the Android
-<a href="{@docRoot}tools/extras/support-library.html">Support Library</a> (revision 5 or higher) sample
-{@code AccessibilityDelegateSupportActivity} in
+<a href="{@docRoot}tools/extras/support-library.html">Support Library</a> (revision 5 or higher)
+sample {@code AccessibilityDelegateSupportActivity} in
({@code &lt;sdk&gt;/extras/android/support/v4/samples/Support4Demos/}).</p>
<p class="note"><strong>Note:</strong> You may find information on implementing accessibility for
@@ -525,50 +548,141 @@ approach is to use the
methods.</p>
-<h2 id="test">Testing Accessibility</h2>
+<h3 id="virtual-hierarchy">Providing a customized accessibility context</h3>
+
+<p>In Android 4.0 (API Level 14), the framework was enhanced to allow accessibility services to
+ inspect the containing view hierarchy of a user interface component that generates an
+ accessibility event. This enhancement allows accessibility services to provide a much richer set
+ of contextual information with which to aid users.</p>
+
+<p>There are some cases where accessibility services cannot get adequate information
+ from the view hierarchy. An example of this is a custom interface control that has two or more
+ separately clickable areas, such as a calendar control. In this case, the services cannot get
+ adequate information because the clickable subsections are not part of the view hierarchy.</p>
+
+<img src="calendar.png" alt="" id="figure1" />
+<p class="img-caption">
+ <strong>Figure 1.</strong> A custom calendar view with selectable day elements.
+</p>
+
+<p>In the example shown in Figure 1, the entire calendar is implemented as a single view, so if you
+ do not do anything else, accessibility services do not receive enough information about the
+ content of the view and the user's selection within the view. For example, if a user clicks on the
+ day containing <strong>17</strong>, the accessibility framework only receives the description
+ information for the whole calendar control. In this case, the TalkBack accessibility service would
+ simply announce "Calendar" or, only slightly better, "April Calendar" and the user would be left
+ to wonder what day was selected.</p>
+
+<p>To provide adequate context information for accessibility services in situations like this,
+ the framework provides a way to specify a virtual view hierarchy. A <em>virtual view
+ hierarchy</em> is a way for application developers to provide a complementary view hierarchy
+ to accessibility services that more closely matches the actual information on screen. This
+ approach allows accessibility services to provide more useful context information to users.</p>
+
+<p>Another situation where a virtual view hierarchy may be needed is a user interface containing
+ a set of controls (views) that have closely related functions, where an action on one control
+ affects the contents of one or more elements, such as a number picker with separate up and down
+ buttons. In this case, accessibility services cannot get adequate information because action on
+ one control changes content in another and the relationship of those controls may not be apparent
+ to the service. To handle this situation, group the related controls with a containing view and
+ provide a virtual view hierarchy from this container to clearly represent the information and
+ behavior provided by the controls.</p>
+
+<p>In order to provide a virtual view hierarchy for a view, override the {@link
+ android.view.View#getAccessibilityNodeProvider} method in your custom view or view group and
+ return an implementation of {@link android.view.accessibility.AccessibilityNodeProvider}. For an
+ example implementation of this accessibility feature, see
+ {@code AccessibilityNodeProviderActivity} in the ApiDemos sample project. You can implement a
+ virtual view hierarchy that is compatible with Android 1.6 and later by using the
+ <a href="{@docRoot}tools/extras/support-library.html">Support Library</a> with the
+ {@link android.support.v4.view.ViewCompat#getAccessibilityNodeProvider
+ ViewCompat.getAccessibilityNodeProvider()} method and providing an implementation with
+ {@link android.support.v4.view.accessibility.AccessibilityNodeProviderCompat}.</p>
+
+
+<h3 id="custom-touch-events">Handling custom touch events</h3>
+
+<p>Custom view controls may require non-standard touch event behavior. For example, a custom
+control may use the {@link android.view.View#onTouchEvent} listener method to detect the
+{@link android.view.MotionEvent#ACTION_DOWN} and {@link android.view.MotionEvent#ACTION_UP} events
+and trigger a special click event. In order to maintain compatibility with accessibility services,
+the code that handles this custom click event must do the following:</p>
-<p>Testing the accessibility of your application is an important part of ensuring your users have a
-great experience. You can test the most important parts of accessibility by testing your application
-with audible feedback enabled and testing navigation within your application using directional
-controls.</p>
-
-<h3 id="test-audibles">Testing audible feedback</h3>
-<p>You can simulate the experience for many users by enabling an accessibility service that speaks
-as you move around the screen. The Explore by Touch accessibility service, which is available on
-devices with Android 4.0 and later. The <a
-href="https://play.google.com/store/apps/details?id=com.google.android.marvin.talkback">TalkBack</a>
-accessibility service, by the <a href="http://code.google.com/p/eyes-free/">Eyes-Free
-Project</a> comes preinstalled on many Android devices.</p>
-
-<p>To enable TalkBack on revisions of Android prior to Android 4.0:</p>
<ol>
- <li>Launch the Settings application.</li>
- <li>Navigate to the <strong>Accessibility</strong> category and select it.</li>
- <li>Select <strong>Accessibility</strong> to enable it.</li>
- <li>Select <strong>TalkBack</strong> to enable it.</li>
+ <li>Generate an appropriate {@link android.view.accessibility.AccessibilityEvent} for the
+ interpreted click action.</li>
+ <li>Enable accessibility services to perform the custom click action for users who are not able to
+ use a touch screen.</li>
</ol>
-<p class="note"><strong>Note:</strong> If the TalkBack accessibility service is not available, you
-can install it for free from <a href="http://play.google.com">Google Play</a>.</p>
+<p>To handle these requirements in an efficient way, your code should override the
+{@link android.view.View#performClick} method, which must call the super implementation of this
+method and then execute whatever actions are required by the click event. When the custom click
+action is detected, that code should then call your {@code performClick()} method. The following
+code example demonstrates this pattern.</p>
-<p>To enable Explore by Touch on Android 4.0 and later:</p>
-<ol>
- <li>Launch the Settings application.</li>
- <li>Navigate to the <strong>Accessibility</strong> category and select it.</li>
- <li>Select the <strong>TalkBack</strong> to enable it.</li>
- <li>Return to the <strong>Accessibility</strong> category and select <strong>Explore by
-Touch</strong> to enable it.
- <p class="note"><strong>Note:</strong> You must turn on TalkBack <em>first</em>, otherwise this
-option is not available.</p>
- </li>
-</ol>
+<pre>
+class CustomTouchView extends View {
-<h3 id="test-navigation">Testing focus navigation</h3>
+ public CustomTouchView(Context context) {
+ super(context);
+ }
+
+ boolean mDownTouch = false;
+
+ &#64;Override
+ public boolean onTouchEvent(MotionEvent event) {
+ super.onTouchEvent(event);
+
+ // Listening for the down and up touch events
+ switch (event.getAction()) {
+ case MotionEvent.ACTION_DOWN:
+ mDownTouch = true;
+ return true;
+
+ case MotionEvent.ACTION_UP:
+ if (mDownTouch) {
+ mDownTouch = false;
+ performClick(); // Call this method to handle the response, and
+ // thereby enable accessibility services to
+ // perform this action for a user who cannot
+ // click the touchscreen.
+ return true;
+ }
+ }
+ return false; // Return false for other touch events
+ }
+
+ &#64;Override
+ public boolean performClick() {
+ // Calls the super implementation, which generates an AccessibilityEvent
+ // and calls the onClick() listener on the view, if any
+ super.performClick();
+
+ // Handle the action for the custom click here
+
+ return true;
+ }
+}
+</pre>
+
+<p>The pattern shown above makes sure that the custom click event is compatible with
+accessibility services by using the {@link android.view.View#performClick} method to both generate
+an accessibility event and provide an entry point for accessibility services to act on behalf of a
+user to perform this custom click event.</p>
+
+<p class="note"><strong>Note:</strong> If your custom view has distinct clickable regions, such as
+a custom calendar view, you must implement a <a href="#virtual-hierarchy">virtual view
+hierarchy</a> by overriding {@link android.view.View#getAccessibilityNodeProvider} in your custom
+view in order to be compatible with accessibility services.</p>
+
+
+<h2 id="test">Testing Accessibility</h2>
+
+<p>Testing the accessibility of your application is an important part of ensuring your users have a
+great experience. You can test the most important accessibility features by using your application
+with audible feedback enabled and navigating within your application using only directional
+controls. For more information on testing accessibility in your application, see the
+<a href="{@docRoot}tools/testing/testing_accessibility.html">Accessibility Testing Checklist</a>.
+</p>
-<p>As part of your accessibility testing, you can test navigation of your application using focus,
-even if your test devices does not have a directional controller. The <a
-href="{@docRoot}tools/help/emulator.html">Android Emulator</a> provides a
-simulated directional controller that you can easily use to test navigation. You can also use a
-software-based directional controller, such as the one provided by the
-<a href="https://play.google.com/store/apps/details?id=com.googlecode.eyesfree.inputmethod.latin">
-Eyes-Free Keyboard</a> to simulate use of a D-pad.</p>
diff --git a/docs/html/guide/topics/ui/accessibility/calendar.png b/docs/html/guide/topics/ui/accessibility/calendar.png
new file mode 100644
index 0000000..ca5c44f
--- /dev/null
+++ b/docs/html/guide/topics/ui/accessibility/calendar.png
Binary files differ
diff --git a/docs/html/guide/topics/ui/accessibility/checklist.jd b/docs/html/guide/topics/ui/accessibility/checklist.jd
new file mode 100644
index 0000000..9473d1b
--- /dev/null
+++ b/docs/html/guide/topics/ui/accessibility/checklist.jd
@@ -0,0 +1,173 @@
+page.title=Accessibility Developer Checklist
+parent.title=Accessibility
+parent.link=index.html
+@jd:body
+
+<div id="qv-wrapper">
+<div id="qv">
+
+ <h2>In this document</h2>
+ <ol>
+ <li><a href="#requirements">Accessibility Requirements</a></li>
+ <li><a href="#recommendations">Accessibility Recommendations</a></li>
+ <li><a href="#special-cases">Special Cases and Considerations</a></li>
+ </ol>
+
+ <h2>See also</h2>
+ <ol>
+ <li><a href="{@docRoot}design/patterns/accessibility.html">Android Design: Accessibility</a></li>
+ <li><a href="{@docRoot}tools/testing/testing_accessibility.html">Accessibility Testing Checklist</a></li>
+ <li><a href="{@docRoot}training/accessibility/index.html">Training: Implementing Accessibility</a></li>
+ <li><a href="{@docRoot}training/design-navigation/index.html">Designing Effective Navigation</a></li>
+ </ol>
+
+</div>
+</div>
+
+<p>Making an application accessible is about a deep commitment to usability, getting the
+details right and delighting your users. This document provides a checklist of accessibility
+requirements, recommendations and considerations to help you make sure your application is
+accessible. Following this checklist does not guarantee your application is accessible, but it's a
+good place to start.</p>
+
+<p>Creating an accessible application is not just the responsibility of developers. Involve your
+design and testing folks as well, and make them are aware of the guidelines for these other stages
+of development:</p>
+
+<ul>
+ <li><a href="{@docRoot}design/patterns/accessibility.html">Android Design: Accessibility</a></li>
+ <li><a href="{@docRoot}tools/testing/testing_accessibility.html">Accessibility Testing
+ Checklist</a></li>
+</ul>
+
+<p>In most cases, creating an accessible Android application does not require extensive code
+restructuring. Rather, it means working through the subtle details of how users interact with your
+application, so you can provide them with feedback they can sense and understand. This checklist
+helps you focus on the key development issues to get the details of accessibility right.</p>
+
+
+<h2 id="requirements">Accessibility Requirements</h2>
+
+<p>The following steps must be completed in order to ensure a minimum level of application
+ accessibility.</p>
+
+<ol>
+ <li><strong>Describe user interface controls:</strong> Provide content
+ <a href="{@docRoot}guide/topics/ui/accessibility/apps.html#label-ui">descriptions</a> for user
+ interface components that do not have visible text, particularly
+ {@link android.widget.ImageButton}, {@link android.widget.ImageView}
+ and {@link android.widget.CheckBox} components. Use the
+ <a href="{@docRoot}reference/android/view/View.html#attr_android:contentDescription">
+ {@code android:contentDescription}</a> XML layout attribute or the {@link
+ android.view.View#setContentDescription} method to provide this information for accessibility
+ services. (Exception: <a href="#decorative">decorative graphics</a>)</li>
+ <li><strong>Enable focus-based navigation:</strong> Make sure
+ <a href="{@docRoot}guide/topics/ui/accessibility/apps.html#focus-nav">users can navigate</a>
+ your screen layouts using hardware-based or software directional controls (D-pads, trackballs,
+ keyboards and navigation gestures). In a few cases, you may need to make user interface components
+ <a href="{@docRoot}reference/android/view/View.html#attr_android:focusable">focusable</a>
+ or change the <a href="{@docRoot}guide/topics/ui/accessibility/apps.html#focus-order">focus
+ order</a> to be more logical for user actions.</li>
+ <li><strong>Custom view controls:</strong> If you build
+ <a href="{@docRoot}guide/topics/ui/custom-components.html">custom interface controls</a> for
+ your application, <a href="{@docRoot}guide/topics/ui/accessibility/apps.html#custom-views">
+ implement accessibility interfaces</a> for your custom views and provide content descriptions.
+ For custom controls that are intended to be compatible with versions of Android back to 1.6,
+ use the <a href="{@docRoot}tools/extras/support-library.html">Support Library</a> to implement
+ the latest accessibility features.</li>
+ <li><strong>No audio-only feedback:</strong> Audio feedback must always have a secondary
+ feedback mechanism to support users who are deaf or hard of hearing. For example, a sound alert
+ for the arrival of a message must be accompanied by a system
+ {@link android.app.Notification}, haptic feedback (if available) or other visual alert.</li>
+ <li><strong>Test:</strong> Test accessibility by navigating your application
+ using directional controls, and using eyes-free navigation with TalkBack enabled.
+ For more accessibility testing information, see the
+ <a href="{@docRoot}tools/testing/testing_accessibility.html">Accessibility Testing
+ Checklist</a>.</li>
+</ol>
+
+
+<h2 id="recommendations">Accessibility Recommendations</h2>
+
+<p>The following steps are recommended for ensuring the accessibility of your application. If you
+ do not take these actions, it may impact the overall accessibility and quality of your
+ application.</p>
+
+<ol>
+ <li><strong>Android Design Accessibility Guidelines:</strong> Before building your layouts,
+ review and follow the accessibility guidelines provided in the
+ <a href="{@docRoot}design/patterns/accessibility.html">Design guidelines</a>.</li>
+ <li><strong>Framework-provided controls:</strong> Use Android's built-in user interface
+ controls whenever possible, as these components provide accessibility support by default.</li>
+ <li><strong>Temporary or self-hiding controls and notifications:</strong> Avoid having user
+ interface controls that fade out or disappear after a certain amount of time. If this behavior
+ is important to your application, provide an alternative interface for these functions.</li>
+</ol>
+
+
+<h2 id="special-cases">Special Cases and Considerations</h2>
+
+<p>The following list describes specific situations where action should be taken to ensure an
+ accessible app. Review this list to see if any of these special cases and considerations apply to
+ your application, and take the appropriate action.</p>
+
+<ol>
+ <li><strong>Text field hints:</strong> For {@link android.widget.EditText} fields, provide an
+ <a href="{@docRoot}reference/android/widget/TextView.html#attr_android:hint">android:hint</a>
+ attribute <em>instead</em> of a content description, to help users understand what content is
+ expected when the text field is empty and allow the contents of the field to be spoken when
+ it is filled.</li>
+ <li><strong>Custom controls with high visual context:</strong> If your application contains a
+ <a href="{@docRoot}guide/topics/ui/custom-components.html">custom control</a> with a high degree
+ of visual context (such as a calendar control), default accessibility services processing may
+ not provide adequate descriptions for users, and you should consider providing a
+ <a href="{@docRoot}guide/topics/ui/accessibility/apps.html#virtual-hierarchy">virtual
+ view hierarchy</a> for your control using
+ {@link android.view.accessibility.AccessibilityNodeProvider}.</li>
+ <li><strong>Custom controls and click handling:</strong> If a custom control in your
+ application performs specific handling of user touch interaction, such as listening with
+ {@link android.view.View#onTouchEvent} for {@link android.view.MotionEvent#ACTION_DOWN
+ MotionEvent.ACTION_DOWN} and {@link android.view.MotionEvent#ACTION_UP MotionEvent.ACTION_UP}
+ and treating it as a click event, you must trigger an {@link
+ android.view.accessibility.AccessibilityEvent} equivalent to a click and provide a way for
+ accessibility services to perform this action for users. For more information, see
+ <a href="{@docRoot}guide/topics/ui/accessibility/apps.html#custom-touch-events">Handling custom
+ touch events</a>.</li>
+ <li><strong>Controls that change function:</strong> If you have buttons or other controls
+ that change function during the normal activity of a user in your application (for example, a
+ button that changes from <strong>Play</strong> to <strong>Pause</strong>), make sure you also
+ change the <a href="{@docRoot}reference/android/view/View.html#attr_android:contentDescription">
+ {@code android:contentDescription}</a> of the button appropriately.</li>
+ <li><strong>Prompts for related controls:</strong> Make sure sets of controls which provide a
+ single function, such as the {@link android.widget.DatePicker}, provide useful audio feedback
+ when an user interacts with the individual controls.</li>
+ <li><strong>Video playback and captioning:</strong> If your application provides video
+ playback, it must support captioning and subtitles to assist users who are deaf or hard of
+ hearing. Your video playback controls must also clearly indicate if captioning is available for
+ a video and provide a clear way of enabling captions.</li>
+ <li><strong>Supplemental accessibility audio feedback:</strong> Use only the Android accessibility
+ framework to provide accessibility audio feedback for your app. Accessibility services such as
+ <a href="https://play.google.com/store/apps/details?id=com.google.android.marvin.talkback"
+ >TalkBack</a> should be the only way your application provides accessibility audio prompts to
+ users. Provide the prompting information with a
+ <a href="{@docRoot}reference/android/view/View.html#attr_android:contentDescription">{@code
+ android:contentDescription}</a> XML layout attribute or dynamically add it using accessibility
+ framework APIs. For example, if your application takes action that you want to announce to a
+ user, such as automatically turning the page of a book, use the {@link
+ android.view.View#announceForAccessibility} method to have accessibility services speak this
+ information to the user.</li>
+ <li><strong>Custom controls with complex visual interactions:</strong> For custom controls that
+ provide complex or non-standard visual interactions, provide a
+ <a href="{@docRoot}guide/topics/ui/accessibility/apps.html#virtual-hierarchy">virtual view
+ hierarchy</a> for your control using {@link android.view.accessibility.AccessibilityNodeProvider}
+ that allows accessibility services to provide a simplified interaction model for the user. If
+ this approach is not feasible, consider providing an alternate view that is accessible.</li>
+ <li><strong>Sets of small controls:</strong> If you have controls that are smaller than
+ the minimum recommended touch size in your application screens, consider grouping these controls
+ together using a {@link android.view.ViewGroup} and providing a
+ <a href="{@docRoot}reference/android/view/View.html#attr_android:contentDescription">{@code
+ android:contentDescription}</a> for the group.</li>
+ <li id="decorative"><strong>Decorative images and graphics:</strong> Elements in application
+ screens that are purely decorative and do not provide any content or enable a user action should
+ not have accessibility content descriptions.</li>
+</ol>
diff --git a/docs/html/guide/topics/ui/accessibility/index.jd b/docs/html/guide/topics/ui/accessibility/index.jd
index 6fd71e2..6cdbde4 100644
--- a/docs/html/guide/topics/ui/accessibility/index.jd
+++ b/docs/html/guide/topics/ui/accessibility/index.jd
@@ -8,47 +8,67 @@ parent.link=../index.html
<h2>Topics</h2>
<ol>
- <li><a href="{@docRoot}guide/topics/ui/accessibility/apps.html">Making Applications Accessible</a>
- </li>
- <li><a href="{@docRoot}guide/topics/ui/accessibility/services.html">Building Accessibility
- Services</a></li>
+ <li><a href="apps.html">
+ Making Applications Accessible</a></li>
+ <li><a href="checklist.html">
+ Accessibility Developer Checklist</a></li>
+ <li><a href="services.html">
+ Building Accessibility Services</a></li>
</ol>
- <h2>Key classes</h2>
+ <h2>See also</h2>
<ol>
- <li>{@link android.view.accessibility.AccessibilityEvent}</li>
- <li>{@link android.accessibilityservice.AccessibilityService}</li>
+ <li><a href="{@docRoot}design/patterns/accessibility.html">Android Design: Accessibility</a></li>
+ <li><a href="{@docRoot}training/accessibility/index.html">Training: Implementing Accessibility</a></li>
+ <li><a href="{@docRoot}tools/testing/testing_accessibility.html">Accessibility Testing Checklist</a></li>
</ol>
-
- <h2>See also</h2>
+
+ <h2>Related Videos</h2>
<ol>
- <li><a href="{@docRoot}training/accessibility/index.html">Implementing Accessibility</a></li>
+ <li>
+ <iframe title="Google I/O 2012 - Making Android Apps Accessible"
+ width="210" height="160"
+ src="http://www.youtube.com/embed/q3HliaMjL38?rel=0&amp;hd=1"
+ frameborder="0" allowfullscreen>
+ </iframe>
+ <li>
</ol>
</div>
</div>
-<p>Many Android users have disabilities that require them to interact with their Android devices in
-different ways. These include users who have visual, physical or age-related disabilities that
-prevent them from fully seeing or using a touchscreen.</p>
+<p>Many Android users have different abilities that require them to interact with their Android
+devices in different ways. These include users who have visual, physical or age-related limitations
+that prevent them from fully seeing or using a touchscreen, and users with hearing loss who may not
+be able to perceive audible information and alerts.</p>
<p>Android provides accessibility features and services for helping these users navigate their
-devices more easily, including text-to-speech, haptic feedback, trackball and D-pad navigation that
-augment their experience. Android application developers can take advantage of these services to
-make their applications more accessible and also build their own accessibility services.</p>
+devices more easily, including text-to-speech, haptic feedback, gesture navigation, trackball and
+directional-pad navigation. Android application developers can take advantage of these services to
+make their applications more accessible.</p>
+
+<p>Android developers can also build their own accessibility services, which can provide
+enhanced usability features such as audio prompting, physical feedback, and alternative navigation
+modes. Accessibility services can provide these enhancements for all applications, a set of
+applications or just a single app.</p>
<p>The following topics show you how to use the Android framework to make applications more
accessible.</p>
<dl>
- <dt><strong><a href="{@docRoot}guide/topics/ui/accessibility/apps.html">Making Applications
-Accessible</a></strong>
+ <dt><strong><a href="{@docRoot}guide/topics/ui/accessibility/apps.html">
+ Making Applications Accessible</a></strong>
</dt>
<dd>Development practices and API features to ensure your application is accessible to users with
disabilities.</dd>
- <dt><strong><a href="{@docRoot}guide/topics/ui/accessibility/services.html">Building Accessibility
-Services</a></strong>
+ <dt><strong><a href="{@docRoot}guide/topics/ui/accessibility/checklist.html">
+ Accessibility Developer Checklist</a></strong>
+ </dt>
+ <dd>A checklist to help developers ensure that their applications are accessible.</dd>
+
+ <dt><strong><a href="{@docRoot}guide/topics/ui/accessibility/services.html">
+ Building Accessibility Services</a></strong>
</dt>
<dd>How to use API features to build services that make other applications more accessible for
users.</dd>
diff --git a/docs/html/guide/topics/ui/accessibility/services.jd b/docs/html/guide/topics/ui/accessibility/services.jd
index 7d36181..2a6fe7a 100644
--- a/docs/html/guide/topics/ui/accessibility/services.jd
+++ b/docs/html/guide/topics/ui/accessibility/services.jd
@@ -14,8 +14,16 @@ parent.link=index.html
<li><a href="#service-config">Accessibility service configuration</a></li>
</ol>
</li>
+ <li><a href="#register">Registering for Accessibility Events</a></li>
<li><a href="#methods">AccessibilityService Methods</a></li>
<li><a href="#event-details">Getting Event Details</a></li>
+ <li><a href="#act-for-users">Taking Action for Users</a>
+ <ol>
+ <li><a href="#detect-gestures">Listening for gestures</a></li>
+ <li><a href="#using-actions">Using accessibility actions</a></li>
+ <li><a href="#focus-types">Using focus types</a></li>
+ </ol>
+ </li>
<li><a href="#examples">Example Code</a></li>
</ol>
@@ -30,7 +38,7 @@ parent.link=index.html
<h2>See also</h2>
<ol>
- <li><a href="{@docRoot}training/accessibility/index.html">Implementing Accessibility</a></li>
+ <li><a href="{@docRoot}training/accessibility/index.html">Training: Implementing Accessibility</a></li>
</ol>
</div>
@@ -45,20 +53,20 @@ might need additional or alternative interface feedback.</p>
create and distribute their own services. This document explains the basics of building an
accessibility service.</p>
-<p>The ability for you to build and deploy accessibility services was introduced with Android
-1.6 (API Level 4) and received significant improvements with Android 4.0 (API Level 14). The Android
-Support Library was also updated with the release of Android 4.0 to provide support for these
-enhanced accessibility features back to Android 1.6. Developers aiming for widely compatible
-accessibility services are encouraged to use the
-<a href="{@docRoot}tools/extras/support-library.html">Support Library</a> and develop for the more
-advanced accessibility features introduced in Android 4.0.</p>
+<p>The ability for you to build and deploy accessibility services was introduced with Android 1.6
+ (API Level 4) and received significant improvements with Android 4.0 (API Level 14). The Android
+ <a href="{@docRoot}tools/extras/support-library.html">Support Library</a> was also updated with
+ the release of Android 4.0 to provide support for these enhanced accessibility features back to
+ Android 1.6. Developers aiming for widely compatible accessibility services are encouraged to use
+ the Support Library and develop for the more advanced accessibility features introduced in
+ Android 4.0.</p>
<h2 id="manifest">Manifest Declarations and Permissions</h2>
<p>Applications that provide accessibility services must include specific declarations in their
- application manifests in order to be treated as an accessibility service by an Android system.
- This section explains the required and optional settings for accessibility services.</p>
+ application manifests to be treated as an accessibility service by the Android system. This
+ section explains the required and optional settings for accessibility services.</p>
<h3 id="service-declaration">Accessibility service declaration</h3>
@@ -66,7 +74,9 @@ advanced accessibility features introduced in Android 4.0.</p>
<p>In order to be treated as an accessibility service, your application must include the
{@code service} element (rather than the {@code activity} element) within the {@code application}
element in its manifest. In addition, within the {@code service} element, you must also include an
-accessibility service intent filter, as shown in the following sample:</p>
+accessibility service intent filter. For compatiblity with Android 4.1 and higher, the manifest
+must also request the {@link android.Manifest.permission#BIND_ACCESSIBILITY_SERVICE} permission
+as shown in the following sample:</p>
<pre>
&lt;application&gt;
@@ -76,6 +86,7 @@ accessibility service intent filter, as shown in the following sample:</p>
&lt;action android:name=&quot;android.accessibilityservice.AccessibilityService&quot; /&gt;
&lt;/intent-filter&gt;
&lt;/service&gt;
+ &lt;uses-permission android:name="android.permission.BIND_ACCESSIBILITY_SERVICE" /&gt;
&lt;/application&gt;
</pre>
@@ -123,6 +134,26 @@ shows example contents for the service configuration file:</p>
/&gt;
</pre>
+<p>For more information about the XML attributes which can be used in the accessibility service
+ configuration file, follow these links to the reference documentation:</p>
+
+<ul>
+ <li><a href="{@docRoot}reference/android/R.styleable.html#AccessibilityService_description">{@code android:description}</a></li>
+ <li><a href="{@docRoot}reference/android/R.styleable.html#AccessibilityService_packageNames">{@code android:packageNames}</a></li>
+ <li><a href="{@docRoot}reference/android/R.styleable.html#AccessibilityService_accessibilityEventTypes">{@code android:accessibilityEventTypes}</a></li>
+ <li><a href="{@docRoot}reference/android/R.styleable.html#AccessibilityService_accessibilityFlags">{@code android:accessibilityFlags}</a></li>
+ <li><a href="{@docRoot}reference/android/R.styleable.html#AccessibilityService_accessibilityFeedbackType">{@code android:accessibilityFeedbackType}</a></li>
+ <li><a href="{@docRoot}reference/android/R.styleable.html#AccessibilityService_notificationTimeout">{@code android:notificationTimeout}</a></li>
+ <li><a href="{@docRoot}reference/android/R.styleable.html#AccessibilityService_canRetrieveWindowContent">{@code android:canRetrieveWindowContent}</a></li>
+ <li><a href="{@docRoot}reference/android/R.styleable.html#AccessibilityService_settingsActivity">{@code android:settingsActivity}</a></li>
+</ul>
+
+<p>For more information about which configuration settings can be dynamically set at runtime, see
+the {@link android.accessibilityservice.AccessibilityServiceInfo} reference documentation.</p>
+
+
+<h2 id="register">Registering for Accessibility Events</h2>
+
<p>One of the most important functions of the accessibility service configuration parameters is to
allow you to specify what types of accessibility events your service can handle. Being able to
specify this information enables accessibility services to cooperate with each other, and allows you
@@ -139,32 +170,27 @@ android.accessibilityservice.AccessibilityServiceInfo#packageNames
AccessibilityServiceInfo.packageNames} member.</li>
<li><strong>Event Types</strong> - Specify the types of accessibility events you want your service
to handle. This parameter can be set in the accessibility service configuration files with the
-{@code android:accessibilityEventTypes} attribute as a comma-separated list, or set using the
+{@code android:accessibilityEventTypes} attribute as a list separated by the {@code |} character
+(for example {@code accessibilityEventTypes="typeViewClicked|typeViewFocused"}), or set using the
{@link android.accessibilityservice.AccessibilityServiceInfo#eventTypes
AccessibilityServiceInfo.eventTypes} member. </li>
</ul>
-<p>For more information about the XML attributes which can be used in the accessibility service
- configuration file, follow these links to the reference documentation:</p>
+<p>When setting up your accessibility service, carefully consider what events your service is able
+to handle and only register for those events. Since users can activate more than one accessibility
+services at a time, your service must not consume events that it is not able to handle. Remember
+that other services may handle those events in order to improve a user's experience.</p>
-<ul>
- <li><a href="{@docRoot}reference/android/R.styleable.html#AccessibilityService_description">{@code android:description}</a></li>
- <li><a href="{@docRoot}reference/android/R.styleable.html#AccessibilityService_packageNames">{@code android:packageNames}</a></li>
- <li><a href="{@docRoot}reference/android/R.styleable.html#AccessibilityService_accessibilityEventTypes">{@code android:accessibilityEventTypes}</a></li>
- <li><a href="{@docRoot}reference/android/R.styleable.html#AccessibilityService_accessibilityFlags">{@code android:accessibilityFlags}</a></li>
- <li><a href="{@docRoot}reference/android/R.styleable.html#AccessibilityService_accessibilityFeedbackType">{@code android:accessibilityFeedbackType}</a></li>
- <li><a href="{@docRoot}reference/android/R.styleable.html#AccessibilityService_notificationTimeout">{@code android:notificationTimeout}</a></li>
- <li><a href="{@docRoot}reference/android/R.styleable.html#AccessibilityService_canRetrieveWindowContent">{@code android:canRetrieveWindowContent}</a></li>
- <li><a href="{@docRoot}reference/android/R.styleable.html#AccessibilityService_settingsActivity">{@code android:settingsActivity}</a></li>
-</ul>
-
-<p>For more information about which configuration settings can be dynamically set at runtime, see
-the {@link android.accessibilityservice.AccessibilityServiceInfo} reference documentation.</p>
+<p class="note"><strong>Note:</strong> The Android framework dispatches accessibility events to
+more than one accessibility service if the services provide different
+<a href="{@docRoot}reference/android/R.styleable.html#AccessibilityService_accessibilityFeedbackType">
+feedback types</a>. However, if two or more services provide the same feedback type, then only the
+first registered service receives the event.</p>
<h2 id="methods">AccessibilityService Methods</h2>
-<p>An application that provides accessibility service must extend the {@link
+<p>An accessibility service must extend the {@link
android.accessibilityservice.AccessibilityService} class and override the following methods from
that class. These methods are presented in the order in which they are called by the Android system,
from when the service is started
@@ -188,15 +214,15 @@ onAccessibilityEvent()} - (required) This method is called back by the system wh
{@link android.view.accessibility.AccessibilityEvent} that matches the event filtering parameters
specified by your accessibility service. For example, when the user clicks a button or focuses on a
user interface control in an application for which your accessibility service is providing feedback.
-When this happens, the system calls this method of your service with the associated {@link
-android.view.accessibility.AccessibilityEvent}, which you can then interpret and provide feedback to
-the user. This method may be called many times over the lifecycle of your service.</li>
+When this happens, the system calls this method, passing the associated {@link
+android.view.accessibility.AccessibilityEvent}, which the service can then interpret and use to
+provide feedback to the user. This method may be called many times over the lifecycle of your
+service.</li>
<li>{@link android.accessibilityservice.AccessibilityService#onInterrupt onInterrupt()} -
(required) This method is called when the system wants to interrupt the feedback your service is
-providing, usually in response to a user taking action, such as moving focus to a different user
-interface control than the one for which you are currently providing feedback. This method may be
-called many times over the lifecycle of your service.</li>
+providing, usually in response to a user action such as moving focus to a different control. This
+method may be called many times over the lifecycle of your service.</li>
<li>{@link android.accessibilityservice.AccessibilityService#onUnbind onUnbind()} - (optional)
This method is called when the system is about to shutdown the accessibility service. Use this
@@ -206,7 +232,9 @@ services, such as the audio manager or device vibrator.</li>
<p>These callback methods provide the basic structure for your accessibility service. It is up to
you to decide on how to process data provided by the Android system in the form of {@link
-android.view.accessibility.AccessibilityEvent} objects and provide feedback to the user.</p>
+android.view.accessibility.AccessibilityEvent} objects and provide feedback to the user. For more
+information about getting information from an accessibility event, see the
+<a href="{@docRoot}training/accessibility/service.html">Implementing Accessibility</a> training.</p>
<h2 id="event-details">Getting Event Details</h2>
@@ -214,15 +242,15 @@ android.view.accessibility.AccessibilityEvent} objects and provide feedback to t
<p>The Android system provides information to accessibility services about the user interface
interaction through {@link android.view.accessibility.AccessibilityEvent} objects. Prior to Android
4.0, the information available in an accessibility event, while providing a significant amount of
-detail about a user interface control selected by the user, typically provided limited contextual
+detail about a user interface control selected by the user, offered limited contextual
information. In many cases, this missing context information might be critical to understanding the
meaning of the selected control.</p>
-<p>A typical example of an interface where context is of critical importance is a calendar or day
-planner. If a user selects a 4:00 PM time slot in a Monday to Friday day list and the accessibility
-service announces “4 PM”, but fails to indicate this is a Friday a Monday, the month or day, this is
-hardly ideal feedback for the user. In this case, the context of a user interface control is of
-critical importance to a user who wants to schedule a meeting.</p>
+<p>An example of an interface where context is critical is a calendar or day planner. If the
+user selects a 4:00 PM time slot in a Monday to Friday day list and the accessibility service
+announces “4 PM”, but does not announce the weekday name, the day of the month, or the month name,
+the resulting feedback is confusing. In this case, the context of a user interface control is
+critical to a user who wants to schedule a meeting.</p>
<p>Android 4.0 significantly extends the amount of information that an accessibility service can
obtain about an user interface interaction by composing accessibility events based on the view
@@ -245,26 +273,167 @@ can obtain additional information about the event using these calls:</p>
AccessibilityEvent.getRecordCount()} and {@link
android.view.accessibility.AccessibilityEvent#getRecord getRecord(int)} - These methods allow you to
retrieve the set of {@link android.view.accessibility.AccessibilityRecord} objects which contributed
-to the {@link android.view.accessibility.AccessibilityEvent} passed to you by the system, which can
-provide more context for your accessibility service.</li>
+to the {@link android.view.accessibility.AccessibilityEvent} passed to you by the system. This level
+of detail provides more context for the event that triggered your accessibility service.</li>
<li>{@link android.view.accessibility.AccessibilityEvent#getSource
AccessibilityEvent.getSource()} - This method returns an {@link
-android.view.accessibility.AccessibilityNodeInfo} object. This object allows you to request the
-parents and children of the component that originated the accessibility event and investigate their
-contents and state in order to provide
+android.view.accessibility.AccessibilityNodeInfo} object. This object allows you to request view
+layout hierarchy (parents and children) of the component that originated the accessibility event.
+This feature allows an accessibility service to investigate the full context of an event, including
+the content and state of any enclosing views or child views.
- <p class="caution"><strong>Important:</strong> The ability to investigate the full view
+<p class="caution"><strong>Important:</strong> The ability to investigate the view
hierarchy from an {@link android.view.accessibility.AccessibilityEvent} potentially exposes private
user information to your accessibility service. For this reason, your service must request this
level of access through the accessibility <a href="#service-config">service configuration XML</a>
file, by including the {@code canRetrieveWindowContent} attribute and setting it to {@code true}. If
you do not include this setting in your service configuration xml file, calls to {@link
android.view.accessibility.AccessibilityEvent#getSource getSource()} fail.</p>
+
+<p class="note"><strong>Note:</strong> In Android 4.1 (API Level 16) and higher, the
+{@link android.view.accessibility.AccessibilityEvent#getSource getSource()} method,
+as well as {@link android.view.accessibility.AccessibilityNodeInfo#getChild
+AccessibilityNodeInfo.getChild()} and
+{@link android.view.accessibility.AccessibilityNodeInfo#getParent getParent()}, return only
+view objects that are considered important for accessibility (views that draw content or respond to
+user actions). If your service requires all views, it can request them by setting the
+{@link android.accessibilityservice.AccessibilityServiceInfo#flags flags} member of the service's
+{@link android.accessibilityservice.AccessibilityServiceInfo} instance to
+{@link android.accessibilityservice.AccessibilityServiceInfo#FLAG_INCLUDE_NOT_IMPORTANT_VIEWS}.</p>
</li>
</ul>
+<h2 id="act-for-users">Taking Action for Users</h2>
+
+<p>Starting with Android 4.0 (API Level 14), accessibility services can act on behalf
+ of users, including changing the input focus and selecting (activating) user interface elements.
+ In Android 4.1 (API Level 16) the range of actions has been expanded to include scrolling lists
+ and interacting with text fields. Accessibility services can
+ also take global actions, such as navigating to the Home screen, pressing the Back button, opening
+ the notifications screen and recent applications list. Android 4.1 also includes a new type of
+ focus, <em>Accessibilty Focus</em>, which makes all visible elements selectable by an
+ accessibility service.</p>
+
+<p>These new capabilities make it possible for developers of accessibility services to create
+ alternative navigation modes such as
+ <a href="{@docRoot}tools/testing/testing_accessibility.html#test-gestures">gesture navigation</a>,
+ and give users with disabilities improved control of their Android devices.</p>
+
+
+<h3 id="detect-gestures">Listening for gestures</h3>
+
+<p>Accessibility services can listen for specific gestures and respond by taking action on behalf
+ of a user. This feature, added in Android 4.1 (API Level 16), and requires that your
+ accessibility service request activation of the Explore by Touch feature. Your service can
+ request this activation by setting the
+ {@link android.accessibilityservice.AccessibilityServiceInfo#flags flags} member of the service’s
+ {@link android.accessibilityservice.AccessibilityServiceInfo} instance to
+ {@link android.accessibilityservice.AccessibilityServiceInfo#FLAG_REQUEST_TOUCH_EXPLORATION_MODE},
+ as shown in the following example.
+ </p>
+
+<pre>
+public class MyAccessibilityService extends AccessibilityService {
+ &#64;Override
+ public void onCreate() {
+ getServiceInfo().flags = AccessibilityServiceInfo.FLAG_REQUEST_TOUCH_EXPLORATION_MODE;
+ }
+ ...
+}
+</pre>
+
+<p>Once your service has requested activation of Explore by Touch, the user must allow the
+ feature to be turned on, if it is not already active. When this feature is active, your service
+ receives notification of accessibility gestures through your service's
+ {@link android.accessibilityservice.AccessibilityService#onGesture onGesture()} callback method
+ and can respond by taking actions for the user.</p>
+
+
+<h3 id="using-actions">Using accessibility actions</h3>
+
+<p>Accessibility services can take action on behalf of users to make interacting with applications
+ simpler and more productive. The ability of accessibility services to perform actions was added
+ in Android 4.0 (API Level 14) and significantly expanded with Android 4.1 (API Level 16).</p>
+
+<p>In order to take actions on behalf of users, your accessibility service must
+ <a href="#register">register</a> to receive events from a few or many applications and request
+ permission to view the content of applications by setting the
+ <a href="{@docRoot}reference/android/R.styleable.html#AccessibilityService_canRetrieveWindowContent">
+ {@code android:canRetrieveWindowContent}</a> to {@code true} in the
+ <a href="#service-config">service configuration file</a>. When events are received by your
+ service, it can then retrieve the
+ {@link android.view.accessibility.AccessibilityNodeInfo} object from the event using
+ {@link android.view.accessibility.AccessibilityEvent#getSource getSource()}.
+ With the {@link android.view.accessibility.AccessibilityNodeInfo} object, your service can then
+ explore the view hierarchy to determine what action to take and then act for the user using
+ {@link android.view.accessibility.AccessibilityNodeInfo#performAction performAction()}.</p>
+
+<pre>
+public class MyAccessibilityService extends AccessibilityService {
+
+ &#64;Override
+ public void onAccessibilityEvent(AccessibilityEvent event) {
+ // get the source node of the event
+ AccessibilityNodeInfo nodeInfo = event.getSource();
+
+ // Use the event and node information to determine
+ // what action to take
+
+ // take action on behalf of the user
+ nodeInfo.performAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD);
+
+ // recycle the nodeInfo object
+ nodeInfo.recycle();
+ }
+ ...
+}
+</pre>
+
+<p>The {@link android.view.accessibility.AccessibilityNodeInfo#performAction performAction()} method
+ allows your service to take action within an application. If your service needs to perform a
+ global action such as navigating to the Home screen, pressing the Back button, opening the
+ notifications screen or recent applications list, then use the
+ {@link android.accessibilityservice.AccessibilityService#performGlobalAction performGlobalAction()}
+ method.</p>
+
+
+<h3 id="focus-types">Using focus types</h3>
+
+<p>Android 4.1 (API Level 16) introduces a new type of user interface focus called <em>Accessibility
+ Focus</em>. This type of focus can be used by accessibility services to select any visible user
+ interface element and act on it. This focus type is different from the more well known <em>Input
+ Focus</em>, which determines what on-screen user interface element receives input when a user
+ types characters, presses <strong>Enter</strong> on a keyboard or pushes the center button of a
+ D-pad control.</p>
+
+<p>Accessibility Focus is completely separate and independent from Input Focus. In fact, it is
+ possible for one element in a user interface to have Input Focus while another element has
+ Accessibility Focus. The purpose of Accessibility Focus is to provide accessibility services with
+ a method of interacting with any visible element on a screen, regardless of whether or not the
+ element is input-focusable from a system perspective. You can see accessibility focus in action by
+ testing accessibility gestures. For more information about testing this feature, see
+ <a href="{@docRoot}tools/testing/testing_accessibility.html#test-gestures">Testing gesture
+ navigation</a>.</p>
+
+<p class="note">
+ <strong>Note:</strong> Accessibility services that use Accessibility Focus are responsible for
+ synchronizing the current Input Focus when an element is capable of this type of focus. Services
+ that do not synchronize Input Focus with Accessibility Focus run the risk of causing problems in
+ applications that expect input focus to be in a specific location when certain actions are taken.
+ </p>
+
+<p>An accessibility service can determine what user interface element has Input Focus or
+ Accessibility Focus using the {@link android.view.accessibility.AccessibilityNodeInfo#findFocus
+ AccessibilityNodeInfo.findFocus()} method. You can also search for elements that can be selected
+ with Input Focus using the
+ {@link android.view.accessibility.AccessibilityNodeInfo#focusSearch focusSearch()} method.
+ Finally, your accessibility service can set Accessibility Focus using the
+ {@link android.view.accessibility.AccessibilityNodeInfo#performAction
+ performAction(AccessibilityNodeInfo.ACTION_SET_ACCESSIBILITY_FOCUS)} method.</p>
+
+
<h2 id="examples">Example Code</h2>
<p>The API Demo project contains two samples which can be used as a starting point for generating
diff --git a/docs/html/guide/topics/ui/controls.jd b/docs/html/guide/topics/ui/controls.jd
index 83bb0c8..a58d9f9 100644
--- a/docs/html/guide/topics/ui/controls.jd
+++ b/docs/html/guide/topics/ui/controls.jd
@@ -15,7 +15,7 @@ checkboxes, zoom buttons, toggle buttons, and many more.</p>
href="{@docRoot}guide/topics/ui/declaring-layout.html">XML layout</a>. For example, here's a
layout with a text field and button:</p>
-<pre>
+<pre style="clear:right">
&lt;?xml version="1.0" encoding="utf-8"?>
&lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
diff --git a/docs/html/guide/topics/ui/dialogs.jd b/docs/html/guide/topics/ui/dialogs.jd
index d1c24df..3cfed13 100644
--- a/docs/html/guide/topics/ui/dialogs.jd
+++ b/docs/html/guide/topics/ui/dialogs.jd
@@ -1,680 +1,801 @@
page.title=Dialogs
-parent.title=User Interface
-parent.link=index.html
@jd:body
+
+
<div id="qv-wrapper">
<div id="qv">
<h2>In this document</h2>
+<ol>
+ <li><a href="#DialogFragment">Creating a Dialog Fragment</a></li>
+ <li><a href="#AlertDialog">Building an Alert Dialog</a>
<ol>
- <li><a href="#ShowingADialog">Showing a Dialog</a></li>
- <li><a href="#DismissingADialog">Dismissing a Dialog</a></li>
- <li><a href="#AlertDialog">Creating an AlertDialog</a>
- <ol>
- <li><a href="#AddingButtons">Adding buttons</a></li>
- <li><a href="#AddingAList">Adding a list</a></li>
- </ol>
- </li>
- <li><a href="#ProgressDialog">Creating a ProgressDialog</a>
- <ol>
- <li><a href="#ShowingAProgressBar">Showing a progress bar</a></li>
- </ol>
- </li>
- <li><a href="#CustomDialog">Creating a Custom Dialog</a></li>
+ <li><a href="#AddingButtons">Adding buttons</a></li>
+ <li><a href="#AddingAList">Adding a list</a></li>
+ <li><a href="#CustomLayout">Creating a Custom Layout</a></li>
</ol>
-
- <h2>Key classes</h2>
+ </li>
+ <li><a href="#PassingEvents">Passing Events Back to the Dialog's Host</a></li>
+ <li><a href="#ShowingADialog">Showing a Dialog</a></li>
+ <li><a href="#FullscreenDialog">Showing a Dialog Fullscreen or as an Embedded Fragment</a>
<ol>
- <li>{@link android.app.Dialog}</li>
- <li>{@link android.app.AlertDialog}</li>
- <li>{@link android.app.DialogFragment}</li>
+ <li><a href="#ActivityAsDialog">Showing an activity as a dialog on large screens</a></li>
</ol>
+ </li>
+ <li><a href="#DismissingADialog">Dismissing a Dialog</a></li>
+</ol>
- <h2>Related tutorials</h2>
+ <h2>Key classes</h2>
<ol>
- <li><a href="{@docRoot}resources/tutorials/views/hello-datepicker.html">Hello
-DatePicker</a></li>
- <li><a href="{@docRoot}resources/tutorials/views/hello-timepicker.html">Hello
-TimePicker</a></li>
+ <li>{@link android.app.DialogFragment}</li>
+ <li>{@link android.app.AlertDialog}</li>
</ol>
<h2>See also</h2>
<ol>
- <li><a href="{@docRoot}design/building-blocks/dialogs.html">Android Design: Dialogs</a></li>
+ <li><a href="{@docRoot}design/building-blocks/dialogs.html">Dialogs design guide</a></li>
+ <li><a href="{@docRoot}guide/topics/ui/controls/pickers.html">Pickers</a> (Date/Time dialogs)</li>
</ol>
</div>
</div>
-<p>A dialog is usually a small window that appears in front of the current Activity.
-The underlying Activity loses focus and the dialog accepts all user interaction. Dialogs are
-normally used for notifications that should interrupt the user and to perform short tasks that
-directly relate to the application in progress (such as a progress bar or a login prompt).</p>
-
-<p>The {@link android.app.Dialog} class is the base class for creating dialogs. However, you
-typically should not instantiate a {@link android.app.Dialog} directly. Instead, you should use one
-of the following subclasses:</p>
-<dl>
- <dt>{@link android.app.AlertDialog}</dt>
- <dd>A dialog that can manage zero, one, two, or three buttons, and/or a list of
- selectable items that can include checkboxes or radio buttons. The AlertDialog
- is capable of constructing most dialog user interfaces and is the suggested dialog type.
- See <a href="#AlertDialog">Creating an AlertDialog</a> below.</dd>
- <dt>{@link android.app.ProgressDialog}</dt>
- <dd>A dialog that displays a progress wheel or progress bar. Because it's an extension of
- the AlertDialog, it also supports buttons.
- See <a href="#ProgressDialog">Creating a ProgressDialog</a> below.</dd>
- <dt>{@link android.app.DatePickerDialog}</dt>
- <dd>A dialog that allows the user to select a date. See the
- <a href="{@docRoot}resources/tutorials/views/hello-datepicker.html">Hello DatePicker</a> tutorial.</dd>
- <dt>{@link android.app.TimePickerDialog}</dt>
- <dd>A dialog that allows the user to select a time. See the
- <a href="{@docRoot}resources/tutorials/views/hello-timepicker.html">Hello TimePicker</a> tutorial.</dd>
-</dl>
-
-<p>If you would like to customize your own dialog, you can extend the
-base {@link android.app.Dialog} object or any of the subclasses listed above and define a new layout.
-See the section on <a href="#CustomDialog">Creating a Custom Dialog</a> below.</p>
+<p>A dialog is a small window that prompts the user to
+make a decision or enter additional information. A dialog does not fill the screen and is
+normally used for modal events that require users to take an action before they can proceed.</p>
<div class="note design">
<p><strong>Dialog Design</strong></p>
- <p>For design guidelines, read Android Design's <a
-href="{@docRoot}design/building-blocks/dialogs.html">Dialogs</a> guide.</p>
+ <p>For information about how to design your dialogs, including recommendations
+ for language, read the <a
+href="{@docRoot}design/building-blocks/dialogs.html">Dialogs</a> design guide.</p>
</div>
+<img src="{@docRoot}images/ui/dialogs.png" />
+<p>The {@link android.app.Dialog} class is the base class for dialogs, but you
+should avoid instantiating {@link android.app.Dialog} directly.
+Instead, use one of the following subclasses:</p>
+<dl>
+ <dt>{@link android.app.AlertDialog}</dt>
+ <dd>A dialog that can show a title, up to three buttons, a list of
+ selectable items, or a custom layout.</dd>
+ <dt>{@link android.app.DatePickerDialog} or {@link android.app.TimePickerDialog}</dt>
+ <dd>A dialog with a pre-defined UI that allows the user to select a date or time.</dd>
+</dl>
-<h2 id="ShowingADialog">Showing a Dialog</h2>
+<div class="sidebox">
+<h2>Avoid ProgressDialog</h2>
+<p>Android includes another dialog class called
+{@link android.app.ProgressDialog} that shows a dialog with a progress bar. However, if you
+need to indicate loading or indeterminate progress, you should instead follow the design
+guidelines for <a href="{@docRoot}design/building-blocks/progress.html">Progress &amp;
+Activity</a> and use a {@link android.widget.ProgressBar} in your layout.</p>
+</div>
-<p>A dialog is always created and displayed as a part of an {@link android.app.Activity}.
-You should normally create dialogs from within your Activity's
-{@link android.app.Activity#onCreateDialog(int)} callback method.
-When you use this callback, the Android system automatically manages the state of
-each dialog and hooks them to the Activity, effectively making it the "owner" of each dialog.
-As such, each dialog inherits certain properties from the Activity. For example, when a dialog
-is open, the Menu key reveals the options menu defined for the Activity and the volume
-keys modify the audio stream used by the Activity.</p>
-
-<p class="note"><strong>Note:</strong> If you decide to create a dialog outside of the
-<code>onCreateDialog()</code> method, it will not be attached to an Activity. You can, however,
-attach it to an Activity with {@link android.app.Dialog#setOwnerActivity(Activity)}.</p>
-
-<p>When you want to show a dialog, call
-{@link android.app.Activity#showDialog(int)} and pass it an integer that uniquely identifies the
-dialog that you want to display.</p>
-
-<p>When a dialog is requested for the first time, Android calls
-{@link android.app.Activity#onCreateDialog(int)} from your Activity, which is
-where you should instantiate the {@link android.app.Dialog}. This callback method
-is passed the same ID that you passed to {@link android.app.Activity#showDialog(int)}.
-After you create the Dialog, return the object at the end of the method.</p>
-
-<p>Before the dialog is displayed, Android also calls the optional callback method
-{@link android.app.Activity#onPrepareDialog(int,Dialog)}. Define this method if you want to change
-any properties of the dialog each time it is opened. This method is called
-every time a dialog is opened, whereas {@link android.app.Activity#onCreateDialog(int)} is only
-called the very first time a dialog is opened. If you don't define
-{@link android.app.Activity#onPrepareDialog(int,Dialog) onPrepareDialog()}, then the dialog will
-remain the same as it was the previous time it was opened. This method is also passed the dialog's
-ID, along with the Dialog object you created in {@link android.app.Activity#onCreateDialog(int)
-onCreateDialog()}.</p>
-
-<p>The best way to define the {@link android.app.Activity#onCreateDialog(int)} and
-{@link android.app.Activity#onPrepareDialog(int,Dialog)} callback methods is with a
-<em>switch</em> statement that checks the <var>id</var> parameter that's passed into the method.
-Each <em>case</em> should check for a unique dialog ID and then create and define the respective Dialog.
-For example, imagine a game that uses two different dialogs: one to indicate that the game
-has paused and another to indicate that the game is over. First, define an integer ID for
-each dialog:</p>
-<pre>
-static final int DIALOG_PAUSED_ID = 0;
-static final int DIALOG_GAMEOVER_ID = 1;
-</pre>
+<p>These classes define the style and structure for your dialog, but you should
+use a {@link android.support.v4.app.DialogFragment} as a container for your dialog.
+The {@link android.support.v4.app.DialogFragment} class provides all the controls you
+need to create your dialog and manage its appearance, instead of calling methods
+on the {@link android.app.Dialog} object.</p>
+
+<p>Using {@link android.support.v4.app.DialogFragment} to manage the dialog
+ensures that it correctly handles lifecycle events
+such as when the user presses the <em>Back</em> button or rotates the screen. The {@link
+android.support.v4.app.DialogFragment} class also allows you to reuse the dialog's UI as an
+embeddable component in a larger UI, just like a traditional {@link
+android.support.v4.app.Fragment} (such as when you want the dialog UI to appear differently
+on large and small screens).</p>
+
+<p>The following sections in this guide describe how to use a {@link
+android.support.v4.app.DialogFragment} in combination with an {@link android.app.AlertDialog}
+object. If you'd like to create a date or time picker, you should instead read the
+<a href="{@docRoot}guide/topics/ui/controls/pickers.html">Pickers</a> guide.</p>
+
+<p class="note"><strong>Note:</strong>
+Because the {@link android.app.DialogFragment} class was originally added with
+Android 3.0 (API level 11), this document describes how to use the {@link
+android.support.v4.app.DialogFragment} class that's provided with the <a
+href="{@docRoot}tools/extras/support-library.html">Support Library</a>. By adding this library
+to your app, you can use {@link android.support.v4.app.DialogFragment} and a variety of other
+APIs on devices running Android 1.6 or higher. If the minimum version your app supports
+is API level 11 or higher, then you can use the framework version of {@link
+android.app.DialogFragment}, but be aware that the links in this document are for the support
+library APIs. When using the support library,
+be sure that you import <code>android.support.v4.app.DialogFragment</code>
+class and <em>not</em> <code>android.app.DialogFragment</code>.</p>
+
+
+<h2 id="DialogFragment">Creating a Dialog Fragment</h2>
+
+<p>You can accomplish a wide variety of dialog designs&mdash;including
+custom layouts and those described in the <a
+href="{@docRoot}design/building-blocks/dialogs.html">Dialogs</a>
+design guide&mdash;by extending
+{@link android.support.v4.app.DialogFragment} and creating a {@link android.app.AlertDialog}
+in the {@link android.support.v4.app.DialogFragment#onCreateDialog
+onCreateDialog()} callback method.</p>
+
+<p>For example, here's a basic {@link android.app.AlertDialog} that's managed within
+a {@link android.support.v4.app.DialogFragment}:</p>
-<p>Then, define the {@link android.app.Activity#onCreateDialog(int)} callback with a
-switch case for each ID:</p>
<pre>
-protected Dialog onCreateDialog(int id) {
- Dialog dialog;
- switch(id) {
- case DIALOG_PAUSED_ID:
- // do the work to define the pause Dialog
- break;
- case DIALOG_GAMEOVER_ID:
- // do the work to define the game over Dialog
- break;
- default:
- dialog = null;
+public class FireMissilesDialogFragment extends DialogFragment {
+ &#64;Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ // Use the Builder class for convenient dialog construction
+ AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
+ builder.setMessage(R.string.dialog_fire_missiles)
+ .setPositiveButton(R.string.fire, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int id) {
+ // FIRE ZE MISSILES!
+ }
+ })
+ .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int id) {
+ // User cancelled the dialog
+ }
+ });
+ // Create the AlertDialog object and return it
+ return builder.create();
}
- return dialog;
}
</pre>
-<p class="note"><strong>Note:</strong> In this example, there's no code inside
-the case statements because the procedure for defining your Dialog is outside the scope
-of this section. See the section below about <a href="#AlertDialog">Creating an AlertDialog</a>,
-offers code suitable for this example.</p>
+<div class="figure" style="width:290px;margin:0 0 0 20px">
+<img src="{@docRoot}images/ui/dialog_buttons.png" alt="" />
+<p class="img-caption"><strong>Figure 1.</strong>
+A dialog with a message and two action buttons.</p>
+</div>
-<p>When it's time to show one of the dialogs, call {@link android.app.Activity#showDialog(int)}
-with the ID of a dialog:</p>
-<pre>
-showDialog(DIALOG_PAUSED_ID);
-</pre>
+<p>Now, when you create an instance of this class and call {@link
+android.support.v4.app.DialogFragment#show show()} on that object, the dialog appears as
+shown in figure 1.</p>
+<p>The next section describes more about using the {@link android.app.AlertDialog.Builder}
+APIs to create the dialog.</p>
-<h2 id="DismissingADialog">Dismissing a Dialog</h2>
+<p>Depending on how complex your dialog is, you can implement a variety of other callback
+methods in the {@link android.support.v4.app.DialogFragment}, including all the basic
+<a href="{@docRoot}guide/components/fragments.html#Lifecycle">fragment lifecycle methods</a>.
-<p>When you're ready to close your dialog, you can dismiss it by calling
-{@link android.app.Dialog#dismiss()} on the Dialog object.
-If necessary, you can also call {@link android.app.Activity#dismissDialog(int)} from the
-Activity, which effectively calls {@link android.app.Dialog#dismiss()} on the
-Dialog for you.</p>
-
-<p>If you are using {@link android.app.Activity#onCreateDialog(int)} to manage the state
-of your dialogs (as discussed in the previous section), then every time your dialog is
-dismissed, the state of the Dialog
-object is retained by the Activity. If you decide that you will no longer need this object or
-it's important that the state is cleared, then you should call
-{@link android.app.Activity#removeDialog(int)}. This will remove any internal references
-to the object and if the dialog is showing, it will dismiss it.</p>
-
-<h3>Using dismiss listeners</h3>
-
-<p>If you'd like your application to perform some procedures the moment that a dialog is dismissed,
-then you should attach an on-dismiss listener to your Dialog.</p>
-
-<p>First define the {@link android.content.DialogInterface.OnDismissListener} interface.
-This interface has just one method,
-{@link android.content.DialogInterface.OnDismissListener#onDismiss(DialogInterface)}, which
-will be called when the dialog is dismissed.
-Then simply pass your OnDismissListener implementation to
-{@link android.app.Dialog#setOnDismissListener(DialogInterface.OnDismissListener)
-setOnDismissListener()}.</p>
-
-<p>However, note that dialogs can also be "cancelled." This is a special case that indicates
-the dialog was explicitly cancelled by the user. This will occur if the user presses the
-"back" button to close the dialog, or if the dialog explicitly calls {@link android.app.Dialog#cancel()}
-(perhaps from a "Cancel" button in the dialog). When a dialog is cancelled,
-the OnDismissListener will still be notified, but if you'd like to be informed that the dialog
-was explicitly cancelled (and not dismissed normally), then you should register
-an {@link android.content.DialogInterface.OnCancelListener} with
-{@link android.app.Dialog#setOnCancelListener(DialogInterface.OnCancelListener)
-setOnCancelListener()}.</p>
-
-
-<h2 id="AlertDialog">Creating an AlertDialog</h2>
-
-<p>An {@link android.app.AlertDialog} is an extension of the {@link android.app.Dialog}
-class. It is capable of constructing most dialog user interfaces and is the suggested dialog type.
-You should use it for dialogs that use any of the following features:</p>
-<ul>
- <li>A title</li>
- <li>A text message</li>
- <li>One, two, or three buttons</li>
- <li>A list of selectable items (with optional checkboxes or radio buttons)</li>
-</ul>
-<p>To create an AlertDialog, use the {@link android.app.AlertDialog.Builder} subclass.
-Get a Builder with {@link android.app.AlertDialog.Builder#AlertDialog.Builder(Context)} and
-then use the class's public methods to define all of the
-AlertDialog properties. After you're done with the Builder, retrieve the
-AlertDialog object with {@link android.app.AlertDialog.Builder#create()}.</p>
-<p>The following topics show how to define various properties of the AlertDialog using the
-AlertDialog.Builder class. If you use any of the following sample code inside your
-{@link android.app.Activity#onCreateDialog(int) onCreateDialog()} callback method,
-you can return the resulting Dialog object to display the dialog.</p>
-<h3 id="AddingButtons">Adding buttons</h3>
+<h2 id="AlertDialog">Building an Alert Dialog</h2>
+
+
+<p>The {@link android.app.AlertDialog} class allows you to build a variety of dialog designs and
+is often the only dialog class you'll need.
+As shown in figure 2, there are three regions of an alert dialog:</p>
+
+<div class="figure" style="width:311px;margin-top:0">
+<img src="{@docRoot}images/ui/dialogs_regions.png" alt="" style="margin-bottom:0"/>
+<p class="img-caption"><strong>Figure 2.</strong> The layout of a dialog.</p>
+</div>
-<img src="{@docRoot}images/dialog_buttons.png" alt="" style="float:right" />
+<ol>
+<li><b>Title</b>
+ <p>This is optional and should be used only when the content area
+ is occupied by a detailed message, a list, or custom layout. If you need to state
+ a simple message or question (such as the dialog in figure 1), you don't need a title.</li>
+<li><b>Content area</b>
+ <p>This can display a message, a list, or other custom layout.</p></li>
+<li><b>Action buttons</b>
+ <p>There should be no more than three action buttons in a dialog.</p></li>
+</ol>
-<p>To create an AlertDialog with side-by-side buttons like the one shown in the screenshot to the right,
-use the <code>set...Button()</code> methods:</p>
+<p>The {@link android.app.AlertDialog.Builder}
+class provides APIs that allow you to create an {@link android.app.AlertDialog}
+with these kinds of content, including a custom layout.</p>
+
+<p>To build an {@link android.app.AlertDialog}:</p>
<pre>
-AlertDialog.Builder builder = new AlertDialog.Builder(this);
-builder.setMessage("Are you sure you want to exit?")
- .setCancelable(false)
- .setPositiveButton("Yes", new DialogInterface.OnClickListener() {
+<b>// 1. Instantiate an {@link android.app.AlertDialog.Builder} with its constructor</b>
+AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
+
+<b>// 2. Chain together various setter methods to set the dialog characteristics</b>
+builder.setMessage(R.string.dialog_message)
+ .setTitle(R.string.dialog_title);
+
+<b>// 3. Get the {@link android.app.AlertDialog} from {@link android.app.AlertDialog.Builder#create()}</b>
+AlertDialog dialog = builder.create();
+</pre>
+
+<p>The following topics show how to define various dialog attributes using the
+{@link android.app.AlertDialog.Builder} class.</p>
+
+
+
+
+<h3 id="AddingButtons">Adding buttons</h3>
+
+<p>To add action buttons like those in figure 2,
+call the {@link android.app.AlertDialog.Builder#setPositiveButton setPositiveButton()} and
+{@link android.app.AlertDialog.Builder#setNegativeButton setNegativeButton()} methods:</p>
+
+<pre style="clear:right">
+AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
+// Add the buttons
+builder.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
- MyActivity.this.finish();
+ // User clicked OK button
}
- })
- .setNegativeButton("No", new DialogInterface.OnClickListener() {
+ });
+builder.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
- dialog.cancel();
+ // User cancelled the dialog
}
});
-AlertDialog alert = builder.create();
+// Set other dialog properties
+...
+
+// Create the AlertDialog
+AlertDialog dialog = builder.create();
</pre>
-<p>First, add a message for the dialog with
-{@link android.app.AlertDialog.Builder#setMessage(CharSequence)}. Then, begin
-method-chaining and set the dialog
-to be <em>not cancelable</em> (so the user cannot close the dialog with the back button)
-with {@link android.app.AlertDialog.Builder#setCancelable(boolean)}. For each button,
-use one of the <code>set...Button()</code> methods, such as
-{@link android.app.AlertDialog.Builder#setPositiveButton(CharSequence,DialogInterface.OnClickListener)
-setPositiveButton()}, that accepts the name for the button and a
+<p>The <code>set...Button()</code> methods require a title for the button (supplied
+by a <a href="{@docRoot}guide/topics/resources/string-resource.html">string resource</a>) and a
{@link android.content.DialogInterface.OnClickListener} that defines the action to take
-when the user selects the button.</p>
+when the user presses the button.</p>
-<p class="note"><strong>Note:</strong> You can only add one of each button type to the
-AlertDialog. That is, you cannot have more than one "positive" button. This limits the number
-of possible buttons to three: positive, neutral, and negative. These names are technically irrelevant to the
-actual functionality of your buttons, but should help you keep track of which one does what.</p>
+<p>There are three different action buttons you can add:</p>
+<dl>
+ <dt>Positive</dt>
+ <dd>You should use this to accept and continue with the action (the "OK" action).</dd>
+ <dt>Negative</dt>
+ <dd>You should use this to cancel the action.</dd>
+ <dt>Neutral</dt>
+ <dd>You should use this when the user may not want to proceed with the action,
+ but doesn't necessarily want to cancel. It appears between the positive and negative
+ buttons. For example, the action might be "Remind me later."</dd>
+</dl>
+<p>You can add only one of each button type to an {@link
+android.app.AlertDialog}. That is, you cannot have more than one "positive" button.</p>
-<h3 id="AddingAList">Adding a list</h3>
-<img src="{@docRoot}images/dialog_list.png" alt="" style="float:right" />
-<p>To create an AlertDialog with a list of selectable items like the one shown to the right,
-use the <code>setItems()</code> method:</p>
+<div class="figure" style="width:290px;margin:0 0 0 40px">
+<img src="{@docRoot}images/ui/dialog_list.png" alt="" />
+<p class="img-caption"><strong>Figure 3.</strong>
+A dialog with a title and list.</p>
+</div>
-<pre>
-final CharSequence[] items = {"Red", "Green", "Blue"};
+<h3 id="AddingAList">Adding a list</h3>
-AlertDialog.Builder builder = new AlertDialog.Builder(this);
-builder.setTitle("Pick a color");
-builder.setItems(items, new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int item) {
- Toast.makeText(getApplicationContext(), items[item], Toast.LENGTH_SHORT).show();
- }
-});
-AlertDialog alert = builder.create();
-</pre>
+<p>There are three kinds of lists available with the {@link android.app.AlertDialog} APIs:</p>
+<ul>
+<li>A traditional single-choice list</li>
+<li>A persistent single-choice list (radio buttons)</li>
+<li>A persistent multiple-choice list (checkboxes)</li>
+</ul>
-<p>First, add a title to the dialog with
-{@link android.app.AlertDialog.Builder#setTitle(CharSequence)}.
-Then, add a list of selectable items with
-{@link android.app.AlertDialog.Builder#setItems(CharSequence[],DialogInterface.OnClickListener)
-setItems()}, which accepts the array of items to display and a
-{@link android.content.DialogInterface.OnClickListener} that defines the action to take
-when the user selects an item.</p>
+<p>To create a single-choice list like the one in figure 3,
+use the {@link android.app.AlertDialog.Builder#setItems setItems()} method:</p>
+
+<pre style="clear:right">
+&#64;Override
+public Dialog onCreateDialog(Bundle savedInstanceState) {
+ AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
+ builder.setTitle(R.string.pick_color);
+ .setItems(R.array.colors_array, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which) {
+ // The 'which' argument contains the index position
+ // of the selected item
+ }
+ });
+ return builder.create();
+}
+</pre>
+<p>Because the list appears in the dialog's content area,
+the dialog cannot show both a message and a list and you should set a title for the
+dialog with {@link android.app.AlertDialog.Builder#setTitle setTitle()}.
+To specify the items for the list, call {@link
+android.app.AlertDialog.Builder#setItems setItems()}, passing an array.
+Alternatively, you can specify a list using {@link
+android.app.AlertDialog.Builder#setAdapter setAdapter()}. This allows you to back the list
+with dynamic data (such as from a database) using a {@link android.widget.ListAdapter}.</p>
+
+<p>If you choose to back your list with a {@link android.widget.ListAdapter},
+always use a {@link android.support.v4.content.Loader} so that the content loads
+asynchronously. This is described further in
+<a href="{@docRoot}guide/topics/ui/declaring-layout.html#AdapterViews">Building Layouts
+with an Adapter</a> and the <a href="{@docRoot}guide/components/loaders.html">Loaders</a>
+guide.</p>
+
+<p class="note"><strong>Note:</strong> By default, touching a list item dismisses the dialog,
+unless you're using one of the following persistent choice lists.</p>
+
+<div class="figure" style="width:290px;margin:-30px 0 0 40px">
+<img src="{@docRoot}images/ui/dialog_checkboxes.png" />
+<p class="img-caption"><strong>Figure 4.</strong>
+A list of multiple-choice items.</p>
+</div>
-<h4>Adding checkboxes and radio buttons</h4>
-<img src="{@docRoot}images/dialog_singlechoicelist.png" alt="" style="float:right" />
+<h4 id="Checkboxes">Adding a persistent multiple-choice or single-choice list</h4>
-<p>To create a list of multiple-choice items (checkboxes) or
-single-choice items (radio buttons) inside the dialog, use the
+<p>To add a list of multiple-choice items (checkboxes) or
+single-choice items (radio buttons), use the
{@link android.app.AlertDialog.Builder#setMultiChoiceItems(Cursor,String,String,
-DialogInterface.OnMultiChoiceClickListener) setMultiChoiceItems()} and
-{@link android.app.AlertDialog.Builder#setSingleChoiceItems(int,int,DialogInterface.OnClickListener)
-setSingleChoiceItems()} methods, respectively.
-If you create one of these selectable lists in the
-{@link android.app.Activity#onCreateDialog(int) onCreateDialog()} callback method,
-Android manages the state of the list for you. As long as the Activity is active,
-the dialog remembers the items that were previously selected, but when the user exits the
-Activity, the selection is lost.
-
-<p class="note"><strong>Note:</strong> To save the selection when the user leaves or
-pauses the Activity, you must properly save and restore the setting throughout
-the <a href="{@docRoot}guide/components/activities.html#Lifecycle">activity lifecycle</a>.
-To permanently save the selections, even when the Activity process is completely shutdown,
-you need to save the settings
-with one of the <a href="{@docRoot}guide/topics/data/data-storage.html">Data
-Storage</a> techniques.</p>
-
-<p>To create an AlertDialog with a list of single-choice items like the one shown to the right,
-use the same code from the previous example, but replace the <code>setItems()</code> method with
+DialogInterface.OnMultiChoiceClickListener) setMultiChoiceItems()} or
{@link android.app.AlertDialog.Builder#setSingleChoiceItems(int,int,DialogInterface.OnClickListener)
-setSingleChoiceItems()}:</p>
+setSingleChoiceItems()} methods, respectively.</p>
+
+<p>For example, here's how you can create a multiple-choice list like the
+one shown in figure 4 that saves the selected
+items in an {@link java.util.ArrayList}:</p>
+
+<pre style="clear:right">
+&#64;Override
+public Dialog onCreateDialog(Bundle savedInstanceState) {
+ mSelectedItems = new ArrayList(); // Where we track the selected items
+ AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
+ // Set the dialog title
+ builder.setTitle(R.string.pick_toppings)
+ // Specify the list array, the items to be selected by default (null for none),
+ // and the listener through which to receive callbacks when items are selected
+ .setMultiChoiceItems(R.array.toppings, null,
+ new DialogInterface.OnMultiChoiceClickListener() {
+ &#64;Override
+ public void onClick(DialogInterface dialog, int which,
+ boolean isChecked) {
+ if (isChecked) {
+ // If the user checked the item, add it to the selected items
+ mSelectedItems.add(which);
+ } else if (mSelectedItems.contains(which)) {
+ // Else, if the item is already in the array, remove it
+ mSelectedItems.remove(Integer.valueOf(which));
+ }
+ }
+ })
+ // Set the action buttons
+ .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
+ &#64;Override
+ public void onClick(DialogInterface dialog, int id) {
+ // User clicked OK, so save the mSelectedItems results somewhere
+ // or return them to the component that opened the dialog
+ ...
+ }
+ })
+ .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
+ &#64;Override
+ public void onClick(DialogInterface dialog, int id) {
+ ...
+ }
+ });
+
+ return builder.create();
+}
+</pre>
+
+<p>Although both a traditional list and a list with radio buttons
+provide a "single choice" action, you should use {@link
+android.app.AlertDialog.Builder#setSingleChoiceItems(int,int,DialogInterface.OnClickListener)
+setSingleChoiceItems()} if you want to persist the user's choice.
+That is, if opening the dialog again later should indicate what the user's current choice is,
+then you create a list with radio buttons.</p>
+
-<pre>
-final CharSequence[] items = {"Red", "Green", "Blue"};
-AlertDialog.Builder builder = new AlertDialog.Builder(this);
-builder.setTitle("Pick a color");
-builder.setSingleChoiceItems(items, -1, new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int item) {
- Toast.makeText(getApplicationContext(), items[item], Toast.LENGTH_SHORT).show();
- }
-});
-AlertDialog alert = builder.create();
-</pre>
-<p>The second parameter in the
-{@link android.app.AlertDialog.Builder#setSingleChoiceItems(CharSequence[],int,DialogInterface.OnClickListener)
-setSingleChoiceItems()} method is an integer value for the <var>checkedItem</var>, which indicates the
-zero-based list position of the default selected item. Use "-1" to indicate that no item should be
-selected by default.</p>
+<h3 id="CustomLayout">Creating a Custom Layout</h3>
-<h2 id="ProgressDialog">Creating a ProgressDialog</h2>
+<div class="figure" style="width:290px;margin:-30px 0 0 40px">
+<img src="{@docRoot}images/ui/dialog_custom.png" alt="" />
+<p class="img-caption"><strong>Figure 5.</strong> A custom dialog layout.</p>
+</div>
-<img src="{@docRoot}images/dialog_progress_spinning.png" alt="" style="float:right" />
+<p>If you want a custom layout in a dialog, create a layout and add it to an
+{@link android.app.AlertDialog} by calling {@link
+android.app.AlertDialog.Builder#setView setView()} on your {@link
+android.app.AlertDialog.Builder} object.</p>
-<p>A {@link android.app.ProgressDialog} is an extension of the {@link android.app.AlertDialog}
-class that can display a progress animation in the form of a spinning wheel, for a task with
-progress that's undefined, or a progress bar, for a task that has a defined progression.
-The dialog can also provide buttons, such as one to cancel a download.</p>
+<p>By default, the custom layout fills the dialog window, but you can still
+use {@link android.app.AlertDialog.Builder} methods to add buttons and a title.</p>
-<p>Opening a progress dialog can be as simple as calling
-{@link android.app.ProgressDialog#show(Context,CharSequence,CharSequence)
-ProgressDialog.show()}. For example, the progress dialog shown to the right can be
-easily achieved without managing the dialog through the
-{@link android.app.Activity#onCreateDialog(int)} callback,
-as shown here:</p>
+<p>For example, here's the layout file for the dialog in Figure 5:</p>
+<p style="clear:right" class="code-caption">res/layout/dialog_signin.xml</p>
<pre>
-ProgressDialog dialog = ProgressDialog.show(MyActivity.this, "",
- "Loading. Please wait...", true);
+&lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content">
+ &lt;ImageView
+ android:src="@drawable/header_logo"
+ android:layout_width="match_parent"
+ android:layout_height="64dp"
+ android:scaleType="center"
+ android:background="#FFFFBB33"
+ android:contentDescription="@string/app_name" />
+ &lt;EditText
+ android:id="@+id/username"
+ android:inputType="textEmailAddress"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="16dp"
+ android:layout_marginLeft="4dp"
+ android:layout_marginRight="4dp"
+ android:layout_marginBottom="4dp"
+ android:hint="@string/username" />
+ &lt;EditText
+ android:id="@+id/password"
+ android:inputType="textPassword"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="4dp"
+ android:layout_marginLeft="4dp"
+ android:layout_marginRight="4dp"
+ android:layout_marginBottom="16dp"
+ android:fontFamily="sans-serif"
+ android:hint="@string/password"/>
+&lt;/LinearLayout>
</pre>
-<p>The first parameter is the application {@link android.content.Context},
-the second is a title for the dialog (left empty), the third is the message,
-and the last parameter is whether the progress
-is indeterminate (this is only relevant when creating a progress bar, which is
-discussed in the next section).
-</p>
+<p class="note"><strong>Tip:</strong> By default, when you set an {@link android.widget.EditText}
+element to use the {@code "textPassword"} input type, the font family is set to monospace, so
+you should change its font family to {@code "sans-serif"} so that both text fields use
+a matching font style.</p>
-<p>The default style of a progress dialog is the spinning wheel.
-If you want to create a progress bar that shows the loading progress with granularity,
-some more code is required, as discussed in the next section.</p>
+<p>To inflate the layout in your {@link android.support.v4.app.DialogFragment},
+get a {@link android.view.LayoutInflater} with
+{@link android.app.Activity#getLayoutInflater()} and call
+{@link android.view.LayoutInflater#inflate inflate()}, where the first parameter
+is the layout resource ID and the second parameter is a parent view for the layout.
+You can then call {@link android.app.AlertDialog#setView setView()}
+to place the layout in the dialog.</p>
+<pre>
+&#64;Override
+public Dialog onCreateDialog(Bundle savedInstanceState) {
+ AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
+ // Get the layout inflater
+ LayoutInflater inflater = getActivity().getLayoutInflater();
+
+ // Inflate and set the layout for the dialog
+ // Pass null as the parent view because its going in the dialog layout
+ builder.setView(inflater.inflate(R.layout.dialog_signin, null))
+ // Add action buttons
+ .setPositiveButton(R.string.signin, new DialogInterface.OnClickListener() {
+ &#64;Override
+ public void onClick(DialogInterface dialog, int id) {
+ // sign in the user ...
+ }
+ })
+ .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int id) {
+ LoginDialogFragment.this.getDialog().cancel();
+ }
+ });
+ return builder.create();
+}
+</pre>
-<h3 id="ShowingAProgressBar">Showing a progress bar</h3>
+<div class="note">
+<p><strong>Tip:</strong> If you want a custom dialog,
+you can instead display an {@link android.app.Activity} as a dialog
+instead of using the {@link android.app.Dialog} APIs. Simply create an activity and set its theme to
+{@link android.R.style#Theme_Holo_Dialog Theme.Holo.Dialog}
+in the <a href="{@docRoot}guide/topics/manifest/activity-element.html">{@code
+&lt;activity&gt;}</a> manifest element:</p>
-<img src="/images/dialog_progress_bar.png" alt="" style="float:right" />
+<pre>
+&lt;activity android:theme="&#64;android:style/Theme.Holo.Dialog" >
+</pre>
+<p>That's it. The activity now displays in a dialog window instead of fullscreen.</p>
+</div>
-<p>To show the progression with an animated progress bar:</p>
-<ol>
- <li>Initialize the
- ProgressDialog with the class constructor,
- {@link android.app.ProgressDialog#ProgressDialog(Context)}.</li>
- <li>Set the progress style to "STYLE_HORIZONTAL" with
- {@link android.app.ProgressDialog#setProgressStyle(int)} and
- set any other properties, such as the message.</li>
- <li>When you're ready to show the dialog, call
- {@link android.app.Dialog#show()} or return the ProgressDialog from the
- {@link android.app.Activity#onCreateDialog(int)} callback.</li>
- <li>You can increment the amount of progress displayed
- in the bar by calling either {@link android.app.ProgressDialog#setProgress(int)} with a value for
- the total percentage completed so far or {@link android.app.ProgressDialog#incrementProgressBy(int)}
- with an incremental value to add to the total percentage completed so far.</li>
-</ol>
-<p>For example, your setup might look like this:</p>
+<h2 id="PassingEvents">Passing Events Back to the Dialog's Host</h2>
+
+<p>When the user touches one of the dialog's action buttons or selects an item from its list,
+your {@link android.support.v4.app.DialogFragment} might perform the necessary
+action itself, but often you'll want to deliver the event to the activity or fragment that
+opened the dialog. To do this, define an interface with a method for each type of click event.
+Then implement that interface in the host component that will
+receive the action events from the dialog.</p>
+
+<p>For example, here's a {@link android.support.v4.app.DialogFragment} that defines an
+interface through which it delivers the events back to the host activity:</p>
+
<pre>
-ProgressDialog progressDialog;
-progressDialog = new ProgressDialog(mContext);
-progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
-progressDialog.setMessage("Loading...");
-progressDialog.setCancelable(false);
+public class NoticeDialogFragment extends DialogFragment {
+
+ /* The activity that creates an instance of this dialog fragment must
+ * implement this interface in order to receive event callbacks.
+ * Each method passes the DialogFragment in case the host needs to query it. */
+ public interface NoticeDialogListener {
+ public void onDialogPositiveClick(DialogFragment dialog);
+ public void onDialogNegativeClick(DialogFragment dialog);
+ }
+
+ // Use this instance of the interface to deliver action events
+ NoticeDialogListener mListener;
+
+ // Override the Fragment.onAttach() method to instantiate the NoticeDialogListener
+ &#64;Override
+ public void onAttach(Activity activity) {
+ super.onAttach(activity);
+ // Verify that the host activity implements the callback interface
+ try {
+ // Instantiate the NoticeDialogListener so we can send events to the host
+ mListener = (NoticeDialogListener) activity;
+ } catch (ClassCastException e) {
+ // The activity doesn't implement the interface, throw exception
+ throw new ClassCastException(activity.toString()
+ + " must implement NoticeDialogListener");
+ }
+ }
+ ...
+}
</pre>
-<p>The setup is simple. Most of the code needed to create a progress dialog is actually
-involved in the process that updates it. You might find that it's
-necessary to create a second thread in your application for this work and then report the progress
-back to the Activity's UI thread with a {@link android.os.Handler} object.
-If you're not familiar with using additional
-threads with a Handler, see the example Activity below that uses a second thread to
-increment a progress dialog managed by the Activity.</p>
-
-<script type="text/javascript">
-function toggleDiv(link) {
- var toggleable = $(link).parent();
- if (toggleable.hasClass("closed")) {
- $(".toggleme", toggleable).slideDown("fast");
- toggleable.removeClass("closed");
- toggleable.addClass("open");
- $(".toggle-img", toggleable).attr("title", "hide").attr("src", "/assets/images/triangle-opened.png");
- } else {
- $(".toggleme", toggleable).slideUp("fast");
- toggleable.removeClass("open");
- toggleable.addClass("closed");
- $(".toggle-img", toggleable).attr("title", "show").attr("src", "/assets/images/triangle-closed.png");
- }
- return false;
-}
-</script>
-<style>
-.toggleme {
- padding:0 0 1px 0;
-}
-.toggleable a {
- text-decoration:none;
-}
-.toggleable.closed .toggleme {
- display:none;
-}
-#jd-content .toggle-img {
- margin:0;
-}
-</style>
-
-<div class="toggleable closed">
- <a href="#" onclick="return toggleDiv(this)">
- <img src="/assets/images/triangle-closed.png" class="toggle-img" />
- <strong>Example ProgressDialog with a second thread</strong></a>
- <div class="toggleme">
- <p>This example uses a second thread to track the progress of a process (which actually just
-counts up to 100). The thread sends a {@link android.os.Message} back to the main
-Activity through a {@link android.os.Handler} each time progress is made. The main Activity then updates the
-ProgressDialog.</p>
+<p>The activity hosting the dialog creates an instance of the dialog
+with the dialog fragment's constructor and receives the dialog's
+events through an implementation of the {@code NoticeDialogListener} interface:</p>
<pre>
-package com.example.progressdialog;
-
-import android.app.Activity;
-import android.app.Dialog;
-import android.app.ProgressDialog;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.Message;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.widget.Button;
-
-public class NotificationTest extends Activity {
- static final int PROGRESS_DIALOG = 0;
- Button button;
- ProgressThread progressThread;
- ProgressDialog progressDialog;
-
- /** Called when the activity is first created. */
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
-
- // Setup the button that starts the progress dialog
- button = (Button) findViewById(R.id.progressDialog);
- button.setOnClickListener(new OnClickListener(){
- public void onClick(View v) {
- showDialog(PROGRESS_DIALOG);
- }
- });
+public class MainActivity extends FragmentActivity
+ implements NoticeDialogFragment.NoticeDialogListener{
+ ...
+
+ public void showNoticeDialog() {
+ // Create an instance of the dialog fragment and show it
+ DialogFragment dialog = new NoticeDialogFragment();
+ dialog.show(getSupportFragmentManager(), "NoticeDialogFragment");
}
-
- protected Dialog onCreateDialog(int id) {
- switch(id) {
- case PROGRESS_DIALOG:
- progressDialog = new ProgressDialog(NotificationTest.this);
- progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
- progressDialog.setMessage("Loading...");
- return progressDialog;
- default:
- return null;
- }
+
+ // The dialog fragment receives a reference to this Activity through the
+ // Fragment.onAttach() callback, which it uses to call the following methods
+ // defined by the NoticeDialogFragment.NoticeDialogListener interface
+ &#64;Override
+ public void onDialogPositiveClick(DialogFragment dialog) {
+ // User touched the dialog's positive button
+ ...
}
&#64;Override
- protected void onPrepareDialog(int id, Dialog dialog) {
- switch(id) {
- case PROGRESS_DIALOG:
- progressDialog.setProgress(0);
- progressThread = new ProgressThread(handler);
- progressThread.start();
+ public void onDialogNegativeClick(DialogFragment dialog) {
+ // User touched the dialog's negative button
+ ...
}
+}
+</pre>
- // Define the Handler that receives messages from the thread and update the progress
- final Handler handler = new Handler() {
- public void handleMessage(Message msg) {
- int total = msg.arg1;
- progressDialog.setProgress(total);
- if (total >= 100){
- dismissDialog(PROGRESS_DIALOG);
- progressThread.setState(ProgressThread.STATE_DONE);
- }
- }
- };
-
- /** Nested class that performs progress calculations (counting) */
- private class ProgressThread extends Thread {
- Handler mHandler;
- final static int STATE_DONE = 0;
- final static int STATE_RUNNING = 1;
- int mState;
- int total;
-
- ProgressThread(Handler h) {
- mHandler = h;
- }
-
- public void run() {
- mState = STATE_RUNNING;
- total = 0;
- while (mState == STATE_RUNNING) {
- try {
- Thread.sleep(100);
- } catch (InterruptedException e) {
- Log.e("ERROR", "Thread Interrupted");
- }
- Message msg = mHandler.obtainMessage();
- msg.arg1 = total;
- mHandler.sendMessage(msg);
- total++;
- }
- }
-
- /* sets the current state for the thread,
- * used to stop the thread */
- public void setState(int state) {
- mState = state;
- }
+<p>Because the host activity implements the {@code NoticeDialogListener}&mdash;which is
+enforced by the {@link android.support.v4.app.Fragment#onAttach onAttach()}
+callback method shown above&mdash;the dialog fragment can use the
+interface callback methods to deliver click events to the activity:</p>
+
+<pre>
+public class NoticeDialogFragment extends DialogFragment {
+ ...
+
+ &#64;Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ // Build the dialog and set up the button click handlers
+ AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
+ builder.setMessage(R.string.dialog_fire_missiles)
+ .setPositiveButton(R.string.fire, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int id) {
+ // Send the positive button event back to the host activity
+ mListener.onDialogPositiveClick(NoticeDialogFragment.this);
+ }
+ })
+ .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int id) {
+ // Send the negative button event back to the host activity
+ mListener.onDialogPositiveClick(NoticeDialogFragment.this);
+ }
+ });
+ return builder.create();
}
}
</pre>
- </div> <!-- end toggleme -->
-</div> <!-- end toggleable -->
-<h2 id="CustomDialog">Creating a Custom Dialog</h2>
+<h2 id="ShowingADialog">Showing a Dialog</h2>
+
+<p>When you want to show your dialog, create an instance of your {@link
+android.support.v4.app.DialogFragment} and call {@link android.support.v4.app.DialogFragment#show
+show()}, passing the {@link android.support.v4.app.FragmentManager} and a tag name
+for the dialog fragment.</p>
+
+<p>You can get the {@link android.support.v4.app.FragmentManager} by calling
+{@link android.support.v4.app.FragmentActivity#getSupportFragmentManager()} from
+the {@link android.support.v4.app.FragmentActivity} or {@link
+android.support.v4.app.Fragment#getFragmentManager()} from a {@link
+android.support.v4.app.Fragment}. For example:</p>
+
+<pre>
+public void confirmFireMissiles() {
+ DialogFragment newFragment = new FireMissilesDialogFragment();
+ newFragment.show(getSupportFragmentManager(), "missiles");
+}
+</pre>
+
+<p>The second argument, {@code "missiles"}, is a unique tag name that the system uses to save
+and restore the fragment state when necessary. The tag also allows you to get a handle to
+the fragment by calling {@link android.support.v4.app.FragmentManager#findFragmentByTag
+findFragmentByTag()}.</p>
+
+
-<img src="{@docRoot}images/dialog_custom.png" alt="" style="float:right" />
-<p>If you want a customized design for a dialog, you can create your own layout
-for the dialog window with layout and widget elements.
-After you've defined your layout, pass the root View object or
-layout resource ID to {@link android.app.Dialog#setContentView(View)}.</p>
+<h2 id="FullscreenDialog">Showing a Dialog Fullscreen or as an Embedded Fragment</h2>
-<p>For example, to create the dialog shown to the right:</p>
+<p>You might have a UI design in which you want a piece of the UI to appear as a dialog in some
+situations, but as a full screen or embedded fragment in others (perhaps depending on whether
+the device is a large screen or small screen). The {@link android.support.v4.app.DialogFragment}
+class offers you this flexibility because it can still behave as an embeddable {@link
+android.support.v4.app.Fragment}.</p>
+
+<p>However, you cannot use {@link android.app.AlertDialog.Builder AlertDialog.Builder}
+or other {@link android.app.Dialog} objects to build the dialog in this case. If
+you want the {@link android.support.v4.app.DialogFragment} to be
+embeddable, you must define the dialog's UI in a layout, then load the layout in the
+{@link android.support.v4.app.DialogFragment#onCreateView
+onCreateView()} callback.</p>
+
+<p>Here's an example {@link android.support.v4.app.DialogFragment} that can appear as either a
+dialog or an embeddable fragment (using a layout named <code>purchase_items.xml</code>):</p>
-<ol>
- <li>Create an XML layout saved as <code>custom_dialog.xml</code>:
<pre>
-&lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/layout_root"
- android:orientation="horizontal"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:padding="10dp"
- >
- &lt;ImageView android:id="@+id/image"
- android:layout_width="wrap_content"
- android:layout_height="fill_parent"
- android:layout_marginRight="10dp"
- />
- &lt;TextView android:id="@+id/text"
- android:layout_width="wrap_content"
- android:layout_height="fill_parent"
- android:textColor="#FFF"
- />
-&lt;/LinearLayout>
+public class CustomDialogFragment extends DialogFragment {
+ /** The system calls this to get the DialogFragment's layout, regardless
+ of whether it's being displayed as a dialog or an embedded fragment. */
+ &#64;Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ // Inflate the layout to use as dialog or embedded fragment
+ return inflater.inflate(R.layout.purchase_items, container, false);
+ }
+
+ /** The system calls this only when creating the layout in a dialog. */
+ &#64;Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ // The only reason you might override this method when using onCreateView() is
+ // to modify any dialog characteristics. For example, the dialog includes a
+ // title by default, but your custom layout might not need it. So here you can
+ // remove the dialog title, but you must call the superclass to get the Dialog.
+ Dialog dialog = super.onCreateDialog(savedInstanceState);
+ dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
+ return dialog;
+ }
+}
+</pre>
+
+<p>And here's some code that decides whether to show the fragment as a dialog
+or a fullscreen UI, based on the screen size:</p>
+
+<pre>
+public void showDialog() {
+ FragmentManager fragmentManager = getSupportFragmentManager();
+ CustomDialogFragment newFragment = new CustomDialogFragment();
+
+ if (mIsLargeLayout) {
+ // The device is using a large layout, so show the fragment as a dialog
+ newFragment.show(fragmentManager, "dialog");
+ } else {
+ // The device is smaller, so show the fragment fullscreen
+ FragmentTransaction transaction = fragmentManager.beginTransaction();
+ // For a little polish, specify a transition animation
+ transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
+ // To make it fullscreen, use the 'content' root view as the container
+ // for the fragment, which is always the root view for the activity
+ transaction.add(android.R.id.content, newFragment)
+ .addToBackStack(null).commit();
+ }
+}
+</pre>
+
+<p>For more information about performing fragment transactions, see the
+<a href="{@docRoot}guide/components/fragments.html">Fragments</a> guide.</p>
+
+<p>In this example, the <code>mIsLargeLayout</code> boolean specifies whether the current device
+should use the app's large layout design (and thus show this fragment as a dialog, rather
+than fullscreen). The best way to set this kind of boolean is to declare a
+<a href="{@docRoot}guide/topics/resources/more-resources.html#Bool">bool resource value</a>
+with an <a href="{@docRoot}guide/topics/resources/providing-resources.html#AlternativeResources"
+>alternative resource</a> value for different screen sizes. For example, here are two
+versions of the bool resource for different screen sizes:</p>
+
+<p class="code-caption">res/values/bools.xml</p>
+<pre>
+&lt;!-- Default boolean values -->
+&lt;resources>
+ &lt;bool name="large_layout">false&lt;/bool>
+&lt;/resources>
+</pre>
+
+<p class="code-caption">res/values-large/bools.xml</p>
+<pre>
+&lt;!-- Large screen boolean values -->
+&lt;resources>
+ &lt;bool name="large_layout">true&lt;/bool>
+&lt;/resources>
</pre>
- <p>This XML defines an {@link android.widget.ImageView} and a {@link android.widget.TextView}
- inside a {@link android.widget.LinearLayout}.</p>
- <li>Set the above layout as the dialog's content view and define the content
- for the ImageView and TextView elements:</p>
+<p>Then you can initialize the {@code mIsLargeLayout} value during the activity's
+{@link android.app.Activity#onCreate onCreate()} method:</p>
+
<pre>
-Context mContext = getApplicationContext();
-Dialog dialog = new Dialog(mContext);
+boolean mIsLargeLayout;
-dialog.setContentView(R.layout.custom_dialog);
-dialog.setTitle("Custom Dialog");
+&#64;Override
+public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_main);
-TextView text = (TextView) dialog.findViewById(R.id.text);
-text.setText("Hello, this is a custom dialog!");
-ImageView image = (ImageView) dialog.findViewById(R.id.image);
-image.setImageResource(R.drawable.android);
+ mIsLargeLayout = getResources().getBoolean(R.bool.large_layout);
+}
</pre>
- <p>After you instantiate the Dialog, set your custom layout as the dialog's content view with
- {@link android.app.Dialog#setContentView(int)}, passing it the layout resource ID.
- Now that the Dialog has a defined layout, you can capture View objects from the layout with
- {@link android.app.Dialog#findViewById(int)} and modify their content.</p>
- </li>
- <li>That's it. You can now show the dialog as described in
- <a href="#ShowingADialog">Showing A Dialog</a>.</li>
-</ol>
-<p>A dialog made with the base Dialog class must have a title. If you don't call
-{@link android.app.Dialog#setTitle(CharSequence) setTitle()}, then the space used for the title
-remains empty, but still visible. If you don't want
-a title at all, then you should create your custom dialog using the
-{@link android.app.AlertDialog} class. However, because an AlertDialog is created easiest with
-the {@link android.app.AlertDialog.Builder} class, you do not have access to the
-{@link android.app.Dialog#setContentView(int)} method used above. Instead, you must use
-{@link android.app.AlertDialog.Builder#setView(View)}. This method accepts a {@link android.view.View} object,
-so you need to inflate the layout's root View object from
-XML.</p>
-
-<p>To inflate the XML layout, retrieve the {@link android.view.LayoutInflater} with
-{@link android.app.Activity#getLayoutInflater()}
-(or {@link android.content.Context#getSystemService(String) getSystemService()}),
-and then call
-{@link android.view.LayoutInflater#inflate(int, ViewGroup)}, where the first parameter
-is the layout resource ID and the second is the ID of the root View. At this point, you can use
-the inflated layout to find View objects in the layout and define the content for the
-ImageView and TextView elements. Then instantiate the AlertDialog.Builder and set the
-inflated layout for the dialog with {@link android.app.AlertDialog.Builder#setView(View)}.</p>
-
-<p>Here's an example, creating a custom layout in an AlertDialog:</p>
+<h3 id="ActivityAsDialog">Showing an activity as a dialog on large screens</h3>
+
+<p>Instead of showing a dialog as a fullscreen UI when on small screens, you can accomplish
+the same result by showing an {@link android.app.Activity} as a dialog when on
+large screens. Which approach you choose depends on your app design, but
+showing an activity as a dialog is often useful when your app is already designed for small
+screens and you'd like to improve the experience on tablets by showing a short-lived activity
+as a dialog.</p>
+
+<p>To show an activity as a dialog only when on large screens,
+apply the {@link android.R.style#Theme_Holo_DialogWhenLarge Theme.Holo.DialogWhenLarge}
+theme to the <a href="{@docRoot}guide/topics/manifest/activity-element.html">{@code
+&lt;activity&gt;}</a> manifest element:</p>
<pre>
-AlertDialog.Builder builder;
-AlertDialog alertDialog;
-
-Context mContext = getApplicationContext();
-LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(LAYOUT_INFLATER_SERVICE);
-View layout = inflater.inflate(R.layout.custom_dialog,
- (ViewGroup) findViewById(R.id.layout_root));
-
-TextView text = (TextView) layout.findViewById(R.id.text);
-text.setText("Hello, this is a custom dialog!");
-ImageView image = (ImageView) layout.findViewById(R.id.image);
-image.setImageResource(R.drawable.android);
-
-builder = new AlertDialog.Builder(mContext);
-builder.setView(layout);
-alertDialog = builder.create();
+&lt;activity android:theme="&#64;android:style/Theme.Holo.DialogWhenLarge" >
</pre>
-<p>Using an AlertDialog for your custom layout lets you
-take advantage of built-in AlertDialog features like managed buttons,
-selectable lists, a title, an icon and so on.</p>
+<p>For more information about styling your activities with themes, see the <a
+href="{@docRoot}guide/topics/ui/themes.html">Styles and Themes</a> guide.</p>
+
-<p>For more information, refer to the reference documentation for the
-{@link android.app.Dialog} and {@link android.app.AlertDialog.Builder}
-classes.</p>
+<h2 id="DismissingADialog">Dismissing a Dialog</h2>
+
+<p>When the user touches any of the action buttons created with an
+{@link android.app.AlertDialog.Builder}, the system dismisses the dialog for you.</p>
+
+<p>The system also dismisses the dialog when the user touches an item in a dialog list, except
+when the list uses radio buttons or checkboxes. Otherwise, you can manually dismiss your dialog
+by calling {@link android.support.v4.app.DialogFragment#dismiss()} on your {@link
+android.support.v4.app.DialogFragment}.</p>
+
+<p>In case you need to perform certain
+actions when the dialog goes away, you can implement the {@link
+android.support.v4.app.DialogFragment#onDismiss onDismiss()} method in your {@link
+android.support.v4.app.DialogFragment}.</p>
+
+<p>You can also <em>cancel</em> a dialog. This is a special event that indicates the user
+explicitly left the dialog without completing the task. This occurs if the user presses the
+<em>Back</em> button, touches the screen outside the dialog area,
+or if you explicitly call {@link android.app.Dialog#cancel()} on the {@link
+android.app.Dialog} (such as in response to a "Cancel" button in the dialog).</p>
+
+<p>As shown in the example above, you can respond to the cancel event by implementing
+{@link android.support.v4.app.DialogFragment#onCancel onCancel()} in your {@link
+android.support.v4.app.DialogFragment} class.</p>
+
+<p class="note"><strong>Note:</strong> The system calls
+{@link android.support.v4.app.DialogFragment#onDismiss onDismiss()} upon each event that
+invokes the {@link android.support.v4.app.DialogFragment#onCancel onCancel()} callback. However,
+if you call {@link android.app.Dialog#dismiss Dialog.dismiss()} or {@link
+android.support.v4.app.DialogFragment#dismiss DialogFragment.dismiss()},
+the system calls {@link android.support.v4.app.DialogFragment#onDismiss onDismiss()} <em>but
+not</em> {@link android.support.v4.app.DialogFragment#onCancel onCancel()}. So you should generally
+call {@link android.support.v4.app.DialogFragment#dismiss dismiss()} when the user presses the
+<em>positive</em> button in your dialog in order to remove the dialog from view.</p>
diff --git a/docs/html/guide/topics/ui/notifiers/notifications.jd b/docs/html/guide/topics/ui/notifiers/notifications.jd
index 273b5f7..8026b7d 100644
--- a/docs/html/guide/topics/ui/notifiers/notifications.jd
+++ b/docs/html/guide/topics/ui/notifiers/notifications.jd
@@ -1,646 +1,998 @@
-page.title=Status Notifications
-parent.title=Notifications
-parent.link=index.html
+page.title=Notifications
@jd:body
<div id="qv-wrapper">
- <div id="qv">
- <h2>Quickview</h2>
- <ul>
- <li>A status notification allows your application to notify the user of an event
-without interupting their current activity</li>
- <li>You can attach an intent to your notification that the system will initiate when the
-user clicks it</li>
- </ul>
-
- <h2>In this document</h2>
+<div id="qv">
+<h2>In this document</h2>
+<ol>
+ <li><a href="#NotificationUI">Notification Display Elements</a>
<ol>
- <li><a href="#Basics">The Basics</a></li>
- <li><a href="#HandlingNotifications">Responding to Notifications</a></li>
- <li><a href="#ManageYourNotifications">Managing your Notifications</a></li>
- <li><a href="#CreateANotification">Creating a Notification</a>
- <ol>
- <li><a href="#Updating">Updating the notification</a></li>
- <li><a href="#Sound">Adding a sound</a></li>
- <li><a href="#Vibration">Adding vibration</a></li>
- <li><a href="#Lights">Adding flashing lights</a></li>
- <li><a href="#More">More features</a></li>
- </ol>
- </li>
- <li><a href="#CustomExpandedView">Creating a Custom Notification Layout</a></li>
+ <li><a href="#NormalNotify">Normal view</a></li>
+ <li><a href="#BigNotify">Big view</a></li>
</ol>
- <h2>Key classes</h2>
+ </li>
+ <li><a href="#CreateNotification">Creating a Notification</a>
<ol>
- <li>{@link android.app.Notification}</li>
- <li>{@link android.app.NotificationManager}</li>
+ <li><a href="#Required">Required notification contents</a></li>
+ <li><a href="#Optional">Optional notification contents and settings</a></li>
+ <li><a href="#Actions">Notification actions</a></li>
+ <li><a href="#SimpleNotification">Creating a simple notification</a></li>
+ <li><a href="#ApplyStyle">Applying a big view style to a notification</a></li>
+ <li><a href="#Compatibility">Handling compatibility</a></li>
</ol>
-
- <h2>See also</h2>
+ </li>
+ <li><a href="#Managing">Managing Notifications</a>
<ol>
- <li><a href="{@docRoot}design/patterns/notifications.html">Android
-Design: Notifications</a></li>
+ <li><a href="#Updating">Updating notifications</a></li>
+ <li><a href="#Removing">Removing notifications</a></li>
</ol>
- </div>
-</div>
-
-<p>A status notification adds an icon to the system's status bar
-(with an optional ticker-text message) and a notification message in the notifications window.
-When the user selects the notification, Android fires an
-{@link android.content.Intent} that is defined by the {@link android.app.Notification} (usually to
-launch an {@link android.app.Activity}).
-You can also configure the notification to alert the user with a sound, a vibration, and flashing
-lights on the device.</p>
-
-<p>A status notification should be used for any case in
-which a background service needs to alert the user about an event that requires a response. A
-background service
-<strong>should never</strong> launch an activity on its own in order to receive user interaction.
-The service should instead create a status notification that will launch the activity
-when selected by the user.</p>
-
-<p>Figure 1 shows the status bar with a notification icon on the left side.</p>
-<img src="{@docRoot}images/status_bar.png" alt="" />
-<p class="img-caption"><strong>Figure 1.</strong> Status bar with a notification.</p>
-
-<p>Figure 2 shows the notification's message in the notifications window.</p>
-
-<img src="{@docRoot}images/notifications_window.png" alt="" />
-<p class="img-caption"><strong>Figure 2.</strong> The notifications window.</p>
-
-
-<div class="note design">
-<p><strong>Notification Design</strong></p>
- <p>For design guidelines, read Android Design's <a
-href="{@docRoot}design/patterns/notifications.html">Notifications</a> guide.</p>
-</div>
-
-
-
-<h2 id="Basics">The Basics</h2>
-
-<p>An {@link android.app.Activity} or {@link android.app.Service} can initiate a status
-notification. Because an activity can perform actions only while it is
-running in the foreground and its window has focus, you will usually create status notifications
-from a
-service. This way, the notification can be created from the background,
-while the user is using another application or
-while the device is asleep. To create a notification, you must use two
-classes: {@link android.app.Notification} and {@link android.app.NotificationManager}.</p>
-
-<p>Use an instance of the {@link android.app.Notification} class to define the properties of your
-status notification, such as the status icon, the notification message, and extra settings
-such as a sound to play. The {@link android.app.NotificationManager} is an Android system service
-that executes and manages all status notifications. You do not instantiate the
-{@link android.app.NotificationManager} directly. In order
-to give it your {@link android.app.Notification}, you must retrieve a reference to the
-{@link android.app.NotificationManager} with
-{@link android.app.Activity#getSystemService(String) getSystemService()} and
-then, when you want to notify the user, pass it your {@link android.app.Notification} with
-{@link android.app.NotificationManager#notify(int,Notification) notify()}. </p>
-
-<p>To create a status notification:</p>
-<ol>
- <li>Get a reference to the {@link android.app.NotificationManager}:
-<pre>
-String ns = Context.NOTIFICATION_SERVICE;
-NotificationManager mNotificationManager = (NotificationManager) getSystemService(ns);
-</pre>
</li>
- <!-- use Notification.Builder in 3.0 -->
- <li>Instantiate the {@link android.app.Notification}:
-<pre>
-int icon = R.drawable.notification_icon;
-CharSequence tickerText = "Hello";
-long when = System.currentTimeMillis();
-
-Notification notification = new Notification(icon, tickerText, when);
-</pre>
- </li>
- <li>Define the notification's message and {@link android.app.PendingIntent}:
-<pre>
-Context context = getApplicationContext();
-CharSequence contentTitle = "My notification";
-CharSequence contentText = "Hello World!";
-Intent notificationIntent = new Intent(this, MyClass.class);
-PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
-
-notification.setLatestEventInfo(context, contentTitle, contentText, contentIntent);
-</pre>
+ <li><a href="#NotificationResponse">Preserving Navigation when Starting an Activity</a>
+ <ol>
+ <li><a href="#DirectEntry">Setting up a regular activity PendingIntent</a></li>
+ <li><a href="#ExtendedNotification">Setting up a special activity PendingIntent</a></li>
+ </ol>
</li>
- <li>Pass the {@link android.app.Notification} to the {@link android.app.NotificationManager}:
-<pre>
-private static final int HELLO_ID = 1;
-
-mNotificationManager.notify(HELLO_ID, notification);
-</pre>
- <p>That's it. Your user has now been notified.</p>
+ <li><a href="#Progress">Displaying Progress in a Notification</a>
+ <ol>
+ <li><a href="#FixedProgress">Displaying a fixed-duration progress indicator</a></li>
+ <li><a href="#ActivityIndicator">Displaying a continuing activity indicator</a></li>
+ </ol>
</li>
+ <li><a href="#CustomNotification">Custom Notification Layouts</a></li>
</ol>
-
-<h2 id="HandlingNotifications">Responding to Notifications</h2>
-
-<p>A central part of the user's experience with a notification revolves around
-how it interacts with the application's UI flow. You must implement
-this correctly to provide a consistent user experience within your app.</p>
-
-<p>Two typical examples of notifications are provided by Calendar, which can send out
-notifications of upcoming events, and Email, which can send out notifications
-when new messages arrive. These represent the two recommended patterns for handling
-notifications: either launching into an activity that is separate from the
-main application, or launching an entirely new instance of the application
-showing the appropriate point for the notification.</p>
-
-<p>The following scenario shows how the activity stack should work
-in these two typical notification flows, first handling a Calendar notification:
-</p>
-
+ <h2>Key classes</h2>
+ <ol>
+ <li>{@link android.app.NotificationManager}</li>
+ <li>{@link android.support.v4.app.NotificationCompat}</li>
+ </ol>
+ <h2>Videos</h2>
+ <ol>
+ <li>
+ <a href="http://www.youtube.com/watch?v=Yc8YrVc47TI&feature=player_detailpage#t=1672s">
+ Notifications in 4.1</a>
+ </li>
+ </ol>
+<h2>See also</h2>
<ol>
- <li>User is creating a new event in Calendar. They realize they
- need to copy part of an email message into this event.
- </li>
- <li>
- The user chooses Home &gt; Email.
- </li>
- <li>
- While in Email, they receive a notification from Calendar for an upcoming
- meeting.
- </li>
- <li>
- So they choose that notification, which takes them to a
- dedicated Calendar activity that displays brief details of the
- upcoming meeting.
- </li>
- <li>
- The user has seen enough to know they have a meeting coming up,
- so they press the <em>Back</em> button. They are now returned to Email, which
- is where they were when they took the notification.
- </li>
+ <li>
+ <a href="{@docRoot}design/patterns/notifications.html">Android Design: Notifications</a>
+ </li>
</ol>
-
-<p>Handling an Email notification:</p>
-
+</div>
+</div>
+<p>
+ A notification is a message you can display to the user outside of your application's
+ normal UI. When you tell the system to issue a notification, it first appears as an icon in the
+ <strong>notification area</strong>. To see the details of the notification, the user opens the
+ <strong>notification drawer</strong>. Both the notification area and the notification drawer
+ are system-controlled areas that the user can view at any time.
+</p>
+<img
+ id="figure1"
+ src="{@docRoot}images/ui/notifications/iconic_notification.png"
+ height="120" alt="" />
+<p class="img-caption">
+ <strong>Figure 1.</strong> Notifications in the notification area.
+</p>
+<img id="figure2" src="{@docRoot}images/ui/notifications/normal_notification.png"
+ height="293" alt="" />
+<p class="img-caption">
+ <strong>Figure 2.</strong> Notifications in the notification drawer.
+</p>
+<div class="note design">
+ <p>
+ <strong>Notification Design</strong>
+ </p>
+ <p>
+ Notifications, as an important part of the Android UI, have their own design guidelines. To
+ learn how to design notifications and their interactions, read the Android Design Guide
+ <a href="{@docRoot}design/patterns/notifications.html">Notifications</a> topic.
+ </p>
+</div>
+<p class="note">
+ <strong>Note:</strong> Except where noted, this guide refers to the
+ {@link android.support.v4.app.NotificationCompat.Builder NotificationCompat.Builder} class
+ in the version 4 <a href="{@docRoot}tools/extras/support-library.html">Support Library</a>.
+ The class {@link android.app.Notification.Builder Notification.Builder} was added in Android
+ 3.0.
+</p>
+<!-- ------------------------------------------------------------------------------------------ -->
+<!-- ------------------------------------------------------------------------------------------ -->
+<h2 id="NotificationUI">Notification Display Elements</h2>
+<p>
+ Notifications in the notification drawer can appear in one of two visual styles, depending on
+ the version and the state of the drawer:
+</p>
+<dl>
+ <dt>
+ Normal view
+ </dt>
+ <dd>
+ The standard view of the notifications in the notification drawer.
+ </dd>
+ <dt>
+ Big view
+ </dt>
+ <dd>
+ A large view that's visible when the notification is expanded. Big view is part of the
+ expanded notification feature available as of Android 4.1.
+ </dd>
+</dl>
+<p>
+ These styles are described in the following sections.
+</p>
+<!-- ------------------------------------------------------------------------------------------ -->
+<h3 id="NormalNotify">Normal view</h3>
+<p>
+ A notification in normal view appears in an area that's up to 64 dp tall. Even if you create a
+ notification with a big view style, it will appear in normal view until it's expanded. This
+ is an example of a normal view:
+</p>
+<img
+ src="{@docRoot}images/ui/notifications/normal_notification_callouts.png"
+ alt=""
+ height="153"
+ id="figure3" />
+<p class="img-caption">
+ <strong>Figure 3.</strong> Notification in normal view.
+</p>
+<p>
+ The callouts in the illustration refer to the following:
+</p>
<ol>
- <li>
- The user is currently in Email composing a message, and needs to
- check a date in their calendar.
- </li>
- <li>
- The user chooses Home &gt; Calendar.
- </li>
- <li>
- While in Calendar, they receive a notification from Email about a new
- message.
- </li>
- <li>
- They select the notification, which brings them to Email with the message
- details displayed. This has replaced what they were previously doing
- (writing an e-mail), but that message is still saved in their drafts.
- </li>
- <li>
- The user presses <em>Back</em> once to go to the message list (the typical flow in the
- Email app), and press <em>Back</em> again to return to Calendar as they left it.
- </li>
+ <li>Content title</li>
+ <li>Large icon</li>
+ <li>Content text</li>
+ <li>Content info</li>
+ <li>Small icon</li>
+ <li>
+ Time that the notification was issued. You can set an explicit value with
+ {@link android.support.v4.app.NotificationCompat.Builder#setWhen setWhen()}; if you don't
+ it defaults to the time that the system received the notification.
+ </li>
</ol>
-
-<p>In an Email style of notification, the UI launched by the notification
-shows the main application in a state representing that notification.
-For example, when the Email application comes to the foreground from its
-notification, it displays either the conversion list or a specific
-conversation depending on whether there are multiple or only one new
-email. To achieve this, we want to completely replace whatever current
-state the application is in with a new activity stack representing the
-new notification state.</p>
-
-<p>The following code illustrates how to show this kind of notification. Of
-most interest is the <code>makeMessageIntentStack()</code> method, which constructs
-an array of intents representing the app's new activity stack for this state.
-(If you are using fragments, you may need to initialize your fragment and
-app state so that pressing <em>Back</em> will switch the UI back to its parent state.)
-The core of this is the {@link android.content.Intent#makeRestartActivityTask
-Intent.makeRestartActivityTask()} method, which constructs the root activity
-of the stack with the appropriate flags, such as
-{@link android.content.Intent#FLAG_ACTIVITY_CLEAR_TASK Intent.FLAG_ACTIVITY_CLEAR_TASK}.</p>
-
-{@sample development/samples/ApiDemos/src/com/example/android/apis/app/IncomingMessage.java
- app_notification}
-
-<p>In a Calendar style of notification, the UI launched by the notification
-is a dedicated activity that is not part of the normal application flow.
-For example, when the user receives a Calendar notification, choosing that
-notification starts a special activity that displays a list
-of upcoming calendar events &mdash; this view is available only
-from the notification, not through the Calendar's normal user
-interface.</p>
-
-<p>The code for posting this type of notification is very straight-forward; it
-is like the above, but the {@link android.app.PendingIntent} is for just a single
-activity, our dedicated notification activity.</p>
-
-{@sample development/samples/ApiDemos/src/com/example/android/apis/app/IncomingMessage.java
- interstitial_notification}
-
-<p>This is not enough, however. Normally Android considers all activities within
-an application to be part of that application's UI flow, so simply launching the
-activity like this can cause it to be mixed with your normal application back stack
-in undesired ways. To make it behave correctly, in the manifest declaration
-for the activity the attributes
-<code>android:launchMode="singleTask"</code>,
-<code>android:taskAffinity=""</code> and
-<code>android:excludeFromRecents="true"</code>
-must be set. The full activity declaration for this sample is:</p>
-
-{@sample development/samples/ApiDemos/AndroidManifest.xml interstitial_affinity}
-
-<p>You must be careful when launching other activities from this initial activity,
-because this is not a top-level part of the application, does not appear in
-recents, and needs to be relaunched at any point from the notification with new data
-to show. This best approach is to make sure any activity launched from it is
-launched in its own task. When doing this care must be taken to make sure this
-new task interacts well with the current state of your exiting application's
-task. This is essentially
-the same as switching to the main application as described for the Email style
-notification shown before. Given the <code>makeMessageIntentStack()</code>
-method previously shown, handling a click then would look something like this:</p>
-
-{@sample development/samples/ApiDemos/src/com/example/android/apis/app/IncomingMessageInterstitial.java
- app_launch}
-
-<h2 id="ManageYourNotifications">Managing your Notifications</h2>
-
-<p>The {@link android.app.NotificationManager} is a system service that manages all
-notifications. You must retrieve a reference to it with the
-{@link android.app.Activity#getSystemService(String) getSystemService()} method.
-For example:</p>
-<pre>
-String ns = Context.NOTIFICATION_SERVICE;
-NotificationManager mNotificationManager = (NotificationManager) getSystemService(ns);
-</pre>
-
-<p>When you want to deliver your status notification, pass the {@link android.app.Notification}
-to the {@link android.app.NotificationManager} with {@link
-android.app.NotificationManager#notify(int,Notification)}.
-The first parameter is the unique ID for the notification and the second is the {@link
-android.app.Notification} object.
-The ID uniquely identifies the notification from within your
-application. The ID is necessary if you need to update the notification or (if
-your application manages different kinds of notifications) select the appropriate action
-when the user returns to your application via the intent defined in the notification.</p>
-
-<p>To clear the status notification when the user selects it from the notifications
-window, add the "FLAG_AUTO_CANCEL" flag to your {@link android.app.Notification}. You can
-also clear it manually with {@link android.app.NotificationManager#cancel(int)}, passing it the
-notification ID, or clear all your notifications with {@link
-android.app.NotificationManager#cancelAll()}.</p>
-
-
-<h2 id="CreateANotification">Creating a Notification</h2>
-
-<p>A {@link android.app.Notification} object defines the details of the notification
-message that is displayed in the status bar and notifications window, and any other
-alert settings, such as sounds and blinking lights.</p>
-
-<p>A status notification <em>requires</em> all of the following:</p>
-<ul>
- <li>An icon for the status bar</li>
- <li>A title and message, unless you define a
- <a href="#CustomExpandedView">custom notification layout</a></li>
- <li>A {@link android.app.PendingIntent}, to be fired when the notification is selected</li>
-</ul>
-<p>Optional settings for the status notification include:</p>
+<!-- ------------------------------------------------------------------------------------------ -->
+<h3 id="BigNotify">Big view</h3>
+<p>
+ A notification's big view appears only when the notification is expanded, which happens when the
+ notification is at the top of the notification drawer, or when the user expands the
+ notification with a gesture. Expanded notifications are available starting with Android 4.1.
+</p>
+<p>
+ The following screenshot shows an inbox-style notification:
+</p>
+<img src="{@docRoot}images/ui/notifications/bigpicture_notification_callouts.png"
+ alt=""
+ height="240"
+ id="figure4" />
+<p class="img-caption">
+ <strong>Figure 4.</strong> Big view notification.
+</p>
+<p>
+ Notice that the big view shares most of its visual elements with the normal view. The
+ only difference is callout number 7, the details area. Each big view style sets this area in
+ a different way. The available styles are:
+</p>
+<dl>
+ <dt>
+ Big picture style
+ </dt>
+ <dd>
+ The details area contains a bitmap up to 256 dp tall in its detail section.
+ </dd>
+ <dt>
+ Big text style
+ </dt>
+ <dd>
+ Displays a large text block in the details section.
+ </dd>
+ <dt>
+ Inbox style
+ </dt>
+ <dd>
+ Displays lines of text in the details section.
+ </dd>
+</dl>
+<p>
+ All of the big view styles also have the following content options that aren't
+ available in normal view:
+</p>
+<dl>
+ <dt>
+ Big content title
+ </dt>
+ <dd>
+ Allows you to override the normal view's content title with a title that appears only in
+ the expanded view.
+ </dd>
+ <dt>
+ Summary text
+ </dt>
+ <dd>
+ Allows you to add a line of text below the details area.
+ </dd>
+</dl>
+<p>
+ Applying a big view style to a notification is described in the section
+ <a href="#ApplyStyle">Applying a big view style to a notification</a>.
+</p>
+<!-- ------------------------------------------------------------------------------------------ -->
+<!-- ------------------------------------------------------------------------------------------ -->
+<h2 id="CreateNotification">Creating a Notification</h2>
+<p>
+ You specify the UI information and actions for a notification in a
+ {@link android.support.v4.app.NotificationCompat.Builder NotificationCompat.Builder} object.
+ To create the notification itself, you call
+ {@link android.support.v4.app.NotificationCompat.Builder#build
+ NotificationCompat.Builder.build()}, which returns a {@link android.app.Notification} object
+ containing your specifications.
+ To issue the notification, you pass the {@link android.app.Notification} object to the system
+ by calling {@link android.app.NotificationManager#notify NotificationManager.notify()}.
+</p>
+<!-- ------------------------------------------------------------------------------------------ -->
+<h3 id="Required">Required notification contents</h3>
+<p>
+ A {@link android.app.Notification} object <em>must</em> contain the following:
+</p>
<ul>
- <li>A ticker-text message for the status bar</li>
- <li>An alert sound</li>
- <li>A vibrate setting</li>
- <li>A flashing LED setting</li>
+ <li>
+ A small icon, set by
+ {@link android.support.v4.app.NotificationCompat.Builder#setSmallIcon setSmallIcon()}
+ </li>
+ <li>
+ A title, set by
+ {@link android.support.v4.app.NotificationCompat.Builder#setContentTitle setContentTitle()}
+ </li>
+ <li>
+ Detail text, set by
+ {@link android.support.v4.app.NotificationCompat.Builder#setContentText setContentText()}
+ </li>
</ul>
-
-<p>The starter-kit for a new notification includes the
-{@link android.app.Notification#Notification(int,CharSequence,long)} constructor and the
-{@link android.app.Notification#setLatestEventInfo(Context,CharSequence,CharSequence,PendingIntent)}
-method. These define all the required settings for a notification.
-The following snippet demonstrates a basic notification setup:</p>
-<pre>
-int icon = R.drawable.notification_icon; // icon from resources
-CharSequence tickerText = "Hello"; // ticker-text
-long when = System.currentTimeMillis(); // notification time
-Context context = getApplicationContext(); // application Context
-CharSequence contentTitle = "My notification"; // message title
-CharSequence contentText = "Hello World!"; // message text
-
-Intent notificationIntent = new Intent(this, MyClass.class);
-PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
-
-// the next two lines initialize the Notification, using the configurations above
-Notification notification = new Notification(icon, tickerText, when);
-notification.setLatestEventInfo(context, contentTitle, contentText, contentIntent);
-</pre>
-
-
-<h3 id="Updating">Updating the notification</h3>
-
-<p>You can update the information in your status notification as events
-continue to occur in your application. For example, when a new SMS text message arrives
-before previous messages have been read, the Messaging application updates the existing
-notification to display the total number of new messages received.
-This practice of updating an existing notification is much better than adding new
-notifications, because it avoids clutter in the notifications window.</p>
-
-<p>Because each notification is uniquely identified
-by the {@link android.app.NotificationManager} with an integer ID, you can revise the notification
-by calling {@link
-android.app.Notification#setLatestEventInfo(Context,CharSequence,CharSequence,PendingIntent)
-setLatestEventInfo()} with new values, change some field values of the notification, and then call
-{@link android.app.NotificationManager#notify(int,Notification) notify()} again.</p>
-
-<p>You can revise each property with the object member fields
-(except for the {@link android.content.Context} and the notification title and text). You
-should always revise the text message when you update the notification by calling
-{@link android.app.Notification#setLatestEventInfo(Context,CharSequence,CharSequence,PendingIntent)
-setLatestEventInfo()} with new values for <var>contentTitle</var> and <var>contentText</var>.
-Then call {@link android.app.NotificationManager#notify(int,Notification) notify()} to update the
-notification. (Of course, if you've created a <a href="#CustomExpandedView">custom notification
-layout</a>, then updating these title and text values has no effect.)</p>
-
-
-<h3 id="Sound">Adding a sound</h3>
-
-<p>You can alert the user with the default notification sound
-(which is defined by the user) or with a sound specified by your application.</p>
-
-<p>To use the user's default sound, add "DEFAULT_SOUND" to the <var>defaults</var> field:</p>
-<pre>
-notification.defaults |= Notification.DEFAULT_SOUND;
-</pre>
-
-<p>To use a different sound with your notifications, pass a Uri reference to the
-<var>sound</var> field.
-The following example uses a known audio file saved to the device SD card:</p>
-<pre>
-notification.sound = Uri.parse("file:///sdcard/notification/ringer.mp3");
-</pre>
-
-<p>In the next example, the audio file is chosen from the internal
-{@link android.provider.MediaStore.Audio.Media MediaStore}'s {@link android.content.ContentProvider}:</p>
+<h3 id="Optional">Optional notification contents and settings</h3>
+<p>
+ All other notification settings and contents are optional. To learn more about them,
+ see the reference documentation for {@link android.support.v4.app.NotificationCompat.Builder}.
+</p>
+<!-- ------------------------------------------------------------------------------------------ -->
+<h3 id="Actions">Notification actions</h3>
+<p>
+ Although they're optional, you should add at least one action to your notification.
+ An action allows users to go directly from the notification to an
+ {@link android.app.Activity} in your application, where they can look at one or more events
+ or do further work.
+</p>
+<p>
+ A notification can provide multiple actions. You should always define the action that's
+ triggered when the user clicks the notification; usually this action opens an
+ {@link android.app.Activity} in your application. You can also add buttons to the notification
+ that perform additional actions such as snoozing an alarm or responding immediately to a text
+ message; this feature is available as of Android 4.1. If you use additional action buttons, you
+ must also make their functionality available in an {@link android.app.Activity} in your app; see
+ the section <a href="#Compatibility">Handling compatibility</a> for more details.
+</p>
+<p>
+ Inside a {@link android.app.Notification}, the action itself is defined by a
+ {@link android.app.PendingIntent} containing an {@link android.content.Intent} that starts
+ an {@link android.app.Activity} in your application. To associate the
+ {@link android.app.PendingIntent} with a gesture, call the appropriate method of
+ {@link android.support.v4.app.NotificationCompat.Builder}. For example, if you want to start
+ {@link android.app.Activity} when the user clicks the notification text in
+ the notification drawer, you add the {@link android.app.PendingIntent} by calling
+ {@link android.support.v4.app.NotificationCompat.Builder#setContentIntent setContentIntent()}.
+</p>
+<p>
+ Starting an {@link android.app.Activity} when the user clicks the notification is the most
+ common action scenario. You can also start an {@link android.app.Activity} when the user
+ dismisses an {@link android.app.Activity}. In Android 4.1 and later, you can start an
+ {@link android.app.Activity} from an action button. To learn more, read the reference guide for
+ {@link android.support.v4.app.NotificationCompat.Builder}.
+</p>
+<!-- ------------------------------------------------------------------------------------------ -->
+<h3 id="SimpleNotification">Creating a simple notification</h3>
+<p>
+ The following snippet illustrates a simple notification that specifies an activity to open when
+ the user clicks the notification. Notice that the code creates a
+ {@link android.support.v4.app.TaskStackBuilder} object and uses it to create the
+ {@link android.app.PendingIntent} for the action. This pattern is explained in more detail
+ in the section <a href="#NotificationResponse">
+ Preserving Navigation when Starting an Activity</a>:
+</p>
<pre>
-notification.sound = Uri.withAppendedPath(Audio.Media.INTERNAL_CONTENT_URI, "6");
+NotificationCompat.Builder mBuilder =
+ new NotificationCompat.Builder(this)
+ .setSmallIcon(R.drawable.notification_icon)
+ .setContentTitle("My notification")
+ .setContentText("Hello World!");
+// Creates an explicit intent for an Activity in your app
+Intent resultIntent = new Intent(this, ResultActivity.class);
+
+// The stack builder object will contain an artificial back stack for the
+// started Activity.
+// This ensures that navigating backward from the Activity leads out of
+// your application to the Home screen.
+TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
+// Adds the back stack for the Intent (but not the Intent itself)
+stackBuilder.addParentStack(ResultActivity.class);
+// Adds the Intent that starts the Activity to the top of the stack
+stackBuilder.addNextIntent(resultIntent);
+PendingIntent resultPendingIntent =
+ stackBuilder.getPendingIntent(
+ 0,
+ PendingIntent.FLAG_UPDATE_CURRENT
+ );
+mBuilder.setContentIntent(resultPendingIntent);
+NotificationManager mNotificationManager =
+ (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
+// mId allows you to update the notification later on.
+mNotificationManager.notify(mId, mBuilder.build());
</pre>
-
-<p>In this case, the exact ID of the media file ("6") is known and appended to the content
-{@link android.net.Uri}. If you don't know the exact ID, you must query all the
-media available in the {@link android.provider.MediaStore} with a {@link
-android.content.ContentResolver}.
-See the <a href="{@docRoot}guide/topics/providers/content-providers.html">Content Providers</a>
-documentation for more information on using a ContentResolver.</p>
-
-<p>If you want the sound to continuously repeat until the user responds to the notification
-or the notification is cancelled, add {@link android.app.Notification#FLAG_INSISTENT} to the
-<var>flags</var> field.</p>
-
-<p class="note"><strong>Note:</strong> If the <var>defaults</var> field includes
-{@link android.app.Notification#DEFAULT_SOUND}, then the default sound overrides any sound defined
-by the <var>sound</var> field.</p>
-
-
-<h3 id="Vibration">Adding vibration</h3>
-
-<p>You can alert the user with the the default
-vibration pattern or with a vibration pattern defined by your application.</p>
-
-<p>To use the default pattern, add {@link android.app.Notification#DEFAULT_VIBRATE} to the
-<var>defaults</var> field:</p>
+<p>That's it. Your user has now been notified.</p>
+<!-- ------------------------------------------------------------------------------------------ -->
+<h3 id="ApplyStyle">Applying a big view style to a notification</h3>
+<p>
+ To have a notification appear in a big view when it's expanded, first create a
+ {@link android.support.v4.app.NotificationCompat.Builder} object with the normal view options
+ you want. Next, call {@link android.support.v4.app.NotificationCompat.Builder#setStyle
+ Builder.setStyle()} with a big view style object as its argument.
+</p>
+<p>
+ Remember that expanded notifications are not available on platforms prior to Android 4.1. To
+ learn how to handle notifications for Android 4.1 and for earlier platforms, read the
+ section <a href="#Compatibility">Handling compatibility</a>.
+</p>
+<p>
+ For example, the following code snippet demonstrates how to alter the notification created
+ in the previous snippet to use the Inbox big view style:
+</p>
<pre>
-notification.defaults |= Notification.DEFAULT_VIBRATE;
+NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this)
+ .setSmallIcon(R.drawable.notification_icon)
+ .setContentTitle("Event tracker")
+ .setContentText("Events received")
+NotificationCompat.InboxStyle inboxStyle =
+ new NotificationCompat.InboxStyle();
+String[] events = new String[6];
+// Sets a title for the Inbox style big view
+inboxStyle.SetBigContentTitle("Event tracker details:");
+...
+// Moves events into the big view
+for (int i=0; i &lt; events.length; i++) {
+
+ inboxStyle.addLine(events[i]);
+}
+// Moves the big view style object into the notification object.
+mBuilder.setStyle(inBoxStyle);
+...
+// Issue the notification here.
</pre>
-
-<p>To define your own vibration pattern, pass an array of <em>long</em> values to the
-<var>vibrate</var> field:</p>
+<h3 id="Compatibility">Handling compatibility</h3>
+<p>
+ Not all notification features are available for a particular version, even though
+ the methods to set them are in the support library class
+ {@link android.support.v4.app.NotificationCompat.Builder NotificationCompat.Builder}.
+ For example, action buttons, which depend on expanded notifications, only appear on Android
+ 4.1 and higher, because expanded notifications themselves are only available on
+ Android 4.1 and higher.
+</p>
+<p>
+ To ensure the best compatibility, create notifications with
+ {@link android.support.v4.app.NotificationCompat NotificationCompat} and its subclasses,
+ particularly {@link android.support.v4.app.NotificationCompat.Builder
+ NotificationCompat.Builder}. In addition, follow this process when you implement a notification:
+</p>
+<ol>
+ <li>
+ Provide all of the notification's functionality to all users, regardless of the version
+ they're using. To do this, verify that all of the functionality is available from an
+ {@link android.app.Activity} in your app. You may want to add a new
+ {@link android.app.Activity} to do this.
+ <p>
+ For example, if you want to use
+ {@link android.support.v4.app.NotificationCompat.Builder#addAction addAction()} to
+ provide a control that stops and starts media playback, first implement this
+ control in an {@link android.app.Activity} in your app.
+ </p>
+ </li>
+ <li>
+ Ensure that all users can get to the functionality in the {@link android.app.Activity},
+ by having it start when users click the notification. To do this,
+ create a {@link android.app.PendingIntent} for the {@link android.app.Activity}. Call
+ {@link android.support.v4.app.NotificationCompat.Builder#setContentIntent
+ setContentIntent()} to add the {@link android.app.PendingIntent} to the notification.
+ </li>
+ <li>
+ Now add the expanded notification features you want to use to the notification. Remember
+ that any functionality you add also has to be available in the {@link android.app.Activity}
+ that starts when users click the notification.
+ </li>
+</ol>
+<!-- ------------------------------------------------------------------------------------------ -->
+<!-- ------------------------------------------------------------------------------------------ -->
+<h2 id="Managing">Managing Notifications</h2>
+<p>
+ When you need to issue a notification multiple times for the same type of event, you
+ should avoid making a completely new notification. Instead, you should consider updating a
+ previous notification, either by changing some of its values or by adding to it, or both.
+</p>
+<p>
+ For example, Gmail notifies the user that new emails have arrived by increasing its count of
+ unread messages and by adding a summary of each email to the notification. This is called
+ "stacking" the notification; it's described in more detail in the
+ <a href="{@docRoot}design/patterns/notifications.html">Notifications</a> Design guide.
+</p>
+<p class="note">
+ <strong>Note:</strong> This Gmail feature requires the "inbox" big view style, which is
+ part of the expanded notification feature available starting in Android 4.1.
+</p>
+<p>
+ The following section describes how to update notifications and also how to remove them.
+</p>
+<h3 id="Updating">Updating notifications</h3>
+<p>
+ To set up a notification so it can be updated, issue it with a notification ID by
+ calling {@link android.app.NotificationManager#notify(int, Notification)
+ NotificationManager.notify(ID, notification)}. To update this notification once you've issued
+ it, update or create a {@link android.support.v4.app.NotificationCompat.Builder} object,
+ build a {@link android.app.Notification} object from it, and issue the
+ {@link android.app.Notification} with the same ID you used previously. If
+ the previous notification is still visible, the system updates it from the contents of
+ the {@link android.app.Notification} object. If the previous notification has been dismissed, a
+ new notification is created instead.
+</p>
+<p>
+ The following snippet demonstrates a notification that is updated to reflect the
+ number of events that have occurred. It stacks the notification, showing a summary:
+</p>
<pre>
-long[] vibrate = {0,100,200,300};
-notification.vibrate = vibrate;
+mNotificationManager =
+ (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
+// Sets an ID for the notification, so it can be updated
+int notifyID = 1;
+mNotifyBuilder = new NotificationCompat.Builder(this)
+ .setContentTitle("New Message")
+ .setContentText("You've received new messages.")
+ .setSmallIcon(R.drawable.ic_notify_status)
+numMessages = 0;
+// Start of a loop that processes data and then notifies the user
+...
+ mNotifyBuilder.setContentText(currentText)
+ .setNumber(++numMessages);
+ // Because the ID remains unchanged, the existing notification is
+ // updated.
+ mNotificationManager.notify(
+ notifyID,
+ mNotifyBuilder.build());
+...
</pre>
-
-<p>The long array defines the alternating pattern for the length of vibration off and on
-(in milliseconds). The first value is how long to wait (off) before beginning, the second
-value is the length of the first vibration, the third is the next length off, and so on.
-The pattern can be as long as you like, but it can't be set to repeat.
+<p>
+ This produces a notification that looks like this:
</p>
-
-<p class="note"><strong>Note:</strong> If the <var>defaults</var> field includes
-{@link android.app.Notification#DEFAULT_VIBRATE}, then the default vibration overrides any vibration
-defined by the
-<var>vibrate</var> field.</p>
-
-
-<h3 id="Lights">Adding flashing lights</h3>
-
-<p>To alert the user by flashing LED lights, you can implement the default
-light pattern (if available), or define your own color and pattern for the lights.</p>
-
-<p>To use the default light setting, add {@link android.app.Notification#DEFAULT_LIGHTS} to the
-<var>defaults</var> field:</p>
+<img
+ id="figure5"
+ src="{@docRoot}images/ui/notifications/updated_notification.png"
+ alt=""
+ height="118"/>
+<p class="img-caption">
+ <strong>Figure 5.</strong> Updated notification displayed in the notification drawer.
+</p>
+<!-- ------------------------------------------------------------------------------------------ -->
+<h3 id="Removing">Removing notifications</h3>
+<p>
+ Notifications remain visible until one of the following happens:
+</p>
+<ul>
+ <li>
+ The user dismisses the notification either individually or by using "Clear All" (if
+ the notification can be cleared).
+ </li>
+ <li>
+ The user clicks the notification, and you called
+ {@link android.support.v4.app.NotificationCompat.Builder#setAutoCancel setAutoCancel()} when
+ you created the notification.
+ </li>
+ <li>
+ You call {@link android.app.NotificationManager#cancel(int) cancel()} for a specific
+ notification ID. This method also deletes ongoing notifications.
+ </li>
+ <li>
+ You call {@link android.app.NotificationManager#cancelAll() cancelAll()}, which removes
+ all of the notifications you previously issued.
+ </li>
+</ul>
+<!-- ------------------------------------------------------------------------------------------ -->
+<!-- ------------------------------------------------------------------------------------------ -->
+<h2 id="NotificationResponse">Preserving Navigation when Starting an Activity</h2>
+<p>
+ When you start an {@link android.app.Activity} from a notification, you must preserve the
+ user's expected navigation experience. Clicking <i>Back</i> should take the user back through
+ the application's normal work flow to the Home screen, and clicking <i>Recents</i> should show
+ the {@link android.app.Activity} as a separate task. To preserve the navigation experience, you
+ should start the {@link android.app.Activity} in a fresh task. How you set up the
+ {@link android.app.PendingIntent} to give you a fresh task depends on the nature of the
+ {@link android.app.Activity} you're starting. There are two general situations:
+</p>
+<dl>
+ <dt>
+ Regular activity
+ </dt>
+ <dd>
+ You're starting an {@link android.app.Activity} that's part of the application's normal
+ workflow. In this situation, set up the {@link android.app.PendingIntent} to
+ start a fresh task, and provide the {@link android.app.PendingIntent} with a back stack
+ that reproduces the application's normal <i>Back</i> behavior.
+ <p>
+ Notifications from the Gmail app demonstrate this. When you click a notification for
+ a single email message, you see the message itself. Touching <b>Back</b> takes you
+ backwards through Gmail to the Home screen, just as if you had entered Gmail from the
+ Home screen rather than entering it from a notification.
+ </p>
+ <p>
+ This happens regardless of the application you were in when you touched the
+ notification. For example, if you're in Gmail composing a message, and you click a
+ notification for a single email, you go immediately to that email. Touching <i>Back</i>
+ takes you to the inbox and then the Home screen, rather than taking you to the
+ message you were composing.
+ </p>
+ </dd>
+ <dt>
+ Special activity
+ </dt>
+ <dd>
+ The user only sees this {@link android.app.Activity} if it's started from a notification.
+ In a sense, the {@link android.app.Activity} extends the notification by providing
+ information that would be hard to display in the notification itself. For this situation,
+ set up the {@link android.app.PendingIntent} to start in a fresh task. There's no need to
+ create a back stack, though, because the started {@link android.app.Activity} isn't part of
+ the application's activity flow. Clicking <i>Back</i> will still take the user to the
+ Home screen.
+ </dd>
+</dl>
+<!-- ------------------------------------------------------------------------------------------ -->
+<h3 id="DirectEntry">Setting up a regular activity PendingIntent</h3>
+<p>
+ To set up a {@link android.app.PendingIntent} that starts a direct entry
+ {@link android.app.Activity}, follow these steps:
+</p>
+<ol>
+ <li>
+ Define your application's {@link android.app.Activity} hierarchy in the manifest.
+ <ol style="list-style-type: lower-alpha;">
+ <li>
+ Add support for Android 4.0.3 and earlier. To do this, specify the parent of the
+ {@link android.app.Activity} you're starting by adding a
+<code><a href="{@docRoot}guide/topics/manifest/meta-data-element.html">&lt;meta-data&gt;</a></code>
+ element as the child of the
+<code><a href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;activity&gt;</a></code>.
+ <p>
+ For this element, set
+<code><a href="{@docRoot}guide/topics/manifest/meta-data-element.html#nm">android:name</a>="android.support.PARENT_ACTIVITY"</code>.
+ Set
+<code><a href="{@docRoot}/guide/topics/manifest/meta-data-element.html#val">android:value</a>="&lt;parent_activity_name&gt;"</code>
+ where <code>&lt;parent_activity_name&gt;</code> is the value of
+<code><a href="{@docRoot}guide/topics/manifest/meta-data-element.html#nm">android:name</a></code>
+ for the parent
+<code><a href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;activity&gt;</a></code>
+ element. See the following XML for an example.
+ </p>
+ </li>
+ <li>
+ Also add support for Android 4.1 and later. To do this, add the
+<code><a href="{@docRoot}guide/topics/manifest/activity-element.html#parent">android:parentActivityName</a></code>
+ attribute to the
+<code><a href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;activity&gt;</a></code>
+ element of the {@link android.app.Activity} you're starting.
+ </li>
+ </ol>
+ <p>
+ The final XML should look like this:
+ </p>
<pre>
-notification.defaults |= Notification.DEFAULT_LIGHTS;
+&lt;activity
+ android:name=".MainActivity"
+ android:label="&#64;string/app_name" &gt;
+ &lt;intent-filter&gt;
+ &lt;action android:name="android.intent.action.MAIN" /&gt;
+ &lt;category android:name="android.intent.category.LAUNCHER" /&gt;
+ &lt;/intent-filter&gt;
+&lt;/activity&gt;
+&lt;activity
+ android:name=".ResultActivity"
+ android:parentActivityName=".MainActivity"&gt;
+ &lt;meta-data
+ android:name="android.support.PARENT_ACTIVITY"
+ android:value=".MainActivity"/&gt;
+&lt;/activity&gt;
</pre>
-
-<p>To define your own color and pattern, define a value for the <var>ledARGB</var> field
-(for the color), the <var>ledOffMS</var> field (length of time, in milliseconds, to
-keep the light off), the <var>ledOnMS</var> (length of time, in milliseconds, to keep the light on),
-and also add {@link android.app.Notification#FLAG_SHOW_LIGHTS} to the <var>flags</var> field:</p>
+ </li>
+ <li>
+ Create a back stack based on the {@link android.content.Intent} that starts the
+ {@link android.app.Activity}:
+ <ol style="list-style-type: lower-alpha;">
+ <li>
+ Create the {@link android.content.Intent} to start the {@link android.app.Activity}.
+ </li>
+ <li>
+ Create a stack builder by calling {@link android.app.TaskStackBuilder#create
+ TaskStackBuilder.create()}.
+ </li>
+ <li>
+ Add the back stack to the stack builder by calling
+ {@link android.support.v4.app.TaskStackBuilder#addParentStack addParentStack()}.
+ For each {@link android.app.Activity} in the hierarchy you've defined in the
+ manifest, the back stack contains an {@link android.content.Intent} object that
+ starts the {@link android.app.Activity}. This method also adds flags that start the
+ stack in a fresh task.
+ <p class="note">
+ <strong>Note:</strong> Although the argument to
+ {@link android.support.v4.app.TaskStackBuilder#addParentStack addParentStack()}
+ is a reference to the started {@link android.app.Activity}, the method call
+ doesn't add the {@link android.content.Intent} that starts the
+ {@link android.app.Activity}. Instead, that's taken care of in the next step.
+ </p>
+ </li>
+ <li>
+ Add the {@link android.content.Intent} that starts the {@link android.app.Activity}
+ from the notification, by calling
+ {@link android.support.v4.app.TaskStackBuilder#addNextIntent addNextIntent()}.
+ Pass the {@link android.content.Intent} you created in the first step as the
+ argument to
+ {@link android.support.v4.app.TaskStackBuilder#addNextIntent addNextIntent()}.
+ </li>
+ <li>
+ If you need to, add arguments to {@link android.content.Intent} objects on the
+ stack by calling {@link android.support.v4.app.TaskStackBuilder#editIntentAt
+ TaskStackBuilder.editIntentAt()}. This is sometimes necessary to ensure that the
+ target {@link android.app.Activity} displays meaningful data when the user navigates
+ to it using <i>Back</i>.
+ </li>
+ <li>
+ Get a {@link android.app.PendingIntent} for this back stack by calling
+ {@link android.support.v4.app.TaskStackBuilder#getPendingIntent getPendingIntent()}.
+ You can then use this {@link android.app.PendingIntent} as the argument to
+ {@link android.support.v4.app.NotificationCompat.Builder#setContentIntent
+ setContentIntent()}.
+ </li>
+ </ol>
+ </li>
+</ol>
+<p>
+ The following code snippet demonstrates the process:
+</p>
<pre>
-notification.ledARGB = 0xff00ff00;
-notification.ledOnMS = 300;
-notification.ledOffMS = 1000;
-notification.flags |= Notification.FLAG_SHOW_LIGHTS;
+...
+Intent resultIntent = new Intent(this, ResultActivity.class);
+TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
+// Adds the back stack
+stackBuilder.addParentStack(ResultActivity.class);
+// Adds the Intent to the top of the stack
+stackBuilder.addNextIntent(resultIntent);
+// Gets a PendingIntent containing the entire back stack
+PendingIntent resultPendingIntent =
+ stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
+...
+NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
+builder.setContentIntent(resultPendingIntent);
+NotificationManager mNotificationManager =
+ (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
+mNotificationManager.notify(id, builder.build());
</pre>
-
-<p>In this example, the green light repeatedly flashes on for 300 milliseconds and
-turns off for one second. Not every color in the spectrum is supported by the
-device LEDs, and not every device supports the same colors, so the hardware
-estimates to the best of its ability. Green is the most common notification color.</p>
-
-
-<h3 id="More">More features</h3>
-
-<p>You can add several more features to your notifications
-using {@link android.app.Notification} fields and flags. Some useful features include the
-following:</p>
-
-<dl>
- <dt>{@link android.app.Notification#FLAG_AUTO_CANCEL} flag</dt>
- <dd>Add this to the <var>flags</var> field to automatically cancel the notification
- after it is selected from the notifications window.</dd>
- <dt>{@link android.app.Notification#FLAG_INSISTENT} flag</dt>
- <dd>Add this to the <var>flags</var> field to repeat the audio until the
- user responds.</dd>
- <dt>{@link android.app.Notification#FLAG_ONGOING_EVENT} flag</dt>
- <dd>Add this to the <var>flags</var> field to group the notification under the "Ongoing"
- title in the notifications window. This indicates that the application is on-going &mdash;
- its processes are still running in the background, even when the application is not
- visible (such as with music or a phone call).</dd>
- <dt>{@link android.app.Notification#FLAG_NO_CLEAR} flag</dt>
- <dd>Add this to the <var>flags</var> field to indicate that the notification should
- <em>not</em> be cleared by the "Clear notifications" button. This is particularly useful if
- your notification is on-going.</dd>
- <dt>{@link android.app.Notification#number} field</dt>
- <dd>This value indicates the current number of events represented by the notification.
- The appropriate number is overlaid on top of the status icon.
- If you intend to use this field, then you must start with "1" when the Notification is first
- created. (If you change the value from zero to anything greater during an update, the number
- is not shown.)</dd>
- <dt>{@link android.app.Notification#iconLevel} field</dt>
- <dd>This value indicates the current level of a
- {@link android.graphics.drawable.LevelListDrawable} that is used for the notification icon.
- You can animate the icon in the status bar by changing this value to correlate with the
- drawable's defined in a LevelListDrawable. See the {@link android.graphics.drawable.LevelListDrawable}
- reference for more information.</dd>
-</dl>
-
-<p>See the {@link android.app.Notification} class reference for more information about additional
-features that you can customize for your application.</p>
-
-
-<h2 id="CustomExpandedView">Creating a Custom Notification Layout</h2>
-
-<div class="figure" style="width:200px;margin-top:0">
-<img src="{@docRoot}images/custom_message.png" alt="" />
-<p class="img-caption"><strong>Figure 3.</strong> Notification with a custom layout.</p>
-</div>
-
-<p>By default, the notification that appears in the notifications window includes a title
-and the message text.
-These are defined by the <var>contentTitle</var> and <var>contentText</var>
-parameters of the {@link android.app.Notification#setLatestEventInfo(Context,CharSequence,CharSequence,PendingIntent)
-setLatestEventInfo()} method. However, you can also define a custom layout for the
-notification using
-{@link android.widget.RemoteViews}. Figure 3 shows an example of a
-custom notification layout. It looks similar to the default notification, but is
-actually created with a custom XML layout.</p>
-
-<p>To define your own layout for the notification,
-instantiate a {@link android.widget.RemoteViews} object that inflates a custom layout file, then
-pass the {@link android.widget.RemoteViews} to the <var>contentView</var> field of your
-Notification.</p>
-
-<p>Creating a custom notification layout is best understood with an example:</p>
-
+<!-- ------------------------------------------------------------------------------------------ -->
+<h3 id="ExtendedNotification">Setting up a special activity PendingIntent</h3>
+<p>
+ The following section describes how to set up a special activity
+ {@link android.app.PendingIntent}.
+</p>
+<p>
+ A special {@link android.app.Activity} doesn't need a back stack, so you don't have to
+ define its {@link android.app.Activity} hierarchy in the manifest, and you don't have
+ to call
+ {@link android.support.v4.app.TaskStackBuilder#addParentStack addParentStack()} to build a
+ back stack. Instead, use the manifest to set up the {@link android.app.Activity} task options,
+ and create the {@link android.app.PendingIntent} by calling
+ {@link android.app.PendingIntent#getActivity getActivity()}:
+</p>
<ol>
- <li>Create the XML layout for the notification.
- For example, the following layout is called <code>custom_notification.xml</code>:
+ <li>
+ In your manifest, add the following attributes to the
+<code><a href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;activity&gt;</a></code>
+ element for the {@link android.app.Activity}
+ <dl>
+ <dt>
+<code><a href="guide/topics/manifest/activity-element.html#nm">android:name</a>="<i>activityclass</i>"</code>
+ </dt>
+ <dd>
+ The activity's fully-qualified class name.
+ </dd>
+ <dt>
+<code><a href="{@docRoot}guide/topics/manifest/activity-element.html#aff">android:taskAffinity</a>=""</code>
+ </dt>
+ <dd>
+ Combined with the
+ {@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK FLAG_ACTIVITY_NEW_TASK} flag
+ that you set in code, this ensures that this {@link android.app.Activity} doesn't
+ go into the application's default task. Any existing tasks that have the
+ application's default affinity are not affected.
+ </dd>
+ <dt>
+<code><a href="{@docRoot}guide/topics/manifest/activity-element.html#exclude">android:excludeFromRecents</a>="true"</code>
+ </dt>
+ <dd>
+ Excludes the new task from <i>Recents</i>, so that the user can't accidentally
+ navigate back to it.
+ </dd>
+ </dl>
+ <p>
+ This snippet shows the element:
+ </p>
<pre>
-&lt;RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/layout"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:padding="10dp" >
- &lt;ImageView android:id="@+id/image"
- android:layout_width="wrap_content"
- android:layout_height="fill_parent"
- android:layout_alignParentLeft="true"
- android:layout_marginRight="10dp" />
- &lt;TextView android:id="@+id/title"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_toRightOf="@id/image"
- style="@style/NotificationTitle" />
- &lt;TextView android:id="@+id/text"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_toRightOf="@id/image"
- android:layout_below="@id/title"
- style="@style/NotificationText" />
-&lt;/RelativeLayout>
+&lt;activity
+ android:name=".ResultActivity"
+...
+ android:launchMode="singleTask"
+ android:taskAffinity=""
+ android:excludeFromRecents="true"&gt;
+&lt;/activity&gt;
+...
</pre>
-
- <p>Notice that the two {@link android.widget.TextView} elements include the {@code style}
-attribute. It's important that you use style resources for the text in your custom
-notifications, because the background color of the notification can vary across different
-devices and platform versions. Beginning with Android 2.3 (API level 9), the system defines a
-style for the text it uses for the default notification layouts. Thus, you should apply
-that style when running on Android 2.3 or higher to ensure that your text is visible against
-the background.</p>
-
- <p>For example, to use the standard text colors on versions of Android lower than 2.3, you
-should use the following styles for {@code res/values/styles.xml}:</p>
+ </li>
+ <li>
+ Build and issue the notification:
+ <ol style="list-style-type: lower-alpha;">
+ <li>
+ Create an {@link android.content.Intent} that starts the
+ {@link android.app.Activity}.
+ </li>
+ <li>
+ Set the {@link android.app.Activity} to start in a new, empty task by calling
+ {@link android.content.Intent#setFlags setFlags()} with the flags
+ {@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK FLAG_ACTIVITY_NEW_TASK}
+ and
+ {@link android.content.Intent#FLAG_ACTIVITY_CLEAR_TASK FLAG_ACTIVITY_CLEAR_TASK}.
+ </li>
+ <li>
+ Set any other options you need for the {@link android.content.Intent}.
+ </li>
+ <li>
+ Create a {@link android.app.PendingIntent} from the {@link android.content.Intent}
+ by calling {@link android.app.PendingIntent#getActivity getActivity()}.
+ You can then use this {@link android.app.PendingIntent} as the argument to
+ {@link android.support.v4.app.NotificationCompat.Builder#setContentIntent
+ setContentIntent()}.
+ </li>
+ </ol>
+ <p>
+ The following code snippet demonstrates the process:
+ </p>
<pre>
-&lt;?xml version="1.0" encoding="utf-8"?>
-&lt;resources>
- &lt;style name="NotificationText">
- &lt;item name="android:textColor">?android:attr/textColorPrimary&lt;/item>
- &lt;/style>
- &lt;style name="NotificationTitle">
- &lt;item name="android:textColor">?android:attr/textColorPrimary&lt;/item>
- &lt;item name="android:textStyle">bold&lt;/item>
- &lt;/style>
- &lt;!-- If you want a slightly different color for some text,
- consider using ?android:attr/textColorSecondary -->
-&lt;/resources>
+// Instantiate a Builder object.
+NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
+// Creates an Intent for the Activity
+Intent notifyIntent =
+ new Intent(new ComponentName(this, ResultActivity.class));
+// Sets the Activity to start in a new, empty task
+notifyIntent.setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK);
+// Creates the PendingIntent
+PendingIntent notifyIntent =
+ PendingIntent.getActivity(
+ this,
+ 0,
+ notifyIntent
+ PendingIntent.FLAG_UPDATE_CURRENT
+);
+
+// Puts the PendingIntent into the notification builder
+builder.setContentIntent(notifyIntent);
+// Notifications are issued by sending them to the
+// NotificationManager system service.
+NotificationManager mNotificationManager =
+ (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
+// Builds an anonymous Notification object from the builder, and
+// passes it to the NotificationManager
+mNotificationManager.notify(id, builder.build());
</pre>
- <p>Then, to apply the system's default colors for notifications on Android
-2.3 and higher, use the following styles for {@code res/values-v9/styles.xml}:</p>
+ </li>
+</ol>
+<!-- ------------------------------------------------------------------------------------------ -->
+<!-- ------------------------------------------------------------------------------------------ -->
+<h2 id="Progress">Displaying Progress in a Notification</h2>
+<p>
+ Notifications can include an animated progress indicator that shows users the status
+ of an ongoing operation. If you can estimate how long the operation takes and how much of it
+ is complete at any time, use the "determinate" form of the indicator
+ (a progress bar). If you can't estimate the length of the operation, use the
+ "indeterminate" form of the indicator (an activity indicator).
+</p>
+<p>
+ Progress indicators are displayed with the platform's implementation of the
+ {@link android.widget.ProgressBar} class.
+</p>
+<p>
+ To use a progress indicator on platforms starting with Android 4.0, call
+ {@link android.support.v4.app.NotificationCompat.Builder#setProgress setProgress()}. For
+ previous versions, you must create your own custom notification layout that
+ includes a {@link android.widget.ProgressBar} view.
+</p>
+<p>
+ The following sections describe how to display progress in a notification using
+ {@link android.support.v4.app.NotificationCompat.Builder#setProgress setProgress()}.
+</p>
+<!-- ------------------------------------------------------------------------------------------ -->
+<h3 id="FixedProgress">Displaying a fixed-duration progress indicator</h3>
+<p>
+ To display a determinate progress bar, add the bar to your notification by calling
+ {@link android.support.v4.app.NotificationCompat.Builder#setProgress setProgress()
+ setProgress(max, progress, false)} and then issue the notification. As your operation proceeds,
+ increment <code>progress</code>, and update the notification. At the end of the operation,
+ <code>progress</code> should equal <code>max</code>. A common way to call
+ {@link android.support.v4.app.NotificationCompat.Builder#setProgress setProgress()}
+ is to set <code>max</code> to 100 and then increment <code>progress</code> as a
+ "percent complete" value for the operation.
+</p>
+<p>
+ You can either leave the progress bar showing when the operation is done, or remove it. In
+ either case, remember to update the notification text to show that the operation is complete.
+ To remove the progress bar, call
+ {@link android.support.v4.app.NotificationCompat.Builder#setProgress setProgress()
+ setProgress(0, 0, false)}. For example:
+</p>
<pre>
-&lt;?xml version="1.0" encoding="utf-8"?>
-&lt;resources>
- &lt;style name="NotificationText" parent="android:TextAppearance.StatusBar.EventContent" />
- &lt;style name="NotificationTitle" parent="android:TextAppearance.StatusBar.EventContent.Title" />
-&lt;/resources>
+...
+mNotifyManager =
+ (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
+mBuilder = new NotificationCompat.Builder(this);
+mBuilder.setContentTitle("Picture Download")
+ .setContentText("Download in progress")
+ .setSmallIcon(R.drawable.ic_notification);
+// Start a lengthy operation in a background thread
+new Thread(
+ new Runnable() {
+ &#64;Override
+ public void run() {
+ int incr;
+ // Do the "lengthy" operation 20 times
+ for (incr = 0; incr &lt;= 100; incr+=5) {
+ // Sets the progress indicator to a max value, the
+ // current completion percentage, and "determinate"
+ // state
+ mBuilder.setProgress(100, incr, false);
+ // Displays the progress bar for the first time.
+ mNotifyManager.notify(0, mBuilder.build());
+ // Sleeps the thread, simulating an operation
+ // that takes time
+ try {
+ // Sleep for 5 seconds
+ Thread.sleep(5*1000);
+ } catch (InterruptedException e) {
+ Log.d(TAG, "sleep failure");
+ }
+ }
+ // When the loop is finished, updates the notification
+ mBuilder.setContentText("Download complete")
+ // Removes the progress bar
+ .setProgress(0,0,false);
+ mNotifyManager.notify(ID, mBuilder.build());
+ }
+ }
+// Starts the thread by calling the run() method in its Runnable
+).start();
</pre>
- <p>Now, when running on Android 2.3 (API level 9) or higher, the text in your custom view will
-use the same colors that the system does for default notifications. This is important because later
-versions of Android actually change the background color of the notifications to be dark. Inheriting
-the system's styles ensures that your text will be light in such cases, but also if the background
-is some other unexpected color, your text will also change as appropriate.</p>
- </li>
-
- <li>Now, in the application code, use the RemoveViews
- methods to define the image and text. Then pass the RemoteViews object to the <var>contentView</var>
- field of the Notification, as shown in this example:
+<p>
+ The resulting notifications are shown in figure 6. On the left side is a snapshot of the
+ notification during the operation; on the right side is a snapshot of it after the operation
+ has finished.
+</p>
+<img
+ id="figure6"
+ src="{@docRoot}images/ui/notifications/progress_bar_summary.png"
+ height="84"
+ alt="" />
+<p class="img-caption">
+<strong>Figure 6.</strong> The progress bar during and after the operation.</p>
+<!-- ------------------------------------------------------------------------------------------ -->
+<h3 id="ActivityIndicator">Displaying a continuing activity indicator</h3>
+<p>
+ To display an indeterminate activity indicator, add it to your notification with
+ {@link android.support.v4.app.NotificationCompat.Builder#setProgress setProgress(0, 0, true)}
+ (the first two arguments are ignored), and issue the notification. The result is an indicator
+ that has the same style as a progress bar, except that its animation is ongoing.
+</p>
+<p>
+ Issue the notification at the beginning of the operation. The animation will run until you
+ modify your notification. When the operation is done, call
+ {@link android.support.v4.app.NotificationCompat.Builder#setProgress setProgress()
+ setProgress(0, 0, false)} and then update the notification to remove the activity indicator.
+ Always do this; otherwise, the animation will run even when the operation is complete. Also
+ remember to change the notification text to indicate that the operation is complete.
+</p>
+<p>
+ To see how activity indicators work, refer to the preceding snippet. Locate the following lines:
+</p>
<pre>
-RemoteViews contentView = new RemoteViews(getPackageName(), R.layout.custom_notification_layout);
-contentView.setImageViewResource(R.id.image, R.drawable.notification_image);
-contentView.setTextViewText(R.id.title, "Custom notification");
-contentView.setTextViewText(R.id.text, "This is a custom layout");
-notification.contentView = contentView;
+// Sets the progress indicator to a max value, the current completion
+// percentage, and "determinate" state
+mBuilder.setProgress(100, incr, false);
+// Issues the notification
+mNotifyManager.notify(0, mBuilder.build());
</pre>
-
- <p>As shown here, pass the application's package name and the layout
- resource ID to the RemoteViews constructor. Then, define the content for the ImageView and TextView,
- using the {@link android.widget.RemoteViews#setImageViewResource(int, int) setImageViewResource()}
- and {@link android.widget.RemoteViews#setTextViewText(int, CharSequence) setTextViewText()}.
- In each case, pass the reference ID of the appropriate View object that you want to set, along with
- the value for that View. Finally, the RemoteViews object is passed to the Notification in the
- <var>contentView</var> field.</p>
- </li>
-
- <li>Because you don't need the
- {@link android.app.Notification#setLatestEventInfo(Context,CharSequence,CharSequence,PendingIntent)
- setLatestEventInfo()} method when using a custom view, you must define the Intent for the Notification
- with the <var>contentIntent</var> field, as in this example:
+<p>
+ Replace the lines you've found with the following lines:
+</p>
<pre>
-Intent notificationIntent = new Intent(this, MyClass.class);
-PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
-notification.contentIntent = contentIntent;
+ // Sets an activity indicator for an operation of indeterminate length
+mBuilder.setProgress(0, 0, false);
+// Issues the notification
+mNotifyManager.notify(0, mBuilder.build());
</pre>
- </li>
-
- <li>The notification can now be sent as usual:
- <pre>mNotificationManager.notify(CUSTOM_VIEW_ID, notification);</pre>
- </li>
+<p>
+ The resulting indicator is shown in figure 7:
+</p>
+<img
+ id="figure7"
+ src="{@docRoot}images/ui/notifications/activity_indicator.png"
+ height="99"
+ alt="" />
+<p class="img-caption"><strong>Figure 7.</strong> An ongoing activity indicator.</p>
+
+<!-- ------------------------------------------------------------------------------------------ -->
+<!-- ------------------------------------------------------------------------------------------ -->
+<!-- ------------------------------------------------------------------------------------------ -->
+
+<!-- ------------------------------------------------------------------------------------------ -->
+<h2 id="CustomNotification">Custom Notification Layouts</h2>
+<p>
+ The notifications framework allows you to define a custom notification layout, which
+ defines the notification's appearance in a {@link android.widget.RemoteViews} object.
+ Custom layout notifications are similar to normal notifications, but they're based on a
+ {@link android.widget.RemoteViews} defined in a XML layout file.
+</p>
+<p>
+ The height available for a custom notification layout depends on the notification view. Normal
+ view layouts are limited to 64 dp, and expanded view layouts are limited to 256 dp.
+</p>
+<p>
+ To define a custom notification layout, start by instantiating a
+ {@link android.widget.RemoteViews} object that inflates an XML layout file. Then,
+ instead of calling methods such as
+ {@link android.support.v4.app.NotificationCompat.Builder#setContentTitle setContentTitle()},
+ call {@link android.support.v4.app.NotificationCompat.Builder#setContent setContent()}. To set
+ content details in the custom notification, use the methods in
+ {@link android.widget.RemoteViews} to set the values of the view's children:
+</p>
+<ol>
+ <li>
+ Create an XML layout for the notification in a separate file. You can use any file name
+ you wish, but you must use the extension <code>.xml</code>
+ </li>
+ <li>
+ In your app, use {@link android.widget.RemoteViews} methods to define your notification's
+ icons and text. Put this {@link android.widget.RemoteViews} object into your
+ {@link android.support.v4.app.NotificationCompat.Builder} by calling
+ {@link android.support.v4.app.NotificationCompat.Builder#setContent setContent()}. Avoid
+ setting a background {@link android.graphics.drawable.Drawable} on your
+ {@link android.widget.RemoteViews} object, because your text color may become unreadable.
+ </li>
</ol>
-
-
-<p>The {@link android.widget.RemoteViews} class also includes methods that you can use to easily add
-a {@link android.widget.Chronometer} or {@link android.widget.ProgressBar}
-in your notification's layout. For more information about creating custom layouts for your
-notification, refer to the {@link android.widget.RemoteViews} class reference.</p>
-
-<p class="caution"><strong>Caution:</strong>
-When creating a custom notification layout, you must take special care to ensure that your
-custom layout functions properly in different device orientations and resolutions. While this
-advice applies to all View layouts created on Android, it is especially important in this case
-because your layout real estate is very restricted. So don't make your custom layout too
-complex and be sure to test it in various configurations.</p>
-
-
-
-
+<p>
+ The {@link android.widget.RemoteViews} class also includes methods that you can use to easily
+ add a {@link android.widget.Chronometer} or {@link android.widget.ProgressBar}
+ to your notification's layout. For more information about creating custom layouts for your
+ notification, refer to the {@link android.widget.RemoteViews} reference documentation.
+</p>
+<p class="caution">
+ <strong>Caution:</strong> When you use a custom notification layout, take special care to
+ ensure that your custom layout works with different device orientations and resolutions. While
+ this advice applies to all View layouts, it's especially important for notifications because
+ the space in the notification drawer is very restricted. Don't make your custom layout too
+ complex, and be sure to test it in various configurations.
+</p>
+<!-- ------------------------------------------------------------------------------------------ -->
+<h4>Using style resources for custom notification text</h4>
+<p>
+ Always use style resources for the text of a custom notification. The background color of the
+ notification can vary across different devices and versions, and using style resources
+ helps you account for this. Starting in Android 2.3, the system defined a style for the
+ standard notification layout text. If you use the same style in applications that target Android
+ 2.3 or higher, you'll ensure that your text is visible against the display background.
+</p>
diff --git a/docs/html/guide/topics/ui/notifiers/toasts.jd b/docs/html/guide/topics/ui/notifiers/toasts.jd
index 1a1fb1f..92c146a 100644
--- a/docs/html/guide/topics/ui/notifiers/toasts.jd
+++ b/docs/html/guide/topics/ui/notifiers/toasts.jd
@@ -1,17 +1,8 @@
-page.title=Toast Notifications
-parent.title=Notifications
-parent.link=index.html
+page.title=Toasts
@jd:body
<div id="qv-wrapper">
- <div id="qv">
- <h2>Quickview</h2>
- <ol>
- <li>A toast is a message that appears on the surface of the screen for a moment, but it
-does not take focus (or pause the current activity), so it cannot accept user input</li>
- <li>You can customize the toast layout to include images</li>
- </ol>
-
+ <div id="qv">
<h2>In this document</h2>
<ol>
<li><a href="#Basics">The Basics</a></li>
@@ -26,22 +17,17 @@ does not take focus (or pause the current activity), so it cannot accept user in
</div>
</div>
-<p>A toast notification is a message that pops up on the surface of the window.
-It only fills the amount of space required for the message and the user's current
-activity remains visible and interactive. The notification automatically fades in and
-out, and does not accept interaction events.</p>
+<p>A toast provides simple feedback about an operation in a small popup.
+It only fills the amount of space required for the message and the current
+activity remains visible and interactive.
+For example, navigating away from an email before you send it triggers a
+"Draft saved" toast to let you know that you can continue editing later.
+Toasts automatically disappear after a timeout.</p>
-<p>The screenshot below shows an example toast notification from the Alarm application.
-Once an alarm is turned on, a toast is displayed to assure you that the
-alarm was set.</p>
<img src="{@docRoot}images/toast.png" alt="" />
-<p>A toast can be created and displayed from an {@link android.app.Activity} or
-{@link android.app.Service}. If you create a toast notification from a Service, it
-appears in front of the Activity currently in focus.</p>
-
-<p>If user response to the notification is required, consider using a
-<a href="notifications.html">Status Bar Notification</a>.</p>
+<p>If user response to a status message is required, consider instead using a
+<a href="{@docRoot}guide/topics/ui/notifiers/notifications.html">Notification</a>.</p>
<h2 id="Basics">The Basics</h2>
@@ -90,8 +76,6 @@ To nudge it down, increase the value of the last parameter.
<h2 id="CustomToastView">Creating a Custom Toast View</h2>
-<img src="{@docRoot}images/custom_toast.png" alt="" style="float:right" />
-
<p>If a simple text message isn't enough, you can create a customized layout for your
toast notification. To create a custom layout, define a View layout,
in XML or in your application code, and pass the root {@link android.view.View} object
@@ -105,17 +89,17 @@ with the following XML (saved as <em>toast_layout.xml</em>):</p>
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
- android:padding="10dp"
+ android:padding="8dp"
android:background="#DAAA"
>
- &lt;ImageView android:id="@+id/image"
+ &lt;ImageView android:src="@drawable/droid"
android:layout_width="wrap_content"
- android:layout_height="fill_parent"
- android:layout_marginRight="10dp"
+ android:layout_height="wrap_content"
+ android:layout_marginRight="8dp"
/>
&lt;TextView android:id="@+id/text"
android:layout_width="wrap_content"
- android:layout_height="fill_parent"
+ android:layout_height="wrap_content"
android:textColor="#FFF"
/>
&lt;/LinearLayout>
@@ -126,13 +110,11 @@ ID to inflate the layout from the XML, as shown here:</p>
<pre>
LayoutInflater inflater = getLayoutInflater();
-View layout = inflater.inflate(R.layout.toast_layout,
+View layout = inflater.inflate(R.layout.custom_toast,
(ViewGroup) findViewById(R.id.toast_layout_root));
-ImageView image = (ImageView) layout.findViewById(R.id.image);
-image.setImageResource(R.drawable.android);
TextView text = (TextView) layout.findViewById(R.id.text);
-text.setText("Hello! This is a custom toast!");
+text.setText("This is a custom toast");
Toast toast = new Toast(getApplicationContext());
toast.setGravity(Gravity.CENTER_VERTICAL, 0, 0);
diff --git a/docs/html/guide/topics/ui/themes.jd b/docs/html/guide/topics/ui/themes.jd
index d787492..bc1c4f0 100644
--- a/docs/html/guide/topics/ui/themes.jd
+++ b/docs/html/guide/topics/ui/themes.jd
@@ -413,8 +413,8 @@ thoroughly describe the styles, so viewing the actual source code for these styl
themes will give you a better understanding of what style properties each one provides.
For a better reference to the Android styles and themes, see the following source code:</p>
<ul>
- <li><a href="http://android.git.kernel.org/?p=platform/frameworks/base.git;a=blob;f=core/res/res/values/styles.xml;h=d7b654e49809cb97a35682754b1394af5c8bc88b;hb=HEAD">Android Styles (styles.xml)</a></li>
- <li><a href="http://android.git.kernel.org/?p=platform/frameworks/base.git;a=blob;f=core/res/res/values/themes.xml;h=6b3d7407d1c895a3c297e60d5beac98e2d34c271;hb=HEAD">Android Themes (themes.xml)</a></li>
+ <li><a href="https://android.googlesource.com/platform/frameworks/base/+/refs/heads/master/core/res/res/values/styles.xml">Android Styles (styles.xml)</a></li>
+ <li><a href="https://android.googlesource.com/platform/frameworks/base/+/refs/heads/master/core/res/res/values/themes.xml">Android Themes (themes.xml)</a></li>
</ul>
<p>These files will help you learn through example. For instance, in the Android themes source code,
@@ -422,9 +422,8 @@ you'll find a declaration for <code>&lt;style name="Theme.Dialog"&gt;</code>. In
you'll see all of the properties that are used to style dialogs that are used by the Android
framework.</p>
-<p>For more information about the syntax used to create styles in XML, see
-<a href="{@docRoot}guide/topics/resources/available-resources.html#stylesandthemes">Available Resource Types:
-Style and Themes</a>.</p>
+<p>For more information about the syntax for styles and themes in XML, see the
+<a href="{@docRoot}guide/topics/resources/style-resource.html">Style Resource</a> document.</p>
<p>For a reference of available style attributes that you can use to define a style or theme
(e.g., "windowBackground" or "textAppearance"), see {@link android.R.attr} or the respective