M7350v1_en_gpl

This commit is contained in:
T
2024-09-09 08:52:07 +00:00
commit f9cc65cfda
65988 changed files with 26357421 additions and 0 deletions
@@ -0,0 +1,532 @@
page.title=Device Administration
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>In this document</h2>
<ol>
<li><a href="#overview">Device Administration API Overview</a>
<ol>
<li><a href="#how">How does it work?</a></li>
<li><a href="#policies">Policies</a></li>
</ol>
</li>
<li><a href="#sample">Sample Application</a></li>
<li><a href="#developing">Developing a Device Administration Application</a>
<ol>
<li><a href="#manifest">Creating the manifest</a></li>
<li><a href="#code">Implementing the code</a></li>
</ol>
</li>
</ol>
<h2>Key classes</h2>
<ol>
<li>{@link android.app.admin.DeviceAdminReceiver}</li>
<li>{@link android.app.admin.DevicePolicyManager}</li>
<li>{@link android.app.admin.DeviceAdminInfo}</li>
</ol>
</div>
</div>
<p>Android 2.2 introduces support for enterprise applications by offering the
Android Device Administration API. The Device Administration API provides device
administration features at the system level. These APIs allow you to create
security-aware applications that are useful in enterprise settings, in which IT
professionals require rich control over employee devices. For example, the
built-in Android Email application has leveraged the new APIs to improve
Exchange support. Through the Email application, Exchange administrators can
enforce password policies &mdash; including alphanumeric passwords or numeric
PINs &mdash; across devices. Administrators can also remotely wipe (that is,
restore factory defaults on) lost or stolen handsets. Exchange users can sync
their email and calendar data.</p>
<p>This document is intended for developers who want to develop enterprise
solutions for Android-powered devices. It discusses the various features
provided by the Device Administration API to provide stronger security for
employee devices that are powered by Android.</p>
<h2 id="overview">Device Administration API Overview</h2>
<p>Here are examples of the types of applications that might use the Device Administration API:</p>
<ul>
<li>Email clients.</li>
<li>Security applications that do remote wipe.</li>
<li>Device management services and applications.</li>
</ul>
<h3 id="how">How does it work?</h3>
<p>You use the Device Administration API to write device admin applications that users
install on their devices. The device admin application enforces the desired
policies. Here's how it works:</p> <ul>
<li>A system administrator writes a device admin application that enforces
remote/local device security policies. These policies could be hard-coded into
the app, or the application could dynamically fetch policies from a third-party
server. </li>
<li>The application is installed on users' devices. Android does
not currently have an automated provisioning solution. Some of the ways a sysadmin might
distribute the application to users are as follows:
<ul>
<li>Android Market.</li>
<li>Enabling non-market installation.</li>
<li>Distributing the application through other means, such as email or websites.</li>
</ul>
</li>
<li>The system prompts the user to enable the device admin application. How
and when this happens depends on how the application is implemented.</li>
<li>Once users enable the device admin application, they are subject to
its policies. Complying with those policies typically confers benefits, such as
access to sensitive systems and data.</li>
</ul>
<p>If users do not enable the device admin app, it remains on the device, but in an inactive state. Users will not be subject to its policies, and they will conversely not get any of the application's benefits&mdash;for example, they may not be able to sync data.</p>
<p>If a user fails to comply with the policies (for example, if a user sets a
password that violates the guidelines), it is up to the application to decide
how to handle this. However, typically this will result in the user not being
able to sync data.</p>
<p>If a device attempts to connect to a server that requires policies not
supported in the Device Administration API, the connection will not
be allowed. The Device Administration API does not currently allow partial
provisioning. In other words, if a device (for example, a legacy device) does
not support all of the stated policies, there is no way to allow the
device to connect.</p>
<p>If a device contains multiple enabled admin applications, the strictest policy is
enforced. There is no way to target a particular admin
application.</p>
<p>To uninstall an existing device admin application, users need to
first unregister the application as an administrator. </p>
<h3 id="policies">Policies</h3>
<p>In an enterprise setting, it's often the case that employee devices must
adhere to a strict set of policies that govern the use of the device. The
Device Administration API supports the policies listed in Table 1.
Note that the Device Administration API currently only supports passwords for screen
lock:</p>
<p class="table-caption"><strong>Table 1.</strong> Policies supported by the Device Administration API.</p>
<table border="1">
<tr>
<th>Policy</th>
<th>Description</th>
</tr>
<tr>
<td>Password enabled</td>
<td>Requires that devices ask for PIN or passwords.</td>
</tr>
<tr>
<td>Minimum password length</td>
<td>Set the required number of characters for the password. For example, you
can require PIN or passwords to have at least six characters. </td> </tr>
<tr>
<td>Alphanumeric password required</td>
<td>Requires that passwords have a
combination of letters and numbers. They may include symbolic characters.
</td>
</tr>
<tr>
<td>Maximum failed password attempts </td>
<td>Specifies how many times a user can enter the wrong password before the
device wipes its data. The Device Administration API also allows administrators to
remotely reset the device to factory defaults. This secures data in case the
device is lost or stolen.</td>
</tr>
<tr>
<td>Maximum inactivity time lock</td>
<td>Sets the length of time since the user last touched the screen or
pressed a button before the device locks the screen. When this happens, users
need to enter their PIN or passwords again before they can use their devices and
access data. The value can be between 1 and 60 minutes.</td> </tr>
</table>
<h4>Other features</h4>
<p>In addition to supporting the policies listed in the above table, the Device
Administration API lets you do the following:</p> <ul>
<li>Prompt user to set a new password.</li>
<li>Lock device immediately.</li>
<li>Wipe the device's data (that is, restore the device to its factory defaults).</li>
</ul>
<h2 id="sample">Sample Application</h2>
<p>The examples used in this document are based on the <a
href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/DeviceAdminSample.html">
Device Administration API
sample</a>, which is included in the SDK samples. For information on downloading and
installing the SDK samples, see <a
href="{@docRoot}resources/samples/get.html">
Getting the Samples</a>. Here is the <a
href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/DeviceAdminSample.html">
complete code</a> for
the sample. </p>
<p>The
sample application offers a demo of device admin features. It presents users
with a user interface that lets them enable the device admin application. Once
they've enabled the application, they can use the buttons in the user interface
to do the following:</p>
<ul>
<li>Set password quality.</li>
<li>Specify the minimum length for the user's password.</li>
<li>Set the password. If the password does not conform to the specified
policies, the system returns an error.</li>
<li>Set how many failed password attempts can occur before the device is wiped
(that is, restored to factory settings).</li>
<li>Set the maximum amount of inactive time that can elapse before the device
locks.</li>
<li>Make the device lock immediately.</li>
<li>Wipe the device's data (that is, restore factory settings).</li>
</ul>
<img src="{@docRoot}images/admin/device-admin-app.png"/>
<p class="img-caption"><strong>Figure 1.</strong> Screenshot of the Sample Application</p>
<h2 id="developing">Developing a Device Administration Application</h2>
<p>System administrators can use the Device Administration API to write an application
that enforces remote/local device security policy enforcement. This section
summarizes the steps involved in creating a device administration
application.</p>
<h3 id="manifest">Creating the manifest</h3>
<p>To use the Device Administration API, the application's
manifest must include the following:</p>
<ul>
<li>A subclass of {@link android.app.admin.DeviceAdminReceiver} that includes the following:
<ul>
<li>The {@link android.Manifest.permission#BIND_DEVICE_ADMIN} permission.</li>
<li>The ability to respond to the {@link android.app.admin.DeviceAdminReceiver#ACTION_DEVICE_ADMIN_ENABLED}
intent, expressed in the manifest as an intent filter.</li>
</ul>
</li>
<li>A declaration of security policies used in metadata.</li>
</ul>
<p>Here is an excerpt from the Device Administration sample manifest:</p>
<pre>&lt;activity android:name=&quot;.app.DeviceAdminSample$Controller&quot;
       android:label=&quot;&#64;string/activity_sample_device_admin&quot;&gt;
 &lt;intent-filter&gt;
       &lt;action android:name=&quot;android.intent.action.MAIN&quot; /&gt;
       &lt;category android:name=&quot;android.intent.category.SAMPLE_CODE&quot; /&gt;
   &lt;/intent-filter&gt;
&lt;/activity&gt;
&lt;receiver android:name=&quot;.app.DeviceAdminSample&quot;
         android:label=&quot;&#64;string/sample_device_admin&quot;
         android:description=&quot;&#64;string/sample_device_admin_description&quot;
         android:permission=&quot;android.permission.BIND_DEVICE_ADMIN&quot;&gt;
   &lt;meta-data android:name=&quot;android.app.device_admin&quot;
              android:resource=&quot;&#64;xml/device_admin_sample&quot; /&gt;
   &lt;intent-filter&gt;
       &lt;action android:name=&quot;android.app.action.DEVICE_ADMIN_ENABLED&quot; /&gt;
   &lt;/intent-filter&gt;
&lt;/receiver&gt;</pre>
<p>Note that:</p>
<ul>
<li>The activity in the sample application is an {@link android.app.Activity}
subclass called <code>Controller</code>. The syntax
<code>&quot;.app.DeviceAdminSample$Controller&quot;</code> indicates that
<code>Controller</code> is an inner class that is nested inside the
<code>DeviceAdminSample</code> class. Note that an Activity does not need to be
an inner class; it just is in this example.</li>
<li>The following attributes refer to string resources that for the sample application reside in
<code>ApiDemos/res/values/strings.xml</code>. For more information about resources, see
<a
href="{@docRoot}guide/topics/resources/index.html">Application Resources</a>.
<ul>
<li><code>android:label=&quot;@string/activity_sample_device_admin&quot;</code> refers to the
user-readable label for the activity.</li>
<li><code>android:label=&quot;@string/sample_device_admin&quot;</code> refers to the
user-readable label for the permission.</li>
<li><code>android:description=&quot;@string/sample_device_admin_description&quot;</code> refers to
the user-readable description of the permission. A descripton is typically longer and more
informative than
a label.</li>
</ul>
<li><code>android:permission=&quot;android.permission.BIND_DEVICE_ADMIN&quot;
</code> is a permission that a {@link android.app.admin.DeviceAdminReceiver} subclass must
have, to ensure that only the system can interact with the receiver (no application can be granted this permission). This
prevents other applications from abusing your device admin app.</li>
<li><code>android.app.action.DEVICE_ADMIN_ENABLED</code> is the the primary
action that a {@link android.app.admin.DeviceAdminReceiver} subclass must handle to be
allowed to manage a device. This is set to the receiver when the user enables
the device admin app. Your code typically handles this in
{@link android.app.admin.DeviceAdminReceiver#onEnabled onEnabled()}. To be supported, the receiver must also
require the {@link android.Manifest.permission#BIND_DEVICE_ADMIN} permission so that other applications
cannot abuse it. </li>
<li>When a user enables the device admin application, that gives the receiver
permission to perform actions in response to the broadcast of particular system
events. When suitable event arises, the application can impose a policy. For
example, if the user attempts to set a new password that doesn't meet the policy
requirements, the application can prompt the user to pick a different password
that does meet the requirements.</li>
<li><code>android:resource=&quot;&#64;xml/device_admin_sample&quot;</code>
declares the security policies used in metadata. The metadata provides additional
information specific to the device administrator, as parsed by the {@link
android.app.admin.DeviceAdminInfo} class. Here are the contents of
<code>device_admin_sample.xml</code>:</li>
</ul>
<pre>&lt;device-admin xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;&gt;
&lt;uses-policies&gt;
&lt;limit-password /&gt;
&lt;watch-login /&gt;
&lt;reset-password /&gt;
&lt;force-lock /&gt;
&lt;wipe-data /&gt;
&lt;/uses-policies&gt;
&lt;/device-admin&gt;
</pre>
<p> In designing your device administration application, you don't need to
include all of the policies, just the ones that are relevant for your app.
</p>
For more discussion of the manifest file, see the <a
href="{@docRoot}guide/topics/manifest/manifest-intro.html">Android Developers Guide</a>.
<h3 id="code">Implementing the code</h3>
<p>The Device Administration API includes the following classes:</p>
<dl>
<dt>{@link android.app.admin.DeviceAdminReceiver}</dt>
<dd>Base class for implementing a device administration component. This class provides
a convenience for interpreting the raw intent actions that are sent by the
system. Your Device Administration application must include a
{@link android.app.admin.DeviceAdminReceiver} subclass.</dd>
<dt>{@link android.app.admin.DevicePolicyManager}</dt>
<dd>A class for managing policies enforced on a device. Most clients of
this class must have published a {@link android.app.admin.DeviceAdminReceiver} that the user
has currently enabled. The {@link android.app.admin.DevicePolicyManager} manages policies for
one or more {@link android.app.admin.DeviceAdminReceiver} instances</dd>
<dt>{@link android.app.admin.DeviceAdminInfo}</dt>
<dd>This class is used to specify metadata
for a device administrator component.</dd>
</dl>
<p>These classes provide the foundation for a fully functional device administration application.
The rest of this section describes how you use the {@link
android.app.admin.DeviceAdminReceiver} and
{@link android.app.admin.DevicePolicyManager} APIs to write a device admin application.</p>
<h4 id="receiver">Subclassing DeviceAdminReceiver</h4>
<p>To create a device admin application, you must subclass
{@link android.app.admin.DeviceAdminReceiver}. The {@link android.app.admin.DeviceAdminReceiver} class
consists of a series of callbacks that are triggered when particular events
occur.</p>
<p>In its {@link android.app.admin.DeviceAdminReceiver} subclass, the sample application
simply displays a {@link android.widget.Toast} notification in response to particular
events. For example:</p>
<pre>public class DeviceAdminSample extends DeviceAdminReceiver {
...
&#64;Override
    public void onEnabled(Context context, Intent intent) {
        showToast(context, &quot;Sample Device Admin: enabled&quot;);
    }
    &#64;Override
    public CharSequence onDisableRequested(Context context, Intent intent) {
        return &quot;This is an optional message to warn the user about disabling.&quot;;
    }
    &#64;Override
    public void onDisabled(Context context, Intent intent) {
        showToast(context, &quot;Sample Device Admin: disabled&quot;);
    }
    &#64;Override
    public void onPasswordChanged(Context context, Intent intent) {
        showToast(context, &quot;Sample Device Admin: pw changed&quot;);
    }
void showToast(Context context, CharSequence msg) {
Toast.makeText(context, msg, Toast.LENGTH_SHORT).show();
}
...
}</pre>
<h4 id="enabling">Enabling the application</h4>
<p>One of the major events a device admin application has to handle is the user
enabling the application. The user must explicitly enable the application for
the policies to be enforced. If the user chooses not to enable the application
it will still be present on the device, but its policies will not be enforced, and the user will not
get any of the application's benefits.</p>
<p>The process of enabling the application begins when the user performs an
action that triggers the {@link android.app.admin.DevicePolicyManager#ACTION_ADD_DEVICE_ADMIN}
intent. In the
sample application, this happens when the user clicks the <strong>Enable
Admin</strong> button. </p>
<p>When the user clicks the <strong>Enable Admin</strong> button, the display
changes to prompt the user to enable the device admin application, as shown in figure
2.</p>
<img src="{@docRoot}images/admin/device-admin-activate-prompt.png"/>
<p class="img-caption"><strong>Figure 2.</strong> Sample Application: Activating the Application</p>
<p>Below is the code that gets executed when the user clicks the <strong>Enable
Admin</strong> button shown in figure 1. </p>
<pre> private OnClickListener mEnableListener = new OnClickListener() {
public void onClick(View v) {
// Launch the activity to have the user enable our admin.
        Intent intent = new Intent(DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN);
intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN,
mDeviceAdminSample);
        intent.putExtra(DevicePolicyManager.EXTRA_ADD_EXPLANATION,
               &quot;Additional text explaining why this needs to be added.&quot;);
        startActivityForResult(intent, RESULT_ENABLE);
}
};
...
// This code checks whether the device admin app was successfully enabled.
&#64;Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case RESULT_ENABLE:
if (resultCode == Activity.RESULT_OK) {
Log.i(&quot;DeviceAdminSample&quot;, &quot;Administration enabled!&quot;);
            } else {
                Log.i(&quot;DeviceAdminSample&quot;, &quot;Administration enable FAILED!&quot;);
            }
            return;
    }
    super.onActivityResult(requestCode, resultCode, data);
}</pre>
<p>The line
<code>intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN,
mDeviceAdminSample)</code> states that <code>mDeviceAdminSample</code> (which is
a {@link android.app.admin.DeviceAdminReceiver} component) is the target policy.
This line invokes the user interface shown in figure 2, which guides users through
adding the device administrator to the system (or allows them to reject it).</p>
<p>When the application needs to perform an operation that is contingent on the
device admin application being enabled, it confirms that the application is
active. To do this it uses the {@link android.app.admin.DevicePolicyManager} method
{@link android.app.admin.DevicePolicyManager#isAdminActive(android.content.ComponentName) isAdminActive()}. Notice that the {@link android.app.admin.DevicePolicyManager}
method {@link android.app.admin.DevicePolicyManager#isAdminActive(android.content.ComponentName) isAdminActive()} takes a {@link android.app.admin.DeviceAdminReceiver}
component as its argument:</p>
<pre>
DevicePolicyManager mDPM;
...
boolean active = mDPM.isAdminActive(mDeviceAdminSample);
if (active) {
// Admin app is active, so do some admin stuff
               ...
} else {
// do something else
}
</pre>
<h3 id="admin_ops">Managing policies</h3>
<p>{@link android.app.admin.DevicePolicyManager} is a public class for managing policies
enforced on a device. {@link android.app.admin.DevicePolicyManager} manages policies for one
or more {@link android.app.admin.DeviceAdminReceiver} instances. </p>
<p>You get a handle to the {@link android.app.admin.DevicePolicyManager} as follows: </p>
<pre>
DevicePolicyManager mDPM =
(DevicePolicyManager)getSystemService(Context.DEVICE_POLICY_SERVICE);
</pre>
<p>This section describes how to use {@link android.app.admin.DevicePolicyManager} to perform
administrative tasks:</p>
<ul>
<li><a href="#pwd">Set password policies</a></li>
<li><a href="#lock">Set device lock</a></li>
<li><a href="#wipe">Perform data wipe</a></li>
</ul>
<h4 id="pwd">Set password policies</h4>
<p>{@link android.app.admin.DevicePolicyManager} includes APIs for setting and enforcing the
device password policy. In the Device Administration API, the password only applies to
screen lock. This section describes common password-related tasks.</p>
<h5>Set a password for the device</h5>
<p>This code displays a user interface prompting the user to set a password:</p>
<pre>Intent intent = new Intent(DevicePolicyManager.ACTION_SET_NEW_PASSWORD);
startActivity(intent);
</pre>
<h5>Set the password quality</h5>
<p>The password quality can be one of the following {@link android.app.admin.DevicePolicyManager} constants: </p>
<dl>
<dt>{@link android.app.admin.DevicePolicyManager#PASSWORD_QUALITY_ALPHABETIC}</dt><dd>The user must enter a
password containing at least alphabetic (or other symbol) characters.</dd>
<dt>{@link android.app.admin.DevicePolicyManager#PASSWORD_QUALITY_ALPHANUMERIC}</dt><dd>The user must enter a
password containing at least <em>both</em> numeric <em>and</em> alphabetic (or
other symbol) characters.</dd>
<dt>{@link android.app.admin.DevicePolicyManager#PASSWORD_QUALITY_NUMERIC}</dt><dd>The user must enter a password
containing at least numeric characters.</dd>
<dt>{@link android.app.admin.DevicePolicyManager#PASSWORD_QUALITY_SOMETHING}</dt><dd>The policy requires some kind
of password, but doesn't care what it is.</dd>
<dt>{@link android.app.admin.DevicePolicyManager#PASSWORD_QUALITY_UNSPECIFIED}</dt><dd>
The policy has no requirements for the password. </dd>
</dl>
<p>For example, this is how you would set the password policy to require an alphanumeric password:</p>
<pre>
DevicePolicyManager mDPM;
ComponentName mDeviceAdminSample;
...
mDPM.setPasswordQuality(mDeviceAdminSample, DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC);
</pre>
<h5>Set the minimum password length</h5>
<p>You can specify that a password must be at least the specified minimum
length. For example:</p>
<pre>DevicePolicyManager mDPM;
ComponentName mDeviceAdminSample;
int pwLength;
...
mDPM.setPasswordMinimumLength(mDeviceAdminSample, pwLength);
</pre>
<h5>Set maximum failed password attempts</h5>
<p>You can set the maximum number of allowed failed password attempts before the
device is wiped (that is, reset to factory settings). For example:</p>
<pre>DevicePolicyManager mDPM;
ComponentName mDeviceAdminSample;
int maxFailedPw;
...
mDPM.setMaximumFailedPasswordsForWipe(mDeviceAdminSample, maxFailedPw);</pre>
<h4 id="lock">Set device lock</h4>
<p>You can set the maximum period of user inactivity that can occur before the
device locks. For example:</p>
<pre>
DevicePolicyManager mDPM;
ComponentName mDeviceAdminSample;
...
long timeMs = 1000L*Long.parseLong(mTimeout.getText().toString());
mDPM.setMaximumTimeToLock(mDeviceAdminSample, timeMs);
</pre>
<p>You can also programmatically tell the device to lock immediately:</p>
<pre>
DevicePolicyManager mDPM;
mDPM.lockNow();</pre>
<h4 id="wipe">Perform data wipe</h4>
<p>You can use the {@link android.app.admin.DevicePolicyManager} method
{@link android.app.admin.DevicePolicyManager#wipeData wipeData()} to reset the device to factory settings. This is useful
if the device is lost or stolen. Often the decision to wipe the device is the
result of certain conditions being met. For example, you can use
{@link android.app.admin.DevicePolicyManager#setMaximumFailedPasswordsForWipe setMaximumFailedPasswordsForWipe()} to state that a device should be
wiped after a specific number of failed password attempts.</p>
<p>You wipe data as follows:</p>
<pre>
DevicePolicyManager mDPM;
mDPM.wipeData(0);</pre>
<p>The {@link android.app.admin.DevicePolicyManager#wipeData wipeData()} method takes as its parameter a bit mask of
additional options. Currently the value must be 0. </p>
@@ -0,0 +1,484 @@
page.title=App Widgets
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>Quickview</h2>
<ul>
<li>App Widgets provide users access to some of your application features
directly from the Home screen (without the need to launch an activity)</li>
<li>App Widgets are backed by a special kind of broadcast receiver that handles the App
Widget lifecycle</li>
</ul>
<h2>In this document</h2>
<ol>
<li><a href="#Basics">The Basics</a></li>
<li><a href="#Manifest">Declaring an App Widget in the Manifest</a></li>
<li><a href="#MetaData">Adding the AppWidgetProviderInfo Metadata</a></li>
<li><a href="#CreatingLayout">Creating the App Widget Layout</a></li>
<li><a href="#AppWidgetProvider">Using the AppWidgetProvider Class</a>
<ol>
<li><a href="#ProviderBroadcasts">Receiving App Widget broadcast Intents</a></li>
</ol>
</li>
<li><a href="#Configuring">Creating an App Widget Configuration Activity</a>
<ol>
<li><a href="#UpdatingFromTheConfiguration">Updating the App Widget from
the configuration Activity</a></li>
</ol>
</li>
</ol>
<h2>Key classes</h2>
<ol>
<li>{@link android.appwidget.AppWidgetProvider}</li>
<li>{@link android.appwidget.AppWidgetProviderInfo}</li>
<li>{@link android.appwidget.AppWidgetManager}</li>
</ol>
<h2>See also</h2>
<ol>
<li><a href="{@docRoot}guide/practices/ui_guidelines/widget_design.html">App Widget Design
Guidelines</a></li>
<li><a href="http://android-developers.blogspot.com/2009/04/introducing-home-screen-widgets-and.html">Introducing
home screen widgets and the AppWidget framework &raquo;</a></li>
</ol>
</div>
</div>
<p>App Widgets are miniature application views that can be embedded in other applications
(such as the Home screen) and receive periodic updates. These views are referred
to as Widgets in the user interface,
and you can publish one with an App Widget provider. An application component that is
able to hold other App Widgets is called an App Widget host. The screenshot below shows
the Music App Widget.</p>
<img src="{@docRoot}images/appwidget.png" alt="" />
<p>This document describes how to publish an App Widget using an App Widget provider.</p>
<h2 id="Basics">The Basics</h2>
<p>To create an App Widget, you need the following:</p>
<dl>
<dt>{@link android.appwidget.AppWidgetProviderInfo} object</dt>
<dd>Describes the metadata for an App Widget, such as the App Widget's layout, update frequency,
and the AppWidgetProvider class. This should be defined in XML.</dd>
<dt>{@link android.appwidget.AppWidgetProvider} class implementation</dt>
<dd>Defines the basic methods that allow you to programmatically interface with the App Widget,
based on broadcast events. Through it, you will receive broadcasts when the App Widget is updated,
enabled, disabled and deleted.</dd>
<dt>View layout</dt>
<dd>Defines the initial layout for the App Widget, defined in XML.</dd>
</dl>
<p>Additionally, you can implement an App Widget configuration Activity. This is an optional
{@link android.app.Activity} that launches when the user adds your App Widget and allows him or her
to modify App Widget settings at create-time.</p>
<p>The following sections describe how to setup each of these components.</p>
<h2 id="Manifest">Declaring an App Widget in the Manifest</h2>
<p>First, declare the {@link android.appwidget.AppWidgetProvider} class in your application's
<code>AndroidManifest.xml</code> file. For example:</p>
<pre>
&lt;receiver android:name="ExampleAppWidgetProvider" >
&lt;intent-filter>
&lt;action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
&lt;/intent-filter>
&lt;meta-data android:name="android.appwidget.provider"
android:resource="@xml/example_appwidget_info" />
&lt;/receiver>
</pre>
<p>The <code>&lt;receiver&gt;</code> element requires the <code>android:name</code>
attribute, which specifies the {@link android.appwidget.AppWidgetProvider} used
by the App Widget.</p>
<p>The <code>&lt;intent-filter&gt;</code> element must include an <code>&lt;action></code>
element with the <code>android:name</code> attribute. This attribute specifies
that the {@link android.appwidget.AppWidgetProvider} accepts the {@link
android.appwidget.AppWidgetManager#ACTION_APPWIDGET_UPDATE ACTION_APPWIDGET_UPDATE} broadcast.
This is the only broadcast that you must explicitly declare. The {@link android.appwidget.AppWidgetManager}
automatically sends all other App Widget broadcasts to the AppWidgetProvider as necessary.</p>
<p>The <code>&lt;meta-data&gt;</code> element specifies the
{@link android.appwidget.AppWidgetProviderInfo} resource and requires the
following attributes:</p>
<ul>
<li><code>android:name</code> - Specifies the metadata name. Use <code>android.appwidget.provider</code>
to identify the data as the {@link android.appwidget.AppWidgetProviderInfo} descriptor.</li>
<li><code>android:resource</code> - Specifies the {@link android.appwidget.AppWidgetProviderInfo}
resource location.</li>
</ul>
<h2 id="MetaData">Adding the AppWidgetProviderInfo Metadata</h2>
<p>The {@link android.appwidget.AppWidgetProviderInfo} defines the essential
qualities of an App Widget, such as its minimum layout dimensions, its initial layout resource,
how often to update the App Widget, and (optionally) a configuration Activity to launch at create-time.
Define the AppWidgetProviderInfo object in an XML resource using a single
<code>&lt;appwidget-provider></code> element and save it in the project's <code>res/xml/</code>
folder.</p>
<p>For example:</p>
<pre>
&lt;appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:minWidth="294dp"
android:minHeight="72dp"
android:updatePeriodMillis="86400000"
android:initialLayout="@layout/example_appwidget"
android:configure="com.example.android.ExampleAppWidgetConfigure" >
&lt;/appwidget-provider>
</pre>
<p>Here's a summary of the <code>&lt;appwidget-provider></code> attributes:</p>
<ul>
<li>The values for the <code>minWidth</code> and <code>minHeight</code> attributes specify the minimum
area required by the App Widget's layout.
<p>The default Home screen positions App Widgets in its window based on a grid of
cells that have a defined height and width. If the values for an App Widget's minimum width
or height don't match the dimensions of the cells,
then the App Widget dimensions round <em>up</em> to the nearest cell size.
(See the <a href="{@docRoot}guide/practices/ui_guidelines/widget_design.html">App Widget Design
Guidelines</a> for more information on the Home screen cell sizes.)</p>
<p>Because the Home screen's layout orientation (and thus, the cell sizes) can change,
as a rule of thumb, you should assume the worst-case cell size of 74 pixels for the height
<em>and</em> width of a cell. However, you must subtract 2 from the final dimension to account
for any integer rounding errors that occur in the pixel count. To find your minimum width
and height in density-independent pixels (dp), use this formula:<br/>
<code>(number of cells * 74) - 2</code><br/>
Following this formula, you should use 72 dp for a height of one cell, 294 dp and for a width of four cells.</p>
</li>
<li>The <code>updatePeriodMillis</code> attribute defines how often the App Widget framework should
request an update from the {@link android.appwidget.AppWidgetProvider} by calling the
{@link android.appwidget.AppWidgetProvider#onUpdate(Context,AppWidgetManager,int[])
onUpdate()} method. The actual update is not guaranteed to occur exactly on time with this value
and we suggest updating as infrequently as possible&mdash;perhaps no more than once an hour to
conserve the battery. You might also allow the user to adjust the frequency in a
configuration&mdash;some people might want a stock ticker to update every 15 minutes, or maybe
only four times a day.
<p class="note"><strong>Note:</strong> If the device is asleep when it is time for an update
(as defined by <code>updatePeriodMillis</code>), then the device will wake up in order
to perform the update. If you don't update more than once per hour, this probably won't
cause significant problems for the battery life. If, however, you need to update more
frequently and/or you do not need to update while the device is asleep, then you can instead
perform updates based on an alarm that will not wake the device. To do so, set an alarm with
an Intent that your AppWidgetProvider receives, using the {@link android.app.AlarmManager}.
Set the alarm type to either {@link android.app.AlarmManager#ELAPSED_REALTIME} or
{@link android.app.AlarmManager#RTC}, which will only
deliver the alarm when the device is awake. Then set <code>updatePeriodMillis</code> to
zero (<code>"0"</code>).</p>
</li>
<li>The <code>initialLayout</code> attribute points to the layout resource that defines the
App Widget layout.</li>
<li>The <code>configure</code> attribute defines the {@link android.app.Activity} to launch when
the user adds the App Widget, in order for him or her to configure App Widget properties. This is optional
(read <a href="#Configuring">Creating an App Widget Configuration Activity</a> below).</li>
</ul>
<p>See the {@link android.appwidget.AppWidgetProviderInfo} class for more information on the
attributes accepted by the <code>&lt;appwidget-provider></code> element.</p>
<h2 id="CreatingLayout">Creating the App Widget Layout</h2>
<p>You must define an initial layout for your App Widget in XML and save it in the project's
<code>res/layout/</code> directory. You can design your App Widget using the View objects listed
below, but before you begin designing your App Widget, please read and understand the
<a href="{@docRoot}guide/practices/ui_guidelines/widget_design.html">App Widget Design
Guidelines</a>.</p>
<p>Creating the App Widget layout is simple if you're
familiar with <a href="{@docRoot}guide/topics/ui/declaring-layout.html">Declaring Layout in XML</a>.
However, you must be aware that App Widget layouts are based on {@link android.widget.RemoteViews},
which do not support every kind of layout or view widget.</p>
<p>A RemoteViews object (and, consequently, an App Widget) can support the
following layout classes:</p>
<ul class="nolist">
<li>{@link android.widget.FrameLayout}</li>
<li>{@link android.widget.LinearLayout}</li>
<li>{@link android.widget.RelativeLayout}</li>
</ul>
<p>And the following widget classes:</p>
<ul class="nolist">
<li>{@link android.widget.AnalogClock}</li>
<li>{@link android.widget.Button}</li>
<li>{@link android.widget.Chronometer}</li>
<li>{@link android.widget.ImageButton}</li>
<li>{@link android.widget.ImageView}</li>
<li>{@link android.widget.ProgressBar}</li>
<li>{@link android.widget.TextView}</li>
</ul>
<p>Descendants of these classes are not supported.</p>
<h2 id="AppWidgetProvider">Using the AppWidgetProvider Class</h2>
<div class="sidebox-wrapper">
<div class="sidebox">
<p>You must declare your AppWidgetProvider class implementation as a broadcast receiver
using the <code>&lt;receiver></code> element in the AndroidManifest (see
<a href="#Manifest">Declaring an App Widget in the Manifest</a> above).</p>
</div>
</div>
<p>The {@link android.appwidget.AppWidgetProvider} class extends BroadcastReceiver as a convenience
class to handle the App Widget broadcasts. The AppWidgetProvider receives only the event broadcasts that
are relevant to the App Widget, such as when the App Widget is updated, deleted, enabled, and disabled.
When these broadcast events occur, the AppWidgetProvider receives the following method calls:</p>
<dl>
<dt>{@link android.appwidget.AppWidgetProvider#onUpdate(Context,AppWidgetManager,int[])}</dt>
<dd>This is called to update the App Widget at intervals defined by the <code>updatePeriodMillis</code>
attribute in the AppWidgetProviderInfo (see <a href="#MetaData">Adding the
AppWidgetProviderInfo Metadata</a> above). This method is also called
when the user adds the App Widget, so it should perform the essential setup,
such as define event handlers for Views and start a temporary
{@link android.app.Service}, if necessary. However, if you have declared a configuration
Activity, <strong>this method is not called</strong> when the user adds the App Widget,
but is called for the subsequent updates. It is the responsibility of the
configuration Activity to perform the first update when configuration is done.
(See <a href="#Configuring">Creating an App Widget Configuration Activity</a> below.)</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>
<dt>{@link android.appwidget.AppWidgetProvider#onEnabled(Context)}</dt>
<dd>This is called when an instance the App Widget is created for the first time. For example, if the user
adds two instances of your App Widget, this is only called the first time.
If you need to open a new database or perform other setup that only needs to occur once
for all App Widget instances, then this is a good place to do it.</dd>
<dt>{@link android.appwidget.AppWidgetProvider#onDisabled(Context)}</dt>
<dd>This is called when the last instance of your App Widget is deleted from the App Widget host.
This is where you should clean up any work done in
{@link android.appwidget.AppWidgetProvider#onEnabled(Context)},
such as delete a temporary database.</dd>
<dt>{@link android.appwidget.AppWidgetProvider#onReceive(Context,Intent)}</dt>
<dd>This is called for every broadcast and before each of the above callback methods.
You normally don't need to implement this method because the default AppWidgetProvider
implementation filters all App Widget broadcasts and calls the above
methods as appropriate.</dd>
</dl>
<p class="warning"><strong>Note:</strong> In Android 1.5, there is a known issue in which the
<code>onDeleted()</code> method will not be called when it should be. To work around this issue,
you can implement {@link android.appwidget.AppWidgetProvider#onReceive(Context,Intent)
onReceive()} as described in this
<a href="http://groups.google.com/group/android-developers/msg/e405ca19df2170e2">Group post</a>
to receive the <code>onDeleted()</code> callback.
</p>
<p>The most important AppWidgetProvider callback is
{@link android.appwidget.AppWidgetProvider#onUpdate(Context,AppWidgetManager,int[])
onUpdated()} because it is called when each App Widget is added to a host (unless you use
a configuration Activity). If your App Widget accepts any
user interaction events, then you need to register the event handlers in this callback.
If your App Widget doesn't create temporary
files or databases, or perform other work that requires clean-up, then
{@link android.appwidget.AppWidgetProvider#onUpdate(Context,AppWidgetManager,int[])
onUpdated()} may be the only callback method you need to define. For example, if you want an App Widget
with a button that launches an Activity when clicked, you could use the following
implementation of AppWidgetProvider:</p>
<pre>
public class ExampleAppWidgetProvider extends AppWidgetProvider {
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
final int N = appWidgetIds.length;
// Perform this loop procedure for each App Widget that belongs to this provider
for (int i=0; i&lt;N; i++) {
int appWidgetId = appWidgetIds[i];
// Create an Intent to launch ExampleActivity
Intent intent = new Intent(context, ExampleActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);
// Get the layout for the App Widget and attach an on-click listener to the button
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.appwidget_provider_layout);
views.setOnClickPendingIntent(R.id.button, pendingIntent);
// Tell the AppWidgetManager to perform an update on the current App Widget
appWidgetManager.updateAppWidget(appWidgetId, views);
}
}
}
</pre>
<p>This AppWidgetProvider defines only the
{@link android.appwidget.AppWidgetProvider#onUpdate(Context,AppWidgetManager,int[])
onUpdated()} method for the purpose
of defining a {@link android.app.PendingIntent} that launches an {@link android.app.Activity}
and attaching it to the App Widget's button
with {@link android.widget.RemoteViews#setOnClickPendingIntent(int,PendingIntent)}.
Notice that it includes a loop that iterates through each entry in <code>appWidgetIds</code>, which
is an array of IDs that identify each App Widget created by this provider.
In this way, if the user creates more than one instance of the App Widget, then they are
all updated simultaneously. However, only one <code>updatePeriodMillis</code> schedule will be
managed for all instances of the App Widget. For example, if the update schedule is defined
to be every two hours, and a second instance
of the App Widget is added one hour after the first one, then they will both be updated
on the period defined by the first one and the second update period will be ignored
(they'll both be updated every two hours, not every hour).</p>
<p class="note"><strong>Note:</strong> Because the AppWidgetProvider is a BroadcastReceiver,
your process is not guaranteed to keep running after the callback methods return (see
<a href="{@docRoot}guide/topics/fundamentals.html#broadlife">Application Fundamentals &gt;
Broadcast Receiver Lifecycle</a> for more information). If your App Widget setup process can take several
seconds (perhaps while performing web requests) and you require that your process continues,
consider starting a {@link android.app.Service}
in the {@link android.appwidget.AppWidgetProvider#onUpdate(Context,AppWidgetManager,int[])
onUpdated()} method. From within the Service, you can perform your own updates to the App Widget
without worrying about the AppWidgetProvider closing down due to an
<a href="{@docRoot}guide/practices/design/responsiveness.html">Application Not Responding</a>
(ANR) error. See the
<a href="http://code.google.com/p/wiktionary-android/source/browse/trunk/Wiktionary/src/com/example/android/wiktionary/WordWidget.java">Wiktionary
sample's AppWidgetProvider</a> for an example of an App Widget running a {@link android.app.Service}.</p>
<p>Also see the <a
href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/appwidget/ExampleAppWidgetProvider.html">
ExampleAppWidgetProvider.java</a> sample class.</p>
<h3 id="ProviderBroadcasts">Receiving App Widget broadcast Intents</h3>
<p>{@link android.appwidget.AppWidgetProvider} is just a convenience class. If 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>
<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>
</ul>
<h2 id="Configuring">Creating an App Widget Configuration Activity</h2>
<p>If you would like the user to configure settings when he or she adds a new App Widget,
you can create an App Widget configuration Activity. This {@link android.app.Activity}
will be automatically launched by the App Widget host and allows the user to configure
available settings for the App Widget at create-time, such as the App Widget color, size,
update period or other functionality settings.</p>
<p>The configuration Activity should be declared as a normal Activity in the Android manifest file.
However, it will be launched by the App Widget host with the {@link
android.appwidget.AppWidgetManager#ACTION_APPWIDGET_CONFIGURE ACTION_APPWIDGET_CONFIGURE} action,
so the Activity needs to accept this Intent. For example:</p>
<pre>
&lt;activity android:name=".ExampleAppWidgetConfigure">
&lt;intent-filter>
&lt;action android:name="android.appwidget.action.APPWIDGET_CONFIGURE" />
&lt;/intent-filter>
&lt;/activity>
</pre>
<p>Also, the Activity must be declared in the AppWidgetProviderInfo XML file, with the
<code>android:configure</code> attribute (see <a href="#MetaData">Adding
the AppWidgetProviderInfo Metadata</a> above). For example, the configuration Activity
can be declared like this:</p>
<pre>
&lt;appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
...
android:configure="com.example.android.ExampleAppWidgetConfigure"
... >
&lt;/appwidget-provider>
</pre>
<p>Notice that the Activity is declared with a fully-qualified namespace, because
it will be referenced from outside your package scope.</p>
<p>That's all you need to get started with a configuration Activity. Now all you need is the actual
Activity. There are, however, two important things to remember when you implement the Activity:</p>
<ul>
<li>The App Widget host calls the configuration Activity and the configuration Activity should always
return a result. The result should include the App Widget ID
passed by the Intent that launched the Activity (saved in the Intent extras as
{@link android.appwidget.AppWidgetManager#EXTRA_APPWIDGET_ID}).</li>
<li>The {@link android.appwidget.AppWidgetProvider#onUpdate(Context,AppWidgetManager,int[])
onUpdate()} method <strong>will not be called</strong> when the App Widget is created
(the system will not send the ACTION_APPWIDGET_UPDATE broadcast when a configuration Activity
is launched). It is the responsibility of the configuration Activity to request an update from the
AppWidgetManager when the App Widget is first created. However,
{@link android.appwidget.AppWidgetProvider#onUpdate(Context,AppWidgetManager,int[])
onUpdate()} will be called for subsequent updates&mdash;it is only skipped the first time.</li>
</ul>
<p>See the code snippets in the following section for an example of how to return a result
from the configuration and update the App Widget.</p>
<h3 id="UpdatingFromTheConfiguration">Updating the App Widget from the configuration Activity</h3>
<p>When an App Widget uses a configuration Activity, it is the responsibility of the Activity
to update the App Widget when configuration is complete.
You can do so by requesting an update directly from the
{@link android.appwidget.AppWidgetManager}.</p>
<p>Here's a summary of the procedure to properly update the App Widget and close
the configuration Activity:</p>
<ol>
<li>First, get the App Widget ID from the Intent that launched the Activity:
<pre>
Intent intent = getIntent();
Bundle extras = intent.getExtras();
if (extras != null) {
mAppWidgetId = extras.getInt(
AppWidgetManager.EXTRA_APPWIDGET_ID,
AppWidgetManager.INVALID_APPWIDGET_ID);
}
</pre>
</li>
<li>Perform your App Widget configuration.</li>
<li>When the configuration is complete, get an instance of the AppWidgetManager by calling
{@link android.appwidget.AppWidgetManager#getInstance(Context)}:
<pre>
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
</pre>
</li>
<li>Update the App Widget with a {@link android.widget.RemoteViews} layout by calling
{@link android.appwidget.AppWidgetManager#updateAppWidget(int,RemoteViews)}:
<pre>
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.example_appwidget);
appWidgetManager.updateAppWidget(mAppWidgetId, views);
</pre>
</li>
<li>Finally, create the return Intent, set it with the Activity result, and finish the Activity:</li>
<pre>
Intent resultValue = new Intent();
resultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mAppWidgetId);
setResult(RESULT_OK, resultValue);
finish();
</pre>
</li>
</ol>
<p class="note"><strong>Tip:</strong> When your configuration Activity first opens, set
the Activity result to RESULT_CANCELED. This way, if the user backs-out of the Activity before
reaching the end, the App Widget host is notified that the configuration was cancelled and the
App Widget will not be added.</p>
<p>See the <a
href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/appwidget/ExampleAppWidgetConfigure.html">
ExampleAppWidgetConfigure.java</a> sample class in ApiDemos for an example.</p>
+937
View File
@@ -0,0 +1,937 @@
page.title=Data Backup
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>Quickview</h2>
<ul>
<li>Back up the user's data to the cloud in case the user loses it</li>
<li>If the user upgrades to a new Android-powered device, your app can restore the user's
data onto the new device</li>
<li>Easily back up SharedPreferences and private files with BackupAgentHelper</li>
<li>Requires API Level 8</li>
</ul>
<h2>In this document</h2>
<ol>
<li><a href="#Basics">The Basics</a></li>
<li><a href="#BackupManifest">Declaring the Backup Agent in Your Manifest</a></li>
<li><a href="#BackupKey">Registering for Android Backup Service</a></li>
<li><a href="#BackupAgent">Extending BackupAgent</a>
<ol>
<li><a href="#RequiredMethods">Required Methods</a></li>
<li><a href="#PerformingBackup">Performing backup</a></li>
<li><a href="#PerformingRestore">Performing restore</a></li>
</ol>
</li>
<li><a href="#BackupAgentHelper">Extending BackupAgentHelper</a>
<ol>
<li><a href="#SharedPreferences">Backing up SharedPreferences</a></li>
<li><a href="#Files">Backing up Private Files</a></li>
</ol>
</li>
<li><a href="#RestoreVersion">Checking the Restore Data Version</a></li>
<li><a href="#RequestingBackup">Requesting Backup</a></li>
<li><a href="#RequestingRestore">Requesting Restore</a></li>
<li><a href="#Testing">Testing Your Backup Agent</a></li>
</ol>
<h2>Key classes</h2>
<ol>
<li>{@link android.app.backup.BackupManager}</li>
<li>{@link android.app.backup.BackupAgent}</li>
<li>{@link android.app.backup.BackupAgentHelper}</li>
</ol>
<h2>See also</h2>
<ol>
<li><a href="{@docRoot}guide/developing/tools/bmgr.html">{@code bmgr} tool</a></li>
</ol>
</div>
</div>
<p>Android's {@link android.app.backup backup} service allows you to copy your persistent
application data to remote "cloud" storage, in order to provide a restore point for the
application data and settings. If a user performs a factory reset or converts to a new
Android-powered device, the system automatically restores your backup data when the application
is re-installed. This way, your users don't need to reproduce their previous data or
application settings. This process is completely transparent to the user and does not affect the
functionality or user experience in your application.</p>
<p>During a backup operation (which your application can request), Android's Backup Manager ({@link
android.app.backup.BackupManager}) queries your application for backup data, then hands it to
a backup transport, which then delivers the data to the cloud storage. During a
restore operation, the Backup Manager retrieves the backup data from the backup transport and
returns it to your application so your application can restore the data to the device. It's
possible for your application to request a restore, but that shouldn't be necessary&mdash;Android
automatically performs a restore operation when your application is installed and there exists
backup data associated with the user. The primary scenario in which backup data is restored is when
a user resets their device or upgrades to a new device and their previously installed
applications are re-installed.</p>
<p class="note"><strong>Note:</strong> The backup service is <em>not</em> designed for
synchronizing application data with other clients or saving data that you'd like to access during
the normal application lifecycle. You cannot read or write backup data on demand and cannot access
it in any way other than through the APIs provided by the Backup Manager.</p>
<p>The backup transport is the client-side component of Android's backup framework, which is
customizable by
the device manufacturer and service provider. The backup transport may differ from device to device
and which backup transport is available on any given device is transparent to your application. The
Backup Manager APIs isolate your application from the actual backup transport available on a given
device&mdash;your application communicates with the Backup Manager through a fixed set of APIs,
regardless of the underlying transport.</p>
<p>Data backup is <em>not</em> guaranteed to be available on all Android-powered
devices. However, your application is not adversely affected in the event
that a device does not provide a backup transport. If you believe that users will benefit from data
backup in your application, then you can implement it as described in this document, test it, then
publish your application without any concern about which devices actually perform backup. When your
application runs on a device that does not provide a backup transport, your application operates
normally, but will not receive callbacks from the Backup Manager to backup data.</p>
<p>Although you cannot know what the current transport is, you are always assured that your
backup data cannot be read by other applications on the device. Only the Backup Manager and backup
transport have access to the data you provide during a backup operation.</p>
<p class="caution"><strong>Caution:</strong> Because the cloud storage and transport service can
differ from device to device, Android makes no guarantees about the security of your data while
using backup. You should always be cautious about using backup to store sensitive data, such as
usernames and passwords.</p>
<h2 id="Basics">The Basics</h2>
<p>To backup your application data, you need to implement a backup agent. Your backup
agent is called by the Backup Manager to provide the data you want to back up. It is also called
to restore your backup data when the application is re-installed. The Backup Manager handles all
your data transactions with the cloud storage (using the backup transport) and your backup agent
handles all your data transactions on the device.</p>
<p>To implement a backup agent, you must:</p>
<ol>
<li>Declare your backup agent in your manifest file with the <a
href="{@docRoot}guide/topics/manifest/application-element.html#agent">{@code
android:backupAgent}</a> attribute.</li>
<li>Register your application with a backup service. Google offers <a
href="http://code.google.com/android/backup/index.html">Android Backup Service</a> as a backup
service for most Android-powered devices, which requires that you register your application in
order for it to work. Any other backup services available might also require you to register
in order to store your data on their servers.</li>
<li>Define a backup agent by either:</p>
<ol type="a">
<li><a href="#BackupAgent">Extending BackupAgent</a>
<p>The {@link android.app.backup.BackupAgent} class provides the central interface with
which your application communicates with the Backup Manager. If you extend this class
directly, you must override {@link
android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor)
onBackup()} and {@link
android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor)
onRestore()} to handle the backup and restore operations for your data.</p>
<p><em>Or</em></p>
<li><a href="#BackupAgentHelper">Extending BackupAgentHelper</a>
<p>The {@link android.app.backup.BackupAgentHelper} class provides a convenient
wrapper around the {@link android.app.backup.BackupAgent} class, which minimizes the amount of code
you need to write. In your {@link android.app.backup.BackupAgentHelper}, you must use one or more
"helper" objects, which automatically backup and restore certain types of data, so that you do not
need to implement {@link
android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor)
onBackup()} and {@link
android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor)
onRestore()}.</p>
<p>Android currently provides backup helpers that will backup and restore complete files
from {@link android.content.SharedPreferences} and <a
href="{@docRoot}guide/topics/data/data-storage.html#filesInternal">internal storage</a>.</p>
</li>
</ol>
</li>
</ol>
<h2 id="BackupManifest">Declaring the Backup Agent in Your Manifest</h2>
<p>This is the easiest step, so once you've decided on the class name for your backup agent, declare
it in your manifest with the <a
href="{@docRoot}guide/topics/manifest/application-element.html#agent">{@code
android:backupAgent}</a> attribute in the <a
href="{@docRoot}guide/topics/manifest/application-element.html">{@code
&lt;application&gt;}</a> tag.</p>
<p>For example:</p>
<pre>
&lt;manifest ... &gt;
...
&lt;application android:label="MyApplication"
<b>android:backupAgent="MyBackupAgent"</b>&gt;
&lt;activity ... &gt;
...
&lt;/activity&gt;
&lt;/application&gt;
&lt;/manifest&gt;
</pre>
<p>Another attribute you might want to use is <a
href="{@docRoot}guide/topics/manifest/application-element.html#restoreany">{@code
android:restoreAnyVersion}</a>. This attribute takes a boolean value to indicate whether you
want to restore the application data regardless of the current application version compared to the
version that produced the backup data. (The default value is "{@code false}".) See <a
href="#RestoreVersion">Checking the Restore Data Version</a> for more information.</p>
<p class="note"><strong>Note:</strong> The backup service and the APIs you must use are
available only on devices running API Level 8 (Android 2.2) or greater, so you should also
set your <a
href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code android:minSdkVersion}</a>
attribute to "8". However, if you implement proper <a
href="{@docRoot}resources/articles/backward-compatibility.html">backward compatibility</a> in
your application, you can support this feature for devices running API Level 8 or greater, while
remaining compatible with older devices.</p>
<h2 id="BackupKey">Registering for Android Backup Service</h2>
<p>Google provides a backup transport with <a
href="http://code.google.com/android/backup/index.html">Android Backup Service</a> for most
Android-powered devices running Android 2.2 or greater.</p>
<p>In order for you application to perform backup using Android Backup Service, you must
register your application with the service to receive a Backup Service Key, then
declare the Backup Service Key in your Android manifest.</p>
<p>To get your Backup Service Key, <a
href="http://code.google.com/android/backup/signup.html">register for Android Backup Service</a>.
When you register, you will be provided a Backup Service Key and the appropriate {@code
&lt;meta-data&gt;} XML code for your Android manifest file, which you must include as a child of the
{@code &lt;application&gt;} element. For example:</p>
<pre>
&lt;application android:label="MyApplication"
android:backupAgent="MyBackupAgent"&gt;
...
&lt;meta-data android:name="com.google.android.backup.api_key"
android:value="AEdPqrEAAAAIDaYEVgU6DJnyJdBmU7KLH3kszDXLv_4DIsEIyQ" /&gt;
&lt;/application&gt;
</pre>
<p>The <code>android:name</code> must be <code>"com.google.android.backup.api_key"</code> and
the <code>android:value</code> must be the Backup Service Key received from the Android Backup
Service registration.</p>
<p>If you have multiple applications, you must register each one, using the respective package
name.</p>
<p class="note"><strong>Note:</strong> The backup transport provided by Android Backup Service is
not guaranteed to be available
on all Android-powered devices that support backup. Some devices might support backup
using a different transport, some devices might not support backup at all, and there is no way for
your application to know what transport is used on the device. However, if you implement backup for
your application, you should always include a Backup Service Key for Android Backup Service so
your application can perform backup when the device uses the Android Backup Service transport. If
the device does not use Android Backup Service, then the {@code &lt;meta-data&gt;} element with the
Backup Service Key is ignored.</p>
<h2 id="BackupAgent">Extending BackupAgent</h2>
<p>Most applications shouldn't need to extend the {@link android.app.backup.BackupAgent} class
directly, but should instead <a href="#BackupAgentHelper">extend BackupAgentHelper</a> to take
advantage of the built-in helper classes that automatically backup and restore your files. However,
you might want to extend {@link android.app.backup.BackupAgent} directly if you need to:</p>
<ul>
<li>Version your data format. For instance, if you anticipate the need to revise the
format in which you write your application data, you can build a backup agent to cross-check your
application version during a restore operation and perform any necessary compatibility work if the
version on the device is different than that of the backup data. For more information, see <a
href="#RestoreVersion">Checking the Restore Data Version</a>.</li>
<li>Instead of backing up an entire file, you can specify the portions of data the should be
backed up and how each portion is then restored to the device. (This can also help you manage
different versions, because you read and write your data as unique entities, rather than
complete files.)</li>
<li>Back up data in a database. If you have an SQLite database that you want to restore when
the user re-installs your application, you need to build a custom {@link
android.app.backup.BackupAgent} that reads the appropriate data during a backup operation, then
create your table and insert the data during a restore operation.</li>
</ul>
<p>If you don't need to perform any of the tasks above and want to back up complete files from
{@link android.content.SharedPreferences} or <a
href="{@docRoot}guide/topics/data/data-storage.html#filesInternal">internal storage</a>, you
should skip to <a href="#BackupAgentHelper">Extending BackupAgentHelper</a>.</p>
<h3 id="RequiredMethods">Required Methods</h3>
<p>When you create a backup agent by extending {@link android.app.backup.BackupAgent}, you
must implement the following callback methods:</p>
<dl>
<dt>{@link
android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor)
onBackup()}</dt>
<dd>The Backup Manager calls this method after you <a href="#RequestingBackup">request a
backup</a>. In this method, you read your application data from the device and pass the data you
want to back up to the Backup Manager, as described below in <a href="#PerformingBackup">Performing
backup</a>.</dd>
<dt>{@link
android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor)
onRestore()}</dt>
<dd>The Backup Manager calls this method during a restore operation (you can <a
href="#RequestingRestore">request a restore</a>, but the system automatically performs restore when
the user re-installs your application). When it calls this method, the Backup Manager delivers your
backup data, which you then restore to the device, as described below in <a
href="#PerformingRestore">Performing restore</a>.</dd>
</dl>
<h3 id="PerformingBackup">Performing backup</h3>
<p>When it's time to back up your application data, the Backup Manager calls your {@link
android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor)
onBackup()} method. This is where you must provide your application data to the Backup Manager so
it can be saved to cloud storage.</p>
<p>Only the Backup Manager can call your backup agent's {@link
android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor)
onBackup()} method. Each time that your application data changes and you want to perform a backup,
you must request a backup operation by calling {@link
android.app.backup.BackupManager#dataChanged()} (see <a href="#RequestingBackup">Requesting
Backup</a> for more information). A backup request does not result in an immediate call to your
{@link
android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor)
onBackup()} method. Instead, the Backup Manager waits for an appropriate time, then performs
backup for all applications that have requested a backup since the last backup was performed.</p>
<p class="note"><strong>Tip:</strong> While developing your application, you can initiate an
immediate backup operation from the Backup Manager with the <a
href="{@docRoot}guide/developing/tools/bmgr.html">{@code bmgr} tool</a>.</p>
<p>When the Backup Manager calls your {@link
android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor)
onBackup()} method, it passes three parameters:</p>
<dl>
<dt>{@code oldState}</dt>
<dd>An open, read-only {@link android.os.ParcelFileDescriptor} pointing to the last backup
state provided by your application. This is not the backup data from cloud storage, but a
local representation of the data that was backed up the last time {@link
android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor)
onBackup()} was called (as defined by {@code newState}, below, or from {@link
android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor)
onRestore()}&mdash;more about this in the next section). Because {@link
android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor)
onBackup()} does not allow you to read existing backup data in
the cloud storage, you can use this local representation to determine whether your data has changed
since the last backup.</dd>
<dt>{@code data}</dt>
<dd>A {@link android.app.backup.BackupDataOutput} object, which you use to deliver your backup
data to the Backup Manager.</dd>
<dt>{@code newState}</dt>
<dd>An open, read/write {@link android.os.ParcelFileDescriptor} pointing to a file in which
you must write a representation of the data that you delivered to {@code data} (a representation
can be as simple as the last-modified timestamp for your file). This object is
returned as {@code oldState} the next time the Backup Manager calls your {@link
android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor)
onBackup()} method. If you do not write your backup data to {@code newState}, then {@code oldState}
will point to an empty file next time Backup Manager calls {@link
android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor)
onBackup()}.</dd>
</dl>
<p>Using these parameters, you should implement your {@link
android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor)
onBackup()} method to do the following:</p>
<ol>
<li>Check whether your data has changed since the last backup by comparing {@code oldState} to
your current data. How you read data in {@code oldState} depends on how you originally wrote it to
{@code newState} (see step 3). The easiest way to record the state of a file is with its
last-modified timestamp. For example, here's how you can read and compare a timestamp from {@code
oldState}:
<pre>
// Get the oldState input stream
FileInputStream instream = new FileInputStream(oldState.getFileDescriptor());
DataInputStream in = new DataInputStream(instream);
try {
// Get the last modified timestamp from the state file and data file
long stateModified = in.readLong();
long fileModified = mDataFile.lastModified();
if (stateModified != fileModified) {
// The file has been modified, so do a backup
// Or the time on the device changed, so be safe and do a backup
} else {
// Don't back up because the file hasn't changed
return;
}
} catch (IOException e) {
// Unable to read state file... be safe and do a backup
}
</pre>
<p>If nothing has changed and you don't need to back up, skip to step 3.</p>
</li>
<li>If your data has changed, compared to {@code oldState}, write the current data to
{@code data} to back it up to the cloud storage.
<p>You must write each chunk of data as an "entity" in the {@link
android.app.backup.BackupDataOutput}. An entity is a flattened binary data
record that is identified by a unique key string. Thus, the data set that you back up is
conceptually a set of key-value pairs.</p>
<p>To add an entity to your backup data set, you must:</p>
<ol>
<li>Call {@link android.app.backup.BackupDataOutput#writeEntityHeader(String,int)
writeEntityHeader()}, passing a unique string key for the data you're about to write and the data
size.</li>
<li>Call {@link android.app.backup.BackupDataOutput#writeEntityData(byte[],int)
writeEntityData()}, passing a byte buffer that contains your data and the number of bytes to write
from the buffer (which should match the size passed to {@link
android.app.backup.BackupDataOutput#writeEntityHeader(String,int) writeEntityHeader()}).</li>
</ol>
<p>For example, the following code flattens some data into a byte stream and writes it into a
single entity:</p>
<pre>
// Create buffer stream and data output stream for our data
ByteArrayOutputStream bufStream = new ByteArrayOutputStream();
DataOutputStream outWriter = new DataOutputStream(bufStream);
// Write structured data
outWriter.writeUTF(mPlayerName);
outWriter.writeInt(mPlayerScore);
// Send the data to the Backup Manager via the BackupDataOutput
byte[] buffer = bufStream.toByteArray();
int len = buffer.length;
data.writeEntityHeader(TOPSCORE_BACKUP_KEY, len);
data.writeEntityData(buffer, len);
</pre>
<p>Perform this for each piece of data that you want to back up. How you divide your data into
entities is up to you (and you might use just one entity).</p>
</li>
<li>Whether or not you perform a backup (in step 2), write a representation of the current data to
the {@code newState} {@link android.os.ParcelFileDescriptor}. The Backup Manager retains this object
locally as a representation of the data that is currently backed up. It passes this back to you as
{@code oldState} the next time it calls {@link
android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor)
onBackup()} so you can determine whether another backup is necessary (as handled in step 1). If you
do not write the current data state to this file, then
{@code oldState} will be empty during the next callback.
<p>The following example saves a representation of the current data into {@code newState} using
the file's last-modified timestamp:</p>
<pre>
FileOutputStream outstream = new FileOutputStream(newState.getFileDescriptor());
DataOutputStream out = new DataOutputStream(outstream);
long modified = mDataFile.lastModified();
out.writeLong(modified);
</pre>
</li>
</ol>
<p class="caution"><strong>Caution:</strong> If your application data is saved to a file, make sure
that you use synchronized statements while accessing the file so that your backup agent does not
read the file while an Activity in your application is also writing the file.</p>
<h3 id="PerformingRestore">Performing restore</h3>
<p>When it's time to restore your application data, the Backup Manager calls your backup
agent's {@link android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor)
onRestore()} method. When it calls this method, the Backup Manager delivers your backup data so
you can restore it onto the device.</p>
<p>Only the Backup Manager can call {@link
android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor)
onRestore()}, which happens automatically when the system installs your application and
finds existing backup data. However, you can request a restore operation for
your application by calling {@link
android.app.backup.BackupManager#requestRestore(RestoreObserver) requestRestore()} (see <a
href="#RequestingRestore">Requesting restore</a> for more information).</p>
<p class="note"><strong>Note:</strong> While developing your application, you can also request a
restore operation with the <a href="{@docRoot}guide/developing/tools/bmgr.html">{@code bmgr}
tool</a>.</p>
<p>When the Backup Manager calls your {@link
android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor)
onRestore()} method, it passes three parameters:</p>
<dl>
<dt>{@code data}</dt>
<dd>A {@link android.app.backup.BackupDataInput}, which allows you to read your backup
data.</dd>
<dt>{@code appVersionCode}</dt>
<dd>An integer representing the value of your application's <a
href="{@docRoot}guide/topics/manifest/manifest-element.html#vcode">{@code android:versionCode}</a>
manifest attribute, as it was when this data was backed up. You can use this to cross-check the
current application version and determine if the data format is compatible. For more
information about using this to handle different versions of restore data, see the section
below about <a href="#RestoreVersion">Checking the Restore Data Version</a>.</dd>
<dt>{@code newState}</dt>
<dd>An open, read/write {@link android.os.ParcelFileDescriptor} pointing to a file in which
you must write the final backup state that was provided with {@code data}. This object is
returned as {@code oldState} the next time {@link
android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor)
onBackup()} is called. Recall that you must also write the same {@code newState} object in the
{@link
android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor)
onBackup()} callback&mdash;also doing it here ensures that the {@code oldState} object given to
{@link
android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor)
onBackup()} is valid even the first time {@link
android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor)
onBackup()} is called after the device is restored.</dd>
</dl>
<p>In your implementation of {@link
android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor)
onRestore()}, you should call {@link android.app.backup.BackupDataInput#readNextHeader()} on the
{@code data} to iterate
through all entities in the data set. For each entity found, do the following:</p>
<ol>
<li>Get the entity key with {@link android.app.backup.BackupDataInput#getKey()}.</li>
<li>Compare the entity key to a list of known key values that you should have declared as static
final strings inside your {@link android.app.backup.BackupAgent} class. When the key matches one of
your known key strings, enter into a statement to extract the entity data and save it to the device:
<ol>
<li>Get the entity data size with {@link
android.app.backup.BackupDataInput#getDataSize()} and create a byte array of that size.</li>
<li>Call {@link android.app.backup.BackupDataInput#readEntityData(byte[],int,int)
readEntityData()} and pass it the byte array, which is where the data will go, and specify the
start offset and the size to read.</li>
<li>Your byte array is now full and you can read the data and write it to the device
however you like.</li>
</ol>
</li>
<li>After you read and write your data back to the device, write the state of your data to the
{@code newState} parameter the same as you do during {@link
android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor)
onBackup()}.
</ol>
<p>For example, here's how you can restore the data backed up by the example in the previous
section:</p>
<pre>
&#64;Override
public void onRestore(BackupDataInput data, int appVersionCode,
ParcelFileDescriptor newState) throws IOException {
// There should be only one entity, but the safest
// way to consume it is using a while loop
while (data.readNextHeader()) {
String key = data.getKey();
int dataSize = data.getDataSize();
// If the key is ours (for saving top score). Note this key was used when
// we wrote the backup entity header
if (TOPSCORE_BACKUP_KEY.equals(key)) {
// Create an input stream for the BackupDataInput
byte[] dataBuf = new byte[dataSize];
data.readEntityData(dataBuf, 0, dataSize);
ByteArrayInputStream baStream = new ByteArrayInputStream(dataBuf);
DataInputStream in = new DataInputStream(baStream);
// Read the player name and score from the backup data
mPlayerName = in.readUTF();
mPlayerScore = in.readInt();
// Record the score on the device (to a file or something)
recordScore(mPlayerName, mPlayerScore);
} else {
// We don't know this entity key. Skip it. (Shouldn't happen.)
data.skipEntityData();
}
}
// Finally, write to the state blob (newState) that describes the restored data
FileOutputStream outstream = new FileOutputStream(newState.getFileDescriptor());
DataOutputStream out = new DataOutputStream(outstream);
out.writeUTF(mPlayerName);
out.writeInt(mPlayerScore);
}
</pre>
<p>In this example, the {@code appVersionCode} parameter passed to {@link
android.app.backup.BackupAgent#onRestore onRestore()} is not used. However, you might want to use
it if you've chosen to perform backup when the user's version of the application has actually moved
backward (for example, the user went from version 1.5 of your app to 1.0). For more information, see
the section about <a href="#RestoreVersion">Checking the Restore Data Version</a>.</p>
<div class="special">
<p>For an example implementation of {@link android.app.backup.BackupAgent}, see the <a
href="{@docRoot}resources/samples/BackupRestore/src/com/example/android/backuprestore/ExampleAgent.html">{@code
ExampleAgent}</a> class in the <a
href="{@docRoot}resources/samples/BackupRestore/index.html">Backup and Restore</a> sample
application.</p>
</div>
<h2 id="BackupAgentHelper">Extending BackupAgentHelper</h2>
<p>You should build your backup agent using {@link android.app.backup.BackupAgentHelper} if you want
to back up complete files (from either {@link android.content.SharedPreferences} or <a
href="{@docRoot}guide/topics/data/data-storage.html#filesInternal">internal storage</a>).
Building your backup agent with {@link android.app.backup.BackupAgentHelper} requires far less
code than extending {@link android.app.backup.BackupAgent}, because you don't have to implement
{@link
android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor)
onBackup()} and {@link
android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor)
onRestore()}.</p>
<p>Your implementation of {@link android.app.backup.BackupAgentHelper} must
use one or more backup helpers. A backup helper is a specialized
component that {@link android.app.backup.BackupAgentHelper} summons to perform backup and
restore operations for a particular type of data. The Android framework currently provides two
different helpers:</p>
<ul>
<li>{@link android.app.backup.SharedPreferencesBackupHelper} to backup {@link
android.content.SharedPreferences} files.</li>
<li>{@link android.app.backup.FileBackupHelper} to backup files from <a
href="{@docRoot}guide/topics/data/data-storage.html#filesInternal">internal storage</a>.</li>
</ul>
<p>You can include multiple helpers in your {@link android.app.backup.BackupAgentHelper}, but only
one helper is needed for each data type. That is, if you have multiple {@link
android.content.SharedPreferences} files, then you need only one {@link
android.app.backup.SharedPreferencesBackupHelper}.</p>
<p>For each helper you want to add to your {@link android.app.backup.BackupAgentHelper}, you must do
the following during your {@link android.app.backup.BackupAgent#onCreate()} method:</p>
<ol>
<li>Instantiate in instance of the desired helper class. In the class constructor, you must
specify the appropriate file(s) you want to backup.</li>
<li>Call {@link android.app.backup.BackupAgentHelper#addHelper(String,BackupHelper) addHelper()}
to add the helper to your {@link android.app.backup.BackupAgentHelper}.</li>
</ol>
<p>The following sections describe how to create a backup agent using each of the available
helpers.</p>
<h3 id="SharedPreferences">Backing up SharedPreferences</h3>
<p>When you instantiate a {@link android.app.backup.SharedPreferencesBackupHelper}, you must
include the name of one or more {@link android.content.SharedPreferences} files.</p>
<p>For example, to back up a {@link android.content.SharedPreferences} file named
"user_preferences", a complete backup agent using {@link android.app.backup.BackupAgentHelper} looks
like this:</p>
<pre>
public class MyPrefsBackupAgent extends BackupAgentHelper {
// The name of the SharedPreferences file
static final String PREFS = "user_preferences";
// A key to uniquely identify the set of backup data
static final String PREFS_BACKUP_KEY = "prefs";
// Allocate a helper and add it to the backup agent
&#64;Override
public void onCreate() {
SharedPreferencesBackupHelper helper = new SharedPreferencesBackupHelper(this, PREFS);
addHelper(PREFS_BACKUP_KEY, helper);
}
}
</pre>
<p>That's it! That's your entire backup agent. The {@link
android.app.backup.SharedPreferencesBackupHelper} includes all the code
needed to backup and restore a {@link android.content.SharedPreferences} file.</p>
<p>When the Backup Manager calls {@link
android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor)
onBackup()} and {@link
android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor)
onRestore()}, {@link android.app.backup.BackupAgentHelper} calls your backup helpers to perform
backup and restore for your specified files.</p>
<p class="note"><strong>Note:</strong> {@link android.content.SharedPreferences} are threadsafe, so
you can safely read and write the shared preferences file from your backup agent and
other activities.</p>
<h3 id="Files">Backing up other files</h3>
<p>When you instantiate a {@link android.app.backup.FileBackupHelper}, you must include the name of
one or more files that are saved to your application's <a
href="{@docRoot}guide/topics/data/data-storage.html#filesInternal">internal storage</a>
(as specified by {@link android.content.ContextWrapper#getFilesDir()}, which is the same
location where {@link android.content.Context#openFileOutput(String,int) openFileOutput()} writes
files).</p>
<p>For example, to backup two files named "scores" and "stats," a backup agent using {@link
android.app.backup.BackupAgentHelper} looks like this:</p>
<pre>
public class MyFileBackupAgent extends BackupAgentHelper {
// The name of the SharedPreferences file
static final String TOP_SCORES = "scores";
static final String PLAYER_STATS = "stats";
// A key to uniquely identify the set of backup data
static final String FILES_BACKUP_KEY = "myfiles";
// Allocate a helper and add it to the backup agent
void onCreate() {
FileBackupHelper helper = new FileBackupHelper(this, TOP_SCORES, PLAYER_STATS);
addHelper(FILES_BACKUP_KEY, helper);
}
}
</pre>
<p>The {@link android.app.backup.FileBackupHelper} includes all the code necessary to backup and
restore files that are saved to your application's <a
href="{@docRoot}guide/topics/data/data-storage.html#filesInternal">internal storage</a>..</p>
<p>However, reading and writing to files on internal storage is <strong>not threadsafe</strong>. To
ensure that your backup agent does not read or write your files at the same time as your activities,
you must use synchronized statements each time you perform a read or write. For example,
in any Activity where you read and write the file, you need an object to use as the intrinsic
lock for the synchronized statements:</p>
<div class="sidebox-wrapper">
<div class="sidebox">
<p><strong>Interesting Fact:</strong></p>
<p>A zero-length array is lighter-weight than a normal Object, so it's great for an
intrinsic lock.</p>
</div>
</div>
<pre>
// Object for intrinsic lock
static final Object[] sDataLock = new Object[0];
</pre>
<p>Then create a synchronized statement with this lock each time you read or write the files. For
example, here's a synchronized statement for writing the latest score in a game to a file:</p>
<pre>
try {
synchronized (MyActivity.sDataLock) {
File dataFile = new File({@link android.content.Context#getFilesDir()}, TOP_SCORES);
RandomAccessFile raFile = new RandomAccessFile(dataFile, "rw");
raFile.writeInt(score);
}
} catch (IOException e) {
Log.e(TAG, "Unable to write to file");
}
</pre>
<p>You should synchronize your read statements with the same lock.</p>
<p>Then, in your {@link android.app.backup.BackupAgentHelper}, you must override {@link
android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor)
onBackup()} and {@link
android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor)
onRestore()} to synchronize the backup and restore operations with the same
intrinsic lock. For example, the {@code MyFileBackupAgent} example from above needs the following
methods:</p>
<pre>
&#64;Override
public void onBackup(ParcelFileDescriptor oldState, BackupDataOutput data,
ParcelFileDescriptor newState) throws IOException {
// Hold the lock while the FileBackupHelper performs backup
synchronized (MyActivity.sDataLock) {
super.onBackup(oldState, data, newState);
}
}
&#64;Override
public void onRestore(BackupDataInput data, int appVersionCode,
ParcelFileDescriptor newState) throws IOException {
// Hold the lock while the FileBackupHelper restores the file
synchronized (MyActivity.sDataLock) {
super.onRestore(data, appVersionCode, newState);
}
}
</pre>
<p>That's it. All you need to do is add your {@link android.app.backup.FileBackupHelper} in the
{@link android.app.backup.BackupAgent#onCreate()} method and override {@link
android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor)
onBackup()} and {@link
android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor)
onRestore()} to synchronize read and write operations.</p>
<div class="special">
<p>For an example implementation of {@link
android.app.backup.BackupAgentHelper} with {@link android.app.backup.FileBackupHelper}, see the
{@code FileHelperExampleAgent} class in the <a
href="{@docRoot}resources/samples/BackupRestore/index.html">Backup and Restore</a> sample
application.</p>
</div>
<h2 id="RestoreVersion">Checking the Restore Data Version</h2>
<p>When the Backup Manager saves your data to cloud storage, it automatically includes the version
of your application, as defined by your manifest file's <a
href="{@docRoot}guide/topics/manifest/manifest-element.html#vcode">{@code android:versionCode}</a>
attribute. Before the Backup Manager calls your backup agent to restore your data, it
looks at the <a
href="{@docRoot}guide/topics/manifest/manifest-element.html#vcode">{@code
android:versionCode}</a> of the installed application and compares it to the value
recorded in the restore data set. If the version recorded in the restore data set is
<em>newer</em> than the application version on the device, then the user has downgraded their
application. In this case, the Backup Manager will abort the restore operation for your application
and not call your {@link
android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor) onRestore()}
method, because the restore set is considered meaningless to an older version.</p>
<p>You can override this behavior with the <a
href="{@docRoot}guide/topics/manifest/application-element.html#restoreany">{@code
android:restoreAnyVersion}</a> attribute. This attribute is either "{@code true}" or "{@code
false}" to indicate whether you want to restore the application regardless of the restore set
version. The default value is "{@code false}". If you define this to be "{@code true}" then the
Backup Manager will ignore the <a
href="{@docRoot}guide/topics/manifest/manifest-element.html#vcode">{@code android:versionCode}</a>
and call your {@link
android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor) onRestore()}
method in all cases. In doing so, you can manually check for the version difference in your {@link
android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor) onRestore()}
method and take any steps necessary to make the data compatible if the versions conflict.</p>
<p>To help you handle different versions during a restore operation, the {@link
android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor) onRestore()}
method passes you the version code included with the restore data set as the {@code appVersionCode}
parameter. You can then query the current application's version code with the {@link
android.content.pm.PackageInfo#versionCode PackageInfo.versionCode} field. For example:</p>
<pre>
PackageInfo info;
try {
String name = {@link android.content.ContextWrapper#getPackageName() getPackageName}();
info = {@link android.content.ContextWrapper#getPackageManager
getPackageManager}().{@link android.content.pm.PackageManager#getPackageInfo(String,int)
getPackageInfo}(name,0);
} catch (NameNotFoundException nnfe) {
info = null;
}
int version;
if (info != null) {
version = info.versionCode;
}
</pre>
<p>Then simply compare the {@code version} acquired from {@link android.content.pm.PackageInfo}
to the {@code appVersionCode} passed into {@link
android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor) onRestore()}.
</p>
<p class="caution"><strong>Caution:</strong> Be certain you understand the consequences of setting
<a href="{@docRoot}guide/topics/manifest/application-element.html#restoreany">{@code
android:restoreAnyVersion}</a> to "{@code true}" for your application. If each version of your
application that supports backup does not properly account for variations in your data format during
{@link
android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor) onRestore()},
then the data on the device could be saved in a format incompatible with the version currently
installed on the device.</p>
<h2 id="RequestingBackup">Requesting Backup</h2>
<p>You can request a backup operation at any time by calling {@link
android.app.backup.BackupManager#dataChanged()}. This method notifies the Backup Manager that you'd
like to backup your data using your backup agent. The Backup Manager then calls your backup
agent's {@link
android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor)
onBackup()} method at an opportune time in the future. Typically, you should
request a backup each time your data changes (such as when the user changes an application
preference that you'd like to back up). If you call {@link
android.app.backup.BackupManager#dataChanged()} several times consecutively, before the Backup
Manager requests a backup from your agent, your agent still receives just one call to {@link
android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor)
onBackup()}.</p>
<p class="note"><strong>Note:</strong> While developing your application, you can request a
backup and initiate an immediate backup operation with the <a
href="{@docRoot}guide/developing/tools/bmgr.html">{@code bmgr}
tool</a>.</p>
<h2 id="RequestingRestore">Requesting Restore</h2>
<p>During the normal life of your application, you shouldn't need to request a restore operation.
They system automatically checks for backup data and performs a restore when your application is
installed. However, you can manually request a restore operation by calling {@link
android.app.backup.BackupManager#requestRestore(RestoreObserver) requestRestore()}, if necessary. In
which case, the Backup Manager calls your {@link
android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor) onRestore()}
implementation, passing the data from the current set of backup data.</p>
<p class="note"><strong>Note:</strong> While developing your application, you can request a
restore operation with the <a href="{@docRoot}guide/developing/tools/bmgr.html">{@code bmgr}
tool</a>.</p>
<h2 id="Testing">Testing Your Backup Agent</h2>
<p>Once you've implemented your backup agent, you can test the backup and restore functionality
with the following procedure, using <a
href="{@docRoot}guide/developing/tools/bmgr.html">{@code bmgr}</a>.</p>
<ol>
<li>Install your application on a suitable Android system image
<ul>
<li>If using the emulator, create and use an AVD with Android 2.2 (API Level 8).</li>
<li>If using a device, the device must be running Android 2.2 or greater and have Android
Market built in.</li>
</ul>
</li>
<li>Ensure that backup is enabled
<ul>
<li>If using the emulator, you can enable backup with the following command from your SDK
{@code tools/} path:
<pre class="no-pretty-print">adb shell bmgr enable true</pre>
</li>
<li>If using a device, open the system <b>Settings</b>, select <b>Privacy</b>, then enable
<b>Back up my data</b> and <b>Automatic restore</b>.
</ul>
</li>
<li>Open your application and initialize some data
<p>If you've properly implemented backup in your application, then it should request a
backup each time the data changes. For example, each time the user changes some data, your app
should call {@link android.app.backup.BackupManager#dataChanged()}, which adds a backup request to
the Backup Manager queue. For testing purposes, you can also make a request with the following
{@code bmgr} command:</p>
<pre class="no-pretty-print">adb shell bmgr backup <em>your.package.name</em></pre>
</li>
<li>Initiate a backup operation:
<pre class="no-pretty-print">adb shell bmgr run</pre>
<p>This forces the Backup Manager to perform all backup requests that are in its
queue.</p>
<li>Uninstall your application:
<pre class="no-pretty-print">adb uninstall <em>your.package.name</em></pre>
</li>
<li>Re-install your application.</li>
</ol>
<p>If your backup agent is successful, all the data you initialized in step 4 is restored.</p>
@@ -0,0 +1,457 @@
page.title=Data Storage
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>Storage quickview</h2>
<ul>
<li>Use Shared Preferences for primitive data</li>
<li>Use internal device storage for private data</li>
<li>Use external storage for large data sets that are not private</li>
<li>Use SQLite databases for structured storage</li>
</ul>
<h2>In this document</h2>
<ol>
<li><a href="#pref">Using Shared Preferences</a></li>
<li><a href="#filesInternal">Using the Internal Storage</a></li>
<li><a href="#filesExternal">Using the External Storage</a></li>
<li><a href="#db">Using Databases</a></li>
<li><a href="#netw">Using a Network Connection</a></li>
</ol>
<h2>See also</h2>
<ol>
<li><a href="#pref">Content Providers and Content Resolvers</a></li>
</ol>
</div>
</div>
<p>Android provides several options for you to save persistent application data. The solution you
choose depends on your specific needs, such as whether the data should be private to your
application or accessible to other applications (and the user) and how much space your data
requires.
</p>
<p>Your data storage options are the following:</p>
<dl>
<dt><a href="#pref">Shared Preferences</a></dt>
<dd>Store private primitive data in key-value pairs.</dd>
<dt><a href="#filesInternal">Internal Storage</a></dt>
<dd>Store private data on the device memory.</dd>
<dt><a href="#filesExternal">External Storage</a></dt>
<dd>Store public data on the shared external storage.</dd>
<dt><a href="#db">SQLite Databases</a></dt>
<dd>Store structured data in a private database.</dd>
<dt><a href="#netw">Network Connection</a></dt>
<dd>Store data on the web with your own network server.</dd>
</dl>
<p>Android provides a way for you to expose even your private data to other applications
&mdash; with a <a href="{@docRoot}guide/topics/providers/content-providers.html">content
provider</a>. A content provider is an optional component that exposes read/write access to
your application data, subject to whatever restrictions you want to impose. For more information
about using content providers, see the
<a href="{@docRoot}guide/topics/providers/content-providers.html">Content Providers</a>
documentation.
</p>
<h2 id="pref">Using Shared Preferences</h2>
<p>The {@link android.content.SharedPreferences} class provides a general framework that allows you
to save and retrieve persistent key-value pairs of primitive data types. You can use {@link
android.content.SharedPreferences} to save any primitive data: booleans, floats, ints, longs, and
strings. This data will persist across user sessions (even if your application is killed).</p>
<div class="sidebox-wrapper">
<div class="sidebox">
<h3>User Preferences</h3>
<p>Shared preferences are not strictly for saving "user preferences," such as what ringtone a
user has chosen. If you're interested in creating user preferences for your application, see {@link
android.preference.PreferenceActivity}, which provides an Activity framework for you to create
user preferences, which will be automatically persisted (using shared preferences).</p>
</div>
</div>
<p>To get a {@link android.content.SharedPreferences} object for your application, use one of
two methods:</p>
<ul>
<li>{@link android.content.Context#getSharedPreferences(String,int)
getSharedPreferences()} - Use this if you need multiple preferences files identified by name,
which you specify with the first parameter.</li>
<li>{@link android.app.Activity#getPreferences(int) getPreferences()} - Use this if you need
only one preferences file for your Activity. Because this will be the only preferences file
for your Activity, you don't supply a name.</li>
</ul>
<p>To write values:</p>
<ol>
<li>Call {@link android.content.SharedPreferences#edit()} to get a {@link
android.content.SharedPreferences.Editor}.</li>
<li>Add values with methods such as {@link
android.content.SharedPreferences.Editor#putBoolean(String,boolean) putBoolean()} and {@link
android.content.SharedPreferences.Editor#putString(String,String) putString()}.</li>
<li>Commit the new values with {@link android.content.SharedPreferences.Editor#commit()}</li>
</ol>
<p>To read values, use {@link android.content.SharedPreferences} methods such as {@link
android.content.SharedPreferences#getBoolean(String,boolean) getBoolean()} and {@link
android.content.SharedPreferences#getString(String,String) getString()}.</p>
<p>
Here is an example that saves a preference for silent keypress mode in a
calculator:
</p>
<pre>
public class Calc extends Activity {
public static final String PREFS_NAME = "MyPrefsFile";
&#64;Override
protected void onCreate(Bundle state){
super.onCreate(state);
. . .
// Restore preferences
SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0);
boolean silent = settings.getBoolean("silentMode", false);
setSilent(silent);
}
&#64;Override
protected void onStop(){
super.onStop();
// We need an Editor object to make preference changes.
// All objects are from android.context.Context
SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0);
SharedPreferences.Editor editor = settings.edit();
editor.putBoolean("silentMode", mSilentMode);
// Commit the edits!
editor.commit();
}
}
</pre>
<a name="files"></a>
<h2 id="filesInternal">Using the Internal Storage</h2>
<p>You can save files directly on the device's internal storage. By default, files saved
to the internal storage are private to your application and other applications cannot access
them (nor can the user). When the user uninstalls your application, these files are removed.</p>
<p>To create and write a private file to the internal storage:</p>
<ol>
<li>Call {@link android.content.Context#openFileOutput(String,int) openFileOutput()} with the
name of the file and the operating mode. This returns a {@link java.io.FileOutputStream}.</li>
<li>Write to the file with {@link java.io.FileOutputStream#write(byte[]) write()}.</li>
<li>Close the stream with {@link java.io.FileOutputStream#close()}.</li>
</ol>
<p>For example:</p>
<pre>
String FILENAME = "hello_file";
String string = "hello world!";
FileOutputStream fos = openFileOutput(FILENAME, Context.MODE_PRIVATE);
fos.write(string.getBytes());
fos.close();
</pre>
<p>{@link android.content.Context#MODE_PRIVATE} will create the file (or replace a file of
the same name) and make it private to your application. Other modes available are: {@link
android.content.Context#MODE_APPEND}, {@link
android.content.Context#MODE_WORLD_READABLE}, and {@link
android.content.Context#MODE_WORLD_WRITEABLE}.</p>
<p>To read a file from internal storage:</p>
<ol>
<li>Call {@link android.content.Context#openFileInput openFileInput()} and pass it the
name of the file to read. This returns a {@link java.io.FileInputStream}.</li>
<li>Read bytes from the file with {@link java.io.FileInputStream#read(byte[],int,int)
read()}.</li>
<li>Then close the stream with {@link java.io.FileInputStream#close()}.</li>
</ol>
<p class="note"><strong>Tip:</strong> If you want to save a static file in your application at
compile time, save the file in your project <code>res/raw/</code> directory. You can open it with
{@link android.content.res.Resources#openRawResource(int) openRawResource()}, passing the {@code
R.raw.<em>&lt;filename&gt;</em>} resource ID. This method returns an {@link java.io.InputStream}
that you can use to read the file (but you cannot write to the original file).
</p>
<h3 id="InternalCache">Saving cache files</h3>
<p>If you'd like to cache some data, rather than store it persistently, you should use {@link
android.content.Context#getCacheDir()} to open a {@link
java.io.File} that represents the internal directory where your application should save
temporary cache files.</p>
<p>When the device is
low on internal storage space, Android may delete these cache files to recover space. However, you
should not rely on the system to clean up these files for you. You should always maintain the cache
files yourself and stay within a reasonable limit of space consumed, such as 1MB. When the user
uninstalls your application, these files are removed.</p>
<h3 id="InternalMethods">Other useful methods</h3>
<dl>
<dt>{@link android.content.Context#getFilesDir()}</dt>
<dd>Gets the absolute path to the filesystem directory where your internal files are saved.</dd>
<dt>{@link android.content.Context#getDir(String,int) getDir()}</dt>
<dd>Creates (or opens an existing) directory within your internal storage space.</dd>
<dt>{@link android.content.Context#deleteFile(String) deleteFile()}</dt>
<dd>Deletes a file saved on the internal storage.</dd>
<dt>{@link android.content.Context#fileList()}</dt>
<dd>Returns an array of files currently saved by your application.</dd>
</dl>
<h2 id="filesExternal">Using the External Storage</h2>
<p>Every Android-compatible device supports a shared "external storage" that you can use to
save files. This can be a removable storage media (such as an SD card) or an internal
(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
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>
<h3>Checking media availability</h3>
<p>Before you do any work with the external storage, you should always call {@link
android.os.Environment#getExternalStorageState()} to check whether the media is available. The
media might be mounted to a computer, missing, read-only, or in some other state. For example,
here's how you can check the availability:</p>
<pre>
boolean mExternalStorageAvailable = false;
boolean mExternalStorageWriteable = false;
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state)) {
// We can read and write the media
mExternalStorageAvailable = mExternalStorageWriteable = true;
} else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
// We can only read the media
mExternalStorageAvailable = true;
mExternalStorageWriteable = false;
} else {
// Something else is wrong. It may be one of many other states, but all we need
// to know is we can neither read nor write
mExternalStorageAvailable = mExternalStorageWriteable = false;
}
</pre>
<p>This example checks whether the external storage is available to read and write. The
{@link android.os.Environment#getExternalStorageState()} method returns other states that you
might want to check, such as whether the media is being shared (connected to a computer), is missing
entirely, has been removed badly, etc. You can use these to notify the user with more information
when your application needs to access the media.</p>
<h3>Accessing files on external storage</h3>
<p>If you're using API Level 8 or greater, use {@link
android.content.Context#getExternalFilesDir(String) getExternalFilesDir()} to open a {@link
java.io.File} that represents the external storage directory where you should save your
files. This method takes a <code>type</code> parameter that specifies the type of subdirectory you
want, such as {@link android.os.Environment#DIRECTORY_MUSIC} and
{@link android.os.Environment#DIRECTORY_RINGTONES} (pass <code>null</code> to receive
the root of your application's file directory). This method will create the
appropriate directory if necessary. By specifying the type of directory, you
ensure that the Android's media scanner will properly categorize your files in the system (for
example, ringtones are identified as ringtones and not music). If the user uninstalls your
application, this directory and all its contents will be deleted.</p>
<p>If you're using API Level 7 or lower, use {@link
android.os.Environment#getExternalStorageDirectory()}, to open a {@link
java.io.File} representing the root of the external storage. You should then write your data in the
following directory:</p>
<pre class="no-pretty-print classic">
/Android/data/<em>&lt;package_name&gt;</em>/files/
</pre>
<p>The {@code <em>&lt;package_name&gt;</em>} is your Java-style package name, such as "{@code
com.example.android.app}". If the user's device is running API Level 8 or greater and they
uninstall your application, this directory and all its contents will be deleted.</p>
<div class="sidebox-wrapper" style="margin-top:3em">
<div class="sidebox">
<h4>Hiding your files from the Media Scanner</h4>
<p>Include an empty file named {@code .nomedia} in your external files directory (note the dot
prefix in the filename). This will prevent Android's media scanner from reading your media
files and including them in apps like Gallery or Music.</p>
</div>
</div>
<h3>Saving files that should be shared</h3>
<p>If you want to save files that are not specific to your application and that should <em>not</em>
be deleted when your application is uninstalled, save them to one of the public directories on the
external storage. These directories lay at the root of the external storage, such as {@code
Music/}, {@code Pictures/}, {@code Ringtones/}, and others.</p>
<p>In API Level 8 or greater, use {@link
android.os.Environment#getExternalStoragePublicDirectory(String)
getExternalStoragePublicDirectory()}, passing it the type of public directory you want, such as
{@link android.os.Environment#DIRECTORY_MUSIC}, {@link android.os.Environment#DIRECTORY_PICTURES},
{@link android.os.Environment#DIRECTORY_RINGTONES}, or others. This method will create the
appropriate directory if necessary.</p>
<p>If you're using API Level 7 or lower, use {@link
android.os.Environment#getExternalStorageDirectory()} to open a {@link java.io.File} that represents
the root of the external storage, then save your shared files in one of the following
directories:</p>
<ul class="nolist"></li>
<li><code>Music/</code> - Media scanner classifies all media found here as user music.</li>
<li><code>Podcasts/</code> - Media scanner classifies all media found here as a podcast.</li>
<li><code>Ringtones/ </code> - Media scanner classifies all media found here as a ringtone.</li>
<li><code>Alarms/</code> - Media scanner classifies all media found here as an alarm sound.</li>
<li><code>Notifications/</code> - Media scanner classifies all media found here as a notification
sound.</li>
<li><code>Pictures/</code> - All photos (excluding those taken with the camera).</li>
<li><code>Movies/</code> - All movies (excluding those taken with the camcorder).</li>
<li><code>Download/</code> - Miscellaneous downloads.</li>
</ul>
<h3 id="ExternalCache">Saving cache files</h3>
<p>If you're using API Level 8 or greater, use {@link
android.content.Context#getExternalCacheDir()} to open a {@link java.io.File} that represents the
external storage directory where you should save cache files. If the user uninstalls your
application, these files will be automatically deleted. However, during the life of your
application, you should manage these cache files and remove those that aren't needed in order to
preserve file space.</p>
<p>If you're using API Level 7 or lower, use {@link
android.os.Environment#getExternalStorageDirectory()} to open a {@link java.io.File} that represents
the root of the external storage, then write your cache data in the following directory:</p>
<pre class="no-pretty-print classic">
/Android/data/<em>&lt;package_name&gt;</em>/cache/
</pre>
<p>The {@code <em>&lt;package_name&gt;</em>} is your Java-style package name, such as "{@code
com.example.android.app}".</p>
<h2 id="db">Using Databases</h2>
<p>Android provides full support for <a href="http://www.sqlite.org/">SQLite</a> databases.
Any databases you create will be accessible by name to any
class in the application, but not outside the application.</p>
<p>The recommended method to create a new SQLite database is to create a subclass of {@link
android.database.sqlite.SQLiteOpenHelper} and override the {@link
android.database.sqlite.SQLiteOpenHelper#onCreate(SQLiteDatabase) onCreate()} method, in which you
can execute a SQLite command to create tables in the database. For example:</p>
<pre>
public class DictionaryOpenHelper extends SQLiteOpenHelper {
private static final int DATABASE_VERSION = 2;
private static final String DICTIONARY_TABLE_NAME = "dictionary";
private static final String DICTIONARY_TABLE_CREATE =
"CREATE TABLE " + DICTIONARY_TABLE_NAME + " (" +
KEY_WORD + " TEXT, " +
KEY_DEFINITION + " TEXT);";
DictionaryOpenHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
&#64;Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(DICTIONARY_TABLE_CREATE);
}
}
</pre>
<p>You can then get an instance of your {@link android.database.sqlite.SQLiteOpenHelper}
implementation using the constructor you've defined. To write to and read from the database, call
{@link android.database.sqlite.SQLiteOpenHelper#getWritableDatabase()} and {@link
android.database.sqlite.SQLiteOpenHelper#getReadableDatabase()}, respectively. These both return a
{@link android.database.sqlite.SQLiteDatabase} object that represents the database and
provides methods for SQLite operations.</p>
<div class="sidebox-wrapper">
<div class="sidebox">
<p>Android does not impose any limitations beyond the standard SQLite concepts. We do recommend
including an autoincrement value key field that can be used as a unique ID to
quickly find a record. This is not required for private data, but if you
implement a <a href="{@docRoot}guide/topics/providers/content-providers.html">content provider</a>,
you must include a unique ID using the {@link android.provider.BaseColumns#_ID BaseColumns._ID}
constant.
</p>
</div>
</div>
<p>You can execute SQLite queries using the {@link android.database.sqlite.SQLiteDatabase}
{@link
android.database.sqlite.SQLiteDatabase#query(boolean,String,String[],String,String[],String,String,String,String)
query()} methods, which accept various query parameters, such as the table to query,
the projection, selection, columns, grouping, and others. For complex queries, such as
those that require column aliases, you should use
{@link android.database.sqlite.SQLiteQueryBuilder}, which provides
several convienent methods for building queries.</p>
<p>Every SQLite query will return a {@link android.database.Cursor} that points to all the rows
found by the query. The {@link android.database.Cursor} is always the mechanism with which
you can navigate results from a database query and read rows and columns.</p>
<p>For sample apps that demonstrate how to use SQLite databases in Android, see the
<a href="{@docRoot}resources/samples/NotePad/index.html">Note Pad</a> and
<a href="{@docRoot}resources/samples/SearchableDictionary/index.html">Searchable Dictionary</a>
applications.</p>
<h3 id="dbDebugging">Database debugging</h3>
<p>The Android SDK includes a {@code sqlite3} database tool that allows you to browse
table contents, run SQL commands, and perform other useful functions on SQLite
databases. See <a href="{@docRoot}guide/developing/tools/adb.html#sqlite">Examining sqlite3
databases from a remote shell</a> to learn how to run this tool.
</p>
<h2 id="netw">Using a Network Connection</h2>
<!-- TODO MAKE THIS USEFUL!! -->
<p>You can use the network (when it's available) to store and retrieve data on your own web-based
services. To do network operations, use classes in the following packages:</p>
<ul class="no-style">
<li><code>{@link java.net java.net.*}</code></li>
<li><code>{@link android.net android.net.*}</code></li>
</ul>
@@ -0,0 +1,9 @@
<html>
<head>
<meta http-equiv="refresh" content="0;url=data-storage.html">
<title>Redirecting...</title>
</head>
<body>
<a href="data-storage.html">click here</a> if you are not redirected.
</body>
</html>
@@ -0,0 +1,9 @@
<html>
<head>
<meta http-equiv="refresh" content="0;url=opengl.html">
<title>Redirecting...</title>
</head>
<body>
<a href="opengl.html">click here</a> if you are not redirected.
</body>
</html>
@@ -0,0 +1,53 @@
page.title=OpenGL
@jd:body
<p>Android includes support for 3D hardware acceleration. This functionality is
accessed via the OpenGL API &mdash; specifically, the OpenGL ES API.</p>
<p>OpenGL ES is a flavor of the OpenGL specification intended for embedded
devices. Versions of OpenGL ES are loosely peered to versions of the primary
OpenGL standard. Android currently supports OpenGL ES 1.0, which corresponds
to OpenGL 1.3. So, if the application you have in mind is possible with OpenGL
1.3 on a desktop system, it should be possible on Android.</p>
<p>The specific API provided by Android is similar to the J2ME JSR239 OpenGL
ES API. However, it may not be identical, so watch out for deviations.</p>
<h2>Using the API</h2>
<p>Here's how to use the API at an extremely high level:</p>
<ol>
<li>Write a custom View subclass.</li>
<li>Obtain a handle to an OpenGLContext, which provides access to the OpenGL functionality.</li>
<li>In your View's onDraw() method, get a handle to a GL object, and use its methods to perform GL operations.</li>
</ol>
<p>For an example of this usage model (based on the classic GL ColorCube),
see
<a href="{@docRoot}samples/ApiDemos/src/com/example/android/apis/graphics/GLView1.html">com.android.samples.graphics.GLView1.java</a>
in the ApiDemos sample code project. A slightly more sophisticated version showing how to use
it with threads can be found in
<a href="{@docRoot}samples/ApiDemos/src/com/example/android/apis/graphics/GLSurfaceViewActivity.html">com.android.samples.graphics.GLSurfaceViewActivity.java</a>.
</p>
<p>Writing a summary of how to actually write 3D applications using OpenGL is
beyond the scope of this text and is left as an exercise for the reader.</p>
<h2>Links to Additional Information</h2>
<p>Information about OpenGL ES can be
found at <a title="http://www.khronos.org/opengles/"
href="http://www.khronos.org/opengles/">http://www.khronos.org/opengles/</a>.</p>
<p>Information specifically
about OpenGL ES 1.0 (including a detailed specification) can be found
at <a title="http://www.khronos.org/opengles/1_X/"
href="http://www.khronos.org/opengles/1_X/">http://www.khronos.org/opengles/1_X/</a>.</p>
<p>The documentation for the Android {@link javax.microedition.khronos.opengles.GL
OpenGL ES implementations} are also available.</p>
<p>Finally, note that though Android does include some basic support for
OpenGL ES 1.1, the support is <strong>not complete</strong>, and should not be relied
upon at this time.</p>
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,499 @@
page.title=2D Graphics
parent.title=2D and 3D Graphics
parent.link=index.html
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>In this document</h2>
<ol>
<li><a href="#drawables">Drawables</a>
<ol>
<li><a href="#drawables-from-images">Creating from resource images</a></li>
<li><a href="#drawables-from-xml">Creating from resource XML</a></li>
</ol>
</li>
<li><a href="#shape-drawable">Shape Drawable</a></li>
<!-- <li><a href="#state-list">StateListDrawable</a></li> -->
<li><a href="#nine-patch">Nine-patch</a></li>
<li><a href="#tween-animation">Tween Animation</a></li>
<li><a href="#frame-animation">Frame Animation</a></li>
</ol>
</div>
</div>
<p>Android offers a custom 2D graphics library for drawing and animating shapes and images.
The {@link android.graphics.drawable} and {@link android.view.animation}
packages are where you'll find the common classes used for drawing and animating in two-dimensions.
</p>
<p>This document offers an introduction to drawing graphics in your Android application.
We'll discuss the basics of using Drawable objects to draw
graphics, how to use a couple subclasses of the Drawable class, and how to
create animations that either tween (move, stretch, rotate) a single graphic
or animate a series of graphics (like a roll of film).</p>
<h2 id="drawables">Drawables</h2>
<p>A {@link android.graphics.drawable.Drawable} is a general abstraction for "something that can be drawn."
You'll discover that the Drawable class extends to define a variety of specific kinds of drawable graphics,
including {@link android.graphics.drawable.BitmapDrawable}, {@link android.graphics.drawable.ShapeDrawable},
{@link android.graphics.drawable.PictureDrawable}, {@link android.graphics.drawable.LayerDrawable}, and several more.
Of course, you can also extend these to define your own custom Drawable objects that behave in unique ways.</p>
<p>There are three ways to define and instantiate a Drawable: using an image saved in your project resources;
using an XML file that defines the Drawable properties; or using the normal class constructors. Below, we'll discuss
each the first two techniques (using constructors is nothing new for an experienced developer).</p>
<h3 id="drawables-from-images">Creating from resource images</h3>
<p>A simple way to add graphics to your application is by referencing an image file from your project resources.
Supported file types are PNG (preferred), JPG (acceptable) and GIF (discouraged). This technique would
obviously be preferred for application icons, logos, or other graphics such as those used in a game.</p>
<p>To use an image resource, just add your file to the <code>res/drawable/</code> directory of your project.
From there, you can reference it from your code or your XML layout.
Either way, it is referred using a resource ID, which is the file name without the file type
extension (E.g., <code>my_image.png</code> is referenced as <var>my_image</var>).</p>
<p class="note"><strong>Note:</strong> Image resources placed in <code>res/drawable/</code> may be
automatically optimized with lossless image compression by the
<a href="{@docRoot}guide/developing/tools/aapt.html">aapt</a> tool. For example, a true-color PNG that does
not require more than 256 colors may be converted to an 8-bit PNG with a color palette. This
will result in an image of equal quality but which requires less memory. So be aware that the
image binaries placed in this directory can change during the build. If you plan on reading
an image as a bit stream in order to convert it to a bitmap, put your images in the <code>res/raw/</code>
folder instead, where they will not be optimized.</p>
<h4>Example code</h4>
<p>The following code snippet demonstrates how to build an {@link android.widget.ImageView} that uses an image
from drawable resources and add it to the layout.</p>
<pre>
LinearLayout mLinearLayout;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Create a LinearLayout in which to add the ImageView
mLinearLayout = new LinearLayout(this);
// Instantiate an ImageView and define its properties
ImageView i = new ImageView(this);
i.setImageResource(R.drawable.my_image);
i.setAdjustViewBounds(true); // set the ImageView bounds to match the Drawable's dimensions
i.setLayoutParams(new Gallery.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
// Add the ImageView to the layout and set the layout as the content view
mLinearLayout.addView(i);
setContentView(mLinearLayout);
}
</pre>
<p>In other cases, you may want to handle your image resource as a
{@link android.graphics.drawable.Drawable} object.
To do so, create a Drawable from the resource like so:
<pre>
Resources res = mContext.getResources();
Drawable myImage = res.getDrawable(R.drawable.my_image);
</pre>
<p class="warning"><strong>Note:</strong> Each unique resource in your project can maintain only one
state, no matter how many different objects you may instantiate for it. For example, if you instantiate two
Drawable objects from the same image resource, then change a property (such as the alpha) for one of the
Drawables, then it will also affect the other. So when dealing with multiple instances of an image resource,
instead of directly transforming the Drawable, you should perform a <a href="#tween-animation">tween animation</a>.</p>
<h4>Example XML</h4>
<p>The XML snippet below shows how to add a resource Drawable to an
{@link android.widget.ImageView} in the XML layout (with some red tint just for fun).
<pre>
&lt;ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:tint="#55ff0000"
android:src="@drawable/my_image"/>
</pre>
<p>For more information on using project resources, read about
<a href="{@docRoot}guide/topics/resources/index.html">Resources and Assets</a>.</p>
<h3 id="drawables-from-xml">Creating from resource XML</h3>
<p>By now, you should be familiar with Android's principles of developing a
<a href="{@docRoot}guide/topics/ui/index.html">User Interface</a>. Hence, you understand the power
and flexibility inherent in defining objects in XML. This philosophy caries over from Views to Drawables.
If there is a Drawable object that you'd like to create, which is not initially dependent on variables defined by
your application code or user interaction, then defining the Drawable in XML is a good option.
Even if you expect your Drawable to change its properties during the user's experience with your application,
you should consider defining the object in XML, as you can always modify properties once it is instantiated.</p>
<p>Once you've defined your Drawable in XML, save the file in the <code>res/drawable/</code> directory of
your project. Then, retrieve and instantiate the object by calling
{@link android.content.res.Resources#getDrawable(int) Resources.getDrawable()}, passing it the resource ID
of your XML file. (See the <a href="#drawable-xml-example">example below</a>.)</p>
<p>Any Drawable subclass that supports the <code>inflate()</code> method can be defined in
XML and instantiated by your application.
Each Drawable that supports XML inflation utilizes specific XML attributes that help define the object
properties (see the class reference to see what these are). See the class documentation for each
Drawable subclass for information on how to define it in XML.
<h4 id="drawable-xml-example">Example</h4>
<p>Here's some XML that defines a TransitionDrawable:</p>
<pre>
&lt;transition xmlns:android="http://schemas.android.com/apk/res/android">
&lt;item android:drawable="&#64;drawable/image_expand">
&lt;item android:drawable="&#64;drawable/image_collapse">
&lt;/transition>
</pre>
<p>With this XML saved in the file <code>res/drawable/expand_collapse.xml</code>,
the following code will instantiate the TransitionDrawable and set it as the content of an ImageView:</p>
<pre>
Resources res = mContext.getResources();
TransitionDrawable transition = (TransitionDrawable) res.getDrawable(R.drawable.expand_collapse);
ImageView image = (ImageView) findViewById(R.id.toggle_image);
image.setImageDrawable(transition);
</pre>
<p>Then this transition can be run forward (for 1 second) with:</p>
<pre>transition.startTransition(1000);</pre>
<p>Refer to the Drawable classes listed above for more information on the XML attributes supported by each.</p>
<h2 id="shape-drawable">Shape Drawable</h2>
<p>When you want to dynamically draw some two-dimensional graphics, a {@link android.graphics.drawable.ShapeDrawable}
object will probably suit your needs. With a ShapeDrawable, you can programmatically draw
primitive shapes and style them in any way imaginable.</p>
<p>A ShapeDrawable is an extension of {@link android.graphics.drawable.Drawable}, so you can use one where ever
a Drawable is expected &mdash; perhaps for the background of a View, set with
{@link android.view.View#setBackgroundDrawable(android.graphics.drawable.Drawable) setBackgroundDrawable()}.
Of course, you can also draw your shape as its own custom {@link android.view.View},
to be added to your layout however you please.
Because the ShapeDrawable has its own <code>draw()</code> method, you can create a subclass of View that
draws the ShapeDrawable during the <code>View.onDraw()</code> method.
Here's a basic extension of the View class that does just this, to draw a ShapeDrawable as a View:</p>
<pre>
public class CustomDrawableView extends View {
private ShapeDrawable mDrawable;
public CustomDrawableView(Context context) {
super(context);
int x = 10;
int y = 10;
int width = 300;
int height = 50;
mDrawable = new ShapeDrawable(new OvalShape());
mDrawable.getPaint().setColor(0xff74AC23);
mDrawable.setBounds(x, y, x + width, y + height);
}
protected void onDraw(Canvas canvas) {
mDrawable.draw(canvas);
}
}
</pre>
<p>In the constructor, a ShapeDrawable is defines as an {@link android.graphics.drawable.shapes.OvalShape}.
It's then given a color and the bounds of the shape are set. If you do not set the bounds, then the
shape will not be drawn, whereas if you don't set the color, it will default to black.</p>
<p>With the custom View defined, it can be drawn any way you like. With the sample above, we can
draw the shape programmatically in an Activity:</p>
<pre>
CustomDrawableView mCustomDrawableView;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mCustomDrawableView = new CustomDrawableView(this);
setContentView(mCustomDrawableView);
}
</pre>
<p>If you'd like to draw this custom drawable from the XML layout instead of from the Activity,
then the CustomDrawable class must override the {@link android.view.View#View(android.content.Context, android.util.AttributeSet) View(Context, AttributeSet)} constructor, which is called when
instantiating a View via inflation from XML. Then add a CustomDrawable element to the XML,
like so:</p>
<pre>
&lt;com.example.shapedrawable.CustomDrawableView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
</pre>
<p>The ShapeDrawable class (like many other Drawable types in the {@link android.graphics.drawable} package)
allows you to define various properties of the drawable with public methods.
Some properties you might want to adjust include
alpha transparency, color filter, dither, opacity and color.</p>
<p>You can also define primitive drawable shapes using XML. For more information, see the
section about Shape Drawables in the <a
href="{@docRoot}guide/topics/resources/drawable-resource.html#Shape">Drawable Resources</a>
document.</p>
<!-- TODO
<h2 id="state-list">StateListDrawable</h2>
<p>A StateListDrawable is an extension of the DrawableContainer class, making it little different.
The primary distinction is that the
StateListDrawable manages a collection of images for the Drawable, instead of just one.
This means that it can switch the image when you want, without switching objects. However, the
intention of the StateListDrawable is to automatically change the image used based on the state
of the object it's attached to.
-->
<h2 id="nine-patch">Nine-patch</h2>
<p>A {@link android.graphics.drawable.NinePatchDrawable} graphic is a stretchable bitmap image, which Android
will automatically resize to accommodate the contents of the View in which you have placed it as the background.
An example use of a NinePatch is the backgrounds used by standard Android buttons &mdash;
buttons must stretch to accommodate strings of various lengths. A NinePatch drawable is a standard PNG
image that includes an extra 1-pixel-wide border. It must be saved with the extension <code>.9.png</code>,
and saved into the <code>res/drawable/</code> directory of your project.
</p>
<p>
The border is used to define the stretchable and static areas of
the image. You indicate a stretchable section by drawing one (or more) 1-pixel-wide
black line(s) in the left and top part of the border. (You can have as
many stretchable sections as you want.) The relative size of the stretchable
sections stays the same, so the largest sections always remain the largest.
</p>
<p>
You can also define an optional drawable section of the image (effectively,
the padding lines) by drawing a line on the right and bottom lines.
If a View object sets the NinePatch as its background and then specifies the
View's text, it will stretch itself so that all the text fits inside only
the area designated by the right and bottom lines (if included). If the
padding lines are not included, Android uses the left and top lines to
define this drawable area.
</p>
<p>To clarify the difference between the different lines, the left and top lines define
which pixels of the image are allowed to be replicated in order to stretch the image.
The bottom and right lines define the relative area within the image that the contents
of the View are allowed to lie within.</p>
<p>
Here is a sample NinePatch file used to define a button:
</p>
<img src="{@docRoot}images/ninepatch_raw.png" alt="" />
<p>This NinePatch defines one stretchable area with the left and top lines
and the drawable area with the bottom and right lines. In the top image, the dotted grey
lines identify the regions of the image that will be replicated in order to stretch the image. The pink
rectangle in the bottom image identifies the region in which the contents of the View are allowed.
If the contents don't fit in this region, then the image will be stretched so that they do.
</p>
<p>The <a href="{@docRoot}guide/developing/tools/draw9patch.html">Draw 9-patch</a> tool offers
an extremely handy way to create your NinePatch images, using a WYSIWYG graphics editor. It
even raises warnings if the region you've defined for the stretchable area is at risk of
producing drawing artifacts as a result of the pixel replication.
</p>
<h3>Example XML</h3>
<p>Here's some sample layout XML that demonstrates how to add a NinePatch image to a
couple of buttons. (The NinePatch image is saved as <code>res/drawable/my_button_background.9.png</code>
<pre>
&lt;Button id="@+id/tiny"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerInParent="true"
android:text="Tiny"
android:textSize="8sp"
android:background="@drawable/my_button_background"/&gt;
&lt;Button id="@+id/big"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerInParent="true"
android:text="Biiiiiiig text!"
android:textSize="30sp"
android:background="@drawable/my_button_background"/&gt;
</pre>
<p>Note that the width and height are set to "wrap_content" to make the button fit neatly around the text.
</p>
<p>Below are the two buttons rendered from the XML and NinePatch image shown above.
Notice how the width and height of the button varies with the text, and the background image
stretches to accommodate it.
</p>
<img src="{@docRoot}images/ninepatch_examples.png" alt=""/>
<h2 id="tween-animation">Tween Animation</h2>
<p>A tween animation can perform a series of simple transformations (position, size, rotation, and transparency) on
the contents of a View object. So, if you have a TextView object, you can move, rotate, grow, or shrink the text.
If it has a background image, the background image will be transformed along with the text.
The {@link android.view.animation animation package} provides all the classes used in a tween animation.</p>
<p>A sequence of animation instructions defines the tween animation, defined by either XML or Android code.
Like defining a layout, an XML file is recommended because it's more readable, reusable, and swappable
than hard-coding the animation. In the example below, we use XML. (To learn more about defining an animation
in your application code, instead of XML, refer to the
{@link android.view.animation.AnimationSet} class and other {@link android.view.animation.Animation} subclasses.)</p>
<p>The animation instructions define the transformations that you want to occur, when they will occur,
and how long they should take to apply. Transformations can be sequential or simultaneous &mdash;
for example, you can have the contents of a TextView move from left to right, and then
rotate 180 degrees, or you can have the text move and rotate simultaneously. Each transformation
takes a set of parameters specific for that transformation (starting size and ending size
for size change, starting angle and ending angle for rotation, and so on), and
also a set of common parameters (for instance, start time and duration). To make
several transformations happen simultaneously, give them the same start time;
to make them sequential, calculate the start time plus the duration of the preceding transformation.
</p>
<p>The animation XML file belongs in the <code>res/anim/</code> directory of your Android project.
The file must have a single root element: this will be either a single <code>&lt;alpha&gt;</code>,
<code>&lt;scale&gt;</code>, <code>&lt;translate&gt;</code>, <code>&lt;rotate&gt;</code>, interpolator element,
or <code>&lt;set&gt;</code> element that holds groups of these elements (which may include another
<code>&lt;set&gt;</code>). By default, all animation instructions are applied simultaneously.
To make them occur sequentially, you must specify the <code>startOffset</code> attribute, as shown in the example below.
</p>
<p>The following XML from one of the ApiDemos is used to stretch,
then simultaneously spin and rotate a View object.
</p>
<pre>
&lt;set android:shareInterpolator="false"&gt;
&lt;scale
android:interpolator="&#64;android:anim/accelerate_decelerate_interpolator"
android:fromXScale="1.0"
android:toXScale="1.4"
android:fromYScale="1.0"
android:toYScale="0.6"
android:pivotX="50%"
android:pivotY="50%"
android:fillAfter="false"
android:duration="700" /&gt;
&lt;set android:interpolator="&#64;android:anim/decelerate_interpolator"&gt;
&lt;scale
android:fromXScale="1.4"
android:toXScale="0.0"
android:fromYScale="0.6"
android:toYScale="0.0"
android:pivotX="50%"
android:pivotY="50%"
android:startOffset="700"
android:duration="400"
android:fillBefore="false" /&gt;
&lt;rotate
android:fromDegrees="0"
android:toDegrees="-45"
android:toYScale="0.0"
android:pivotX="50%"
android:pivotY="50%"
android:startOffset="700"
android:duration="400" /&gt;
&lt;/set&gt;
&lt;/set&gt;
</pre>
<p>Screen coordinates (not used in this example) are (0,0) at the upper left hand corner,
and increase as you go down and to the right.</p>
<p>Some values, such as pivotX, can be specified relative to the object itself or relative to the parent.
Be sure to use the proper format for what you want ("50" for 50% relative to the parent, or "50%" for 50%
relative to itself).</p>
<p>You can determine how a transformation is applied over time by assigning an
{@link android.view.animation.Interpolator}. Android includes
several Interpolator subclasses that specify various speed curves: for instance,
{@link android.view.animation.AccelerateInterpolator} tells
a transformation to start slow and speed up. Each one has an attribute value that can be applied in the XML.</p>
<p>With this XML saved as <code>hyperspace_jump.xml</code> in the <code>res/anim/</code> directory of the
project, the following Java code will reference it and apply it to an {@link android.widget.ImageView} object
from the layout.
</p>
<pre>
ImageView spaceshipImage = (ImageView) findViewById(R.id.spaceshipImage);
Animation hyperspaceJumpAnimation = AnimationUtils.loadAnimation(this, R.anim.hyperspace_jump);
spaceshipImage.startAnimation(hyperspaceJumpAnimation);
</pre>
<p>As an alternative to <code>startAnimation()</code>, you can define a starting time for the animation with
<code>{@link android.view.animation.Animation#setStartTime(long) Animation.setStartTime()}</code>,
then assign the animation to the View with
<code>{@link android.view.View#setAnimation(android.view.animation.Animation) View.setAnimation()}</code>.
</p>
<p>For more information on the XML syntax, available tags and attributes, see <a
href="{@docRoot}guide/topics/resources/animation-resource.html">Animation Resources</a>.</p>
<p class="note"><strong>Note:</strong> Regardless of how your animation may move or resize, the bounds of the
View that holds your animation will not automatically adjust to accommodate it. Even so, the animation will still
be drawn beyond the bounds of its View and will not be clipped. However, clipping <em>will occur</em>
if the animation exceeds the bounds of the parent View.</p>
<h2 id="frame-animation">Frame Animation</h2>
<p>This is a traditional animation in the sense that it is created with a sequence of different
images, played in order, like a roll of film. The {@link android.graphics.drawable.AnimationDrawable}
class is the basis for frame animations.</p>
<p>While you can define the frames of an animation in your code, using the
{@link android.graphics.drawable.AnimationDrawable} class API, it's more simply accomplished with a single XML
file that lists the frames that compose the animation. Like the tween animation above, the XML file for this kind
of animation belongs in the <code>res/drawable/</code> directory of your Android project. In this case,
the instructions are the order and duration for each frame of the animation.</p>
<p>The XML file consists of an <code>&lt;animation-list></code> element as the root node and a series
of child <code>&lt;item></code> nodes that each define a frame: a drawable resource for the frame and the frame duration.
Here's an example XML file for a frame-by-frame animation:</p>
<pre>
&lt;animation-list xmlns:android="http://schemas.android.com/apk/res/android"
android:oneshot="true">
&lt;item android:drawable="&#64;drawable/rocket_thrust1" android:duration="200" />
&lt;item android:drawable="&#64;drawable/rocket_thrust2" android:duration="200" />
&lt;item android:drawable="&#64;drawable/rocket_thrust3" android:duration="200" />
&lt;/animation-list>
</pre>
<p>This animation runs for just three frames. By setting the <code>android:oneshot</code> attribute of the
list to <var>true</var>, it will cycle just once then stop and hold on the last frame. If it is set <var>false</var> then
the animation will loop. With this XML saved as <code>rocket_thrust.xml</code> in the <code>res/drawable/</code> directory
of the project, it can be added as the background image to a View and then called to play. Here's an example Activity,
in which the animation is added to an {@link android.widget.ImageView} and then animated when the screen is touched:</p>
<pre>
AnimationDrawable rocketAnimation;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
ImageView rocketImage = (ImageView) findViewById(R.id.rocket_image);
rocketImage.setBackgroundResource(R.drawable.rocket_thrust);
rocketAnimation = (AnimationDrawable) rocketImage.getBackground();
}
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
rocketAnimation.start();
return true;
}
return super.onTouchEvent(event);
}
</pre>
<p>It's important to note that the <code>start()</code> method called on the AnimationDrawable cannot be
called during the <code>onCreate()</code> method of your Activity, because the AnimationDrawable is not yet fully attached
to the window. If you want to play the animation immediately, without
requiring interaction, then you might want to call it from the
<code>{@link android.app.Activity#onWindowFocusChanged(boolean) onWindowFocusChanged()}</code> method in
your Activity, which will get called when Android brings your window into focus.</p>
<p>For more information on the XML syntax, available tags and attributes, see <a
href="{@docRoot}guide/topics/resources/animation-resource.html">Animation Resources</a>.</p>
@@ -0,0 +1,203 @@
page.title=Graphics
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>In this document</h2>
<ol>
<li><a href="#options">Consider your Options</a></li>
<li><a href="#draw-to-view">Simple Graphics Inside a View</a></li>
<li><a href="#draw-with-canvas">Draw with a Canvas</a>
<ol>
<li><a href="#on-view">On a View</a></li>
<li><a href="#on-surfaceview">On a SurfaceView</a></li>
</ol>
</li>
</ol>
</div>
</div>
<p>Android graphics are powered by a custom 2D graphics library and OpenGL ES 1.0
for high performance 3D graphics. The most common 2D graphics APIs can be found in the
{@link android.graphics.drawable drawable package}. OpenGL APIs are available
from the Khronos {@link javax.microedition.khronos.opengles OpenGL ES package},
plus some Android {@link android.opengl OpenGL utilities}.</p>
<p>When starting a project, it's important to consider exactly what your graphical demands will be.
Varying graphical tasks are best accomplished with varying techniques. For example, graphics and animations
for a rather static application should be implemented much differently than graphics and animations
for an interactive game or 3D rendering.</p>
<p>Here, we'll discuss a few of the options you have for drawing graphics on Android,
and which tasks they're best suited for.</p>
<p>If you're specifically looking for information on drawing 3D graphics, this page won't
help a lot. However, the information below about how to <a href="#draw-with-canvas">Draw with a
Canvas</a> (and the section on SurfaceView),
will give you a quick idea of how you should draw to the View hierarchy. For more information
on Android's 3D graphic utilities (provided by the OpenGL ES API),
read <a href="opengl.html">3D with OpenGL</a> and refer to other OpenGL documentation.</p>
<h2 id="options">Consider your Options</h2>
<p>When drawing 2D graphics, you'll typically do so in one of two ways:</p>
<ol type="a">
<li>Draw your graphics or animations into a View object from your layout. In this manner,
the drawing (and any animation) of your graphics is handled by the system's
normal View hierarchy drawing process &mdash; you simply define the graphics to go inside the View.</li>
<li>Draw your graphics directly to a Canvas. This way, you personally call the appropriate class's
<code>draw()</code> method (passing it your Canvas), or one of the Canvas <code>draw...()</code> methods (like
<code>{@link android.graphics.Canvas#drawPicture(Picture,Rect) drawPicture()}</code>). In doing so, you are also in
control of any animation.</li>
</ol>
<p>Option "a," drawing to a View, is your best choice when you want to draw simple graphics that do not
need to change dynamically and are not part of a performance-intensive game. For example, you should
draw your graphics into a View when you want to display a static graphic or predefined animation, within
an otherwise static application. Read <a href="#draw-to-view">Simple Graphics Inside a View</a>.</li>
<p>Option "b," drawing to a Canvas, is better when your application needs to regularly re-draw itself.
Basically, any video game should be drawing to the Canvas on its own. However, there's more than
one way to do this: </p>
<ul>
<li>In the same thread as your UI Activity, wherein you create a custom View component in
your layout, call <code>{@link android.view.View#invalidate()}</code> and then handle the
<code>{@link android.view.View#onDraw(Canvas) onDraw()}</code> callback..</li>
<li>Or, in a separate thread, wherein you manage a {@link android.view.SurfaceView} and
perform draws to the Canvas as fast as your thread is capable
(you do not need to request <code>invalidate()</code>).</li>
</ul>
<p>...Begin by reading <a href="#draw-with-canvas">Draw with a Canvas</a>.</p>
<h2 id="draw-to-view">Simple Graphics Inside a View</h2>
<p>If you'll be drawing some simple graphics (images, shapes, colors, pre-defined animations, etc.),
then you should probably just draw to the background of a View or
to the content of an {@link android.widget.ImageView} in your layout.
In this case, you can skip the rest of this document and learn how to
draw graphics and animations in the <a href="2d-graphics.html">2D Graphics</a> document.
</p>
<h2 id="draw-with-canvas">Draw with a Canvas</h2>
<p>When you're writing an application in which you would like to perform specialized drawing
and/or control the animation of graphics,
you should do so by drawing through a {@link android.graphics.Canvas}. A Canvas works for you as
a pretense, or interface, to the actual surface upon which your graphics will be drawn &mdash; it
holds all of your "draw" calls. Via the Canvas, your drawing is actually performed upon an
underlying {@link android.graphics.Bitmap}, which is placed into the window.</p>
<p>In the event that you're drawing within the <code>{@link android.view.View#onDraw(Canvas) onDraw()}</code>
callback method, the Canvas is provided for you and you need only place your drawing calls upon it.
You can also acquire a Canvas from <code>{@link android.view.SurfaceHolder#lockCanvas() SurfaceHolder.lockCanvas()}</code>,
when dealing with a SurfaceView object. (Both of these scenarios are discussed in the following sections.)
However, if you need to create a new Canvas, then you must define the {@link android.graphics.Bitmap}
upon which drawing will actually be performed. The Bitmap is always required for a Canvas. You can set up
a new Canvas like this:</p>
<pre>
Bitmap b = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(b);
</pre>
<p>Now your Canvas will draw onto the defined Bitmap. After drawing upon it with the Canvas, you can then carry your
Bitmap to another Canvas with one of the <code>{@link android.graphics.Canvas#drawBitmap(Bitmap,Matrix,Paint)
Canvas.drawBitmap(Bitmap,...)}</code> methods. It's recommended that you ultimately draw your final
graphics through a Canvas offered to you
by <code>{@link android.view.View#onDraw(Canvas) View.onDraw()}</code> or
<code>{@link android.view.SurfaceHolder#lockCanvas() SurfaceHolder.lockCanvas()}</code> (see the following sections).</p>
<p>The {@link android.graphics.Canvas} class has its own set of drawing methods that you can use,
like <code>drawBitmap(...)</code>, <code>drawRect(...)</code>, <code>drawText(...)</code>, and many more.
Other classes that you might use also have <code>draw()</code> methods. For example, you'll probably
have some {@link android.graphics.drawable.Drawable} objects that you want to put on the Canvas. Drawable
has its own <code>{@link android.graphics.drawable.Drawable#draw(Canvas) draw()}</code> method
that takes your Canvas as an argument.</p>
<h3 id="on-view">On a View</h3>
<p>If your application does not require a significant amount of processing or
frame-rate speed (perhaps for a chess game, a snake game,
or another slowly-animated application), then you should consider creating a custom View component
and drawing with a Canvas in <code>{@link android.view.View#onDraw(Canvas) View.onDraw()}</code>.
The most convenient aspect of doing so is that the Android framework will
provide you with a pre-defined Canvas to which you will place your drawing calls.</p>
<p>To start, extend the {@link android.view.View} class (or descendant thereof) and define
the <code>{@link android.view.View#onDraw(Canvas) onDraw()}</code> callback method. This method will be called by the Android
framework to request that your View draw itself. This is where you will perform all your calls
to draw through the {@link android.graphics.Canvas}, which is passed to you through the <code>onDraw()</code> callback.</p>
<p>The Android framework will only call <code>onDraw()</code> as necessary. Each time that
your application is prepared to be drawn, you must request your View be invalidated by calling
<code>{@link android.view.View#invalidate()}</code>. This indicates that you'd like your View to be drawn and
Android will then call your <code>onDraw()</code> method (though is not guaranteed that the callback will
be instantaneous). </p>
<p>Inside your View component's <code>onDraw()</code>, use the Canvas given to you for all your drawing,
using various <code>Canvas.draw...()</code> methods, or other class <code>draw()</code> methods that
take your Canvas as an argument. Once your <code>onDraw()</code> is complete, the Android framework will
use your Canvas to draw a Bitmap handled by the system.</p>
<p class="note"><strong>Note: </strong> In order to request an invalidate from a thread other than your main
Activity's thread, you must call <code>{@link android.view.View#postInvalidate()}</code>.</p>
<p>Also read <a href="{@docRoot}guide/topics/ui/custom-components.html">Building Custom Components</a>
for a guide to extending a View class, and <a href="2d-graphics.html">2D Graphics: Drawables</a> for
information on using Drawable objects like images from your resources and other primitive shapes.</p>
<p>For a sample application, see the Snake game, in the SDK samples folder:
<code>&lt;your-sdk-directory>/samples/Snake/</code>.</p>
<h3 id="on-surfaceview">On a SurfaceView</h3>
<p>The {@link android.view.SurfaceView} is a special subclass of View that offers a dedicated
drawing surface within the View hierarchy. The aim is to offer this drawing surface to
an application's secondary thread, so that the application isn't required
to wait until the system's View hierarchy is ready to draw. Instead, a secondary thread
that has reference to a SurfaceView can draw to its own Canvas at its own pace.</p>
<p>To begin, you need to create a new class that extends {@link android.view.SurfaceView}. The class should also
implement {@link android.view.SurfaceHolder.Callback}. This subclass is an interface that will notify you
with information about the underlying {@link android.view.Surface}, such as when it is created, changed, or destroyed.
These events are important so that you know when you can start drawing, whether you need
to make adjustments based on new surface properties, and when to stop drawing and potentially
kill some tasks. Inside your SurfaceView class is also a good place to define your secondary Thread class, which will
perform all the drawing procedures to your Canvas.</p>
<p>Instead of handling the Surface object directly, you should handle it via
a {@link android.view.SurfaceHolder}. So, when your SurfaceView is initialized, get the SurfaceHolder by calling
<code>{@link android.view.SurfaceView#getHolder()}</code>. You should then notify the SurfaceHolder that you'd
like to receive SurfaceHolder callbacks (from {@link android.view.SurfaceHolder.Callback}) by calling
{@link android.view.SurfaceHolder#addCallback(SurfaceHolder.Callback) addCallback()}
(pass it <var>this</var>). Then override each of the
{@link android.view.SurfaceHolder.Callback} methods inside your SurfaceView class.</p>
<p>In order to draw to the Surface Canvas from within your second thread, you must pass the thread your SurfaceHandler
and retrieve the Canvas with <code>{@link android.view.SurfaceHolder#lockCanvas() lockCanvas()}</code>.
You can now take the Canvas given to you by the SurfaceHolder and do your necessary drawing upon it.
Once you're done drawing with the Canvas, call
<code>{@link android.view.SurfaceHolder#unlockCanvasAndPost(Canvas) unlockCanvasAndPost()}</code>, passing it
your Canvas object. The Surface will now draw the Canvas as you left it. Perform this sequence of locking and
unlocking the canvas each time you want to redraw.</p>
<p class="note"><strong>Note:</strong> On each pass you retrieve the Canvas from the SurfaceHolder,
the previous state of the Canvas will be retained. In order to properly animate your graphics, you must re-paint the
entire surface. For example, you can clear the previous state of the Canvas by filling in a color
with <code>{@link android.graphics.Canvas#drawColor(int) drawColor()}</code> or setting a background image
with <code>{@link android.graphics.Canvas#drawBitmap(Bitmap,Rect,RectF,Paint) drawBitmap()}</code>. Otherwise,
you will see traces of the drawings you previously performed.</p>
<p>For a sample application, see the Lunar Lander game, in the SDK samples folder:
<code>&lt;your-sdk-directory>/samples/LunarLander/</code>. Or,
browse the source in the <a href="{@docRoot}guide/samples/index.html">Sample Code</a> section.</p>
@@ -0,0 +1,53 @@
page.title=3D with OpenGL
parent.title=2D and 3D Graphics
parent.link=index.html
@jd:body
<p>Android includes support for high performance 3D graphics
via the OpenGL API &mdash; specifically, the OpenGL ES API.</p>
<p>OpenGL ES is a flavor of the OpenGL specification intended for embedded
devices. Versions of <a href="http://www.khronos.org/opengles/">OpenGL ES</a> are loosely peered to versions of the primary
OpenGL standard. Android currently supports OpenGL ES 1.0, which corresponds
to OpenGL 1.3. So, if the application you have in mind is possible with OpenGL
1.3 on a desktop system, it should be possible on Android.</p>
<p>The specific API provided by Android is similar to the J2ME JSR239 OpenGL
ES API. However, it may not be identical, so watch out for deviations.</p>
<h2>Using the API</h2>
<p>Here's how to use the API at an extremely high level:</p>
<ol>
<li>Write a custom View subclass.</li>
<li>Obtain a handle to an OpenGLContext, which provides access to the OpenGL functionality.</li>
<li>In your View's onDraw() method, get a handle to a GL object, and use its methods to perform GL operations.</li>
</ol>
<p>For an example of this usage model (based on the classic GL ColorCube), showing how to use
it with threads can be found in
<a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/graphics/GLSurfaceViewActivity.html">com.android.samples.graphics.GLSurfaceViewActivity.java</a>.
</p>
<p>Writing a summary of how to actually write 3D applications using OpenGL is
beyond the scope of this text and is left as an exercise for the reader.</p>
<h2>Links to Additional Information</h2>
<p>Information about OpenGL ES can be
found at <a title="http://www.khronos.org/opengles/"
href="http://www.khronos.org/opengles/">http://www.khronos.org/opengles/</a>.</p>
<p>Information specifically
about OpenGL ES 1.0 (including a detailed specification) can be found
at <a title="http://www.khronos.org/opengles/1_X/"
href="http://www.khronos.org/opengles/1_X/">http://www.khronos.org/opengles/1_X/</a>.</p>
<p>The documentation for the Android {@link javax.microedition.khronos.opengles
OpenGL ES implementations} are also available.</p>
<p>Finally, note that though Android does include some basic support for
OpenGL ES 1.1, the support is <strong>not complete</strong>, and should not be relied
upon at this time.</p>
+8
View File
@@ -0,0 +1,8 @@
<html>
<head>
<meta http-equiv="refresh" content="0;url=../index.html">
</head>
<body>
<a href="../index.html">click here</a> if you are not redirected.
</body>
</html>
@@ -0,0 +1,9 @@
<html>
<head>
<meta http-equiv="refresh" content="0;url=intents-filters.html">
<title>Redirecting...</title>
</head>
<body>
<a href="intents-filters.html">click here</a> if you are not redirected.
</body>
</html>
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,109 @@
page.title=Location and Maps
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>Quickview</h2>
<ul>
<li>Android provides a location framework that your application can use to determine the
device's location and bearing and register for updates</li>
<li>A Google Maps external library is available that lets you display and manage Maps data</li>
</ul>
<h2>Topics</h2>
<ol>
<li><a href="{@docRoot}guide/topics/location/obtaining-user-location.html">Obtaining User
Location</a></li>
</ol>
<h2>See Also</h2>
<ol>
<li><a
href="http://code.google.com/android/add-ons/google-apis/maps-overview.html">Google
Maps External Library &raquo;</a></li>
</ol>
</div>
</div>
<p>Location and maps-based applications are compelling for mobile device users. You
can build these capabilities into your applications using the classes of the {@link
android.location} package and the Google Maps external library. The sections below provide details.
</p>
<h2 id="location">Location Services</h2>
<p>Android gives your applications access to the location services supported by
the device through the classes in the {@code android.location} package. The
central component of the location framework is the
{@link android.location.LocationManager} system service, which provides APIs to
determine location and bearing of the underlying device (if available). </p>
<p>As with other system services, you do not instantiate a {@link android.location.LocationManager}
directly. Rather, you request an instance from the system by calling
{@link android.content.Context#getSystemService(String)
getSystemService(Context.LOCATION_SERVICE)}. The method returns a handle to a new {@link
android.location.LocationManager} instance.</p>
<p>Once your application has a {@link android.location.LocationManager}, your application
is able to do three things:</p>
<ul>
<li>Query for the list of all {@link android.location.LocationProvider}s for the last known
user location.</li>
<li>Register/unregister for periodic updates of the user's current location from a
location provider (specified either by criteria or name).</li>
<li>Register/unregister for a given {@link android.content.Intent} to be fired if the device
comes within a given proximity (specified by radius in meters) of a given lat/long.</li>
</ul>
<p>For more information, read the guide to <a
href="{@docRoot}guide/topics/location/obtaining-user-location.html">Obtaining User
Location</a>.</p>
<h2 id="maps">Google Maps External Library</h2>
<p>To make it easier for you to add powerful mapping capabilities to your
application, Google provides a Maps external library that includes the
com.google.android.maps package. The classes of the com.google.android.maps
package offer built-in downloading, rendering, and caching of Maps tiles, as
well as a variety of display options and controls. </p>
<p>The key class in the Maps package is
<code>com.google.android.maps.MapView</code>, a subclass of
{@link android.view.ViewGroup ViewGroup}. A MapView displays a map with data obtained
from the Google Maps service. When the MapView has focus, it will capture
keypresses and touch gestures to pan and zoom the map automatically, including
handling network requests for additional maps tiles. It also provides all of the
UI elements necessary for users to control the map. Your application can also
use MapView class methods to control the MapView programmatically and draw a
number of Overlay types on top of the map. </p>
<p>In general, the MapView class provides a wrapper around the Google Maps API
that lets your application manipulate Google Maps data through class methods,
and it lets you work with Maps data as you would other types of Views.</p>
<p>The Maps external library is not part of the standard Android library, so it
may not be present on some compliant Android-powered devices. Similarly, the
Maps external library is not included in the standard Android library provided
in the SDK. So that you can develop using the classes of the
com.google.android.maps package, the Maps external library is made available to
you as part of the Google APIs add-on for the Android SDK. </p>
<p>To learn more about the Maps external library and how to download and use the
Google APIs add-on, visit</p>
<p style="margin-left:2em;"><a
href="http://code.google.com/android/add-ons/google-apis">http://code.google.com/android/add-ons/google-apis</a></p>
<p>For your convenience, the Google APIs add-on is also available as a downloadable component from
the Android SDK and AVD Manager (see <a href="{@docRoot}sdk/adding-components.html">Adding SDK
Components</a>).</p>
<p class="note"><strong>Note:</strong> In order to display Google Maps data in a
MapView, you must register with the Google Maps service and obtain a Maps API
Key. For information about how to get a Maps API Key, see <a
href="http://code.google.com/android/add-ons/google-apis/mapkey.html">Obtaining
a Maps API Key</a>.</p>
@@ -0,0 +1,454 @@
page.title=Obtaining User Location
parent.title=Location and Maps
parent.link=index.html
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>Quickview</h2>
<ul>
<li>The Network Location Provider provides good location data without using GPS</li>
<li>Obtaining user location can consume a lot of battery, so be careful how
long you listen for updates</li>
</ul>
<h2>In this document</h2>
<ol>
<li><a href="#Challenges">Challenges in Determining User Location</a></li>
<li><a href="#Updates">Requesting Location Updates</a>
<ol>
<li><a href="#Permission">Requesting User Permissions</a></li>
</ol>
</li>
<li><a href="#BestPerformance">Defining a Model for the Best Performance</a>
<ol>
<li><a href="#Flow">Flow for obtaining user location</a></li>
<li><a href="#StartListening">Deciding when to start listening for updates</a></li>
<li><a href="#FastFix">Getting a fast fix with the last known location</a></li>
<li><a href="#StopListening">Deciding when to stop listening for updates</a></li>
<li><a href="#BestEstimate">Maintaining a current best estimate</a></li>
<li><a href="#Adjusting">Adjusting the model to save battery and data exchange</a></li>
</ol>
</li>
<li><a href="#MockData">Providing Mock Location Data</a></li>
</ol>
<h2>Key classes</h2>
<ol>
<li>{@link android.location.LocationManager}</li>
<li>{@link android.location.LocationListener}</li>
</ol>
</div>
</div>
<p>Knowing where the user is allows your application to be smarter and deliver
better information to the user. When developing a location-aware application for Android, you can
utilize GPS and Android's Network Location Provider to acquire the user location. Although
GPS is most accurate, it only works outdoors, it quickly consumes battery power, and doesn't return
the location as quickly as users want. Android's Network Location Provider determines user location
using cell tower and Wi-Fi signals, providing location information in a way that
works indoors and outdoors, responds faster, and uses less battery power. To obtain the user
location in your application, you can use both GPS and the Network Location Provider, or just
one.</p>
<h2 id="Challenges">Challenges in Determining User Location</h2>
<p>Obtaining user location from a mobile device can be complicated. There are several reasons
why a location reading (regardless of the source) can contain errors and be inaccurate.
Some sources of error in the user location include:</p>
<ul>
<li><b>Multitude of location sources</b>
<p>GPS, Cell-ID, and Wi-Fi can each provide a clue to users location. Determining which to use
and trust is a matter of trade-offs in accuracy, speed, and battery-efficiency.</p>
</li>
<li><b>User movement</b>
<p>Because the user location changes, you must account for movement by re-estimating user
location every so often.</p>
</li>
<li><b>Varying accuracy</b>
<p>Location estimates coming from each location source are not consistent in their
accuracy. A location obtained 10 seconds ago from one source might be more accurate than the newest
location from another or same source.</p>
</li>
</ul>
<p>These problems can make it difficult to obtain a reliable user location reading. This
document provides information to help you meet these challenges to obtain a reliable location
reading. It also provides ideas that you can use in your
application to provide the user with an accurate and responsive geo-location experience.</p>
<h2 id="Updates">Requesting Location Updates</h2>
<p>Before addressing some of the location errors described above, here is an introduction to
how you can obtain user location on Android.</p>
<p>Getting user location in Android works by means of callback. You indicate that you'd
like to receive location updates from the {@link android.location.LocationManager} ("Location
Manager") by calling {@link android.location.LocationManager#requestLocationUpdates
requestLocationUpdates()}, passing it a
{@link android.location.LocationListener}. Your {@link android.location.LocationListener} must
implement several callback methods that the Location Manager calls when the user location
changes or when the status of the service changes.</p>
<p>For example, the following code shows how to define a {@link android.location.LocationListener}
and request location updates:
</p>
<pre>
// Acquire a reference to the system Location Manager
LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
// Define a listener that responds to location updates
LocationListener locationListener = new LocationListener() {
public void onLocationChanged(Location location) {
// Called when a new location is found by the network location provider.
makeUseOfNewLocation(location);
}
public void onStatusChanged(String provider, int status, Bundle extras) {}
public void onProviderEnabled(String provider) {}
public void onProviderDisabled(String provider) {}
};
// Register the listener with the Location Manager to receive location updates
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locationListener);
</pre>
<p>The first parameter in {@link
android.location.LocationManager#requestLocationUpdates requestLocationUpdates()} is the type of
location provider to use (in this case, the Network Location Provider for cell tower and Wi-Fi
based location). You can control the frequency at which your listener receives updates
with the second and third parameter&mdash;the second is the minimum time interval between
notifications and the third is the minimum change in distance between notifications&mdash;setting
both to zero requests location notifications as frequently as possible. The last parameter is your
{@link android.location.LocationListener}, which receives callbacks for location updates.</p>
<p>To request location updates from the GPS provider,
substitute <code>GPS_PROVIDER</code> for <code>NETWORK_PROVIDER</code>. You can also request
location updates from both the GPS and the Network Location Provider by calling {@link
android.location.LocationManager#requestLocationUpdates requestLocationUpdates()} twice&mdash;once
for <code>NETWORK_PROVIDER</code> and once for <code>GPS_PROVIDER</code>.</p>
<h3 id="Permission">Requesting User Permissions</h3>
<p>In order to receive location updates from <code>NETWORK_PROVIDER</code> or
<code>GPS_PROVIDER</code>, you must request user permission by declaring either the {@code
ACCESS_COARSE_LOCATION} or {@code ACCESS_FINE_LOCATION} permission, respectively, in your Android
manifest file. For example:</p>
<pre>
&lt;manifest ... &gt;
&lt;uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /&gt;
...
&lt;/manifest&gt;
</pre>
<p>Without these permissions, your application will fail at runtime when requesting
location updates.</p>
<p class="note"><strong>Note:</strong> If you are using both <code>NETWORK_PROVIDER</code> and
<code>GPS_PROVIDER</code>, then you need to request only the {@code ACCESS_FINE_LOCATION}
permission, because it includes permission for both providers. (Permission for {@code
ACCESS_COARSE_LOCATION} includes permission only for <code>NETWORK_PROVIDER</code>.)</p>
<h2 id="BestPerformance">Defining a Model for the Best Performance</h2>
<p>Location-based applications are now commonplace, but due to the less than optimal
accuracy, user movement, the multitude of methods to obtain the location, and the desire to conserve
battery, getting user location is complicated. To overcome the obstacles of obtaining a good user
location while preserving battery power, you must define a consistent model that specifies how your
application obtains the user location. This model includes when you start and stop listening for
updates and when to use cached location data.</p>
<h3 id="Flow">Flow for obtaining user location</h3>
<p>Here's the typical flow of procedures for obtaining the user location:</p>
<ol>
<li>Start application.</li>
<li>Sometime later, start listening for updates from desired location providers.</li>
<li>Maintain a "current best estimate" of location by filtering out new, but less accurate
fixes.</li>
<li>Stop listening for location updates.</li>
<li>Take advantage of the last best location estimate.</li>
</ol>
<p>Figure 1 demonstrates this model in a timeline that visualizes the period in which an
application is listening for location updates and the events that occur during that time.</p>
<img src="{@docRoot}images/location/getting-location.png" alt="" />
<p class="img-caption"><strong>Figure 1.</strong> A timeline representing the window in which an
application listens for location updates.</p>
<p>This model of a window&mdash;during which location updates are received&mdash;frames many of
the decisions you need to make when adding location-based services to your application.</p>
<h3 id="StartListening">Deciding when to start listening for updates</h3>
<p>You might want to start listening for location updates as soon as your application starts, or
only after users activate a certain feature. Be aware that long windows of listening for location
fixes can consume a lot of battery power, but short periods might not allow for sufficient
accuracy.</p>
<p>As demonstrated above, you can begin listening for updates by calling {@link
android.location.LocationManager#requestLocationUpdates requestLocationUpdates()}:</p>
<pre>
LocationProvider locationProvider = LocationManager.NETWORK_PROVIDER;
// Or, use GPS location data:
// LocationProvider locationProvider = LocationManager.GPS_PROVIDER;
locationManager.requestLocationUpdates(locationProvider, 0, 0, locationListener);
</pre>
<h3 id="FastFix">Getting a fast fix with the last known location</h3>
<p>The time it takes for your location listener to receive the first location fix is often too
long for users wait. Until a more accurate location is provided to your location listener, you
should utilize a cached location by calling {@link
android.location.LocationManager#getLastKnownLocation}:</p>
<pre>
LocationProvider locationProvider = LocationManager.NETWORK_PROVIDER;
// Or use LocationManager.GPS_PROVIDER
Location lastKnownLocation = locationManager.getLastKnownLocation(locationProvider);
</pre>
<h3 id="StopListening">Deciding when to stop listening for updates</h3>
<p>The logic of deciding when new fixes are no longer necessary might range from very simple to
very complex depending on your application. A short gap between when the location is acquired and
when the location is used, improves the accuracy of the estimate. Always beware that listening for a
long time consumes a lot of battery power, so as soon as you have the information you need, you
should stop
listening for updates by calling {@link android.location.LocationManager#removeUpdates}:</p>
<pre>
// Remove the listener you previously added
locationManager.removeUpdates(locationListener);
</pre>
<h3 id="BestEstimate">Maintaining a current best estimate</h3>
<p>You might expect that the most recent location fix is the most accurate.
However, because the accuracy of a location fix varies, the most recent fix is not always the best.
You should include logic for choosing location fixes based on several criteria. The criteria also
varies depending on the use-cases of the application and field testing.</p>
<p>Here are a few steps you can take to validate the accuracy of a location fix:</p>
<ul>
<li>Check if the location retrieved is significantly newer than the previous estimate.</li>
<li>Check if the accuracy claimed by the location is better or worse than the previous
estimate.</li>
<li>Check which provider the new location is from and determine if you trust it more.</li>
</ul>
<p>An elaborate example of this logic can look something like this:</p>
<pre>
private static final int TWO_MINUTES = 1000 * 60 * 2;
/** Determines whether one Location reading is better than the current Location fix
* @param location The new Location that you want to evaluate
* @param currentBestLocation The current Location fix, to which you want to compare the new one
*/
protected boolean isBetterLocation(Location location, Location currentBestLocation) {
if (currentBestLocation == null) {
// A new location is always better than no location
return true;
}
// Check whether the new location fix is newer or older
long timeDelta = location.getTime() - currentBestLocation.getTime();
boolean isSignificantlyNewer = timeDelta &gt; TWO_MINUTES;
boolean isSignificantlyOlder = timeDelta &lt; -TWO_MINUTES;
boolean isNewer = timeDelta > 0;
// If it's been more than two minutes since the current location, use the new location
// because the user has likely moved
if (isSignificantlyNewer) {
return true;
// If the new location is more than two minutes older, it must be worse
} else if (isSignificantlyOlder) {
return false;
}
// Check whether the new location fix is more or less accurate
int accuracyDelta = (int) (location.getAccuracy() - currentBestLocation.getAccuracy());
boolean isLessAccurate = accuracyDelta &gt; 0;
boolean isMoreAccurate = accuracyDelta &lt; 0;
boolean isSignificantlyLessAccurate = accuracyDelta &gt; 200;
// Check if the old and new location are from the same provider
boolean isFromSameProvider = isSameProvider(location.getProvider(),
currentBestLocation.getProvider());
// Determine location quality using a combination of timeliness and accuracy
if (isMoreAccurate) {
return true;
} else if (isNewer &amp;&amp; !isLessAccurate) {
return true;
} else if (isNewer &amp;&amp; !isSignificantlyLessAccurate &amp;&amp; isFromSameProvider) {
return true;
}
return false;
}
/** Checks whether two providers are the same */
private boolean isSameProvider(String provider1, String provider2) {
if (provider1 == null) {
return provider2 == null;
}
return provider1.equals(provider2);
}
</pre>
<h3 id="Adjusting">Adjusting the model to save battery and data exchange</h3>
<p>As you test your application, you might find that your model for providing good location and
good performance needs some adjustment. Here are some things you might change to find a good
balance between the two.</p>
<h4>Reduce the size of the window</h4>
<p>A smaller window in which you listen for location updates means less interaction with GPS and
network location services, thus, preserving battery life. But it also allows for fewer locations
from which to choose a best estimate.</p>
<h4>Set the location providers to return updates less frequently</h4>
<p>Reducing the rate at which new updates appear during the window can also improve battery
efficiency, but at the cost of accuracy. The value of the trade-off depends on how your
application is used. You can reduce the rate of updates by increasing the parameters in {@link
android.location.LocationManager#requestLocationUpdates requestLocationUpdates()} that specify the
interval time and minimum distance change.</p>
<h4>Restrict a set of providers</h4>
<p>Depending on the environment where your application is used or the desired level of accuracy,
you might choose to use only the Network Location Provider or only GPS, instead of both. Interacting
with only one of the services reduces battery usage at a potential cost of accuracy.</p>
<h2>Common application cases</h2>
<p>There are many reasons you might want to obtain the user location in your application. Below
are a couple scenarios in which you can use the user location to enrich your application. Each
scenario also describes good practices for when you should start and stop listening for the
location, in order to get a good reading and help preserve battery life.</p>
<h3>Tagging user-created content with a location</h3>
<p>You might be creating an application where user-created content is tagged with a location.
Think of users sharing their local experiences, posting a review for a restaurant, or recording some
content that can be augmented with their current location. A model of how this
interaction might happen, with respect to the location services, is visualized in figure 2.</p>
<img src="{@docRoot}images/location/content-tagging.png" alt="" />
<p class="img-caption"><strong>Figure 2.</strong> A timeline representing the window in which
the user location is obtained and listening stops when the user consumes the current location.</p>
<p>This lines up with the previous model of how user location is obtained in code (figure 1). For
best location accuracy, you might choose to start listening for location updates when users begin
creating
the content or even when the application starts, then stop listening for updates when content is
ready to be posted or recorded. You might need to consider how long a typical task of creating the
content takes and judge if this duration allows for efficient collection of a location estimate.</p>
<h3>Helping the user decide on where to go</h3>
<p>You might be creating an application that attempts to provide users with a set
of options about where to go. For example, you're looking to provide a list of nearby restaurants,
stores, and entertainment and the order of recommendations changes depending on the user
location.</p>
<p>To accommodate such a flow, you might choose to:</p>
<ul>
<li>Rearrange recommendations when a new best estimate is obtained</li>
<li>Stop listening for updates if the order of recommendations has stabilized</li>
</ul>
<p>This kind of model is visualized in figure 3.</p>
<img src="{@docRoot}images/location/where-to-go.png" alt="" />
<p class="img-caption"><strong>Figure 3.</strong> A timeline representing the window in which a
dynamic set of data is updated each time the user location updates.</p>
<h2 id="MockData">Providing Mock Location Data</h2>
<p>As you develop your application, you'll certainly need to test how well your model for obtaining
user location works. This is most easily done using a real Android-powered device. If, however, you
don't have a device, you can still test your location-based features by mocking location data in
the Android emulator. There are three different ways to send your application mock location
data: using Eclipse, DDMS, or the "geo" command in the emulator console.</p>
<p class="note"><strong>Note:</strong> Providing mock location data is injected as GPS location
data, so you must request location updates from <code>GPS_PROVIDER</code> in order for mock location
data to work.</p>
<h3 id="MockEclipse">Using Eclipse</h3>
<p>Select <b>Window</b> &gt; <b>Show View</b> &gt; <b>Other</b> &gt; <b>Emulator Control</b>.</p>
<p>In the Emulator Control panel, enter GPS coordinates under Location Controls as individual
lat/long coordinates, with a GPX file for route playback, or a KML file for multiple place marks.
(Be sure that you have a device selected in the Devices panel&mdash;available from <b>Window</b>
&gt; <b>Show View</b> &gt; <b>Other</b> &gt; <b>Devices</b>.)</p>
<h3 id="MockDdms">Using DDMS</h3>
<p>With the DDMS tool, you can simulate location data a few different ways:</p>
<ul>
<li>Manually send individual longitude/latitude coordinates to the device.</li>
<li>Use a GPX file describing a route for playback to the device.</li>
<li>Use a KML file describing individual place marks for sequenced playback to the device.</li>
</ul>
<p>For more information on using DDMS to spoof location data, see the
<a href="{@docRoot}guide/developing/tools/ddms.html#emulator-control">Using DDMS guide</a>.
<h3 id="MockGeo">Using the "geo" command in the emulator console</h3>
<p>To send mock location data from the command line:</p>
<ol>
<li>Launch your application in the Android emulator and open a terminal/console in your SDK's
<code>/tools</code> directory.</li>
<li>Connect to the emulator console:
<pre>telnet localhost <em>&lt;console-port&gt;</em></pre></li>
<li>Send the location data:</p>
<ul><li><code>geo fix</code> to send a fixed geo-location.
<p>This command accepts a longitude and latitude in decimal degrees, and
an optional altitude in meters. For example:</p>
<pre>geo fix -121.45356 46.51119 4392</pre>
</li>
<li><code>geo nmea</code> to send an NMEA 0183 sentence.
<p>This command accepts a single NMEA sentence of type '$GPGGA' (fix data) or '$GPRMC' (transit
data).
For example:</p>
<pre>geo nmea $GPRMC,081836,A,3751.65,S,14507.36,E,000.0,360.0,130998,011.3,E*62</pre>
</li>
</ul>
</li>
</ol>
<p>For information about how to connect to the emulator console, see
<a href="{@docRoot}guide/developing/tools/emulator.html#console">Using the Emulator Console</a>.</p>
@@ -0,0 +1,50 @@
page.title=&lt;action&gt;
@jd:body
<dl class="xml">
<dt>syntax:</dt>
<dd><pre class="stx">&lt;action android:<a href="#nm">name</a>="<i>string</i>" /&gt;</pre></dd>
<dt>contained in:</dt>
<dd><code><a href="{@docRoot}guide/topics/manifest/intent-filter-element.html">&lt;intent-filter&gt;</a></code></dd>
<p>
<dt>description:</dt>
<dd>Adds an action to an intent filter.
An <code><a href="{@docRoot}guide/topics/manifest/intent-filter-element.html">&lt;intent-filter&gt;</a></code> element must contain
one or more {@code &lt;action&gt;} elements. If it doesn't contain any, no
Intent objects will get through the filter. See
<a href="{@docRoot}guide/topics/intents/intents-filters.html">Intents and
Intent Filters</a> for details on intent filters and the role of action
specifications within a filter.
</dd>
<dt>attributes:</dt>
<dd><dl class="attr">
<dt><a name="nm"></a>{@code android:name}</dt>
<dd>The name of the action. Some standard actions are defined in the
{@link android.content.Intent#ACTION_CHOOSER Intent} class as
{@code ACTION_<i>string</i>} constants. To assign one of these actions to
this attribute, prepend "{@code android.intent.action.}" to the
{@code <i>string</i>} that follows {@code ACTION_}.
For example, for {@code ACTION_MAIN}, use "{@code android.intent.action.MAIN}"
and for {@code ACTION_WEB_SEARCH}, use "{@code android.intent.action.WEB_SEARCH}".
<p>
For actions you define, it's best to use the package name as a prefix to
ensure uniqueness. For example, a {@code TRANSMOGRIFY} action might be specified
as follows:
</p>
<pre>&lt;action android:name="com.example.project.TRANSMOGRIFY" /&gt;</pre>
</dd>
</dl></dd>
<!-- ##api level indication## -->
<dt>introduced in:</dt>
<dd>API Level 1</dd>
<dt>see also:</dt>
<dd><code><a href="{@docRoot}guide/topics/manifest/intent-filter-element.html">&lt;intent-filter&gt;</a></code></dd>
</dl>
@@ -0,0 +1,133 @@
page.title=&lt;activity-alias&gt;
@jd:body
<dl class="xml">
<dt>syntax:</dt>
<dd><pre class="stx">&lt;activity-alias android:<a href="#enabled">enabled</a>=["true" | "false"]
android:<a href="#exported">exported</a>=["true" | "false"]
android:<a href="#icon">icon</a>="<i>drawable resource</i>"
android:<a href="#label">label</a>="<i>string resource</i>"
android:<a href="#nm">name</a>="<i>string</i>"
android:<a href="#prmsn">permission</a>="<i>string</i>"
android:<a href="#trgt">targetActivity</a>="<i>string</i>" &gt;
. . .
&lt;/activity-alias&gt;</pre></dd>
<dt>contained in:</dt>
<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/intent-filter-element.html">&lt;intent-filter&gt;</a></code>
<br/><code><a href="{@docRoot}guide/topics/manifest/meta-data-element.html">&lt;meta-data&gt;</a></code></dd>
<dt>description:</dt>
<dd>An alias for an activity, named by the {@code targetActivity}
attribute. The target must be in the same application as the
alias and it must be declared before the alias in the manifest.
<p>
The alias presents the target activity as a independent entity.
It can have its own set of intent filters, and they, rather than the
intent filters on the target activity itself, determine which intents
can activate the target through the alias and how the system
treats the alias. For example, the intent filters on the alias may
specify the "<code>{@link android.content.Intent#ACTION_MAIN
android.intent.action.MAIN}</code>"
and "<code>{@link android.content.Intent#CATEGORY_LAUNCHER
android.intent.category.LAUNCHER}</code>" flags, causing it to be
represented in the application launcher, even though none of the
filters on the target activity itself set these flags.
</p>
<p>
With the exception of {@code targetActivity}, {@code &lt;activity-alias&gt;}
attributes are a subset of <code><a href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;activity&gt;</a></code> attributes.
For attributes in the subset, none of the values set for the target carry over
to the alias. However, for attributes not in the subset, the values set for
the target activity also apply to the alias.
</p></dd>
<dt>attributes:</dt>
<dd><dl class="attr">
<dt><a name="enabled"></a>{@code android:enabled}</dt>
<dd>Whether or not the target activity can be instantiated by the system through
this alias &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 activity aliases. The
<code><a href="{@docRoot}guide/topics/manifest/application-element.html">&lt;application&gt;</a></code> and {@code &lt;activity-alias&gt;}
attributes must both be "{@code true}" for the system to be able to instantiate
the target activity through the alias. If either is "{@code false}", the alias
does not work.
</p></dd>
<dt><a name="exported"></a>{@code android:exported}</dt>
<dd>Whether or not components of other applications can launch the target activity
through this alias &mdash; "{@code true}" if they can, and "{@code false}" if not.
If "{@code false}", the target activity can be launched through the alias only by
components of the same application as the alias or applications with the same user ID.
<p>
The default value depends on whether the alias contains intent filters. The
absence of any filters means that the activity can be invoked through the alias
only by specifying the exact name of the alias. This implies that the alias
is intended only for application-internal use (since others would not know its name)
&mdash; so the default value is "{@code false}".
On the other hand, the presence of at least one filter implies that the alias
is intended for external use &mdash; so the default value is "{@code true}".
</p></dd>
<dt><a name="icon"></a>{@code android:icon}</dt>
<dd>An icon for the target activity when presented to users through the alias.
See the <code><a href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;activity&gt;</a></code> element's
<code><a href="{@docRoot}guide/topics/manifest/activity-element.html#icon">icon</a></code> attribute for more information.
<dt><a name="label"></a>{@code android:label}</dt>
<dd>A user-readable label for the alias when presented to users through the alias.
See the the <code><a href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;activity&gt;</a></code> element's
<code><a href="{@docRoot}guide/topics/manifest/activity-element.html#label">label</a></code> attribute for more information.
</p></dd>
<dt><a name="nm">{@code android:name}</dt>
<dd>A unique name for the alias. The name should resemble a fully
qualified class name. But, unlike the name of the target activity,
the alias name is arbitrary; it does not refer to an actual class.
</p></dd>
<dt><a name="prmsn"></a>{@code android:permission}</dt>
<dd>The name of a permission that clients must have to launch the target activity
or get it to do something via the alias. If a caller of
<code>{@link android.content.Context#startActivity startActivity()}</code> or
<code>{@link android.app.Activity#startActivityForResult startActivityForResult()}</code>
has not been granted the specified permission, the target activity will not be
activated.
<p>This attribute supplants any permission set for the target activity itself. If
it is not set, a permission is not needed to activate the target through the alias.
</p>
<p>
For more information on permissions, see the
<a href="{@docRoot}guide/topics/manifest/manifest-intro.html#perms">Permissions</a>
section in the introduction.
</p></dd>
<dt><a name="trgt"></a>{@code android:targetActivity}</dt>
<dd>The name of the activity that can be activated through the alias.
This name must match the {@code name} attribute of an
<code><a href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;activity&gt;</a></code> element that precedes
the alias in the manifest.
</p></dd>
</dl></dd>
<!-- ##api level indication## -->
<dt>introduced in:</dt>
<dd>API Level 1</dd>
<dt>see also:</dt>
<dd><code><a href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;activity&gt;</a></code></dd>
</dl>
@@ -0,0 +1,780 @@
page.title=&lt;activity&gt;
@jd:body
<dl class="xml">
<dt>syntax:</dt>
<dd><pre class="stx">&lt;activity android:<a href="#reparent">allowTaskReparenting</a>=["true" | "false"]
android:<a href="#always">alwaysRetainTaskState</a>=["true" | "false"]
android:<a href="#clear">clearTaskOnLaunch</a>=["true" | "false"]
android:<a href="#config">configChanges</a>=["mcc", "mnc", "locale",
"touchscreen", "keyboard", "keyboardHidden",
"navigation", "orientation", "screenLayout",
"fontScale", "uiMode"]
android:<a href="#enabled">enabled</a>=["true" | "false"]
android:<a href="#exclude">excludeFromRecents</a>=["true" | "false"]
android:<a href="#exported">exported</a>=["true" | "false"]
android:<a href="#finish">finishOnTaskLaunch</a>=["true" | "false"]
android:<a href="#icon">icon</a>="<i>drawable resource</i>"
android:<a href="#label">label</a>="<i>string resource</i>"
android:<a href="#lmode">launchMode</a>=["multiple" | "singleTop" |
"singleTask" | "singleInstance"]
android:<a href="#multi">multiprocess</a>=["true" | "false"]
android:<a href="#nm">name</a>="<i>string</i>"
android:<a href="#nohist">noHistory</a>=["true" | "false"] <!-- ##api level 3## -->
android:<a href="#prmsn">permission</a>="<i>string</i>"
android:<a href="#proc">process</a>="<i>string</i>"
android:<a href="#screen">screenOrientation</a>=["unspecified" | "user" | "behind" |
"landscape" | "portrait" |
"sensor" | "nosensor"]
android:<a href="#state">stateNotNeeded</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="#wsoft">windowSoftInputMode</a>=["stateUnspecified",
"stateUnchanged", "stateHidden",
"stateAlwaysHidden", "stateVisible",
"stateAlwaysVisible", "adjustUnspecified",
"adjustResize", "adjustPan"] &gt; <!-- ##api level 3## -->
. . .
&lt;/activity&gt;</pre></dd>
<dt>contained in:</dt>
<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/intent-filter-element.html">&lt;intent-filter&gt;</a></code>
<br/><code><a href="{@docRoot}guide/topics/manifest/meta-data-element.html">&lt;meta-data&gt;</a></code></dd>
<dt>description:</dt>
<dd>Declares an activity (an {@link android.app.Activity} subclass) that
implements part of the application's visual user interface. All activities
must be represented by {@code &lt;activity&gt;}
elements in the manifest file. Any that are not declared there will not be seen
by the system and will never be run.
<dt>attributes:</dt>
<dd><dl class="attr">
<dt><a href name="reparent"></a>{@code android:allowTaskReparenting}</dt>
<dd>Whether or not the activity can move from the task that started it to
the task it has an affinity for when that task is next brought to the
front &mdash; "{@code true}" if it can move, and "{@code false}" if it
must remain with the task where it started.
<p>
If this attribute is not set, the value set by the corresponding
<code><a href="{@docRoot}guide/topics/manifest/application-element.html#reparent">allowTaskReparenting</a></code>
attribute of the <code><a href="{@docRoot}guide/topics/manifest/application-element.html">&lt;application&gt;</a></code> element
applies to the activity. The default value is "{@code false}".
</p>
<p>
Normally when an activity is started, it's associated with the task of
the activity that started it and it stays there for its entire lifetime.
You can use this attribute to force it to be re-parented to the task it
has an affinity for when its current task is no longer displayed.
Typically, it's used to cause the activities of an application to move
to the main task associated with that application.
</p>
<p>
For example, if an e-mail message contains a link to a web page, clicking
the link brings up an activity that can display the page. That activity
is defined by the browser application, but is launched as part of the e-mail
task. If it's reparented to the browser task, it will be shown when the
browser next comes to the front, and will be absent when the e-mail task
again comes forward.
</p>
<p>
The affinity of an activity is defined by the
<code><a href="#aff">taskAffinity</a></code> attribute. The affinity
of a task is determined by reading the affinity of its root activity.
Therefore, by definition, a root activity is always in a task with the
same affinity. Since activities with "{@code singleTask}" or
"{@code singleInstance}" launch modes can only be at the root of a task,
re-parenting is limited to the "{@code standard}" and "{@code singleTop}"
modes. (See also the <code><a href="#lmode">launchMode</a></code>
attribute.)
</p></dd>
<dt><a name="always"></a>{@code android:alwaysRetainTaskState}</dt>
<dd>Whether or not the state of the task that the activity is in will always
be maintained by the system &mdash; "{@code true}" if it will be, and
"{@code false}" if the system is allowed to reset the task to its initial
state in certain situations. The default value is "{@code false}". This
attribute is meaningful only for the root activity of a task; it's ignored
for all other activities.
<p>
Normally, the system clears a task (removes all activities from the stack
above the root activity) in certain situations when the user re-selects that
task from the home screen. Typically, this is done if the user hasn't visited
the task for a certain amount of time, such as 30 minutes.
</p>
<p>
However, when this attribute is "{@code true}", users will always return
to the task in its last state, regardless of how they get there. This is
useful, for example, in an application like the web browser where there is
a lot of state (such as multiple open tabs) that users would not like to lose.
</p></dd>
<dt><a name="clear"></a>{@code android:clearTaskOnLaunch}</dt>
<dd>Whether or not all activities will be removed from the task, except for
the root activity, whenever it is re-launched from the home screen &mdash;
"{@code true}" if the task is always stripped down to its root activity, and
"{@code false}" if not. The default value is "{@code false}". This attribute
is meaningful only for activities that start a new task (the root activity);
it's ignored for all other activities in the task.
<p>
When the value is "{@code true}", every time users start the task again, they
are brought to its root activity, regardless of what they were last doing in
the task and regardless of whether they used BACK or HOME to last leave it.
When the value is "{@code false}", the task may be cleared of activities in
some situations (see the
<code><a href="#always">alwaysRetainTaskState</a></code> attribute), but not always.
</p>
<p>
Suppose, for example, that someone launches activity P from the home screen,
and from there goes to activity Q. The user next presses HOME, and then returns
to activity P. Normally, the user would see activity Q, since that is what they
were last doing in P's task. However, if P set this flag to "{@code true}", all
of the activities on top of it (Q in this case) were removed when the user pressed
HOME and the task went to the background. So the user sees only P when returning
to the task.
</p>
<p>
If this attribute and <code><a href="#reparent">allowTaskReparenting</a></code>
are both "{@code true}", any activities that can be re-parented are moved to
the task they share an affinity with; the remaining activities are then dropped,
as described above.
</p></dd>
<dt><a name="config"></a>{@code android:configChanges}</dt>
<dd>Lists configuration changes that the activity will handle itself. When a configuration
change occurs at runtime, the activity is shut down and restarted by default, but declaring a
configuration with this attribute will prevent the activity from being restarted. Instead, the
activity remains running and its <code>{@link android.app.Activity#onConfigurationChanged
onConfigurationChanged()}</code> method is called.
<p class="note"><strong>Note:</strong> Using this attribute should be
avoided and used only as a last-resort. Please read <a
href="{@docRoot}guide/topics/resources/runtime-changes.html">Handling Runtime Changes</a> for more
information about how to properly handle a restart due to a configuration change.</p>
<p>
Any or all of the following strings are valid values for this attribute. Multiple values are
separated by '{@code |}' &mdash; for example, "{@code locale|navigation|orientation}".
</p>
<table>
<tr>
<th>Value</th>
<th>Description</th>
</tr><tr>
<td>"{@code mcc}"</td>
<td>The IMSI mobile country code (MCC) has changed &mdash;
a SIM has been detected and updated the MCC.</td>
</tr><tr>
<td>"{@code mnc}"</td>
<td>The IMSI mobile network code (MNC) has changed &mdash;
a SIM has been detected and updated the MNC.</td>
</tr><tr>
<td>"{@code locale}"</td>
<td>The locale has changed &mdash; the user has selected a new
language that text should be displayed in.</td>
</tr><tr>
<td>"{@code touchscreen}"</td>
<td>The touchscreen has changed. (This should never normally happen.)</td>
</tr><tr>
<td>"{@code keyboard}"</td>
<td>The keyboard type has changed &mdash; for example, the user has
plugged in an external keyboard.</td>
</tr><tr>
<td>"{@code keyboardHidden}"</td>
<td>The keyboard accessibility has changed &mdash; for example, the
user has revealed the hardware keyboard.</td>
</tr><tr>
<td>"{@code navigation}"</td>
<td>The navigation type (trackball/dpad) has changed. (This should never normally happen.)</td>
</tr><tr>
<td>"{@code orientation}"</td>
<td>The screen orientation has changed &mdash; the user has rotated
the device.</td>
</tr><tr>
<td>"{@code screenLayout}"</td>
<td>The screen layout has changed &mdash; this might be caused by a
different display being activated.</td>
</tr><tr>
<td>"{@code fontScale}"</td>
<td>The font scaling factor has changed &mdash; the user has selected
a new global font size.</td>
</tr><tr>
<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>
</tr>
</table>
<p>
All of these configuration changes can impact the resource values seen by the
application. Therefore, when <code>{@link android.app.Activity#onConfigurationChanged
onConfigurationChanged()}</code> is called, it will generally be necessary to again
retrieve all resources (including view layouts, drawables, and so on) to correctly
handle the change.
</p></dd>
<dt><a name="enabled"></a>{@code android:enabled}</dt>
<dd>Whether or not the activity 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 activities. The
<code><a href="{@docRoot}guide/topics/manifest/application-element.html">&lt;application&gt;</a></code>
and {@code &lt;activity&gt;} attributes must both be "{@code true}" (as they both
are by default) for the system to be able to instantiate the activity. If either
is "{@code false}", it cannot be instantiated.
</p></dd>
<dt><a name="exclude"></a>{@code android:excludeFromRecents}</dt>
<dd>Whether or not the activity should be excluded from the list of recently
launched activities that can be displayed to users &mdash; "{@code true}" if
it should be excluded, and "{@code false}" if it should be included.
The default value is "{@code false}".
</p></dd>
<dt><a name="exported"></a>{@code android:exported}</dt>
<dd>Whether or not the activity can be launched by components of other
applications &mdash; "{@code true}" if it can be, and "{@code false}" if not.
If "{@code false}", the activity can be launched only by components of the
same application or applications with the same user ID.
<p>
The default value depends on whether the activity contains intent filters. The
absence of any filters means that the activity can be invoked only by specifying
its exact class name. This implies that the activity is intended only for
application-internal use (since others would not know the class name). So in
this case, the default value is "{@code false}".
On the other hand, the presence of at least one filter implies that the activity
is intended for external use, so the default value is "{@code true}".
</p>
<p>
This attribute is not the only way to limit an activity's exposure to other
applications. You can also use a permission to limit the external entities that
can invoke the activity (see the
<code><a href="{@docRoot}guide/topics/manifest/activity-element.html#prmsn">permission</a></code>
attribute).
</p></dd>
<dt><a name="finish"></a>{@code android:finishOnTaskLaunch}</dt>
<dd>Whether or not an existing instance of the activity should be shut down
(finished) whenever the user again launches its task (chooses the task on the
home screen) &mdash; "{@code true}" if it should be shut down, and "{@code false}"
if not. The default value is "{@code false}".
<p>
If this attribute and
<code><a href="{@docRoot}guide/topics/manifest/activity-element.html#reparent">allowTaskReparenting</a></code>
are both "{@code true}", this attribute trumps the other. The affinity of the
activity is ignored. The activity is not re-parented, but destroyed.
</p>
<dt><a name="icon"></a>{@code android:icon}</dt>
<dd>An icon representing the activity. The icon is displayed to users when
a representation of the activity is required on-screen. For example, icons
for activities that initiate tasks are displayed in the launcher window.
The icon is often accompanied by a label (see the {@code label} attribute).
</p>
<p>
This attribute must be set as a reference to a drawable resource containing
the image definition. If it is not set, the icon specified for the application
as a whole is used instead (see the
<code><a href="{@docRoot}guide/topics/manifest/application-element.html">&lt;application&gt;</a></code>
element's <code><a href="{@docRoot}guide/topics/manifest/application-element.html#icon">icon</a></code> attribute).
</p>
<p>
The activity's icon &mdash; whether set here or by the
<code><a href="{@docRoot}guide/topics/manifest/application-element.html">&lt;application&gt;</a></code>
element &mdash; is also the default icon for all the activity's intent filters (see the
<code><a href="{@docRoot}guide/topics/manifest/intent-filter-element.html">&lt;intent-filter&gt;</a></code> element's
<code><a href="{@docRoot}guide/topics/manifest/intent-filter-element.html#icon">icon</a></code> attribute).
</p></dd>
<dt><a name="label"></a>{@code android:label}</dt>
<dd>A user-readable label for the activity. The label is displayed on-screen
when the activity must be represented to the user. It's often displayed along
with the activity icon.
<p>
If this attribute is not set, the label set for the application as a whole is
used instead (see the <code><a href="{@docRoot}guide/topics/manifest/application-element.html">&lt;application&gt;</a></code> element's
<code><a href="{@docRoot}guide/topics/manifest/application-element.html#label">label</a></code> attribute).
</p>
<p>
The activity's label &mdash; whether set here or by the
<code><a href="{@docRoot}guide/topics/manifest/application-element.html">&lt;application&gt;</a></code> element &mdash; is also the
default label for all the activity's intent filters (see the
<code><a href="{@docRoot}guide/topics/manifest/intent-filter-element.html">&lt;intent-filter&gt;</a></code> element's
<code><a href="{@docRoot}guide/topics/manifest/intent-filter-element.html#label">label</a></code> attribute).
</p>
<p>
The label should be set as a reference to a string resource, so that
it can be localized like other strings in the user interface.
However, as a convenience while you're developing the application,
it can also be set as a raw string.
</p></dd>
<dt><a name="lmode"></a>{@code android:launchMode}</dt>
<dd>An instruction on how the activity should be launched. There are four modes
that work in conjunction with activity flags ({@code FLAG_ACTIVITY_*} constants)
in {@link android.content.Intent} objects to determine what should happen when
the activity is called upon to handle an intent. They are:</p>
<p style="margin-left: 2em">"{@code standard}"
<br>"{@code singleTop}"
<br>"{@code singleTask}"
<br>"{@code singleInstance}"</p>
<p>
The default mode is "{@code standard}".
</p>
<p>
As shown in the table below, the modes fall into two main groups, with
"{@code standard}" and "{@code singleTop}" activities on one side, and
"{@code singleTask}" and "{@code singleInstance}" activities on the other.
An activity with the "{@code standard}" or "{@code singleTop}" launch mode
can be instantiated multiple times. The instances can belong to any task
and can be located anywhere in the activity stack. Typically, they're
launched into the task that called
<code>{@link android.content.Context#startActivity startActivity()}</code>
(unless the Intent object contains a
<code>{@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK}</code>
instruction, in which case a different task is chosen &mdash; see the
<a href="#aff">taskAffinity</a> attribute).
</p>
<p>
In contrast, "<code>singleTask</code>" and "<code>singleInstance</code>" activities
can only begin a task. They are always at the root of the activity stack.
Moreover, the device can hold only one instance of the activity at a time
&mdash; only one such task.
</p>
<p>
The "{@code standard}" and "{@code singleTop}" modes differ from each other
in just one respect: Every time there's a new intent for a "{@code standard}"
activity, a new instance of the class is created to respond to that intent.
Each instance handles a single intent.
Similarly, a new instance of a "{@code singleTop}" activity may also be
created to handle a new intent. However, if the target task already has an
existing instance of the activity at the top of its stack, that instance
will receive the new intent (in an
<code>{@link android.app.Activity#onNewIntent onNewIntent()}</code> call);
a new instance is not created.
In other circumstances &mdash; for example, if an existing instance of the
"{@code singleTop}" activity is in the target task, but not at the top of
the stack, or if it's at the top of a stack, but not in the target task
&mdash; a new instance would be created and pushed on the stack.
</p>
<p>
The "{@code singleTask}" and "{@code singleInstance}" modes also differ from
each other in only one respect: A "{@code singleTask}" activity allows other
activities to be part of its task. It's always at the root of its task, but
other activities (necessarily "{@code standard}" and "{@code singleTop}"
activities) can be launched into that task. A "{@code singleInstance}"
activity, on the other hand, permits no other activities to be part of its task.
It's the only activity in the task. If it starts another activity, that
activity is assigned to a different task &mdash; as if {@code
FLAG_ACTIVITY_NEW_TASK} was in the intent.
</p>
<table>
<tr>
<th>Use Cases</th>
<th>Launch Mode</th>
<th>Multiple Instances?</th>
<th>Comments</th>
</tr>
<tr>
<td rowspan="2" style="width:20%;">Normal launches for most activities</td>
<td>"<code>standard</code>"</td>
<td>Yes</td>
<td>Default. The system always creates a new instance of the activity in the
target task and routes the intent to it.</td>
</tr>
<tr>
<td>"<code>singleTop</code>"</td>
<td>Conditionally</td>
<td>If an instance of the activity already exists at the top of the target task,
the system routes the intent to that instance through a call to its {@link
android.app.Activity#onNewIntent onNewIntent()} method, rather than creating a
new instance of the activity.</td>
</tr>
<tr>
<td rowspan="2">Specialized launches<br>
<em>(not recommended for general use)</em></td>
<td>"<code>singleTask</code>"</td>
<td>No</td>
<td>The system creates the activity at the root of a new task and routes the
intent to it. However, if an instance of the activity already exists, the system
routes the intent to existing instance through a call to its {@link
android.app.Activity#onNewIntent onNewIntent()} method, rather than creating a
new one.</td>
</tr>
<tr>
<td>"<code>singleInstance</code>"</td>
<td>No</td>
<td>Same as "<code>singleTask"</code>, except that the system doesn't launch any
other activities into the task holding the instance. The activity is always the
single and only member of its task.</td>
</tr>
</table>
<p>As shown in the table above, <code>standard</code> is the default mode and is
appropriate for most types of activities. <code>SingleTop</code> is also a
common and useful launch mode for many types of activities. The other modes
&mdash; <code>singleTask</code> and <code>singleInstance</code> &mdash; are
<span style="color:red">not appropriate for most applications</span>,
since they result in an interaction model that is likely to be unfamiliar to
users and is very different from most other applications.
<p>Regardless of the launch mode that you choose, make sure to test the usability
of the activity during launch and when navigating back to it from
other activities and tasks using the BACK key. </p>
<p>For more information on launch modes and their interaction with Intent
flags, see the
<a href="{@docRoot}guide/topics/fundamentals.html#acttask">Activities and
Tasks</a> section of the
<a href="{@docRoot}guide/topics/fundamentals.html">Application Fundamentals</a>
document.
</p>
</dd>
<dt><a name="multi"></a>{@code android:multiprocess}</dt>
<dd>Whether an instance of the activity can be launched into the process of the component
that started it &mdash; "{@code true}" if it can be, and "{@code false}" if not.
The default value is "{@code false}".
<p>
Normally, a new instance of an activity is launched into the process of the
application that defined it, so all instances of the activity run in the same
process. However, if this flag is set to "{@code true}", instances of the
activity can run in multiple processes, allowing the system to create instances
wherever they are used (provided permissions allow it), something that is almost
never necessary or desirable.
</p></dd>
<dt><a name="nm"></a>{@code android:name}</dt>
<dd>The name of the class that implements the activity, a subclass of
{@link android.app.Activity}. The attribute value should be a fully qualified
class name (such as, "{@code com.example.project.ExtracurricularActivity}").
However, as a shorthand, if the first character of the name is a period
(for example, "{@code .ExtracurricularActivity}"), it is appended to the
package name specified in the
<code><a href="{@docRoot}guide/topics/manifest/manifest-element.html">&lt;manifest&gt;</a></code>
element.
<p>
There is no default. The name must be specified.
</p></dd>
<!-- ##api level 3## -->
<dt><a name="nohist"></a>{@code android:noHistory}</dt>
<dd>Whether or not the activity should be removed from the activity stack and
finished (its <code>{@link android.app.Activity#finish finish()}</code>
method called) when the user navigates away from it and it's no longer
visible on screen &mdash; "{@code true}" if it should be finished, and
"{@code false}" if not. The default value is "{@code false}".
<p>
A value of "{@code true}" means that the activity will not leave a
historical trace. It will not remain in the activity stack for the task,
so the user will not be able to return to it.
</p>
<p>
This attribute was introduced in API Level 3.
</p>
<dt><a name="prmsn"></a>{@code android:permission}</dt>
<dd>The name of a permission that clients must have to launch the activity
or otherwise get it to respond to an intent. If a caller of
<code>{@link android.content.Context#startActivity startActivity()}</code> or
<code>{@link android.app.Activity#startActivityForResult startActivityForResult()}</code>
has not been granted the specified permission, its intent will not be
delivered to the activity.
<p>
If this attribute is not set, the permission set by the
<code><a href="{@docRoot}guide/topics/manifest/application-element.html">&lt;application&gt;</a></code>
element's
<code><a href="{@docRoot}guide/topics/manifest/application-element.html#prmsn">permission</a></code>
attribute applies to the activity. If neither attribute is set, the activity is
not protected by a permission.
</p>
<p>
For more information on permissions, see the
<a href="{@docRoot}guide/topics/manifest/manifest-intro.html#sectperm">Permissions</a>
section in the introduction and another document,
<a href="{@docRoot}guide/topics/security/security.html">Security and
Permissions</a>.
</p></dd>
<dt><a name="proc"></a>{@code android:process}</dt>
<dd>The name of the process in which the activity should run. Normally,
all components of an application run in the default process created for the
application. It has the same name as the application package. The <code><a href="{@docRoot}guide/topics/manifest/application-element.html">&lt;application&gt;</a></code> element's
<code><a href="{@docRoot}guide/topics/manifest/application-element.html#proc">process</a></code>
attribute can set a different default for all components. But each component
can override the default, allowing you to spread your application across
multiple processes.
<p>
If the name assigned to this attribute begins with a colon (':'), a new
process, private to the application, is created when it's needed and
the activity runs in that process.
If the process name begins with a lowercase character, the activity will run
in a global process of that name, provided that it has permission to do so.
This allows components in different applications to share a process, reducing
resource usage.
</p></dd>
<dt><a name="screen"></a>{@code android:screenOrientation}</dt>
<dd>The orientation of the activity's display on the device.
The value can be any one of the following strings:
<table>
<tr>
<td>"{@code unspecified}"</td>
<td>The default value. The system chooses the orientation. The policy it
uses, and therefore the choices made in specific contexts, may differ
from device to device.</td>
</tr><tr>
<td>"{@code landscape}"</td>
<td>Landscape orientation (the display is wider than it is tall).</td>
</tr><tr>
<td>"{@code portrait}"</td>
<td>Portrait orientation (the display is taller than it is wide).</td>
</tr><tr>
<td>"{@code user}"</td>
<td>The user's current preferred orientation.</td>
</tr><tr>
<td>"{@code behind}"</td>
<td>The same orientation as the activity that's immediately beneath it in
the activity stack.</td>
</tr><tr>
<td>"{@code sensor}"</td>
<td>The orientation determined by a physical orientation sensor. The
orientation of the display depends on how the user is holding the device;
it changes when the user rotates the device.</td>
</tr><tr>
<td>"{@code nosensor}"</td>
<td>An orientation determined without reference to a physical orientation sensor.
The sensor is ignored, so the display will not rotate based on how the user
moves the device. Except for this distinction, the system chooses the
orientation using the same policy as for the "{@code unspecified}" setting.</td>
</tr>
</table></dd>
<dt><a name="state"></a>{@code android:stateNotNeeded}</dt>
<dd>Whether or not the activity can be killed and successfully restarted
without having saved its state &mdash; "{@code true}" if it can be restarted
without reference to its previous state, and "{@code false}" if its previous
state is required. The default value is "{@code false}".
<p>
Normally, before an activity is temporarily shut down to save resources, its
<code>{@link android.app.Activity#onSaveInstanceState onSaveInstanceState()}</code>
method is called. This method stores the current state of the activity in a
{@link android.os.Bundle} object, which is then passed to
<code>{@link android.app.Activity#onCreate onCreate()}</code> when the activity
is restarted. If this attribute is set to "{@code true}",
{@code onSaveInstanceState()} may not be called and {@code onCreate()} will
be passed {@code null} instead of the Bundle &mdash; just as it was when the
activity started for the first time.
</p>
<p>
A "{@code true}" setting ensures that the activity can be restarted in the
absence of retained state. For example, the activity that displays the
home screen uses this setting to make sure that it does not get removed if it
crashes for some reason.
</p></dd>
<dt><a name="aff"></a>{@code android:taskAffinity}</dt>
<dd>The task that the activity has an affinity for. Activities with
the same affinity conceptually belong to the same task (to the same
"application" from the user's perspective). The affinity of a task
is determined by the affinity of its root activity.
<p>
The affinity determines two things &mdash; the task that the activity is re-parented
to (see the <code><a href="{@docRoot}guide/topics/manifest/activity-element.html#reparent">allowTaskReparenting</a></code>
attribute) and the task that will house the activity when it is launched
with the <code>{@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK}</code>
flag.
</p>
<p>
By default, all activities in an application have the same affinity. You
can set this attribute to group them differently, and even place
activities defined in different applications within the same task. To
specify that the activity does not have an affinity for any task, set
it to an empty string.
<p>
If this attribute is not set, the activity inherits the affinity set
for the application (see the
<code><a href="{@docRoot}guide/topics/manifest/application-element.html">&lt;application&gt;</a></code>
element's
<code><a href="{@docRoot}guide/topics/manifest/application-element.html#aff">taskAffinity</a></code>
attribute). The name of the default affinity for an application is
the package name set by the
<code><a href="{@docRoot}guide/topics/manifest/manifest-element.html">&lt;manifest&gt;</a></code>
element.
</p>
<dt><a name="theme"></a>{@code android:theme}</dt>
<dd>A reference to a style resource defining an overall theme for the activity.
This automatically sets the activity's context to use this theme (see
<code>{@link android.content.Context#setTheme setTheme()}</code>, and may also
cause "starting" animations prior to the activity being launched (to better
match what the activity actually looks like).
<p>
If this attribute is not set, the activity inherits the theme set for the
application as a whole &mdash; see the
<code><a href="{@docRoot}guide/topics/manifest/application-element.html">&lt;application&gt;</a></code>
element's
<code><a href="{@docRoot}guide/topics/manifest/application-element.html#theme">theme</a></code>
attribute. If that attribute is also not set, the default system theme is used.
</p>
<dd>
<!-- ##api level 3## -->
<dt><a name="wsoft"></a>{@code android:windowSoftInputMode}</dt>
<dd>How the main window of the activity interacts with the window containing
the on-screen soft keyboard. The setting for this attribute affects two
things:
<ul>
<li>The state of the soft keyboard &mdash; whether it is hidden or visible
&mdash; when the activity becomes the focus of user attention.</li>
<li>The adjustment made to the activity's main window &mdash; whether it is
resized smaller to make room for the soft keyboard or whether its contents
pan to make the current focus visible when part of the window is covered by
the soft keyboard.</li>
</ul>
<p>
The setting must be one of the values listed in the following table, or a
combination of one "{@code state...}" value plus one "{@code adjust...}"
value. Setting multiple values in either group &mdash; multiple
"{@code state...}" values, for example &mdash has undefined results.
Individual values are separated by a vertical bar ({@code |}). For example:
</p>
<pre>&lt;activity android:windowSoftInputMode="stateVisible|adjustResize" . . . &gt;</pre>
<p>
Values set here (other than "{@code stateUnspecified}" and
"{@code adjustUnspecified}") override values set in the theme.
</p>
<table>
<tr>
<th>Value</th>
<th>Description</th>
</tr><tr>
<td>"{@code stateUnspecified}"</td>
<td>The state of the soft keyboard (whether it is hidden or visible)
is not specified. The system will choose an appropriate state or
rely on the setting in the theme.
<p>
This is the default setting for the behavior of the soft keyboard.
</p></td>
</tr></tr>
<td>"{@code stateUnchanged}"</td>
<td>The soft keyboard is kept in whatever state it was last in,
whether visible or hidden, when the activity comes to the fore.</td>
</tr></tr>
<td>"{@code stateHidden}"</td>
<td>The soft keyboard is hidden when the user chooses the activity
&mdash; that is, when the user affirmatively navigates forward to the
activity, rather than backs into it because of leaving another activity.</td>
</tr></tr>
<td>"{@code stateAlwaysHidden}"</td>
<td>The soft keyboard is always hidden when the activity's main window
has input focus.</td>
</tr></tr>
<td>"{@code stateVisible}"</td>
<td>The soft keyboard is visible when that's normally appropriate
(when the user is navigating forward to the activity's main window).</td>
</tr></tr>
<td>"{@code stateAlwaysVisible}"</td>
<td>The soft keyboard is made visible when the user chooses the
activity &mdash; that is, when the user affirmatively navigates forward
to the activity, rather than backs into it because of leaving another
activity.</td>
</tr></tr>
<td>"{@code adjustUnspecified}"</td>
<td>It is unspecified whether the activity's main window resizes
to make room for the soft keyboard, or whether the contents
of the window pan to make the currentfocus visible on-screen.
The system will automatically select one of these modes depending
on whether the content of the window has any layout views that
can scroll their contents. If there is such a view, the window
will be resized, on the assumption that scrolling can make all
of the window's contents visible within a smaller area.
<p>
This is the default setting for the behavior of the main window.
</p></td>
</tr></tr>
<td>"{@code adjustResize}"</td>
<td>The activity's main window is always resized to make room for
the soft keyboard on screen.</td>
</tr></tr>
<td>"{@code adjustPan}"</td>
<td>The activity's main window is not resized to make room for the soft
keyboard. Rather, the contents of the window are automatically
panned so that the current focus is never obscured by the keyboard
and users can always see what they are typing. This is generally less
desirable than resizing, because the user may need to close the soft
keyboard to get at and interact with obscured parts of the window.</td>
</tr>
</table>
<p>
This attribute was introduced in API Level 3.
</p></dd>
</dl></dd>
<!-- ##api level indication## -->
<dt>introduced in:</dt>
<dd>API Level 1 for all attributes except for
<code><a href="#nohist">noHistory</a></code> and
<code><a href="#wsoft">windowSoftInputMode</a></code>, which were added in API
Level 3.</dd>
<dt>see also:</dt>
<dd><code><a href="{@docRoot}guide/topics/manifest/application-element.html">&lt;application&gt;</a></code>
<br/><code><a href="{@docRoot}guide/topics/manifest/activity-alias-element.html">&lt;activity-alias&gt;</a></code></dd>
</dl>
@@ -0,0 +1,265 @@
page.title=&lt;application&gt;
@jd:body
<dl class="xml">
<dt>syntax:</dt>
<dd><pre class="stx">&lt;application android:<a href="#reparent">allowTaskReparenting</a>=["true" | "false"]
android:<a href="#agent">backupAgent</a>="<i>string</i>"
android:<a href="#debug">debuggable</a>=["true" | "false"]
android:<a href="#desc">description</a>="<i>string resource</i>"
android:<a href="#enabled">enabled</a>=["true" | "false"]
android:<a href="#code">hasCode</a>=["true" | "false"]
android:<a href="#icon">icon</a>="<i>drawable resource</i>"
android:<a href="#killrst">killAfterRestore</a>=["true" | "false"]
android:<a href="#label">label</a>="<i>string resource</i>"
android:<a href="#space">manageSpaceActivity</a>="<i>string</i>"
android:<a href="#nm">name</a>="<i>string</i>"
android:<a href="#prmsn">permission</a>="<i>string</i>"
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="#aff">taskAffinity</a>="<i>string</i>"
android:<a href="#theme">theme</a>="<i>resource or theme</i>" &gt;
. . .
&lt;/application&gt;</pre></dd>
<dt>contained in:</dt>
<dd><code><a href="{@docRoot}guide/topics/manifest/manifest-element.html">&lt;manifest&gt;</a></code></dd>
<dt>can contain:</dt>
<dd><code><a href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;activity&gt;</a></code>
<br/><code><a href="{@docRoot}guide/topics/manifest/activity-alias-element.html">&lt;activity-alias&gt;</a></code>
<br/><code><a href="{@docRoot}guide/topics/manifest/service-element.html">&lt;service&gt;</a></code>
<br/><code><a href="{@docRoot}guide/topics/manifest/receiver-element.html">&lt;receiver&gt;</a></code>
<br/><code><a href="{@docRoot}guide/topics/manifest/provider-element.html">&lt;provider&gt;</a></code>
<br/><code><a href="{@docRoot}guide/topics/manifest/uses-library-element.html">&lt;uses-library&gt;</a></code></dd>
<dt>description:</dt>
<dd>The declaration of the application. This element contains subelements
that declare each of the application's components and has attributes
that can affect all the components. Many of these attributes (such as
{@code icon}, {@code label}, {@code permission}, {@code process},
{@code taskAffinity}, and {@code allowTaskReparenting}) set default values
for corresponding attributes of the component elements. Others (such as
{@code debuggable}, {@code enabled}, {@code description}, and
{@code allowClearUserData}) set values for the application as a whole and
cannot be overridden by the components.</dd>
<dt>attributes</dt>
<dd><dl class="attr">
<dt><a name="reparent"></a>{@code android:allowTaskReparenting}</dt>
<dd>Whether or not activities that the application defines can move from
the task that started them to the task they have an affinity for when that task
is next brought to the front &mdash; "{@code true}" if they can move, and
"{@code false}" if they must remain with the task where they started.
The default value is "{@code false}".
<p>
The
<code><a href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;activity&gt;</a></code>
element has its own
<code><a href="{@docRoot}guide/topics/manifest/activity-element.html#reparent">allowTaskReparenting</a></code>
attribute that can override the value set here. See that attribute for more
information.
</p></dd>
<dt><a name="agent"></a>{@code android:backupAgent}</dt>
<dd>The name of the class that implement's the application's backup agent,
a subclass of {@link android.app.backup.BackupAgent}. The attribute value should be
a fully qualified class name (such as, "{@code com.example.project.MyBackupAgent}").
However, as a shorthand, if the first character of the name is a period
(for example, "{@code .MyBackupAgent}"), it is appended to the
package name specified in the
<code><a href="{@docRoot}guide/topics/manifest/manifest-element.html">&lt;manifest&gt;</a></code>
element.
<p>
There is no default. The name must be specified.
</p></dd>
<dt><a name="debug"></a>{@code android:debuggable}</dt>
<dd>Whether or not the application can be debugged, even when running
on a device in user mode &mdash; "{@code true}" if it can be, and "{@code false}"
if not. The default value is "{@code false}".</dd>
<dt><a name="desc"></a>{@code android:description}</dt>
<dd>User-readable text about the application, longer and more descriptive than the application label. The value must be set as a reference to a string resource. Unlike the label, it cannot be a raw string. There is no default value.</dd>
<dt><a name="enabled"></a>{@code android:enabled}</dt>
<dd>Whether or not the Android system can instantiate components of
the application &mdash; "{@code true}" if it can, and "{@code false}"
if not. If the value is "{@code true}", each component's
{@code enabled} attribute determines whether that component is enabled
or not. If the value is "{@code false}", it overrides the
component-specific values; all components are disabled.
<p>
The default value is "{@code true}".
</p></dd>
<dt><a name="code"></a>{@code android:hasCode}</dt>
<dd>Whether or not the application contains any code &mdash; "{@code true}"
if it does, and "{@code false}" if not. When the value is "{@code false}",
the system does not try to load any application code when launching components.
The default value is "{@code true}".
<p>
An application would not have any code of its own only if it's using nothing
but built-in component classes, such as an activity that uses the {@link
android.app.AliasActivity} class, a rare occurrence.
<dt><a name="icon"></a>{@code android:icon}</dt>
<dd>An icon for the application as whole, and the default icon for
each of the application's components. See the individual
{@code icon} attributes for
<code><a href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;activity&gt;</a></code>,
<code><a href="{@docRoot}guide/topics/manifest/activity-alias-element.html">&lt;activity-alias&gt;</a></code>,
<code><a href="{@docRoot}guide/topics/manifest/service-element.html">&lt;service&gt;</a></code>,
<code><a href="{@docRoot}guide/topics/manifest/receiver-element.html">&lt;receiver&gt;</a></code>, and
<code><a href="{@docRoot}guide/topics/manifest/provider-element.html">&lt;provider&gt;</a></code> elements.
<p>
This attribute must be set as a reference to a drawable resource containing
the image definition. There is no default icon.
</p></dd>
<dt><a name="killrst"></a>{@code android:killAfterRestore}</dt>
<dd>Whether the application in question should be terminated after its
settings have been restored during a full-system restore operation.
Single-package restore operations will never cause the application to
be shut down. Full-system restore operations typically only occur once,
when the phone is first set up. Third-party applications will not normally
need to use this attribute.
<p>The default is {@code true}, which means that after the application
has finished processing its data during a full-system restore, it will be
terminated.
</p></dd>
<dt><a name="label"></a>{@code android:label}</dt>
<dd>A user-readable label for the application as a whole, and a default
label for each of the application's components. See the individual
{@code label} attributes for
<code><a href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;activity&gt;</a></code>,
<code><a href="{@docRoot}guide/topics/manifest/activity-alias-element.html">&lt;activity-alias&gt;</a></code>,
<code><a href="{@docRoot}guide/topics/manifest/service-element.html">&lt;service&gt;</a></code>,
<code><a href="{@docRoot}guide/topics/manifest/receiver-element.html">&lt;receiver&gt;</a></code>, and
<code><a href="{@docRoot}guide/topics/manifest/provider-element.html">&lt;provider&gt;</a></code> elements.
<p>
The label should be set as a reference to a string resource, so that
it can be localized like other strings in the user interface.
However, as a convenience while you're developing the application,
it can also be set as a raw string.
</p></dd>
<dt><a name="space"></a>{@code android:manageSpaceActivity}</dt>
<dd>The fully qualified name of an Activity subclass that the system
can launch to let users manage the memory occupied by the application
on the device. The activity should also be declared with an
<code><a href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;activity&gt;</a></code> element.
</dd>
<dt><a name="nm"></a>{@code android:name}</dt>
<dd>The fully qualified name of an {@link android.app.Application}
subclass implemented for the application. When the application process
is started, this class is instantiated before any of the application's
components.
<p>
The subclass is optional; most applications won't need one.
In the absence of a subclass, Android uses an instance of the base
Application class.
</p></dd>
<dt><a name="prmsn"></a>{@code android:permission}</dt>
<dd>The name of a permission that clients must have in order to interact
with the application. This attribute is a convenient way to set a
permission that applies to all of the application's components. It can
be overwritten by setting the {@code permission} attributes of individual
components.
<p>
For more information on permissions, see the
<a href="{@docRoot}guide/topics/manifest/manifest-intro.html#sectperm">Permissions</a>
section in the introduction and another document,
<a href="{@docRoot}guide/topics/security/security.html">Security and
Permissions</a>.
</p></dd>
<dt><a name="persistent"></a>{@code android:persistent}</dt>
<dd>Whether or not the application should remain running at all times &mdash;
"{@code true}" if it should, and "{@code false}" if not. The default value
is "{@code false}". Applications should not normally set this flag;
persistence mode is intended only for certain system applications.</dd>
<dt><a name="proc"></a>{@code android:process}</dt>
<dd>The name of a process where all components of the application should run.
Each component can override this default by setting its own {@code process}
attribute.
<p>
By default, Android creates a process for an application when the first
of its components needs to run. All components then run in that process.
The name of the default process matches the package name set by the
<code><a href="{@docRoot}guide/topics/manifest/manifest-element.html">&lt;manifest&gt;</a></code> element.
</p>
<p>By setting this attribute to a process name that's shared with another
application, you can arrange for components of both applications to run in
the same process &mdash; but only if the two applications also share a
user ID and be signed with the same certificate.
</p>
<p>
If the name assigned to this attribute begins with a colon (':'), a new
process, private to the application, is created when it's needed.
If the process name begins with a lowercase character, a global process
of that name is created. A global process can be shared with other
applications, reducing resource usage.
</p></dd>
<dt><a href name="restoreany"></a>{@code android:restoreAnyVersion}</dt>
<dd>Indicate 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
attempt restore even when a version mismatch suggests that the data are
incompatible. <em>Use with caution!</em>
<p>The default value of this attribute is {@code false}.
</p></dd>
<dt><a href 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
<code><a href="{@docRoot}guide/topics/manifest/activity-element.html#aff">taskAffinity</a></code>
attributes. See that attribute for more information.
<p>
By default, all activities within an application share the same
affinity. The name of that affinity is the same as the package name
set by the
<code><a href="{@docRoot}guide/topics/manifest/manifest-element.html">&lt;manifest&gt;</a></code> element.
</p></dd>
<dt><a name="theme"></a>{@code android:theme}</dt>
<dd>A reference to a style resource defining a default theme for all
activities in the application. Individual activities can override
the default by setting their own <code><a href="{@docRoot}guide/topics/manifest/activity-element.html#theme">theme</a></code>
attributes; see that attribute for more information.</dd>
</dl></dd>
<!-- ##api level indication## -->
<dt>introduced in:</dt>
<dd>API Level 1</dd>
<dt>see also:</dt>
<dd><code><a href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;activity&gt;</a></code>
<br/><code><a href="{@docRoot}guide/topics/manifest/service-element.html">&lt;service&gt;</a></code>
<br/><code><a href="{@docRoot}guide/topics/manifest/receiver-element.html">&lt;receiver&gt;</a></code>
<br/><code><a href="{@docRoot}guide/topics/manifest/provider-element.html">&lt;provider&gt;</a></code></dd>
</dl>
@@ -0,0 +1,42 @@
page.title=&lt;category&gt;
@jd:body
<dl class="xml">
<dt>syntax:</dt>
<dd><pre class="stx">&lt;category android:<a href="#nm">name</a>="<i>string</i>" /&gt;</pre></dd>
<dt>contained in:</dt>
<dd><code><a href="{@docRoot}guide/topics/manifest/intent-filter-element.html">&lt;intent-filter&gt;</a></code></dd>
<dt>description:</dt>
<dd>Adds a category name to an intent filter. See
<a href="{@docRoot}guide/topics/intents/intents-filters.html">Intents and
Intent Filters</a> for details on intent filters and the role of category
specifications within a filter.</dd>
<dt>attributes:</dt>
<dd><dl class="attr">
<dt><a name="nm"></a>{@code android:name}</dt>
<dd>The name of the category. Standard categories are defined in the
{@link android.content.Intent} class as {@code CATEGORY_<i>name</i>}
constants. The name assigned here can be derived from those constants
by prefixing "{@code android.intent.category.}" to the
{@code <i>name</i>} that follows {@code CATEGORY_}. For example,
the string value for {@code CATEGORY_LAUNCHER} is
"{@code android.intent.category.LAUNCHER}".
<p>
Custom categories should use the package name as a prefix, to ensure
that they are unique.
</p></dd>
</dl></dd>
<!-- ##api level indication## -->
<dt>introduced in:</dt>
<dd>API Level 1</dd>
<dt>see also:</dt>
<dd><code><a href="{@docRoot}guide/topics/manifest/action-element.html">&lt;action&gt;</a></code>
<br/><code><a href="{@docRoot}guide/topics/manifest/data-element.html">&lt;data&gt;</a></code></dd>
</dl>
@@ -0,0 +1,166 @@
page.title=&lt;data&gt;
@jd:body
<dl class="xml">
<dt>syntax:</dt>
<dd><pre class="stx">&lt;data android:<a href="#host">host</a>="<i>string</i>"
android:<a href="#mime">mimeType</a>="<i>string</i>"
android:<a href="#path">path</a>="<i>string</i>"
android:<a href="#path">pathPattern</a>="<i>string</i>"
android:<a href="#path">pathPrefix</a>="<i>string</i>"
android:<a href="#port">port</a>="<i>string</i>"
android:<a href="#scheme">scheme</a>="<i>string</i>" /&gt;</pre></dd>
<dt>contained in:</dt>
<dd><code><a href="{@docRoot}guide/topics/manifest/intent-filter-element.html">&lt;intent-filter&gt;</a></code></dd>
<dt>description:</dt>
<dd>Adds a data specification to an intent filter. The specification can
be just a data type (the <code><a href="{@docRoot}guide/topics/manifest/data-element.html#mime">mimeType</a></code> attribute),
just a URI, or both a data type and a URI. A URI is specified by separate
attributes for each of its parts:
<p style="margin-left: 2em">{@code scheme://host:port/path} <i>or</i>
{@code pathPrefix} <i>or</i> {@code pathPattern}</p>
<p>
These attributes are optional, but also mutually dependent:
If a <code><a href="{@docRoot}guide/topics/manifest/data-element.html#scheme">scheme</a></code> is not specified for the
intent filter, all the other URI attributes are ignored. If a
<code><a href="{@docRoot}guide/topics/manifest/data-element.html#host">host</a></code> is not specified for the filter,
the {@code port} attribute and all the path attributes are ignored.
</p>
<p>
All the {@code &lt;data&gt;} elements contained within the same
<code><a href="{@docRoot}guide/topics/manifest/intent-filter-element.html">&lt;intent-filter&gt;</a></code> element contribute to
the same filter. So, for example, the following filter specification,
</p>
<pre>&lt;intent-filter . . . &gt;
&lt;data android:scheme="something" android:host="project.example.com" /&gt;
. . .
&lt;/intent-filter&gt;</pre>
<p>is equivalent to this one:</p>
<pre>&lt;intent-filter . . . &gt;
&lt;data android:scheme="something" /&gt
&lt;data android:host="project.example.com" /&gt;
. . .
&lt;/intent-filter&gt;</pre>
<p>
You can place any number of &lt;data&gt; elements inside an
<code><a href="{@docRoot}guide/topics/manifest/intent-filter-element.html">&lt;intent-filter&gt;</a></code> to give it multiple data
options. None of its attributes have default values.
</p>
<p>
Information on how intent filters work, including the rules for how Intent objects
are matched against filters, can be found in another document,
<a href="{@docRoot}guide/topics/intents/intents-filters.html">Intents and
Intent Filters</a>. See also the
<a href="{@docRoot}guide/topics/manifest/manifest-intro.html#ifs">Intent Filters</a>
section in the introduction.
</p></dd>
<dt>attributes:</dt>
<dd><dl class="attr">
<dt><a name="host"></a>{@code android:host}</dt>
<dd>The host part of a URI authority. This attribute is meaningless
unless a <code><a href="{@docRoot}guide/topics/manifest/data-element.html#scheme">scheme</a></code> attribute is also
specified for the filter.
<p class="note">Note: host name matching in the Android framework is
case-sensitive, unlike the formal RFC. As a result, you should always specify
host names using lowercase letters.</p>
</dd>
<dt><a name="mime"></a>{@code android:mimeType}</dt>
<dd>A MIME media type, such as {@code image/jpeg} or {@code audio/mpeg4-generic}.
The subtype can be the asterisk wildcard ({@code *}) to indicate that any
subtype matches.
<p class="note">Note: MIME type matching in the Android framework is
case-sensitive, unlike formal RFC MIME types. As a result, you should always
specify MIME types using lowercase letters.</p>
</dd>
<dt><a name="path"></a>{@code android:path}
<br/>{@code android:pathPrefix}
<br/>{@code android:pathPattern}</dt>
<dd>The path part of a URI. The {@code path} attribute specifies a complete
path that is matched against the complete path in an Intent object. The
{@code pathPrefix} attribute specifies a partial path that is matched against
only the initial part of the path in the Intent object. The {@code pathPattern}
attribute specifies a complete path that is matched against the complete path
in the Intent object, but it can contain the following wildcards:
<ul>
<li>An asterisk ('{@code *}') matches a sequence of 0 to many occurrences of
the immediately preceding character.</li>
<li>A period followed by an asterisk ("{@code .*}") matches any sequence of
0 to many characters.</li>
</ul>
<p>
Because '{@code \}' is used as an escape character when the string is read
from XML (before it is parsed as a pattern), you will need to double-escape:
For example, a literal '{@code *}' would be written as "{@code \\*}" and a
literal '{@code \}' would be written as "{@code \\\\}". This is basically
the same as what you would need to write if constructing the string in Java code.
</p>
<p>
For more information on these three types of patterns, see the descriptions of
{@link android.os.PatternMatcher#PATTERN_LITERAL},
{@link android.os.PatternMatcher#PATTERN_PREFIX}, and
{@link android.os.PatternMatcher#PATTERN_SIMPLE_GLOB} in the
{@link android.os.PatternMatcher} class.
</p>
<p>These attributes are meaningful only if the
<code><a href="#scheme">scheme</a></code> and <code><a href="#host">host</a></code>
attributes are also specified for the filter.
</p></dd>
<dt><a name="port"></a>{@code android:port}</dt>
<dd>The port part of a URI authority. This attribute is meaningful only
if the <code><a href="#scheme">scheme</a></code> and
<code><a href="#host">host</a></code> attributes are also specified for
the filter.</dd>
<dt><a name="scheme"></a>{@code android:scheme}</dt>
<dd>The scheme part of a URI. This is the minimal essential attribute for
specifying a URI; at least one {@code scheme} attribute must be set
for the filter, or none of the other URI attributes are meaningful.
<p>
A scheme is specified without the trailing colon (for example,
{@code http}, rather than {@code http:}).
</p>
<p>
If the filter has a data type set (the <code><a href="{@docRoot}guide/topics/manifest/data-element.html#mime">mimeType</a></code>
attribute) but no scheme, the {@code content:} and {@code file:} schemes are
assumed.
</p>
<p class="note">Note: scheme matching in the Android framework is
case-sensitive, unlike the RFC. As a result, you should always specify schemes
using lowercase letters.</p>
</dd>
</dl></dd>
<!-- ##api level indication## -->
<dt>introduced in:</dt>
<dd>API Level 1</dd>
<dt>see also:</dt>
<dd><code><a href="{@docRoot}guide/topics/manifest/action-element.html">&lt;action&gt;</a></code>
<br/><code><a href="{@docRoot}guide/topics/manifest/category-element.html">&lt;category&gt;</a></code></dd>
</dl>
@@ -0,0 +1,89 @@
page.title=&lt;grant-uri-permission&gt;
@jd:body
<dl class="xml">
<dt>syntax:</dt>
<dd><pre class="stx">&lt;grant-uri-permission android:<a href="#path">path</a>="<i>string</i>"
android:<a href="#path">pathPattern</a>="<i>string</i>"
android:<a href="#path">pathPrefix</a>="<i>string</i>" /&gt;</pre></dd>
<dt>contained in:</dt>
<dd><code><a href="{@docRoot}guide/topics/manifest/provider-element.html">&lt;provider&gt;</a></code></dd>
<dt>description:</dt>
<dd>Specifies which data subsets of the parent content provider permission
can be granted for. Data subsets are indicated by the path part of a
{@code content:} URI. (The authority part of the URI identifies the
content provider.)
Granting permission is a way of enabling clients of the provider that don't
normally have permission to access its data to overcome that restriction on
a one-time basis.
<p>
If a content provider's <code><a href="{@docRoot}guide/topics/manifest/provider-element.html#gprmns">grantUriPermissions</a></code>
attribute is "{@code true}", permission can be granted for any the data under
the provider's purview. However, if that attribute is "{@code false}", permission
can be granted only to data subsets that are specified by this element.
A provider can contain any number of {@code &lt;grant-uri-permission&gt;} elements.
Each one can specify only one path (only one of the three possible attributes).
</p>
<p>
For information on how permission is granted, see the
<code><a href="{@docRoot}guide/topics/manifest/intent-filter-element.html">&lt;intent-filter&gt;</a></code> element's
<code><a href="{@docRoot}guide/topics/manifest/provider-element.html#gprmsn">grantUriPermissions</a></code> attribute.
</p></dd>
<dt>attributes:</dt>
<dd><dl class="attr">
<dt><a name="path"></a>{@code android:path}
<br/>{@code android:pathPrefix}
<br/>{@code android:pathPattern}</dt>
<dd>A path identifying the data subset or subsets that permission can be
granted for. The {@code path} attribute specifies a complete path;
permission can be granted only to the particular data subset identified
by that path.
The {@code pathPrefix} attribute specifies the initial part of a path;
permission can be granted to all data subsets with paths that share that
initial part.
The {@code pathPattern} attribute specifies a complete path, but one
that can contain the following wildcards:
<ul>
<li>An asterisk ('{@code *}') matches a sequence of 0 to many occurrences of
the immediately preceding character.</li>
<li><p>A period followed by an asterisk ("{@code .*}") matches any sequence of
0 to many characters.</p></li>
</ul>
<p>
Because '{@code \}' is used as an escape character when the string is read
from XML (before it is parsed as a pattern), you will need to double-escape:
For example, a literal '{@code *}' would be written as "{@code \\*}" and a
literal '{@code \}' would be written as "{@code \\\\}". This is basically
the same as what you would need to write if constructing the string in Java code.
</p>
<p>
For more information on these types of patterns, see the descriptions of
{@link android.os.PatternMatcher#PATTERN_LITERAL},
{@link android.os.PatternMatcher#PATTERN_PREFIX}, and
{@link android.os.PatternMatcher#PATTERN_SIMPLE_GLOB} in the
{@link android.os.PatternMatcher} class.
</p></dd>
</dl></dd>
<!-- ##api level indication## -->
<dt>introduced in:</dt>
<dd>API Level 1</dd>
<dt>see also:</dt>
<dd>the
<code><a href="{@docRoot}guide/topics/manifest/provider-element.html#gprmns">grantUriPermissions</a></code>
attribute of the
<code><a href="{@docRoot}guide/topics/manifest/provider-element.html">&lt;provider&gt;</a></code>
element</dd>
</dl>
@@ -0,0 +1,65 @@
page.title=&lt;instrumentation&gt;
@jd:body
<dl class="xml">
<dt>syntax:</dt>
<dd><pre class="stx">&lt;instrumentation android:<a href="#ftest">functionalTest</a>=["true" | "false"]
android:<a href="#hprof">handleProfiling</a>=["true" | "false"]
android:<a href="#icon">icon</a>="<i>drawable resource</i>"
android:<a href="#label">label</a>="<i>string resource</i>"
android:<a href="#nm">name</a>="<i>string</i>"
android:<a href="#trgt">targetPackage</a>="<i>string</i>" /&gt;</pre></dd>
<dt>contained in:</dt>
<dd><code><a href="{@docRoot}guide/topics/manifest/manifest-element.html">&lt;manifest&gt;</a></code></dd>
<dt>description:</dt>
<dd>Declares an {@link android.app.Instrumentation} class that enables you
to monitor an application's interaction with the system. The Instrumentation
object is instantiated before any of the application's components.</dd>
<dt>attributes:</dt>
<dd><dl class="attr">
<dt><a name="ftest"></a>{@code android:functionalTest}</dt>
<dd>Whether or not the Instrumentation class should run as a functional test
&mdash; "{@code true}" if it should, and "{@code false}" if not. The
default value is "{@code false}".</dd>
<dt><a name="hprof"></a>{@code android:handleProfiling}</dt>
<dd>Whether or not the Instrumentation object will turn profiling on and
off &mdash; "{@code true}" if it determines when profiling starts and
stops, and "{@code false}" if profiling continues the entire time it is
running. A value of "{@code true}" enables the object to target profiling
at a specific set of operations. The default value is "{@code false}".</dd>
<dt><a name="icon"></a>{@code android:icon}</dt>
<dd>An icon that represents the Instrumentation class. This attribute must
be set as a reference to a drawable resource.</dd>
<dt><a name="label"></a>{@code android:label}</dt>
<dd>A user-readable label for the Instrumentation class. The label can
be set as a raw string or a reference to a string resource.</dd>
<dt><a name="nm"></a>{@code android:name}</dt>
<dd>The name of the {@link android.app.Instrumentation} subclass.
This should be a fully qualified class name (such as,
"{@code com.example.project.StringInstrumentation}"). However, as a shorthand,
if the first character of the name is a period, it is appended to the package
name specified in the <code><a href="{@docRoot}guide/topics/manifest/manifest-element.html">&lt;manifest&gt;</a></code> element.
<p>
There is no default. The name must be specified.
</p></dd>
<dt><a name="trgt"></a>{@code android:targetPackage}</dt>
<dd>The application that the Instrumentation object will run against.
An application is identified by the package name assigned in its manifest
file by the <code><a href="{@docRoot}guide/topics/manifest/manifest-element.html">&lt;manifest&gt;</a></code> element.</dd>
</dl></dd>
<!-- ##api level indication## -->
<dt>introduced in:</dt>
<dd>API Level 1</dd>
</dl>
@@ -0,0 +1,134 @@
page.title=&lt;intent-filter&gt;
@jd:body
<dl class="xml">
<dt>syntax:</dt>
<dd><pre class="stx">&lt;intent-filter android:<a href="#icon">icon</a>="<i>drawable resource</i>"
android:<a href="#label">label</a>="<i>string resource</i>"
android:<a href="#priority">priority</a>="<i>integer</i>" &gt;
. . .
&lt;/intent-filter&gt;</pre></dd>
<dt>contained in:</dt>
<dd><code><a href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;activity&gt;</a></code>
<br/><code><a href="{@docRoot}guide/topics/manifest/activity-alias-element.html">&lt;activity-alias&gt;</a></code>
<br/><code><a href="{@docRoot}guide/topics/manifest/service-element.html">&lt;service&gt;</a></code>
<br/><code><a href="{@docRoot}guide/topics/manifest/receiver-element.html">&lt;receiver&gt;</a></code></dd>
<dt>must contain:</dt>
<dd><code><a href="{@docRoot}guide/topics/manifest/action-element.html">&lt;action&gt;</a></code></dd>
<dt>can contain:</dt>
<dd><code><a href="{@docRoot}guide/topics/manifest/category-element.html">&lt;category&gt;</a></code>
<br/><code><a href="{@docRoot}guide/topics/manifest/data-element.html">&lt;data&gt;</a></code></dd>
<dt>description:</dt>
<dd>Specifies the types of intents that an activity, service, or broadcast
receiver can respond to. An intent filter declares the capabilities of its
parent component &mdash; what an activity or service can do and what types
of broadcasts a receiver can handle. It opens the component to receiving
intents of the advertised type, while filtering out those that are not
meaningful for the component.
<p>
Most of the contents of the filter are described by its
<code><a href="{@docRoot}guide/topics/manifest/action-element.html">&lt;action&gt;</a></code>,
<code><a href="{@docRoot}guide/topics/manifest/category-element.html">&lt;category&gt;</a></code>, and
<code><a href="{@docRoot}guide/topics/manifest/data-element.html">&lt;data&gt;</a></code> subelements.
</p>
<p>
For a more detailed discussion of filters, see the separate
<a href="{@docRoot}guide/topics/intents/intents-filters.html">Intents
and Intent Filters</a> document, as well as the
<a href="{@docRoot}guide/topics/manifest/manifest-intro.html#ifs">Intents Filters</a>
section in the introduction.
</p></dd>
<dt>attributes:</dt>
<dd><dl class="attr">
<dt><a name="icon"></a>{@code android:icon}</dt>
<dd>An icon that represents the parent activity, service, or broadcast
receiver when that component is presented to the user as having the
capability described by the filter.
<p>
This attribute must be set as a reference to a drawable resource
containing the image definition. The default value is the icon set
by the parent component's {@code icon} attribute. If the parent
does not specify an icon, the default is the icon set by the
<code><a href="{@docRoot}guide/topics/manifest/application-element.html">&lt;application&gt;</a></code> element.
</p>
<p>
For more on intent filter icons, see
<a href="{@docRoot}guide/topics/manifest/manifest-intro.html#iconlabel">Icons and Labels</a>
in the introduction.
</p></dd>
<dt><a name="label"></a>{@code android:label}</dt>
<dd>A user-readable label for the parent component. This label, rather than
the one set by the parent component, is used when the component is presented
to the user as having the capability described by the filter.
<p>
The label should be set as a reference to a string resource, so that
it can be localized like other strings in the user interface.
However, as a convenience while you're developing the application,
it can also be set as a raw string.
</p>
<p>
The default value is the label set by the parent component. If the
parent does not specify a label, the default is the label set by the
<code><a href="{@docRoot}guide/topics/manifest/application-element.html">&lt;application&gt;</a></code> element's
<code><a href="{@docRoot}guide/topics/manifest/application-element.html#label"> label</a></code> attribute.
</p>
<p>
For more on intent filter labels, see
<a href="{@docRoot}guide/topics/manifest/manifest-intro.html#iconlabel">Icons and Labels</a>
in the introduction.
</p></dd>
<dt><a name="priority"></a>{@code android:priority}</dt>
<dd>The priority that should be given to the parent component with regard
to handling intents of the type described by the filter. This attribute has
meaning for both activities and broadcast receivers:
<ul>
<li>It provides information about how able an activity is to respond to
an intent that matches the filter, relative to other activities that could
also respond to the intent. When an intent could be handled by multiple
activities with different priorities, Android will consider only those with
higher priority values as potential targets for the intent.</li>
<li><p>It controls the order in which broadcast receivers are executed to
receive broadcast messages. Those with higher priority
values are called before those with lower values. (The order applies only
to synchronous messages; it's ignored for asynchronous messages.)</p></li>
</ul>
<p>
Use this attribute only if you really need to impose a specific order in
which the broadcasts are received, or want to force Android to prefer
one activity over others.
</p>
<p>
The value must be an integer, such as "{@code 100}". Higher numbers have a
higher priority.
</p></dd>
</dl></dd>
<!-- ##api level indication## -->
<dt>introduced in:</dt>
<dd>API Level 1</dd>
<dt>see also:</dt>
<dd><code><a href="{@docRoot}guide/topics/manifest/action-element.html">&lt;action&gt;</a></code>
<br/><code><a href="{@docRoot}guide/topics/manifest/category-element.html">&lt;category&gt;</a></code>
<br/><code><a href="{@docRoot}guide/topics/manifest/data-element.html">&lt;data&gt;</a></code></dd>
</dl>
@@ -0,0 +1,182 @@
page.title=&lt;manifest&gt;
@jd:body
<dl class="xml">
<dt>syntax:</dt>
<dd><pre class="stx">&lt;manifest xmlns:<a href="#nspace">android</a>="http://schemas.android.com/apk/res/android"
<a href="#package">package</a>="<i>string</i>"
android:<a href="#uid">sharedUserId</a>="<i>string</i>"
android:<a href="#uidlabel">sharedUserLabel</a>="<i>string resource</i>" <!-- ##api level 3## -->
android:<a href="#vcode">versionCode</a>="<i>integer</i>"
android:<a href="#vname">versionName</a>="<i>string</i>"
android:<a href="#install">installLocation</a>=["auto" | "internalOnly" | "preferExternal"] &gt;
. . .
&lt;/manifest&gt;</pre></dd>
<p>
<dt>contained in:</dt>
<dd><i>none</i></dd>
<p>
<p>
<dt>must contain:</dt>
<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/instrumentation-element.html">&lt;instrumentation&gt;</a></code>
<br/><code><a href="{@docRoot}guide/topics/manifest/permission-element.html">&lt;permission&gt;</a></code>
<br/><code><a href="{@docRoot}guide/topics/manifest/permission-group-element.html">&lt;permission-group&gt;</a></code>
<br/><code><a href="{@docRoot}guide/topics/manifest/permission-tree-element.html">&lt;permission-tree&gt;</a></code>
<br/><code><a href="{@docRoot}guide/topics/manifest/uses-configuration-element.html">&lt;uses-configuration&gt;</a></code> <!-- ##api level 3## -->
<br/><code><a href="{@docRoot}guide/topics/manifest/uses-permission-element.html">&lt;uses-permission&gt;</a></code></dd>
<br/><code><a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html">&lt;uses-sdk&gt;</a></code></dd>
<p>
<dt>description:</dt>
<dd>The root element of the AndroidManifest.xml file. It must
contain an <code><a href="{@docRoot}guide/topics/manifest/application-element.html">&lt;application&gt;</a></code> element
and specify {@code xlmns:android} and {@code package} attributes.</dd>
<dt>attributes:</dt>
<dd>
<dl class="attr">
<dt><a name="nspace"></a>{@code xmlns:android}</dt>
<dd>Defines the Android namespace. This attribute should always be set
to "{@code http://schemas.android.com/apk/res/android}".</dd>
<dt><a name="package"></a>{@code package}</dt>
<dd>A full Java package name for the application. The name should
be unique. The name may contain uppercase or lowercase letters ('A'
through 'Z'), numbers, and underscores ('_'). However, individual
package name parts may only start with letters. For example, applications
published by Google could have names in the form
<code>com.google.app.<i>application_name</i></code>.
<p>
The package name serves as a unique identifier for the application.
It's also the default name for the application process (see the
<code><a href="{@docRoot}guide/topics/manifest/application-element.html">&lt;application&gt;</a></code>
element's
<code><a href="{@docRoot}guide/topics/manifest/application-element.html#aff">process</a></code>
process</a></code> attribute) and the default task affinity of an activity
(see the
<code><a href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;activity&gt;</a></code>
element's
<code><a href="{@docRoot}guide/topics/manifest/activity-element.html#aff">taskAffinity</a></code> attribute).
</p>
</dd>
<dt><a name="uid"></a>{@code android:sharedUserId}</dt>
<dd>The name of a Linux user ID that will be shared with other applications.
By default, Android assigns each application its own unique user ID.
However, if this attribute is set to the same value for two or more applications,
they will all share the same ID &mdash; provided that they are also signed
by the same certificate. Application with the same user ID can access each
other's data and, if desired, run in the same process.</dd>
<dt><a name="uidlabel"></a>{@code android:sharedUserLabel}</dt>
<dd>A user-readable label for the shared user ID. The label must be set as
a reference to a string resource; it cannot be a raw string.
<p>
<!-- ##api level indication## -->
This attribute was introduced in API Level 3. It is meaningful only if the
<code><a href="#uid">sharedUserId</a></code> attribute is also set.
</p>
</dd>
<dt><a name="vcode"></a>{@code android:versionCode}</dt>
<dd>An internal version number. This number is used only to determine whether
one version is more recent than another, with higher numbers indicating more
recent versions. This is not the version number shown to users; that number
is set by the {@code versionName} attribute.
<p>
The value must be set as an integer, such as "100". You can define it however
you want, as long as each successive version has a higher number. For example,
it could be a build number. Or you could translate a version number in "x.y"
format to an integer by encoding the "x" and "y" separately in the lower and
upper 16 bits. Or you could simply increase the number by one each time a new
version is released.
</p>
</dd>
<dt><a name="vname"></a>{@code android:versionName}</dt>
<dd>The version number shown to users. This attribute can be set as a raw
string or as a reference to a string resource. The string has no other purpose
than to be displayed to users. The {@code versionCode} attribute holds
the significant version number used internally.
</dd>
<dt><a name="install"></a>{@code android:installLocation}</dt>
<dd>The default install location for the application.
<p>The following keyword strings are accepted:</p>
<table>
<tr>
<th>Value</th>
<th>Description</th>
</tr><tr>
<td>"{@code internalOnly}"</td>
<td>The application must be installed on the internal device storage only. If this is set,
the application will never be installed on the external storage. If the internal
storage is full, then the system will not install the application. This is also the default behavior
if you do not define {@code android:installLocation}.</td>
</tr><tr>
<td>"{@code auto}"</td>
<td>The application may be installed on the external storage, but the system will install the
application on the internal storage by default. If the internal storage is full, then the system
will install it on the external storage. Once installed, the user can move the application
to either internal or external storage through the system settings.</td>
</tr><tr>
<td>"{@code preferExternal}"</td>
<td>The application prefers to be installed on the external storage (SD card). There is no
guarantee that the system will honor this request. The application might be installed on internal
storage if the external media is unavailable or full, or if the application uses the forward-locking
mechanism (not supported on external storage). Once installed, the user can move the application to
either internal or external storage through the system settings.</td>
</tr>
</table>
<p class="note"><strong>Note:</strong> By default, your application will be installed on the
internal storage and cannot be installed on the external storage unless you define this attribute
to be either "{@code auto}" or "{@code preferExternal}".</p>
<p>When an application is installed on the external storage:</p>
<ul>
<li>The {@code .apk} file is saved
to the external storage, but any application data (such as databases) is still saved on
the internal device memory.</li>
<li>The container in which the {@code .apk} file is saved is encrypted with a key that allows
the application to operate only on the device that installed it. (A user cannot
transfer the SD card to another device and use applications installed on the card.) Though,
multiple SD cards can be used with the same device.</li>
<li>At the user's request, the application can be moved to the internal storage.</li>
</ul>
<p>The user may also request to move an application from the internal storage to the external
storage. However, the system will not allow the user to move the application to external storage if
this attribute is set to {@code internalOnly}, which is the default setting.</p>
<p>Read <a href="{@docRoot}guide/appendix/install-location.html">App Install Location</a> for
more information about using this attribute (including how to maintain backward compatibility).</p>
<p>Introduced in: API Level 8.</p>
</dd>
</dl>
</dd><!-- end attributes -->
<!-- ##api level indication## -->
<dt>introduced in:</dt>
<dd>API Level 1 for all attributes, unless noted otherwise in the attribute description.</dd>
<p>
<dt>see also:</dt>
<dd>
<code><a href="{@docRoot}guide/topics/manifest/application-element.html">&lt;application&gt;</a></code></dd>
</dl>
@@ -0,0 +1,514 @@
page.title=The AndroidManifest.xml File
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>In this document</h2>
<ol>
<li><a href="#filestruct">Structure of the Manifest File</a></li>
<li><a href="#filec">File Conventions</a>
<li><a href="#filef">File Features</a>
<ol>
<li><a href="#ifs">Intent Filters</a></li>
<li><a href="#iconlabel">Icons and Labels</a></li>
<li><a href="#perms">Permissions</a></li>
<li><a href="#libs">Libraries</a></li>
</ol></li>
</ol>
</div>
</div>
<p>
Every application must have an AndroidManifest.xml file (with precisely that
name) in its root directory. The manifest presents essential information about
the application to the Android system, information the system must have before
it can run any of the application's code. Among other things, the manifest
does the following:
</p>
<ul>
<li>It names the Java package for the application.
The package name serves as a unique identifier for the application.</li>
<li>It describes the components of the application &mdash; the activities,
services, broadcast receivers, and content providers that the application is
composed of. It names the classes that implement each of the components and
publishes their capabilities (for example, which {@link android.content.Intent
Intent} messages they can handle). These declarations let the Android system
know what the components are and under what conditions they can be launched.</li>
<li>It determines which processes will host application components.</li>
<li>It declares which permissions the application must have in order to
access protected parts of the API and interact with other applications.</li>
<li>It also declares the permissions that others are required to have in
order to interact with the application's components.</li>
<li>It lists the {@link android.app.Instrumentation} classes that provide
profiling and other information as the application is running. These declarations
are present in the manifest only while the application is being developed and
tested; they're removed before the application is published.</li>
<li>It declares the minimum level of the Android API that the application
requires.</li>
<li>It lists the libraries that the application must be linked against.</li>
</ul>
<h2 id="filestruct">Structure of the Manifest File</h2>
<p>
The diagram below shows the general structure of the manifest file and
every element that it can contain. Each element, along with all of its
attributes, is documented in full in a separate file. To view detailed
information about any element, click on the element name in the diagram,
in the alphabetical list of elements that follows the diagram, or on any
other mention of the element name.
</p>
<pre>
&lt;?xml version="1.0" encoding="utf-8"?&gt;
<a href="{@docRoot}guide/topics/manifest/manifest-element.html">&lt;manifest&gt;</a>
<a href="{@docRoot}guide/topics/manifest/uses-permission-element.html">&lt;uses-permission /&gt;</a>
<a href="{@docRoot}guide/topics/manifest/permission-element.html">&lt;permission /&gt;</a>
<a href="{@docRoot}guide/topics/manifest/permission-tree-element.html">&lt;permission-tree /&gt;</a>
<a href="{@docRoot}guide/topics/manifest/permission-group-element.html">&lt;permission-group /&gt;</a>
<a href="{@docRoot}guide/topics/manifest/instrumentation-element.html">&lt;instrumentation /&gt;</a>
<a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html">&lt;uses-sdk /&gt;</a>
<a href="{@docRoot}guide/topics/manifest/uses-configuration-element.html">&lt;uses-configuration /&gt;</a> <!-- ##api level 3## -->
<a href="{@docRoot}guide/topics/manifest/uses-feature-element.html">&lt;uses-feature /&gt;</a> <!-- ##api level 4## -->
<a href="{@docRoot}guide/topics/manifest/supports-screens-element.html">&lt;supports-screens /&gt;</a> <!-- ##api level 4## -->
<a href="{@docRoot}guide/topics/manifest/application-element.html">&lt;application&gt;</a>
<a href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;activity&gt;</a>
<a href="{@docRoot}guide/topics/manifest/intent-filter-element.html">&lt;intent-filter&gt;</a>
<a href="{@docRoot}guide/topics/manifest/action-element.html">&lt;action /&gt;</a>
<a href="{@docRoot}guide/topics/manifest/category-element.html">&lt;category /&gt;</a>
<a href="{@docRoot}guide/topics/manifest/data-element.html">&lt;data /&gt;</a>
<a href="{@docRoot}guide/topics/manifest/intent-filter-element.html">&lt;/intent-filter&gt;</a>
<a href="{@docRoot}guide/topics/manifest/meta-data-element.html">&lt;meta-data /&gt;</a>
<a href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;/activity&gt;</a>
<a href="{@docRoot}guide/topics/manifest/activity-alias-element.html">&lt;activity-alias&gt;</a>
<a href="{@docRoot}guide/topics/manifest/intent-filter-element.html">&lt;intent-filter&gt;</a> . . . <a href="{@docRoot}guide/topics/manifest/intent-filter-element.html">&lt;/intent-filter&gt;</a>
<a href="{@docRoot}guide/topics/manifest/meta-data-element.html">&lt;meta-data /&gt;</a>
<a href="{@docRoot}guide/topics/manifest/activity-alias-element.html">&lt;/activity-alias&gt;</a>
<a href="{@docRoot}guide/topics/manifest/service-element.html">&lt;service&gt;</a>
<a href="{@docRoot}guide/topics/manifest/intent-filter-element.html">&lt;intent-filter&gt;</a> . . . <a href="{@docRoot}guide/topics/manifest/intent-filter-element.html">&lt;/intent-filter&gt;</a>
<a href="{@docRoot}guide/topics/manifest/meta-data-element.html">&lt;meta-data/&gt;</a>
<a href="{@docRoot}guide/topics/manifest/service-element.html">&lt;/service&gt;</a>
<a href="{@docRoot}guide/topics/manifest/receiver-element.html">&lt;receiver&gt;</a>
<a href="{@docRoot}guide/topics/manifest/intent-filter-element.html">&lt;intent-filter&gt;</a> . . . <a href="{@docRoot}guide/topics/manifest/intent-filter-element.html">&lt;/intent-filter&gt;</a>
<a href="{@docRoot}guide/topics/manifest/meta-data-element.html">&lt;meta-data /&gt;</a>
<a href="{@docRoot}guide/topics/manifest/receiver-element.html">&lt;/receiver&gt;</a>
<a href="{@docRoot}guide/topics/manifest/provider-element.html">&lt;provider&gt;</a>
<a href="{@docRoot}guide/topics/manifest/grant-uri-permission-element.html">&lt;grant-uri-permission /&gt;</a>
<a href="{@docRoot}guide/topics/manifest/meta-data-element.html">&lt;meta-data /&gt;</a>
<a href="{@docRoot}guide/topics/manifest/provider-element.html">&lt;/provider&gt;</a>
<a href="{@docRoot}guide/topics/manifest/uses-library-element.html">&lt;uses-library /&gt;</a>
<a href="{@docRoot}guide/topics/manifest/application-element.html">&lt;/application&gt;</a>
<a href="{@docRoot}guide/topics/manifest/manifest-element.html">&lt;/manifest&gt;</a>
</pre>
<p>
All the elements that can appear in the manifest file are listed below
in alphabetical order. These are the only legal elements; you cannot
add your own elements or attributes.
</p>
<p style="margin-left: 2em">
<code><a href="{@docRoot}guide/topics/manifest/action-element.html">&lt;action&gt;</a></code>
<br/><code><a href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;activity&gt;</a></code>
<br/><code><a href="{@docRoot}guide/topics/manifest/activity-alias-element.html">&lt;activity-alias&gt;</a></code>
<br/><code><a href="{@docRoot}guide/topics/manifest/application-element.html">&lt;application&gt;</a></code>
<br/><code><a href="{@docRoot}guide/topics/manifest/category-element.html">&lt;category&gt;</a></code>
<br/><code><a href="{@docRoot}guide/topics/manifest/data-element.html">&lt;data&gt;</a></code>
<br/><code><a href="{@docRoot}guide/topics/manifest/grant-uri-permission-element.html">&lt;grant-uri-permission&gt;</a></code>
<br/><code><a href="{@docRoot}guide/topics/manifest/instrumentation-element.html">&lt;instrumentation&gt;</a></code>
<br/><code><a href="{@docRoot}guide/topics/manifest/intent-filter-element.html">&lt;intent-filter&gt;</a></code>
<br/><code><a href="{@docRoot}guide/topics/manifest/manifest-element.html">&lt;manifest&gt;</a></code>
<br/><code><a href="{@docRoot}guide/topics/manifest/meta-data-element.html">&lt;meta-data&gt;</a></code>
<br/><code><a href="{@docRoot}guide/topics/manifest/permission-element.html">&lt;permission&gt;</a></code>
<br/><code><a href="{@docRoot}guide/topics/manifest/permission-group-element.html">&lt;permission-group&gt;</a></code>
<br/><code><a href="{@docRoot}guide/topics/manifest/permission-tree-element.html">&lt;permission-tree&gt;</a></code>
<br/><code><a href="{@docRoot}guide/topics/manifest/provider-element.html">&lt;provider&gt;</a></code>
<br/><code><a href="{@docRoot}guide/topics/manifest/receiver-element.html">&lt;receiver&gt;</a></code>
<br/><code><a href="{@docRoot}guide/topics/manifest/service-element.html">&lt;service&gt;</a></code>
<br/><code><a href="{@docRoot}guide/topics/manifest/supports-screens-element.html">&lt;supports-screens&gt;</a></code> <!-- ##api level 4## -->
<br/><code><a href="{@docRoot}guide/topics/manifest/uses-configuration-element.html">&lt;uses-configuration&gt;</a></code> <!-- ##api level 3## -->
<br/><code><a href="{@docRoot}guide/topics/manifest/uses-feature-element.html">&lt;uses-feature&gt;</a></code> <!-- ##api level 4## -->
<br/><code><a href="{@docRoot}guide/topics/manifest/uses-library-element.html">&lt;uses-library&gt;</a></code>
<br/><code><a href="{@docRoot}guide/topics/manifest/uses-permission-element.html">&lt;uses-permission&gt;</a></code>
<br/><code><a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html">&lt;uses-sdk&gt;</a></code>
</p>
<h2 id="filec">File Conventions</h2>
<p>
Some conventions and rules apply generally to all elements and attributes
in the manifest:
</p>
<dl>
<dt><b>Elements</b></dt>
<dd>Only the
<code><a href="{@docRoot}guide/topics/manifest/manifest-element.html">&lt;manifest&gt;</a></code> and
<code><a href="{@docRoot}guide/topics/manifest/application-element.html">&lt;application&gt;</a></code>
elements are required, they each must be present and can occur only once.
Most of the others can occur many times or not at all &mdash; although at
least some of them must be present for the manifest to accomplish anything
meaningful.
<p>
If an element contains anything at all, it contains other elements.
All values are set through attributes, not as character data within an element.
</p>
<p>
Elements at the same level are generally not ordered. For example,
<code><a href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;activity&gt;</a></code>,
<code><a href="{@docRoot}guide/topics/manifest/provider-element.html">&lt;provider&gt;</a></code>, and
<code><a href="{@docRoot}guide/topics/manifest/service-element.html">&lt;service&gt;</a></code>
elements can be intermixed in any sequence. (An
<code><a href="{@docRoot}guide/topics/manifest/activity-alias-element.html">&lt;activity-alias&gt;</a></code>
element is the exception to this rule: It must follow the
<code><a href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;activity&gt;</a></code>
it is an alias for.)
</p></dd>
<dt><b>Attributes</b></dt>
<dd>In a formal sense, all attributes are optional. However, there are some
that must be specified for an element to accomplish its purpose. Use the
documentation as a guide. For truly optional attributes, it mentions a default
value or states what happens in the absence of a specification.
<p>Except for some attributes of the root
<code><a href="{@docRoot}guide/topics/manifest/manifest-element.html">&lt;manifest&gt;</a></code>
element, all attribute names begin with an {@code android:} prefix &mdash;
for example, {@code android:alwaysRetainTaskState}. Because the prefix is
universal, the documentation generally omits it when referring to attributes
by name.</p></dd>
<dt><b>Declaring class names</b></dt>
<dd>Many elements correspond to Java objects, including elements for the
application itself (the
<code><a href="{@docRoot}guide/topics/manifest/application-element.html">&lt;application&gt;</a></code>
element) and its principal components &mdash; activities
(<code><a href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;activity&gt;</a></code>),
services
(<code><a href="{@docRoot}guide/topics/manifest/service-element.html">&lt;service&gt;</a></code>),
broadcast receivers
(<code><a href="{@docRoot}guide/topics/manifest/receiver-element.html">&lt;receiver&gt;</a></code>),
and content providers
(<code><a href="{@docRoot}guide/topics/manifest/provider-element.html">&lt;provider&gt;</a></code>).
<p>
If you define a subclass, as you almost always would for the component classes
({@link android.app.Activity}, {@link android.app.Service},
{@link android.content.BroadcastReceiver}, and {@link android.content.ContentProvider}),
the subclass is declared through a {@code name} attribute. The name must include
the full package designation.
For example, an {@link android.app.Service} subclass might be declared as follows:
</p>
<pre>&lt;manifest . . . &gt;
&lt;application . . . &gt;
&lt;service android:name="com.example.project.SecretService" . . . &gt;
. . .
&lt;/service&gt;
. . .
&lt;/application&gt;
&lt;/manifest&gt;</pre>
<p>
However, as a shorthand, if the first character of the string is a period, the
string is appended to the application's package name (as specified by the
<code><a href="{@docRoot}guide/topics/manifest/manifest-element.html">&lt;manifest&gt;</a></code>
element's
<code><a href="{@docRoot}guide/topics/manifest/manifest-element.html#package">package</a></code>
attribute). The following assignment is the same as the one above:
</p>
<pre>&lt;manifest package="com.example.project" . . . &gt;
&lt;application . . . &gt;
&lt;service android:name=".SecretService" . . . &gt;
. . .
&lt;/service&gt;
. . .
&lt;/application&gt;
&lt;/manifest&gt;</pre>
<p>
When starting a component, Android creates an instance of the named subclass.
If a subclass isn't specified, it creates an instance of the base class.
</p></dd>
<dt><b>Multiple values</b></dt>
<dd>If more than one value can be specified, the element is almost always
repeated, rather than listing multiple values within a single element.
For example, an intent filter can list several actions:
<pre>&lt;intent-filter . . . &gt;
&lt;action android:name="android.intent.action.EDIT" /&gt;
&lt;action android:name="android.intent.action.INSERT" /&gt;
&lt;action android:name="android.intent.action.DELETE" /&gt;
. . .
&lt;/intent-filter&gt;</pre></dd>
<dt><b>Resource values</b></dt>
<dd>Some attributes have values that can be displayed to users &mdash; for
example, a label and an icon for an activity. The values of these attributes
should be localized and therefore set from a resource or theme. Resource
values are expressed in the following format,</p>
<p style="margin-left: 2em">{@code @[<i>package</i>:]<i>type</i>:<i>name</i>}</p>
<p>
where the <i>package</i> name can be omitted if the resource is in the same package
as the application, <i>type</i> is a type of resource &mdash; such as "string" or
"drawable" &mdash; and <i>name</i> is the name that identifies the specific resource.
For example:
</p>
<pre>&lt;activity android:icon="@drawable/smallPic" . . . &gt</pre>
<p>
Values from a theme are expressed in a similar manner, but with an initial '{@code ?}'
rather than '{@code @}':
</p>
<p style="margin-left: 2em">{@code ?[<i>package</i>:]<i>type</i>:<i>name</i>}
</p></dd>
<dt><b>String values</b></dt>
<dd>Where an attribute value is a string, double backslashes ('{@code \\}')
must be used to escape characters &mdash; for example, '{@code \\n}' for
a newline or '{@code \\uxxxx}' for a Unicode character.</dd>
</dl>
<h2 id="filef">File Features</h2>
<p>
The following sections describe how some Android features are reflected
in the manifest file.
</p>
<h3 id="ifs">Intent Filters</h3>
<p>
The core components of an application (its activities, services, and broadcast
receivers) are activated by <i>intents</i>. An intent is a
bundle of information (an {@link android.content.Intent} object) describing a
desired action &mdash; including the data to be acted upon, the category of
component that should perform the action, and other pertinent instructions.
Android locates an appropriate component to respond to the intent, launches
a new instance of the component if one is needed, and passes it the
Intent object.
</p>
<p>
Components advertise their capabilities &mdash; the kinds of intents they can
respond to &mdash; through <i>intent filters</i>. Since the Android system
must learn which intents a component can handle before it launches the component,
intent filters are specified in the manifest as
<code><a href="{@docRoot}guide/topics/manifest/intent-filter-element.html">&lt;intent-filter&gt;</a></code>
elements. A component may have any number of filters, each one describing
a different capability.
</p>
<p>
An intent that explicitly names a target component will activate that component;
the filter doesn't play a role. But an intent that doesn't specify a target by
name can activate a component only if it can pass through one of the component's
filters.
</p>
<p>
For information on how Intent objects are tested against intent filters,
see a separate document,
<a href="{@docRoot}guide/topics/intents/intents-filters.html">Intents
and Intent Filters</a>.
</p>
<h3 id="iconlabel">Icons and Labels</h3>
<p>
A number of elements have {@code icon} and {@code label} attributes for a
small icon and a text label that can be displayed to users. Some also have a
{@code description} attribute for longer explanatory text that can also be
shown on-screen. For example, the
<code><a href="{@docRoot}guide/topics/manifest/permission-element.html">&lt;permission&gt;</a></code>
element has all three of these attributes, so that when the user is asked whether
to grant the permission to an application that has requested it, an icon representing
the permission, the name of the permission, and a description of what it
entails can all be presented to the user.
</p>
<p>
In every case, the icon and label set in a containing element become the default
{@code icon} and {@code label} settings for all of the container's subelements.
Thus, the icon and label set in the
<code><a href="{@docRoot}guide/topics/manifest/application-element.html">&lt;application&gt;</a></code>
element are the default icon and label for each of the application's components.
Similarly, the icon and label set for a component &mdash; for example, an
<code><a href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;activity&gt;</a></code>
element &mdash; are the default settings for each of the component's
<code><a href="{@docRoot}guide/topics/manifest/intent-filter-element.html">&lt;intent-filter&gt;</a></code>
elements. If an
<code><a href="{@docRoot}guide/topics/manifest/application-element.html">&lt;application&gt;</a></code>
element sets a label, but an activity and its intent filter do not,
the application label is treated as the label for both the activity and
the intent filter.
</p>
<p>
The icon and label set for an intent filter are used to represent a component
whenever the component is presented to the user as fulfilling the function
advertised by the filter. For example, a filter with
"{@code android.intent.action.MAIN}" and
"{@code android.intent.category.LAUNCHER}" settings advertises an activity
as one that initiates an application &mdash; that is, as
one that should be displayed in the application launcher. The icon and label
set in the filter are therefore the ones displayed in the launcher.
</p>
<h3 id="perms">Permissions</h3>
<p>
A <i>permission</i> is a restriction limiting access to a part of the code
or to data on the device. The limitation is imposed to protect critical
data and code that could be misused to distort or damage the user experience.
</p>
<p>
Each permission is identified by a unique label. Often the label indicates
the action that's restricted. For example, here are some permissions defined
by Android:
</p>
<p style="margin-left: 2em">{@code android.permission.CALL_EMERGENCY_NUMBERS}
<br/>{@code android.permission.READ_OWNER_DATA}
<br/>{@code android.permission.SET_WALLPAPER}
<br/>{@code android.permission.DEVICE_POWER}</p>
<p>
A feature can be protected by at most one permission.
</p>
<p>
If an application needs access to a feature protected by a permission,
it must declare that it requires that permission with a
<code><a href="{@docRoot}guide/topics/manifest/uses-permission-element.html">&lt;uses-permission&gt;</a></code>
element in the manifest. Then, when the application is installed on
the device, the installer determines whether or not to grant the requested
permission by checking the authorities that signed the application's
certificates and, in some cases, asking the user.
If the permission is granted, the application is able to use the protected
features. If not, its attempts to access those features will simply fail
without any notification to the user.
</p>
<p>
An application can also protect its own components (activities, services,
broadcast receivers, and content providers) with permissions. It can employ
any of the permissions defined by Android (listed in
{@link android.Manifest.permission android.Manifest.permission}) or declared
by other applications. Or it can define its own. A new permission is declared
with the
<code><a href="{@docRoot}guide/topics/manifest/permission-element.html">&lt;permission&gt;</a></code>
element. For example, an activity could be protected as follows:
</p>
<pre>
&lt;manifest . . . &gt;
&lt;permission android:name="com.example.project.DEBIT_ACCT" . . . /&gt;
&lt;uses-permission android:name="com.example.project.DEBIT_ACCT" /&gt;
. . .
&lt;application . . .&gt;
&lt;activity android:name="com.example.project.FreneticActivity"
android:permission="com.example.project.DEBIT_ACCT"
. . . &gt;
. . .
&lt;/activity&gt;
&lt;/application&gt;
&lt;/manifest&gt;
</pre>
<p>
Note that, in this example, the {@code DEBIT_ACCT} permission is not only
declared with the
<code><a href="{@docRoot}guide/topics/manifest/permission-element.html">&lt;permission&gt;</a></code>
element, its use is also requested with the
<code><a href="{@docRoot}guide/topics/manifest/uses-permission-element.html">&lt;uses-permission&gt;</a></code>
element. Its use must be requested in order for other components of the
application to launch the protected activity, even though the protection
is imposed by the application itself.
</p>
<p>
If, in the same example, the {@code permission} attribute was set to a
permission declared elsewhere
(such as {@code android.permission.CALL_EMERGENCY_NUMBERS}, it would not
have been necessary to declare it again with a
<code><a href="{@docRoot}guide/topics/manifest/permission-element.html">&lt;permission&gt;</a></code>
element. However, it would still have been necessary to request its use with
<code><a href="{@docRoot}guide/topics/manifest/uses-permission-element.html">&lt;uses-permission&gt;</a></code>.
</p>
<p>
The
<code><a href="{@docRoot}guide/topics/manifest/permission-tree-element.html">&lt;permission-tree&gt;</a></code>
element declares a namespace for a group of permissions that will be defined in
code. And
<code><a href="{@docRoot}guide/topics/manifest/permission-group-element.html">&lt;permission-group&gt;</a></code>
defines a label for a set of permissions (both those declared in the manifest with
<code><a href="{@docRoot}guide/topics/manifest/permission-element.html">&lt;permission&gt;</a></code>
elements and those declared elsewhere). It affects only how the permissions are
grouped when presented to the user. The
<code><a href="{@docRoot}guide/topics/manifest/permission-group-element.html">&lt;permission-group&gt;</a></code>
element does not specify which permissions belong to the group;
it just gives the group a name. A permission is placed in the group
by assigning the group name to the
<code><a href="{@docRoot}guide/topics/manifest/permission-element.html">&lt;permission&gt;</a></code>
element's
<code><a href="{@docRoot}guide/topics/manifest/permission-element.html#pgroup">permissionGroup</a></code>
attribute.
</p>
<h3 id="libs">Libraries</h3>
<p>
Every application is linked against the default Android library, which
includes the basic packages for building applications (with common classes
such as Activity, Service, Intent, View, Button, Application, ContentProvider,
and so on).
</p>
<p>
However, some packages reside in their own libraries. If your application
uses code from any of these packages, it must explicitly asked to be linked
against them. The manifest must contain a separate
<code><a href="{@docRoot}guide/topics/manifest/uses-library-element.html">&lt;uses-library&gt;</a></code>
element to name each of the libraries. (The library name can be found in the
documentation for the package.)
</p>
@@ -0,0 +1,94 @@
page.title=&lt;meta-data&gt;
@jd:body
<dl class="xml">
<dt>syntax:</dt>
<dd><pre class="stx">&lt;meta-data android:<a href="#nm">name</a>="<i>string</i>"
android:<a href="#rsrc">resource</a>="<i>resource specification</i>"
android:<a href="#val">value</a>="<i>string</i>" /&gt;</pre></dd>
<dt>contained in:</dt>
<dd><code><a href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;activity&gt;</a></code>
<br/><code><a href="{@docRoot}guide/topics/manifest/activity-alias-element.html">&lt;activity-alias&gt;</a></code>
<br/><code><a href="{@docRoot}guide/topics/manifest/service-element.html">&lt;service&gt;</a></code>
<br/><code><a href="{@docRoot}guide/topics/manifest/receiver-element.html">&lt;receiver&gt;</a></code></dd>
<dt>description:</dt>
<dd>A name-value pair for an item of additional, arbitrary data that can
be supplied to the parent component. A component element can contain any
number of {@code &lt;meta-data&gt;} subelements. The values from all of
them are collected in a single {@link android.os.Bundle} object and made
available to the component as the
{@link android.content.pm.PackageItemInfo#metaData
PackageItemInfo.metaData} field.
<p>
Ordinary values are specified through the <code><a href="{@docRoot}guide/topics/manifest/meta-data-element.html#value">value</a></code>
attribute. However, to assign a resource ID as the value, use the
<code><a href="{@docRoot}guide/topics/manifest/meta-data-element.html#resource">resource</a></code> attribute instead. For example,
the following code assigns whatever value is stored in the {@code @string/kangaroo}
resource to the "{@code zoo}" name:
</p>
<pre>&lt;meta-data android:name="zoo" android:value="@string/kangaroo" /&gt;</pre>
<p>
On the other hand, using the {@code resource} attribute would assign "{@code zoo}"
the numeric ID of the resource, not the value stored in the resource:
</p>
<pre>&lt;meta-data android:name="zoo" android:resource="@string/kangaroo" /&gt;</pre>
<p>
It is highly recommended that you avoid supplying related data as
multiple separate {@code &lt;meta-data&gt;} entries. Instead, if you
have complex data to associate with a component, store it as a resource and
use the {@code resource} attribute to inform the component of its ID.
</p></dd>
<dt>attributes:</dt>
<dd><dl class="attr">
<dt><a name="nm"></a>{@code android:name}</dt>
<dd>A unique name for the item. To ensure that the name is unique, use a
Java-style naming convention &mdash; for example,
"{@code com.example.project.activity.fred}".</dd>
<dt><a name="rsrc"></a>{@code android:resource}</dt>
<dd>A reference to a resource. The ID of the resource is the value assigned
to the item. The ID can be retrieved from the meta-data Bundle by the
{@link android.os.Bundle#getInt Bundle.getInt()} method.</dd>
<dt><a name="val"></a>{@code android:value}</dt>
<dd>The value assigned to the item. The data types that can be assigned as values and the Bundle methods that components use to retrieve those values are listed in the following table:
<table>
<tr>
<th>Type</th>
<th>Bundle method</th>
</tr><tr>
<td>String value, using double backslashes ({@code \\}) to escape characters
&mdash; such as "{@code \\n}" and "{@code \\uxxxxx}" for a Unicode character.</td>
<td>{@link android.os.Bundle#getString(String) getString()}</td>
</tr><tr>
<td>Integer value, such as "{@code 100}"</td>
<td>{@link android.os.Bundle#getInt(String) getInt()}</td>
</tr><tr>
<td>Boolean value, either "{@code true}" or "{@code false}"</td>
<td>{@link android.os.Bundle#getBoolean(String) getBoolean()}</td>
</tr><tr>
<td>Color value, in the form "{@code #rgb}", "{@code #argb}",
"{@code #rrggbb}", or "{@code #aarrggbb}"</td>
<td>{@link android.os.Bundle#getString(String) getString()}</td>
</tr><tr>
<td>Float value, such as "{@code 1.23}"</td>
<td>{@link android.os.Bundle#getFloat(String) getFloat()}</td>
</tr>
</table>
</dd>
</dl></dd>
<!-- ##api level indication## -->
<dt>introduced in:</dt>
<dd>API Level 1</dd>
</dl>
@@ -0,0 +1,104 @@
page.title=&lt;path-permission&gt;
@jd:body
<dl class="xml">
<dt>syntax:</dt>
<dd><pre class="stx">
&lt;path-permission android:<a href="#path">path</a>="<i>string</i>"
android:<a href="#pathPrefix">pathPrefix</a>="<i>string</i>"
android:<a href="#pathPattern">pathPattern</a>="<i>string</i>"
android:<a href="#permission">permission</a>="<i>string</i>"
android:<a href="#readPermission">readPermission</a>="<i>string</i>"
android:<a href="#writePermission">writePermission</a>="<i>string</i>" /&gt;
</pre></dd>
<dt>contained in:</dt>
<dd><code><a href="{@docRoot}guide/topics/manifest/provider-element.html">&lt;provider&gt;</a></code></dd>
<!--
<dt>can contain:</dt>
</dd>
-->
<dt>description:</dt>
<dd>Defines the path and required permissions for a specific subset of data
within a content provider. This element can be
specified multiple times to supply multiple paths.
</dd>
<dt>attributes:</dt>
<dd><dl class="attr">
<dt><a name="path"></a>{@code android:path}</dt>
<dd>A complete URI path for a subset of content provider data.
Permission can be granted only to the particular data identified by this path.
When used to provide search suggestion content, it must be appended
with "/search_suggest_query".
</dd>
<dt><a name="pathPrefix"></a>{@code android:pathPrefix}</dt>
<dd>The initial part of a URI path for a subset of content provider data.
Permission can be granted to all data subsets with paths that share this initial part.
</dd>
<dt><a name="pathPattern"></a>{@code android:pathPattern}</dt>
<dd>A complete URI path for a subset of content provider data,
but one that can use the following wildcards:
<ul>
<li>An asterisk ('<code class="Code prettyprint">*</code>'). This matches a sequence of 0 to many occurrences of
the immediately preceding character.</li>
<li>A period followed by an asterisk ("<code class="Code prettyprint">.*</code>"). This matches any sequence of
0 or more characters.</li>
</ul>
<p>
Because '<code class="Code prettyprint">\</code>' is used as an escape character when the string is read
from XML (before it is parsed as a pattern), you will need to double-escape.
For example, a literal '<code class="Code prettyprint">*</code>' would be written as "<code class="Code prettyprint">\\*</code>" and a
literal '<code class="Code prettyprint">\</code>' would be written as "<code class="Code prettyprint">\\</code>". This is basically
the same as what you would need to write if constructing the string in Java code.
</p>
<p>
For more information on these types of patterns, see the descriptions of
<a href="/reference/android/os/PatternMatcher.html#PATTERN_LITERAL">PATTERN_LITERAL</a>,
<a href="/reference/android/os/PatternMatcher.html#PATTERN_PREFIX">PATTERN_PREFIX</a>, and
<a href="/reference/android/os/PatternMatcher.html#PATTERN_SIMPLE_GLOB">PATTERN_SIMPLE_GLOB</a> in the
<a href="/reference/android/os/PatternMatcher.html">PatternMatcher</a> class.
</p>
</dd>
<dt><a name="permission"></a>{@code android:permission}</dt>
<dd>The name of a permission that clients must have in order to read or write the
content provider's data. This attribute is a convenient way of setting a
single permission for both reading and writing. However, the
<code>readPermission</code> and
<code>writePermission</code> attributes take precedence
over this one.
</dd>
<dt><a name="readPermission"></a>{@code android:readPermission}</dt>
<dd>A permission that clients must have in order to query the content provider.
</dd>
<dt><a name="writePermission"></a>{@code android:writePermission}</dt>
<dd>A permission that clients must have in order to make changes to the data controlled by the content provider.
</dd>
</dl></dd>
<!-- ##api level indication## -->
<dt>introduced in:</dt>
<dd>API Level 4</dd>
<dt>see also:</dt>
<dd>{@link android.app.SearchManager}</dd>
<dd>{@link android.Manifest.permission}</dd>
<dd><a href="/guide/topics/security/security.html">Security and
Permissions</a></dd>
</dl>
@@ -0,0 +1,135 @@
page.title=&lt;permission&gt;
@jd:body
<dl class="xml">
<dt>syntax:</dt></dt>
<dd><pre class="stx">&lt;permission android:<a href="#desc">description</a>="<i>string resource</i>"
android:<a href="#icon">icon</a>="<i>drawable resource</i>"
android:<a href="#label">label</a>="<i>string resource</i>"
android:<a href="#nm">name</a>="<i>string</i>"
android:<a href="#pgroup">permissionGroup</a>="<i>string</i>"
android:<a href="#plevel">protectionLevel</a>=["normal" | "dangerous" |
"signature" | "signatureOrSystem"] /&gt;</pre></dd>
<dt>contained in:</dt>
<dd><code><a href="{@docRoot}guide/topics/manifest/manifest-element.html">&lt;manifest&gt;</a></code></dd>
<dt>description:</dt>
<dd>Declares a security permission that can be used to limit access
to specific components or features of this or other applications.
See the <a href="{@docRoot}guide/topics/manifest/manifest-intro.html#perms">Permissions</a>
section in the introduction,
and the <a href="{@docRoot}guide/topics/security/security.html">Security and Permissions</a>
document for more information on how permissions work.</dd>
<dt>attributes:</dt>
<dd><dl class="attr">
<dt><a name="desc"></a>{@code android:description}</dt>
<dd>A user-readable description of the permission, longer and more
informative than the label. It may be displayed to explain the
permission to the user &mdash; for example, when the user is asked
whether to grant the permission to another application.
<p>
This attribute must be set as a reference to a string resource;
unlike the {@code label} attribute, it cannot be a raw string.
</p></dd>
<dt><a name="icon"></a>{@code android:icon}</dt>
<dd>A reference to a drawable resource for an icon that represents the
permission.</dd>
<dt><a name="label"></a>{@code android:label}</dt>
<dd>A name for the permission, one that can be displayed to users.
<p>
As a convenience, the label can be directly set
as a raw string while you're developing the application. However,
when the application is ready to be published, it should be set as a
reference to a string resource, so that it can be localized like other
strings in the user interface.
</p></dd>
<dt><a name="nm"></a>{@code android:name}</dt>
<dd>The name of the permission. This is the name that will be used in
code to refer to the permission &mdash; for example, in a
<code><a href="{@docRoot}guide/topics/manifest/uses-permission-element.html">&lt;uses-permission&gt;</a></code> element and the
{@code permission} attributes of application components.
<p>
The name must be unique, so it should use Java-style scoping &mdash;
for example, "{@code com.example.project.PERMITTED_ACTION}".
</p></dd>
<dt><a name="pgroup"></a>{@code android:permissionGroup}</dt>
<dd>Assigns this permission to a group. The value of this attribute is
the name of the group, which must be declared with the
<code><a href="{@docRoot}guide/topics/manifest/permission-group-element.html">&lt;permission-group&gt;</a></code> element in this
or another application. If this attribute is not set, the permission
does not belong to a group.</dd>
<dt><a name="plevel"></a>{@code android:protectionLevel}</dt>
<dd>Characterizes the potential risk implied in the permission and
indicates the procedure the system should follow when determining
whether or not to grant the permission to an application requesting it.
The value can be set to one of the following strings:
<table>
<tr>
<th>Value</th>
<th>Meaning</th>
</tr><tr>
<td>"{@code normal}"</td>
<td>The default value. A lower-risk permission that gives requesting
applications access to isolated application-level features, with
minimal risk to other applications, the system, or the user.
The system automatically grants this type
of permission to a requesting application at installation, without
asking for the user's explicit approval (though the user always
has the option to review these permissions before installing).
</tr><tr>
<td>"{@code dangerous}"</td>
<td>A higher-risk permission that would give a requesting application
access to private user data or control over the device that can
negatively impact the user. Because this type of permission
introduces potential risk, the system may not automatically
grant it to the requesting application. For example, any dangerous
permissions requested by an application may be displayed to the
user and require confirmation before proceeding, or some other
approach may be taken to avoid the user automatically allowing
the use of such facilities.
</tr><tr>
<td>"{@code signature}"</td>
<td>A permission that the system grants only if the requesting
application is signed with the same certificate as the application
that declared the permission. If the certificates match, the system
automatically grants the permission without notifying the user or
asking for the user's explicit approval.
</tr><tr>
<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
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}"
permission is used for certain special situations where multiple
vendors have applications built into a system image and need
to share specific features explicitly because they are being built
together.
</tr>
</table>
</dd>
</dl></dd>
<!-- ##api level indication## -->
<dt>introduced in:</dt>
<dd>API Level 1</dd>
<dt>see also:</dt>
<dd><code><a href="{@docRoot}guide/topics/manifest/uses-permission-element.html">&lt;uses-permission&gt;</a></code>
<br/><code><a href="{@docRoot}guide/topics/manifest/permission-tree-element.html">&lt;permission-tree&gt;</a></code>
<br/><code><a href="{@docRoot}guide/topics/manifest/permission-group-element.html">&lt;permission-group&gt;</a></code></dd>
</dd>
</dl>
@@ -0,0 +1,63 @@
page.title=&lt;permission-group&gt;
@jd:body
<dl class="xml">
<dt>syntax:</dt>
<dd><pre class="stx">&lt;permission-group android:<a href="#desc">description</a>="<i>string resource</i>"
android:<a href="#icon">icon</a>="<i>drawable resource</i>"
android:<a href="#label">label</a>="<i>string resource</i>"
android:<a href="#nm">name</a>="<i>string</i>" /&gt;</pre></dd>
<dt>contained in:</dt>
<dd><code><a href="{@docRoot}guide/topics/manifest/manifest-element.html">&lt;manifest&gt;</a></code></dd>
<dt>description:</dt>
<dd>Declares a name for a logical grouping of related permissions. Individual
permission join the group through the {@code permissionGroup} attribute of the
<code><a href="{@docRoot}guide/topics/manifest/permission-element.html">&lt;permission&gt;</a></code> element. Members of a group are
presented together in the user interface.
<p>
Note that this element does not declare a permission itself, only a category in
which permissions can be placed. See the
<code><a href="{@docRoot}guide/topics/manifest/permission-element.html">&lt;permission&gt;</a></code> element for element for information
on declaring permissions and assigning them to groups.
</p></dd>
<dt>attributes:</dt>
<dd><dl class="attr">
<dt><a name="desc"></a>{@code android:description}</dt>
<dd>User-readable text that describes the group. The text should be
longer and more explanatory than the label. This attribute must be
set as a reference to a string resource. Unlike the {@code label}
attribute, it cannot be a raw string.</dd>
<dt><a name="icon"></a>{@code android:icon}</dt>
<dd>An icon representing the permission. This attribute must be set
as a reference to a drawable resource containing the image definition.</dd>
<dt><a name="label"></a>{@code android:label}</dt>
<dd>A user-readable name for the group. As a convenience, the label can
be directly set as a raw string while you're developing the application.
However, when the application is ready to be published, it should be set
as a reference to a string resource, so that it can be localized like other
strings in the user interface.</dd>
<dt><a name="nm"></a>{@code android:name}</dt>
<dd>The name of the group. This is the name that can be assigned to a
<code><a href="{@docRoot}guide/topics/manifest/permission-element.html">&lt;permission&gt;</a></code>
element's
<code><a href="{@docRoot}guide/topics/manifest/permission-element.html#pgroup">&lt;permissionGroup&gt;</a></code>
attribute.</dd>
</dl></dd>
<!-- ##api level indication## -->
<dt>introduced in:</dt>
<dd>API Level 1</dd>
<dt>see also:</dt>
<dd><code><a href="{@docRoot}guide/topics/manifest/permission-element.html">&lt;permission&gt;</a></code>
<br/><code><a href="{@docRoot}guide/topics/manifest/permission-tree-element.html">&lt;permission-tree&gt;</a></code>
<br/><code><a href="{@docRoot}guide/topics/manifest/uses-permission-element.html">&lt;uses-permission&gt;</a></code></dd>
</dl>
@@ -0,0 +1,64 @@
page.title=&lt;permission-tree&gt;
@jd:body
<dl class="xml">
<dt>syntax:</dt>
<dd><pre class="stx">&lt;permission-tree android:<a href="#icon">icon</a>="<i>drawable resource</i>"
android:<a href="#label">label</a>="<i>string resource</i>" ]
android:<a href="#nm">name</a>="<i>string</i>" /&gt;</pre></dd>
<dt>contained in:</dt>
<dd><code><a href="{@docRoot}guide/topics/manifest/manifest-element.html">&lt;manifest&gt;</a></code></dd>
<dt>description:</dt>
<dd>Declares the base name for a tree of permissions. The application takes
ownership of all names within the tree. It can dynamically add new permissions
to the tree by calling <code>{@link android.content.pm.PackageManager#addPermission PackageManager.addPermission()}</code>. Names within the tree are separated by
periods ('{@code .}'). For example, if the base name is
{@code com.example.project.taxes}, permissions like the following might be
added:
<p style="margin-left: 2em">{@code com.example.project.taxes.CALCULATE}
<br/>{@code com.example.project.taxes.deductions.MAKE_SOME_UP}
<br/>{@code com.example.project.taxes.deductions.EXAGGERATE}</p>
<p>
Note that this element does not declare a permission itself, only a
namespace in which further permissions can be placed. See the
<code><a href="{@docRoot}guide/topics/manifest/permission-element.html">&lt;permission&gt;</a></code>
element for information on declaring permissions.
<dt>attributes:</dt>
<dd><dl class="attr">
<dt><a name="icon"></a>{@code android:icon}</dt>
<dd>An icon representing all the permissions in the tree. This attribute
must be set as a reference to a drawable resource containing the image
definition.</dd>
<dt><a name="label"></a>{@code android:label}</dt>
<dd>A user-readable name for the group. As a convenience, the label can
be directly set as a raw string for quick and dirty programming. However,
when the application is ready to be published, it should be set as a
reference to a string resource, so that it can be localized like other
strings in the user interface.</dd>
<dt><a name="nm"></a>{@code android:name}</dt>
<dd>The name that's at the base of the permission tree. It serves as
a prefix to all permission names in the tree. Java-style scoping should
be used to ensure that the name is unique. The name must have more than
two period-separated segments in its path &mdash; for example,
{@code com.example.base} is OK, but {@code com.example} is not.</dd>
</dl></dd>
<!-- ##api level indication## -->
<dt>introduced in:</dt>
<dd>API Level 1</dd>
<dt>see also:</dt>
<dd><code><a href="{@docRoot}guide/topics/manifest/permission-element.html">&lt;permission&gt;</a></code>
<br/><code><a href="{@docRoot}guide/topics/manifest/permission-group-element.html">&lt;permission-group&gt;</a></code>
<br/><code><a href="{@docRoot}guide/topics/manifest/uses-permission-element.html">&lt;uses-permission&gt;</a></code>
</dd>
</dl>
@@ -0,0 +1,270 @@
page.title=&lt;provider&gt;
@jd:body
<dl class="xml">
<dt>syntax:</dt>
<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"]
android:<a href="#icon">icon</a>="<i>drawable resource</i>"
android:<a href="#init">initOrder</a>="<i>integer</i>"
android:<a href="#label">label</a>="<i>string resource</i>"
android:<a href="#multi">multiprocess</a>=["true" | "false"]
android:<a href="#nm">name</a>="<i>string</i>"
android:<a href="#prmsn">permission</a>="<i>string</i>"
android:<a href="#proc">process</a>="<i>string</i>"
android:<a href="#rprmsn">readPermission</a>="<i>string</i>"
android:<a href="#sync">syncable</a>=["true" | "false"]
android:<a href="#wprmsn">writePermission</a>="<i>string</i>" &gt;
. . .
&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>
<dt>can contain:</dt>
<dd><code><a href="{@docRoot}guide/topics/manifest/meta-data-element.html">&lt;meta-data&gt;</a></code>
<br/><code><a href="{@docRoot}guide/topics/manifest/grant-uri-permission-element.html">&lt;grant-uri-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>
<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>
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
<code><a href="{@docRoot}guide/topics/manifest/application-element.html">&lt;application&gt;</a></code> and {@code &lt;provider&gt;}
attributes must both be "{@code true}" (as they both
are by default) for the content provider to be enabled. If either is
"{@code false}", the provider is disabled; it cannot be instantiated.
</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>
<dt><a name="gprmsn"></a>{@code android:grantUriPermissions}</dt>
<dd>Whether or not those who ordinarily would not have permission to
access the content provider's data can be granted permission to do so,
temporarily overcoming the restriction imposed by the
<code><a href="{@docRoot}guide/topics/manifest/provider-element.html#rprmsn">readPermission</a></code>,
<code><a href="{@docRoot}guide/topics/manifest/provider-element.html#wprmsn">writePermission</a></code>, and
<code><a href="{@docRoot}guide/topics/manifest/provider-element.html#prmsn">permission</a></code> attributes
&mdash;
"{@code true}" if permission can be granted, and "{@code false}" if not.
If "{@code true}", permission can be granted to any of the content
provider's data. If "{@code false}", permission can be granted only
to the data subsets listed in
<code><a href="{@docRoot}guide/topics/manifest/grant-uri-permission-element.html">&lt;grant-uri-permission&gt;</a></code> subelements,
if any. The default value is "{@code false}".
<p>
Granting permission is a way of giving an application component one-time
access to data protected by a permission. For example, when an e-mail
message contains an attachment, the mail application may call upon the
appropriate viewer to open it, even though the viewer doesn't have general
permission to look at all the content provider's data.
</p>
<p>
In such cases, permission is granted by
<code>{@link android.content.Intent#FLAG_GRANT_READ_URI_PERMISSION}</code>
and <code>{@link android.content.Intent#FLAG_GRANT_WRITE_URI_PERMISSION}</code>
flags in the Intent object that activates the component. For example, the
mail application might put {@code FLAG_GRANT_READ_URI_PERMISSION} in the
Intent passed to {@code Context.startActivity()}. The permission is specific
to the URI in the Intent.
</p>
<p>
If you enable this feature, either by setting this attribute to "{@code true}"
or by defining <code><a href="{@docRoot}guide/topics/manifest/grant-uri-permission-element.html">&lt;grant-uri-permission&gt;</a></code>
subelements, you must call
<code>{@link android.content.Context#revokeUriPermission
Context.revokeUriPermission()}</code> when a covered URI is deleted from
the provider.
</p>
<p>
See also the <code><a href="{@docRoot}guide/topics/manifest/grant-uri-permission-element.html">&lt;grant-uri-permission&gt;</a></code>
element.
</p></dd>
<dt><a name="icon"></a>{@code android:icon}</dt>
<dd>An icon representing the content provider.
This attribute must be set as a reference to a drawable resource containing
the image definition. If it is not set, the icon specified for the application
as a whole is used instead (see the <code><a href="{@docRoot}guide/topics/manifest/application-element.html">&lt;application&gt;</a></code>
element's <code><a href="{@docRoot}guide/topics/manifest/application-element.html#icon">icon</a></code> attribute).</dd>
<dt><a name="init"></a>{@code android:initOrder}</dt>
<dd>The order in which the content provider should be instantiated,
relative to other content providers hosted by the same process.
When there are dependencies among content providers, setting this
attribute for each of them ensures that they are created in the order
required by those dependencies. The value is a simple integer,
with higher numbers being initialized first.</dd>
<dt><a name="label"></a>{@code android:label}</dt>
<dd>A user-readable label for the content provided.
If this attribute is not set, the label set for the application as a whole is
used instead (see the <code><a href="{@docRoot}guide/topics/manifest/application-element.html">&lt;application&gt;</a></code> element's
<code><a href="{@docRoot}guide/topics/manifest/application-element.html#label">label</a></code> attribute).
<p>
The label should be set as a reference to a string resource, so that
it can be localized like other strings in the user interface.
However, as a convenience while you're developing the application,
it can also be set as a raw string.
</p></dd>
<dt><a name="multi"></a>{@code android:multiprocess}</dt>
<dd>Whether or not an instance of the content provider can be created in
every client process &mdash; "{@code true}" if instances can run in multiple
processes, and "{@code false}" if not. The default value is "{@code false}".
<p>
Normally, a content provider is instantiated in the process of the
application that defined it. However, if this flag is set to "{@code true}",
the system can create an instance in every process where there's a client
that wants to interact with it, thus avoiding the overhead of interprocess
communication.
</p></dd>
<dt><a name="nm"></a>{@code android:name}</dt>
<dd>The name of the class that implements the content provider, a subclass of
{@link android.content.ContentProvider}. This should be a fully qualified
class name (such as, "{@code com.example.project.TransportationProvider}").
However, as a shorthand, if the first character of the name is a period,
it is appended to the package name specified in the
<code><a href="{@docRoot}guide/topics/manifest/manifest-element.html">&lt;manifest&gt;</a></code> element.
<p>
There is no default. The name must be specified.
</p></dd>
<dt><a name="prmsn"></a>{@code android:permission}</dt>
<dd>The name of a permission that clients must have to read or write the
content provider's data. This attribute is a convenient way of setting a
single permission for both reading and writing. However, the
<code><a href="#rprmsn">readPermission</a></code> and
<code><a href="#wprmsn">writePermission</a></code> attributes take precedence
over this one. If the <code><a href="{@docRoot}guide/topics/manifest/provider-element.html#rprmsn">readPermission</a></code>
attribute is also set, it controls access for querying the content provider.
And if the <code><a href="#wprmsn">writePermission</a></code> attribute is set,
it controls access for modifying the provider's data.
<p>
For more information on permissions, see the
<a href="{@docRoot}guide/topics/manifest/manifest-intro.html#sectperm">Permissions</a>
section in the introduction and a separate document,
<a href="{@docRoot}guide/topics/security/security.html">Security and
Permissions</a>.
</p></dd>
<dt><a name="proc"></a>{@code android:process}</dt>
<dd>The name of the process in which the content provider should run. Normally,
all components of an application run in the default process created for the
application. It has the same name as the application package. The
<code><a href="{@docRoot}guide/topics/manifest/application-element.html">&lt;application&gt;</a></code> element's
<code><a href="{@docRoot}guide/topics/manifest/application-element.html#proc">process</a></code>
attribute can set a different
default for all components. But each component can override the default
with its own {@code process} attribute, allowing you to spread your
application across multiple processes.
<p>
If the name assigned to this attribute begins with a colon (':'), a new
process, private to the application, is created when it's needed and
the activity runs in that process.
If the process name begins with a lowercase character, the activity will run
in a global process of that name, provided that it has permission to do so.
This allows components in different applications to share a process, reducing
resource usage.
</p></dd>
<dt><a name="rprmsn"></a>{@code android:readPermission}</dt>
<dd>A permission that clients must have to query the content provider.
See also the <code><a href="#prmsn">permission</a></code> and
<code><a href="#wprmsn">writePermission</a></code> attributes.</dd>
<dt><a name="sync"></a>{@code android:syncable}</dt>
<dd>Whether or not the data under the content provider's control
is to be synchronized with data on a server &mdash; "{@code true}"
if it is to be synchronized, and "{@ code false}" if not.</dd>
<dt><a name="wprmsn"></a>{@code android:writePermission}</dt>
<dd>A permission that clients must have to make changes to the data
controlled by the content provider.
See also the <code><a href="#prmsn">permission</a></code> and
<code><a href="#rprmsn">readPermission</a></code> attributes.</dd>
</dl></dd>
<!-- ##api level indication## -->
<dt>introduced in:</dt>
<dd>API Level 1</dd>
<dt>see also:</dt>
<dd><a href="{@docRoot}guide/topics/providers/content-providers.html">Content Providers</a></dd>
</dl>
@@ -0,0 +1,168 @@
page.title=&lt;receiver&gt;
@jd:body
<dl class="xml">
<dt>syntax:</dt>
<dd><pre class="stx">&lt;receiver android:<a href="#enabled">enabled</a>=["true" | "false"]
android:<a href="#exported">exported</a>=["true" | "false"]
android:<a href="#icon">icon</a>="<i>drawable resource</i>"
android:<a href="#label">label</a>="<i>string resource</i>"
android:<a href="#nm">name</a>="<i>string</i>"
android:<a href="#prmsn">permission</a>="<i>string</i>"
android:<a href="#proc">process</a>="<i>string</i>" &gt;
. . .
&lt;/receiver&gt;</pre></dd>
<dt>contained in:</dt>
<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/intent-filter-element.html">&lt;intent-filter&gt;</a></code>
<br/><code><a href="{@docRoot}guide/topics/manifest/meta-data-element.html">&lt;meta-data&gt;</a></code></dd>
<dt>description:</dt>
<dd>Declares a broadcast receiver (a {@link android.content.BroadcastReceiver}
subclass) as one of the application's components. Broadcast receivers enable
applications to receive intents that are broadcast by the system or by other
applications, even when other components of the application are not running.
<p>
There are two ways to make a broadcast receiver known to the system: One is
declare it in the manifest file with this element. The other is to create
the receiver dynamically in code and register it with the <code>{@link
android.content.Context#registerReceiver Context.registerReceiver()}</code>
method. See the {@link android.content.BroadcastReceiver} class description
for more on dynamically created receivers.
</p></dd>
<dt>attributes:</dt>
<dd><dl class="attr">
<dt><a name="enabled"></a>{@code android:enabled}</dt>
<dd>Whether or not the broadcast receiver 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 broadcast receivers. The
<code><a href="{@docRoot}guide/topics/manifest/application-element.html">&lt;application&gt;</a></code> and
{@code &lt;receiver&gt;} attributes must both be "{@code true}" for
the broadcast receiver to be enabled. If either is "{@code false}", it is
disabled; it cannot be instantiated.
</p></dd>
<dt><a name="exported"></a>{@code android:exported}</dt>
<dd>Whether or not the broadcast receiver can receive messages from sources
outside its application &mdash; "{@code true}" if it can, and "{@code false}"
if not. If "{@code false}", the only messages the broadcast receiver can
receive are those sent by components of the same application or applications
with the same user ID.
<p>
The default value depends on whether the broadcast receiver contains intent filters.
The absence of any filters means that it can be invoked only by Intent objects that
specify its exact class name. This implies that the receiver is intended only for
application-internal use (since others would not normally know the class name).
So in this case, the default value is "{@code false}".
On the other hand, the presence of at least one filter implies that the broadcast
receiver is intended to receive intents broadcast by the system or other applications,
so the default value is "{@code true}".
</p>
<p>
This attribute is not the only way to limit a broadcast receiver's external exposure.
You can also use a permission to limit the external entities that can send it messages
(see the <code><a href="{@docRoot}guide/topics/manifest/receiver-element.html#prmsn">permission</a></code> attribute).
</p></dd>
<dt><a name="icon"></a>{@code android:icon}</dt>
<dd>An icon representing the broadcast receiver. This attribute must be set
as a reference to a drawable resource containing the image definition.
If it is not set, the icon specified for the application as a whole is used
instead (see the <code><a href="{@docRoot}guide/topics/manifest/application-element.html">&lt;application&gt;</a></code>
element's <code><a href="{@docRoot}guide/topics/manifest/application-element.html#icon">icon</a></code> attribute).
<p>
The broadcast receiver's icon &mdash; whether set here or by the
<code><a href="{@docRoot}guide/topics/manifest/application-element.html">&lt;application&gt;</a></code> element &mdash; is also the
default icon for all the receiver's intent filters (see the
<code><a href="{@docRoot}guide/topics/manifest/intent-filter-element.html">&lt;intent-filter&gt;</a></code> element's
<code><a href="{@docRoot}guide/topics/manifest/intent-filter-element.html#icon">icon</a></code> attribute).
</p></dd>
<dt><a name="label"></a>{@code android:label}</dt>
<dd>A user-readable label for the broadcast receiver. If this attribute is not
set, the label set for the application as a whole is
used instead (see the <code><a href="{@docRoot}guide/topics/manifest/application-element.html">&lt;application&gt;</a></code> element's
<code><a href="{@docRoot}guide/topics/manifest/application-element.html#label">label</a></code> attribute).
<p>
The broadcast receiver's label &mdash; whether set here or by the
<code><a href="{@docRoot}guide/topics/manifest/application-element.html">&lt;application&gt;</a></code> element &mdash; is also the
default label for all the receiver's intent filters (see the
<code><a href="{@docRoot}guide/topics/manifest/intent-filter-element.html">&lt;intent-filter&gt;</a></code> element's
<code><a href="{@docRoot}guide/topics/manifest/intent-filter-element.html#label">label</a></code> attribute).
</p>
<p>
The label should be set as a reference to a string resource, so that
it can be localized like other strings in the user interface.
However, as a convenience while you're developing the application,
it can also be set as a raw string.
</p></dd>
<dt><a name="nm"></a>{@code android:name}</dt>
<dd>The name of the class that implements the broadcast receiver, a subclass of
{@link android.content.BroadcastReceiver}. This should be a fully qualified
class name (such as, "{@code com.example.project.ReportReceiver}"). However,
as a shorthand, if the first character of the name is a period (for example,
"{@code . ReportReceiver}"), it is appended to the package name specified in
the <code><a href="{@docRoot}guide/topics/manifest/manifest-element.html">&lt;manifest&gt;</a></code> element.
<p>
There is no default. The name must be specified.
</p></dd>
<dt><a name="prmsn"></a>{@code android:permission}</dt>
<dd>The name of a permission that broadcasters must have to send a
message to the broadcast receiver.
If this attribute is not set, the permission set by the
<code><a href="{@docRoot}guide/topics/manifest/application-element.html">&lt;application&gt;</a></code> element's
<code><a href="{@docRoot}guide/topics/manifest/application-element.html#prmsn">permission</a></code> attribute applies
to the broadcast receiver. If neither attribute is set, the receiver
is not protected by a permission.
<p>
For more information on permissions, see the
<a href="{@docRoot}guide/topics/manifest/manifest-intro.html#sectperm">Permissions</a>
section in the introduction and a separate document,
<a href="{@docRoot}guide/topics/security/security.html">Security and Permissions</a>.
</p></dd>
<dt><a name="proc"></a>{@code android:process}</dt>
<dd>The name of the process in which the broadcast receiver should run.
Normally, all components of an application run in the default process created
for the application. It has the same name as the application package. The
<code><a href="{@docRoot}guide/topics/manifest/application-element.html">&lt;application&gt;</a></code> element's
<code><a href="{@docRoot}guide/topics/manifest/application-element.html#proc">process</a></code> attribute can set a different
default for all components. But each component can override the default
with its own {@code process} attribute, allowing you to spread your
application across multiple processes.
<p>
If the name assigned to this attribute begins with a colon (':'), a new
process, private to the application, is created when it's needed and
the broadcast receiver runs in that process.
If the process name begins with a lowercase character, the receiver will run
in a global process of that name, provided that it has permission to do so.
This allows components in different applications to share a process, reducing
resource usage.
</p></dd>
</dl></dd>
<!-- ##api level indication## -->
<dt>introduced in:</dt>
<dd>API Level 1</dd>
</dl>
@@ -0,0 +1,180 @@
page.title=&lt;service&gt;
@jd:body
<dl class="xml">
<dt>syntax:</dt>
<dd><pre class="stx">&lt;service android:<a href="#enabled">enabled</a>=["true" | "false"]
android:<a href="#exported">exported[</a>="true" | "false"]
android:<a href="#icon">icon</a>="<i>drawable resource</i>"
android:<a href="#label">label</a>="<i>string resource</i>"
android:<a href="#nm">name</a>="<i>string</i>"
android:<a href="#prmsn">permission</a>="<i>string</i>"
android:<a href="#proc">process</a>="<i>string</i>" &gt;
. . .
&lt;/service&gt;</pre></dd>
<dt>contained in:</dt>
<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/intent-filter-element.html">&lt;intent-filter&gt;</a></code>
<br/><code><a href="{@docRoot}guide/topics/manifest/meta-data-element.html">&lt;meta-data&gt;</a></code></dd>
<dt>description:</dt>
<dd>Declares a service (a {@link android.app.Service} subclass) as one
of the application's components. Unlike activities, services lack a
visual user interface. They're used to implement long-running background
operations or a rich communications API that can be called by other
applications.
<p>
All services must be represented by {@code &lt;service&gt;} elements in
the manifest file. Any that are not declared there will not be seen
by the system and will never be run.
</p></dd>
<dt>attributes:</dt>
<dd><dl class="attr">
<dt><a name="enabled"></a>{@code android:enabled}</dt>
<dd>Whether or not the service 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 services. The
<code><a href="{@docRoot}guide/topics/manifest/application-element.html">&lt;application&gt;</a></code> and {@code &lt;service&gt;}
attributes must both be "{@code true}" (as they both
are by default) for the service to be enabled. If either is
"{@code false}", the service is disabled; it cannot be instantiated.
</p></dd>
<dt><a name="exported"></a>{@code android:exported}</dt>
<dd>Whether or not components of other applications can invoke
the service or interact with it &mdash; "{@code true}" if they can, and
"{@code false}" if not. When the value is "{@code false}", only
components of the same application or applications
with the same user ID can start the service or bind to it.
<p>
The default value depends on whether the service contains intent filters. The
absence of any filters means that it can be invoked only by specifying
its exact class name. This implies that the service is intended only for
application-internal use (since others would not know the class name). So in
this case, the default value is "{@code false}".
On the other hand, the presence of at least one filter implies that the service
is intended for external use, so the default value is "{@code true}".
</p>
<p>
This attribute is not the only way to limit the exposure of a service to other
applications. You can also use a permission to limit the external entities that
can interact with the service (see the <code><a href="{@docRoot}guide/topics/manifest/service-element.html#prmsn">permission</a></code>
attribute).
</p></dd>
<dt><a name="icon"></a>{@code android:icon}</dt>
<dd>An icon representing the service. This attribute must be set as a
reference to a drawable resource containing the image definition.
If it is not set, the icon specified for the application
as a whole is used instead (see the <code><a href="{@docRoot}guide/topics/manifest/application-element.html">&lt;application&gt;</a></code>
element's <code><a href="{@docRoot}guide/topics/manifest/application-element.html#icon">icon</a></code> attribute).
</p>
<p>
The service's icon &mdash; whether set here or by the
<code><a href="{@docRoot}guide/topics/manifest/application-element.html">&lt;application&gt;</a></code> element &mdash; is also the
default icon for all the service's intent filters (see the
<code><a href="{@docRoot}guide/topics/manifest/intent-filter-element.html">&lt;intent-filter&gt;</a></code> element's
<code><a href="{@docRoot}guide/topics/manifest/intent-filter-element.html#icon">icon</a></code> attribute).
</p></dd>
<dt><a name="label"></a>{@code android:label}</dt>
<dd>A name for the service that can be displayed to users.
If this attribute is not set, the label set for the application as a whole is
used instead (see the <code><a href="{@docRoot}guide/topics/manifest/application-element.html">&lt;application&gt;</a></code> element's
<code><a href="{@docRoot}guide/topics/manifest/application-element.html#label">label</a></code> attribute).
<p>
The service's label &mdash; whether set here or by the
<code><a href="{@docRoot}guide/topics/manifest/application-element.html">&lt;application&gt;</a></code> element &mdash; is also the
default label for all the service's intent filters (see the
<code><a href="{@docRoot}guide/topics/manifest/intent-filter-element.html">&lt;intent-filter&gt;</a></code> element's
<code><a href="{@docRoot}guide/topics/manifest/intent-filter-element.html#label">label</a></code> attribute).
</p>
<p>
The label should be set as a reference to a string resource, so that
it can be localized like other strings in the user interface.
However, as a convenience while you're developing the application,
it can also be set as a raw string.
</p></dd>
<dt><a name="nm"></a>{@code android:name}</dt>
<dd>The name of the {@link android.app.Service} subclass that implements
the service. This should be a fully qualified class name (such as,
"{@code com.example.project.RoomService}"). However, as a shorthand, if
the first character of the name is a period (for example, "{@code .RoomService}"),
it is appended to the package name specified in the
<code><a href="{@docRoot}guide/topics/manifest/manifest-element.html">&lt;manifest&gt;</a></code> element.
<p>
There is no default. The name must be specified.
</p></dd>
<dt><a name="prmsn"></a>{@code android:permission}</dt>
<dd>The name of a permission that that an entity must have in order to
launch the service or bind to it. If a caller of
<code>{@link android.content.Context#startService startService()}</code>,
<code>{@link android.content.Context#bindService bindService()}</code>, or
<code>{@link android.content.Context#stopService stopService()}</code>,
has not been granted this permission, the method will not work and the
Intent object will not be delivered to the service.
<p>
If this attribute is not set, the permission set by the
<code><a href="{@docRoot}guide/topics/manifest/application-element.html">&lt;application&gt;</a></code> element's
<code><a href="{@docRoot}guide/topics/manifest/application-element.html#prmsn">permission</a></code>
attribute applies to the service. If neither attribute is set, the service is
not protected by a permission.
</p>
<p>
For more information on permissions, see the
<a href="{@docRoot}guide/topics/manifest/manifest-intro.html#sectperm">Permissions</a>
section in the introduction and a separate document,
<a href="{@docRoot}guide/topics/security/security.html">Security and Permissions</a>.
</p></dd>
<dt><a name="proc"></a>{@code android:process}</dt>
<dd>The name of the process where the service is to run. Normally,
all components of an application run in the default process created for the
application. It has the same name as the application package. The
<code><a href="{@docRoot}guide/topics/manifest/application-element.html">&lt;application&gt;</a></code> element's
<code><a href="{@docRoot}guide/topics/manifest/application-element.html#proc">process</a></code>
attribute can set a different
default for all components. But component can override the default
with its own {@code process} attribute, allowing you to spread your
application across multiple processes.
<p>
If the name assigned to this attribute begins with a colon (':'), a new
process, private to the application, is created when it's needed and
the service runs in that process.
If the process name begins with a lowercase character, the service will run
in a global process of that name, provided that it has permission to do so.
This allows components in different applications to share a process, reducing
resource usage.
</p></dd>
</dl></dd>
<dt>see also:</dt>
<dd><code><a href="{@docRoot}guide/topics/manifest/application-element.html">&lt;application&gt;</a></code>
<br><code><a href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;activity&gt;</a></code></dd>
<!-- ##api level indication## -->
<dt>introduced in:</dt>
<dd>API Level 1</dd>
</dl>
@@ -0,0 +1,114 @@
page.title=&lt;supports-screens&gt;
@jd:body
<dl class="xml">
<dt>syntax:</dt>
<dd>
<pre class="stx">
&lt;supports-screens android:<a href="#small">smallScreens</a>=["true" | "false"]
android:<a href="#normal">normalScreens</a>=["true" | "false"]
android:<a href="#large">largeScreens</a>=["true" | "false"]
android:<a href="#xlarge">xlargeScreens</a>=["true" | "false"]
android:<a href="#any">anyDensity</a>=["true" | "false"] /&gt;
</pre>
</dd>
<dt>contained in:</dt>
<dd><code><a href="{@docRoot}guide/topics/manifest/manifest-element.html">&lt;manifest&gt;</a></code></dd>
<dt>description:</dt>
<dd>Lets you specify the screen dimensions the
application supports. By default a modern application (using API Level 4 or higher) supports all
screen sizes and must explicitly disable certain screen sizes here;
older applications are assumed to support only the "normal"
screen size. Note that screen size is a separate axis from
density. Screen size is determined as the available pixels to an application
after density scaling has been applied.
<p>Based on the target device screen density, the Android
framework will scale down assets by a factor of 0.75 (low dpi screens)
or scale them up by a factor of 1.5 (high dpi screens).
The screen density is expressed as dots-per-inch (dpi).</p>
<p>For more information, see
<a href="{@docRoot}guide/practices/screens_support.html">Supporting Multiple Screens</a>.</p>
<dt>attributes:</dt>
<dd>
<dl class="attr"><dt><a name="small"></a>{@code android:smallScreens}</dt>
<dd>Indicates whether the application supports smaller screen form-factors.
A small screen is defined as one with a smaller aspect ratio than
the "normal" (traditional HVGA) screen. An application that does
not support small screens <em>will not be available</em> for
small screen devices, because there is little the platform can do
to make such an application work on a smaller screen. If the application has set the <a
href="{@docRoot}guide/topics/manifest/uses-sdk-element.html">{@code &lt;uses-sdk&gt;}</a> element's
{@code android:minSdkVersion} or {@code android:targetSdkVersion} attribute to "4" or higher,
the default value for this is "true", any value less than "4" results in this set to "false".
</dd>
<dt><a name="normal"></a>{@code android:normalScreens}</dt>
<dd>Indicates whether an application supports the "normal" screen
form-factors. Traditionally this is an HVGA medium density
screen, but WQVGA low density and WVGA high density are also
considered to be normal. This attribute is "true" by default,
and applications currently should leave it that way.
</dd>
<dt><a name="large"></a>{@code android:largeScreens}</dt>
<dd>Indicates whether the application supports larger screen form-factors.
A large screen is defined as a screen that is significantly larger
than a "normal" phone screen, and thus may require some special care
on the application's part to make good use of it. An application that
does not support large screens (declares this "false")&mdash;but does support "normal" or
"small" screens&mdash;will be placed as a "postage stamp" on
a large screen, so that it retains the dimensions it was originally
designed for. If the application has set the <a
href="{@docRoot}guide/topics/manifest/uses-sdk-element.html">{@code &lt;uses-sdk&gt;}</a> element's
{@code android:minSdkVersion} or {@code android:targetSdkVersion} attribute to "4" or higher,
the default value for this is "true", any value less than "4" results in this set to "false".
</dd>
<dt><a name="xlarge"></a>{@code android:xlargeScreens}</dt>
<dd>Indicates whether the application supports extra large screen form-factors.
An xlarge screen is defined as a screen that is significantly larger
than a "large" screen, such as a tablet (or something larger) and may require special care
on the application's part to make good use of it. An application that
does not support xlarge screens (declares this "false")&mdash;but does support "large",
"normal", or "small" screens&mdash;will be placed as a "postage stamp" on
an xlarge screen, so that it retains the dimensions it was originally
designed for. If the application has set the <a
href="{@docRoot}guide/topics/manifest/uses-sdk-element.html">{@code &lt;uses-sdk&gt;}</a> element's
{@code android:minSdkVersion} or {@code android:targetSdkVersion} attribute to "4" or higher,
the default value for this is "true", any value less than "4" results in this set to "false".
<p>This attribute was introduced in API Level 9.</p>
</dd>
<dt><a name="any"></a>{@code android:anyDensity}</dt>
<dd>Indicates whether the application includes resources to accommodate any screen
density. Older applications (before API Level 4) are assumed unable to
accomodate all densities and this is "false" by default. Applications using
API Level 4 or higher are assumed able to and this is "true" by default.
You can explicitly supply your abilities here.
</dd>
</dl></dd>
<!-- ##api level indication## -->
<dt>introduced in:</dt>
<dd>API Level 4</dd>
<dt>see also:</dt>
<dd>
<ul>
<li><a href="{@docRoot}guide/practices/screens_support.html">Supporting Multiple
Screens</a></li>
<li>{@link android.util.DisplayMetrics}</li>
</ul>
</dd>
</dl>
@@ -0,0 +1,181 @@
page.title=&lt;uses-configuration&gt;
@jd:body
<!-- ##api level 3## see comment below -->
<!-- the "no___" values are nonsensical if they mean "doesn't work on devices with a
keyboard / navigation control / touch screen." Dianne says that that's what they mean and
that they therefore should be eliminated. Suchi says that they mean "doesn't require a
keyboard / navigation control / touch screen to work." But then what does "undefined" mean?
Seems like some API change is in the works, either eliminating the "no___" values or
"undefined". Since it's unclear what the change will be, I've chosen to document the "no___"
and "undefined" attributes using the same language, which is surely wrong but may make it
easier to update the doc when the change is made. -->
<dl class="xml">
<dt>syntax:</dt>
<dd><pre class="stx">&lt;uses-configuration android:<a href="#five">reqFiveWayNav</a>=["true" | "false"]
android:<a href="#hard">reqHardKeyboard</a>=["true" | "false"]
android:<a href="#kbd">reqKeyboardType</a>=["undefined" | "nokeys" | "qwerty" |
"twelvekey"]
android:<a href="#nav">reqNavigation</a>=["undefined" | "nonav" | "dpad" |
"trackball" | "wheel"]
android:<a href="#touch">reqTouchScreen</a>=["undefined" | "notouch" | "stylus" |
"finger"] /&gt;</pre></dd>
<dt>contained in:</dt>
<dd><code><a href="{@docRoot}guide/topics/manifest/manifest-element.html">&lt;manifest&gt;</a></code></dd>
<dt>description:</dt>
<dd>Indicates what hardware and software features the application requires.
For example, an application might specify that it requires a physical keyboard
or a particular navigation device, like a trackball. The specification is
used to avoid installing the application on devices where it will not work.
<p>
If an application can work with different device configurations, it
should include separate {@code &lt;uses-configuration&gt;} declarations for
each one. Each declaration must be complete. For example, if an application
requires a five-way navigation control, a touch screen that can be operated
with a finger, and either a standard QWERTY keyboard or a numeric 12-key
keypad like those found on most phones, it would specify these requirements
with two {@code &lt;uses-configuration&gt;} elements as follows:
</p>
<pre>&lt;uses-configuration android:reqFiveWayNav="true" android:reqTouchScreen="finger"
android:reqKeyboardType="qwerty" /&gt;
&lt;uses-configuration android:reqFiveWayNav="true" android:reqTouchScreen="finger"
android:reqKeyboardType="twelvekey" /&gt;</pre></dd>
<dt>attributes:</dt>
<dd><dl class="attr">
<dt><a name="five"></a>{@code android:reqFiveWayNav}</dt>
<dd>Whether or not the application requires a five-way navigation control
&mdash; "{@code true}" if it does, and "{@code false}" if not. A five-way
control is one that can move the selection up, down, right, or left, and
also provides a way of invoking the current selection. It could be a
D-pad (directional pad), trackball, or other device.
<p>
If an application requires a directional control, but not a control of a
particular type, it can set this attribute to "{@code true}" and ignore
the <code><a href="#nav">reqNavigation</a></code> attribute. However,
if it requires a particular type of directional control, it can ignore
this attribute and set {@code reqNavigation} instead.
</p></dd>
<dt><a name="hard"></a>{@code android:reqHardKeyboard}</dt>
<dd>Whether or not the application requires a hardware keyboard &mdash;
"{@code true}" if it does, and "{@code false}" if not.</dd>
<dt><a name="kbd"></a>{@code android:reqKeyboardType}</dt>
<dd>The type of keyboard the application requires, if any at all.
This attribute does not distinguish between hardware and software
keyboards. If a hardware keyboard of a certain type is required,
specify the type here and also set the {@code reqHardKeyboard} attribute
to "{@code true}".
<p>
The value must be one of the following strings:
</p>
<table>
<tr>
<th>Value</th>
<th>Description</th>
</tr><tr>
<td>"{@code undefined}"</td>
<td>The application does not require a keyboard.
(A keyboard requirement is not defined.)
This is the default value.</td>
</tr><tr>
<td>"{@code nokeys}"</td>
<td>The application does not require a keyboard.</td>
</tr><tr>
<td>"{@code qwerty}"</td>
<td>The application requires a standard QWERTY keyboard.</td>
</tr><tr>
<td>"{@code twelvekey}"</td>
<td>The application requires a twelve-key keypad, like those on most
phones &mdash; with keys for the digits from {@code 0} through
{@code 9} plus star ({@code *}) and pound ({@code #}) keys.</td>
</tr>
</table></dd>
<dt><a name="nav"></a>{@code android:reqNavigation}</dt>
<dd>The navigation device required by the application, if any. The value
must be one of the following strings:
<table>
<tr>
<th>Value</th>
<th>Description</th>
</tr><tr>
<td>"{@code undefined}"</td>
<td>The application does not require any type of navigation control.
(The navigation requirement is not defined.)
This is the default value.</td>
</tr><tr>
<td>"{@code nonav}"</td>
<td>The application does not require a navigation control.</td>
</tr><tr>
<td>"{@code dpad}"</td>
<td>The application requires a D-pad (directional pad) for navigation.</td>
</tr><tr>
<td>"{@code trackball}"</td>
<td>The application requires a trackball for navigation.</td>
</tr><tr>
<td>"{@code wheel}"</td>
<td>The application requires a navigation wheel.</td>
</tr>
</table>
<p>
If an application requires a navigational control, but the exact type of
control doesn't matter, it can set the
<code><a href="#five">reqFiveWayNav</a></code> attribute to "{@code true}"
rather than set this one.
</p></dd>
<dt><a name="touch"></a>{@code android:reqTouchScreen}</dt>
<dd>The type of touch screen the application requires, if any at all.
The value must be one of the following strings:
<table>
<tr>
<th>Value</th>
<th>Description</th>
</tr><tr>
<td>"{@code undefined}"</td>
<td>The application doesn't require a touch screen.
(The touch screen requirement is undefined.)
This is the default value.</td>
</tr><tr>
<td>"{@code notouch}"</td>
<td>The application doesn't require a touch screen.</td>
</tr><tr>
<td>"{@code stylus}"</td>
<td>The application requires a touch screen that's operated with a stylus.</td>
</tr><tr>
<td>"{@code finger}"</td>
<td>The application requires a touch screen that can be operated with a finger.</td>
</tr>
</table></dd>
</dl></dd>
<!-- ##api level 3## -->
<dt>introduced in:</dt>
<dd>API Level 3</dd>
<dt>see also:</dt>
<dd>
<ul>
<li><code><a href="{@docRoot}guide/topics/manifest/activity-element.html#config">configChanges</a></code>
attribute of the
<code><a href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;activity&gt;</a></code>
element</dd></li>
<li>{@link android.content.pm.ConfigurationInfo}</li>
</ul>
</dd>
</dl>
@@ -0,0 +1,898 @@
page.title=&lt;uses-feature&gt;
@jd:body
<dl class="xml">
<dt>syntax:</dt>
<dd>
<pre class="stx">&lt;uses-feature android:<a href="#name">name</a>="<em>string</em>"
android:<a href="#required">required</a>=["true" | "false"]
android:<a href="#glEsVersion">glEsVersion</a>="<em>integer</em>" /&gt;</pre>
</dd>
<dt>contained in:</dt>
<dd><code><a
href="{@docRoot}guide/topics/manifest/manifest-element.html">&lt;manifest&gt;</a></code></dd>
<div class="sidebox-wrapper">
<img id="rule" src="{@docRoot}assets/images/grad-rule-qv.png">
<div id="qv-sub-rule">
<img src="{@docRoot}assets/images/icon_market.jpg" style="float:left;margin:0;padding:0;">
<p style="color:#669999;">Android Market and <code style="color:#669999;">&lt;uses-feature&gt;</code> elements</p>
<p style="margin-top:1em;">Android Market filters the applications that are visible to users, so
that users can see and download only those applications that are compatible with their
devices. One of the ways Market filters applications is by feature compatibility.</p>
<p style="margin-top:1em;">To do this, Market checks the
<code>&lt;uses-feature&gt;</code> elements in each application's manifest, to
establish the app's feature needs. Market then shows or hides the application to
each user, based on a comparison with the features available on the user's
device. </p>
<p style="margin-top:1em;">By specifying the features that your application requires,
you enable Android Market to present your application only to users whose
devices meet the application's feature requirements, rather than presenting it
to all users. </p>
<p style="margin-top:1em;" class="caution">For important information about how
Android Market uses features as the basis for filtering, please read <a
href="#market-feature-filtering">Android Market and Feature-Based Filtering</a>,
below.</p>
</div>
</div>
<dt>description:</dt>
<dd>Declares a single hardware or software feature that is used by the
application.
<p>The purpose of a <code>&lt;uses-feature&gt;</code> declaration is to inform
any external entity of the set of hardware and software features on which your
application depends. The element offers a <code>required</code> attribute that
lets you specify whether your application requires and cannot function without
the declared feature, or whether it prefers to have the feature but can function
without it. Because feature support can vary across Android devices, the
<code>&lt;uses-feature&gt;</code> element serves an important role in letting an
application describe the device-variable features that it uses.</p>
<p>The set of available features that your application declares corresponds to
the set of feature constants made available by the Android {@link
android.content.pm.PackageManager}, which are listed for
convenience in the <a href="#features-reference">Features Reference</a> tables
at the bottom of this document.
<p>You must specify each feature in a separate <code>&lt;uses-feature&gt;</code>
element, so if your application requires multiple features, it would declare
multiple <code>&lt;uses-feature&gt;</code> elements. For example, an application
that requires both Bluetooth and camera features in the device would declare
these two elements:</p>
<pre>
&lt;uses-feature android:name="android.hardware.bluetooth" />
&lt;uses-feature android:name="android.hardware.camera" />
</pre>
<p>In general, you should always make sure to declare
<code>&lt;uses-feature&gt;</code> elements for all of the features that your
application requires.</p>
<p>Declared <code>&lt;uses-feature></code> elements are informational only, meaning
that the Android system itself does not check for matching feature support on
the device before installing an application. However, other services
(such as Android Market) or applications may check your application's
<code>&lt;uses-feature></code> declarations as part of handling or interacting
with your application. For this reason, it's very important that you declare all of
the features (from the list below) that your application uses. </p>
<p>For some features, there may exist a specfic attribute that allows you to define
a version of the feature, such as the version of Open GL used (declared with
<a href="#glEsVersion"><code>glEsVersion</code></a>). Other features that either do or do not
exist for a device, such as a camera, are declared using the
<a href="#name"><code>name</code></a> attribute.</p>
<p>Although the <code>&lt;uses-feature></code> element is only activated for
devices running API Level 4 or higher, it is recommended to include these
elements for all applications, even if the <a href="uses-sdk-element.html#min"><code>minSdkVersion</code></a>
is "3" or lower. Devices running older versions of the platform will simply
ignore the element.</p>
<p class="note"><strong>Note:</strong> When declaring a feature, remember
that you must also request permissions as appropriate. For example, you must
still request the {@link android.Manifest.permission#CAMERA}
permission before your application can access the camera API. Requesting the
permission grants your application access to the appropriate hardware and
software, while declaring the features used by your application ensures proper
device compatibility.</p>
</dd>
<dt>attributes:</dt>
<dd>
<dl class="attr">
<dt><a name="name"></a><code>android:name</code></dt>
<dd>Specifies a single hardware or software feature used by the application,
as a descriptor string. Valid descriptor values are listed in the <a
href="#hw-features">Hardware features</a> and <a href="#sw-features">Software
features</a> tables, below. </dd>
<dt><a name="required"></a><code>android:required</code></dt> <!-- added in api level 5 -->
<dd>Boolean value that indicates whether the application requires
the feature specified in <code>android:name</code>.
<ul>
<li>When you declare <code>"android:required="true"</code> for a feature,
you are specifying that the application <em>cannot function, or is not
designed to function</em>, when the specified feature is not present on the
device. </li>
<li>When you declare <code>"android:required="false"</code> for a feature, it
means that the application <em>prefers to use the feature</em> if present on
the device, but that it <em>is designed to function without the specified
feature</em>, if necessary. </li>
</ul>
<p>The default value for <code>android:required</code> if not declared is
<code>"true"</code>.</p>
</dd>
<dt><a name="glEsVersion"></a><code>android:glEsVersion</code></dt>
<dd>The OpenGL ES version required by the application. The higher 16 bits
represent the major number and the lower 16 bits represent the minor number. For
example, to specify OpenGL ES version 2.0, you would set the value as
"0x00020000". To specify OpenGL ES 2.1, if/when such a version were made
available, you would set the value as "0x00020001".
<p>An application should specify at most one <code>android:glEsVersion</code>
attribute in its manifest. If it specifies more than one, the
<code>android:glEsVersion</code> with the numerically highest value is used and
any other values are ignored.</p>
<p>If an application does not specify an <code>android:glEsVersion</code>
attribute, then it is assumed that the application requires only OpenGL ES 1.0,
which is supported by all Android-powered devices.</p>
<p>An application can assume that if a platform supports a given OpenGL ES
version, it also supports all numerically lower OpenGL ES versions. Therefore,
an application that requires both OpenGL ES 1.0 and OpenGL ES 2.0 must specify
that it requires OpenGL ES 2.0.</p>
<p>An application that can work with any of several OpenGL ES versions should
only specify the numerically lowest version of OpenGL ES that it requires. (It
can check at run-time whether a higher level of OpenGL ES is available.)</p>
</dd>
</dl>
</dd>
<!-- ##api level indication## -->
<dt>introduced in:</dt>
<dd>API Level 4</dd>
<dt>see also:</dt>
<dd>
<ul>
<li>{@link android.content.pm.PackageManager}</li>
<li>{@link android.content.pm.FeatureInfo}</li>
<li>{@link android.content.pm.ConfigurationInfo}</li>
<li><a href="{@docRoot}guide/topics/manifest/uses-permission-element.html"><code>&lt;uses-permission&gt;</code></a></li>
<li><a href="{@docRoot}guide/appendix/market-filters.html">Android Market Filters</a></li>
</ul>
</dd>
</dl>
<h2 id="market-feature-filtering">Android Market and Feature-Based Filtering</h2>
<p>Android Market filters the applications that are visible to users, so that
users can see and download only those applications that are compatible with
their devices. One of the ways Market filters applications is by feature
compatibility.</p>
<p>To determine an application's feature compatibility with a given user's
device, the Android Market service compares:</p>
<ul>
<li>Features required by the application &mdash; an application declares features in
<code>&lt;uses-feature&gt;</code> elements in its manifest <br/>with...</li>
<li>Features available on the device, in hardware or software &mdash;
a device reports the features it supports as read-only system properties.</li>
</ul>
<p>To ensure an accurate comparison of features, the Android Package Manager
provides a shared set of feature constants that both applications and devices
use to declare feature requirements and support. The available feature constants
are listed in the <a href="#features-reference">Features Reference</a> tables at
the bottom of this document, and in the class documentation for {@link
android.content.pm.PackageManager}.</p>
<p>When the user launches the Market application, the application queries the
Package Manager for the list of features available on the device by calling
{@link android.content.pm.PackageManager#getSystemAvailableFeatures()}. The
Market application then passes the features list up to the Android Market
service when establishing the session for the user.</p>
<p>Each time you upload an application to the Android Market Publisher Site,
Android Market scans the application's manifest file. It looks for
<code>&lt;uses-feature&gt;</code> elements and evaluates them in combination
with other elements, in some cases, such as <code>&lt;uses-sdk&gt;</code> and
<code>&lt;uses-permission&gt;</code> elements. After establishing the
application's set of required features, it stores that list internally as
metadata associated with the application <code>.apk</code> and the application
version. </p>
<p>When a user searches or browses for applications using the Android Market
application, the service compares the features needed by each application with
the features available on the user's device. If all of an application's required
features are present on the device, Android Market allows the user to see the
application and potentially download it. If any required feature is not
supported by the device, Android Market filters the application so that it is
not visible to the user and not available for download. </p>
<p>Because the features you declare in <code>&lt;uses-feature&gt;</code>
elements directly affect how Android Market filters your application, it's
important to understand how Android Market evaluates the application's manifest
and establishes the set of required features. The sections below provide more
information. </p>
<h3 id="declared">Filtering based on explicitly declared features</h3>
<p>An explicitly declared feature is one that your application declares in a
<code>&lt;uses-feature&gt;</code> element. The feature declaration can include
an <code>android:required=["true" | "false"]</code> attribute (if you are
compiling against API level 5 or higher), which lets you specify whether the
application absolutely requires the feature and cannot function properly without
it (<code>"true"</code>), or whether the application prefers to use the feature
if available, but is designed to run without it (<code>"false"</code>).</p>
<p>Android Market handles explictly declared features in this way: </p>
<ul>
<li>If a feature is explicitly declared as being required, Android Market adds
the feature to the list of required features for the application. It then
filters the application from users on devices that do not provide that feature.
For example:
<pre>&lt;uses-feature android:name="android.hardware.camera" android:required="true" /&gt;</pre></li>
<li>If a feature is explicitly declared as <em>not</em> being required, Android
Market <em>does not</em> add the feature to the list of required features. For
that reason, an explicity declared non-required feature is never considered when
filtering the application. Even if the device does not provide the declared
feature, Android Market will still consider the application compatible with the
device and will show it to the user, unless other filtering rules apply. For
example:
<pre>&lt;uses-feature android:name="android.hardware.camera" android:required="false" /&gt;</pre></li>
<li>If a feature is explicitly declared, but without an
<code>android:required</code> attribute, Android Market assumes that the feature
is required and sets up filtering on it. </li>
</ul>
<p>In general, if your application is designed to run on Android 1.6 and earlier
versions, the <code>android:required</code> attribute is not available in the
API and Android Market assumes that any and all
<code>&lt;uses-feature&gt;</code> declarations are required. </p>
<p class="note"><strong>Note:</strong> By declaring a feature explicitly and
including an <code>android:required="false"</code> attribute, you can
effectively disable all filtering on Android Market for the specified feature.
</p>
<h3 id="implicit">Filtering based on implicit features</h3>
<p>An <em>implicit</em> feature is one that an application requires in order to
function properly, but which is <em>not</em> declared in a
<code>&lt;uses-feature&gt;</code> element in the manifest file. Strictly
speaking, every application should <em>always</em> declare all features that it
uses or requires, so the absence of a declaration for a feature used by an
application should be considered an error. However, as a safeguard for users and
developers, Android Market looks for implicit features in each application and
sets up filters for those features, just as it would do for an explicitly
declared feature. </p>
<p>An application might require a feature but not declare it because: </p>
<ul>
<li>The application was compiled against an older version of the Android library
(Android 1.5 or earlier) and the <code>&lt;uses-feature&gt;</code> element was
not available.</li>
<li>The developer incorrectly assumed that the feature would be present on all
devices and a declaration was unnecessary.</li>
<li>The developer omitted the feature declaration accidentally.</li>
<li>The developer declared the feature explicitly, but the declaration was not
valid. For example, a spelling error in the <code>&lt;uses-feature&gt;</code>
element name or an unrecognized string value for the
<code>android:name</code> attribute would invalidate the feature declaration.
</li>
</ul>
<p>To account for the cases above, Android Market attempts to discover an
application's implied feature requirements by examining <em>other elements</em>
declared in the manifest file, specifically,
<code>&lt;uses-permission&gt;</code> elements.</p>
<p>If an application requests hardware-related permissions, Android Market
<em>assumes that the application uses the underlying hardware features and
therefore requires those features</em>, even though there might be no
corresponding to <code>&lt;uses-feature&gt;</code> declarations. For such
permissions, Android Market adds the underlying hardware features to the
metadata that it stores for the application and sets up filters for them.</p>
<p>For example, if an application requests the <code>CAMERA</code> permission
but does not declare a <code>&lt;uses-feature&gt;</code> element for
<code>android.hardware.camera</code>, Android Market considers that the
application requires a camera and should not be shown to users whose devices do
not offer a camera.</p>
<p>If you don't want Android Market to filter based on a specific implied
feature, you can disable that behavior. To do so, declare the feature explicitly
in a <code>&lt;uses-feature&gt;</code> element and include an
<code>android:required="false"</code> attribute. For example, to disable
filtering derived from the <code>CAMERA</code> permission, you would declare
the feature as shown below.</p>
<pre>&lt;uses-feature android:name="android.hardware.camera" android:required="false" /&gt;</pre>
<p class="caution">It's important to understand that the permissions that you
request in <code>&lt;uses-permission&gt;</code> elements can directly affect how
Android Market filters your application. The reference section <a
href="#permissions">Permissions that Imply Feature Requirements</a>,
below, lists the full set of permissions that imply feature requirements and
therefore trigger filtering.</p>
<h3 id="bt-permission-handling">Special handling for Bluetooth feature</h3>
<p>Android Market applies slightly different rules than described above, when
determining filtering for Bluetooth.</p>
<p>If an application declares a Bluetooth permission in a
<code>&lt;uses-permission&gt;</code> element, but does not explicitly declare
the Bluetooth feature in a <code>&lt;uses-feature&gt;</code> element, Android
Market checks the version(s) of the Android platform on which the application is
designed to run, as specified in the <code>&lt;uses-sdk&gt;</code> element. </p>
<p>As shown in the table below, Android Market enables filtering for the
Bluetooth feature only if the application declares its lowest or targeted
platform as Android 2.0 (API level 5) or higher. However, note that Android
market applies the normal rules for filtering when the application explicitly
declares the Bluetooth feature in a <code>&lt;uses-feature&gt;</code> element.
</p>
<p class="caption"><strong>Table 1.</strong> How Android Market determines the
Bluetooth feature requirement for an application that requests a Bluetooth
permission but does not declare the Bluetooth feature in a
<code>&lt;uses-feature&gt;</code> element.</p>
<table style="margin-top:1em;">
<tr>
<th><nobr>If <code>minSdkVersion</code> is ...</nobr></th>
<th><nobr>or <code>targetSdkVersion</code> is</nobr></th>
<th>Result</th>
</tr>
<tr>
<td><nobr>&lt;=4 (or uses-sdk is not declared)</nobr></td>
<td>&lt;=4</td>
<td>Android Market <em>will not</em> filter the application from any devices
based on their reported support for the <code>android.hardware.bluetooth</code>
feature.</td>
</tr>
<tr>
<td>&lt;=4</td>
<td>&gt;=5</td>
<td rowspan="2">Android Market filters the application from any devices that
do not support the <code>android.hardware.bluetooth</code> feature (including
older releases).</td>
</tr>
<tr>
<td>&gt;=5</td>
<td>&gt;=5</td>
</tr>
</table>
<p>The examples below illustrate the different filtering effects, based on how
Android Market handles the Bluetooth feature. </p>
<dl>
<dt>In first example, an application that is designed to run on older API levels
declares a Bluetooth permission, but does not declare the Bluetooth feature in a
<code>&lt;uses-feature&gt;</code> element.</dt>
<dd><em>Result:</em> Android Market does not filter the application from any device.</dd>
</dl>
<pre>&lt;manifest ...>
&lt;uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
&lt;uses-sdk android:minSdkVersion="3" />
...
&lt;/manifest></pre>
<dl>
<dt>In the second example, below, the same application also declares a target
API level of "5". </dt>
<dd><em>Result:</em> Android Market now assumes that the feature is required and
will filter the application from all devices that do not report Bluetooth support,
including devices running older versions of the platform. </dd>
</dl>
<pre>&lt;manifest ...>
&lt;uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
&lt;uses-sdk android:minSdkVersion="3" android:targetSdkVersion="5" />
...
&lt;/manifest></pre>
<dl>
<dt>Here the same application now specifically declares the Bluetooth feature.</dt>
<dd><em>Result:</em> Identical to the previous example (filtering is applied).</dd>
</dl>
<pre>&lt;manifest ...>
&lt;uses-feature android:name="android.hardware.bluetooth" />
&lt;uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
&lt;uses-sdk android:minSdkVersion="3" android:targetSdkVersion="5" />
...
&lt;/manifest></pre>
<dl>
<dt>Finally, in the case below, the same application adds an
<code>android:required="false"</code> attribute.</dt>
<dd><em>Result:</em> Android Market disables filtering based on Bluetooth
feature support, for all devices.</dd>
</dl>
<pre>&lt;manifest ...>
&lt;uses-feature android:name="android.hardware.bluetooth" android:required="false" />
&lt;uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
&lt;uses-sdk android:minSdkVersion="3" android:targetSdkVersion="5" />
...
&lt;/manifest></pre>
<h3>Testing the features required by your application</h3>
<p>You can use the <code>aapt</code> tool, included in the Android SDK, to
determine how Android Market will filter your application, based on its declared
features and permissions. To do so, run <code>aapt</code> with the <code>dump
badging</code> command. This causes <code>aapt</code> to parse your
application's manifest and apply the same rules as used by Android Market to
determine the features that your application requires. </p>
<p>To use the tool, follow these steps: </p>
<ol>
<li>First, build and export your application as an unsigned <code>.apk</code>.
If you are developing in Eclipse with ADT, right-click the project and select
<strong>Android Tools</strong> &gt; <strong>Export Unsigned Application
Package</strong>. Select a destination filename and path and click
<strong>OK</strong>. </li>
<li>Next, locate the <code>aapt</code> tool, if it is not already in your PATH.
If you are using SDK Tools r8 or higher, you can find <code>aapt</code> in the
<code>&lt;<em>SDK</em>&gt;/platform-tools/</code> directory.
<p class="note"><strong>Note:</strong> You must use the version of
<code>aapt</code> that is provided for the latest Platform-Tools component available. If
you do not have the latest Platform-Tools component, download it using the <a
href="{@docRoot}sdk/adding-components.html">Android SDK and AVD Manager</a>.
</p></li>
<li>Run <code>aapt</code> using this syntax: </li>
</ol>
<pre>$ aapt dump badging &lt;<em>path_to_exported_.apk</em>&gt;</pre>
<p>Here's an example of the command output for the second Bluetooth example, above: </p>
<pre>$ ./aapt dump badging BTExample.apk
package: name='com.example.android.btexample' versionCode='' versionName=''
<strong>uses-permission:'android.permission.BLUETOOTH_ADMIN'</strong>
<strong>uses-feature:'android.hardware.bluetooth'</strong>
sdkVersion:'3'
targetSdkVersion:'5'
application: label='BT Example' icon='res/drawable/app_bt_ex.png'
launchable activity name='com.example.android.btexample.MyActivity'label='' icon=''
uses-feature:'android.hardware.touchscreen'
main
supports-screens: 'small' 'normal' 'large'
locales: '--_--'
densities: '160'
</pre>
<h2 id=features-reference>Features Reference</h2>
<p>The tables below provide reference information about hardware and software
features and the permissions that can imply them on Android Market. </p>
<h3 id="hw-features">Hardware features</h3>
<p>The table below describes the hardware feature descriptors supported by the
most current platform release. To signal that your application uses or requires
a hardware feature, declare each value in a <code>android:name</code> attribute
in a separate <code>&lt;uses-feature&gt;</code> element. </p>
<table>
<tr>
<th>Feature Type</th>
<th>Feature Descriptor</th>
<th>Description</th>
<th>Comments</th>
</tr>
<tr>
<td>Audio</td>
<td><code>android.hardware.audio.low_latency</td>
<td>The application uses a low-latency audio pipeline on the device and
is sensitive to delays or lag in sound input or output.</td>
<td>
</td>
</tr>
<tr>
<td>Bluetooth</td>
<td><code>android.hardware.bluetooth</td>
<td>The application uses Bluetooth radio features in the device.</td>
<td>
</td>
</tr>
<tr>
<td rowspan="4">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
away from the screen.</td>
<td></td>
</tr>
<tr>
<td><code>android.hardware.camera.autofocus</code></td>
<td>Subfeature. The application uses the device camera's autofocus capability.</td>
<td rowspan="3">If declared with the <code>"android:required="true"</code>
attribute, these subfeatures implicitly declare the
<code>android.hardware.camera</code> parent feature. </td>
</tr>
<tr>
<td><code>android.hardware.camera.flash</code></td>
<td>Subfeature. The application uses the device camera's flash.</td>
</tr>
<tr>
<td><code>android.hardware.camera.front</code></td>
<td>Subfeature. The application uses a front-facing camera on the device.</td>
</tr>
<tr>
<td rowspan="3">Location</td>
<td><code>android.hardware.location</code></td>
<td>The application uses one or more features on the device for determining
location, such as GPS location, network location, or cell location.</td>
<td></td>
</tr>
<tr>
<td><code>android.hardware.location.network</code></td>
<td>Subfeature. The application uses coarse location coordinates obtained from
a network-based geolocation system supported on the device.</td>
<td rowspan="2">If declared with the <code>"android:required="true"</code>
attribute, these subfeatures implicitly declare the
<code>android.hardware.location</code> parent feature. </td>
</tr>
<tr>
<td><code>android.hardware.location.gps</code></td>
<td>Subfeature. The application uses precise location coordinates obtained
from a Global Positioning System receiver on the device. </td>
</tr>
<tr>
<td>Microphone</td>
<td><code>android.hardware.microphone</code></td>
<td>The application uses a microphone on the device.
</td>
<td></td>
</tr>
<tr>
<td>Near Field Communications</td>
<td><code>android.hardware.nfc</td>
<td>The application uses NFC radio features in the device.</td>
<td></td>
</tr>
<tr>
<td rowspan="6">Sensors</td>
<td><code>android.hardware.sensor.accelerometer</code></td>
<td>The application uses motion readings from an accelerometer on the
device.</td>
<td></td>
</tr>
<tr>
<td><code>android.hardware.sensor.barometer</code></td>
<td>The application uses the device's barometer.</td>
<td></td>
</tr>
<tr>
<td><code>android.hardware.sensor.compass</code></td>
<td>The application uses directional readings from a magnetometer (compass) on
the device.</td>
<td></td>
</tr>
<tr>
<td><code>android.hardware.sensor.gyroscope</code></td>
<td>The application uses the device's gyroscope sensor.</td>
<td></td>
</tr>
<tr>
<td><code>android.hardware.sensor.light</code></td>
<td>The application uses the device's light sensor.</td>
<td></td>
</tr>
<tr>
<td><code>android.hardware.sensor.proximity</code></td>
<td>The application uses the device's proximity sensor.</td>
<td></td>
</tr>
<tr>
<td rowspan="3">Telephony</td>
<td><code>android.hardware.telephony</code></td>
<td>The application uses telephony features on the device, such as telephony
radio with data communication services.</td>
<td></td>
</tr>
<tr>
<td><code>android.hardware.telephony.cdma</code></td>
<td>Subfeature. The application uses CDMA telephony radio features on the
device. </td>
<td rowspan="2">If declared with the <code>"android:required="true"</code>
attribute, these subfeatures implicitly declare the
<code>android.hardware.telephony</code> parent feature. </td>
</tr>
<tr>
<td><code>android.hardware.telephony.gsm</code></td>
<td>Subfeature. The application uses GSM telephony radio features on the
device.</td>
</tr>
<tr>
<td rowspan="4">Touchscreen</td>
<td><code>android.hardware.touchscreen</code></td>
<td>The application uses touchscreen capabilities on the device.</td>
<td></td>
</tr>
<tr>
<td><code>android.hardware.touchscreen.multitouch</code></td>
<td>Subfeature. The application uses basic two-point multitouch capabilities on the device
screen.</td>
<td>If declared with the <code>"android:required="true"</code> attribute, this
subfeature implicitly declares the <code>android.hardware.touchscreen</code>
parent feature. </td>
</tr>
<tr>
<td><code>android.hardware.touchscreen.multitouch.distinct</code></td>
<td>Subfeature. The application uses advanced multipoint multitouch
capabilities on the device screen, such as for tracking two or more points fully
independently.</td>
<td rowspan="2">If declared with the <code>"android:required="true"</code> attribute, this
subfeature implicitly declares the
<code>android.hardware.touchscreen.multitouch</code> parent feature. </td>
</tr>
<tr>
<td><code>android.hardware.touchscreen.multitouch.jazzhand</code></td>
<td>Subfeature. The application uses advanced multipoint multitouch
capabilities on the device screen, for tracking up to five points fully
independently.</td>
</tr>
<tr>
<td>Wifi</td>
<td><code>android.hardware.wifi</code></td>
<td>The application uses 802.11 networking (wifi) features on the device.</td>
<td></td>
</tr>
</table>
<h3 id="sw-features">Software features</h3>
<p>The table below describes the software feature descriptors supported by the
most current platform release. To signal that your application uses or requires
a software feature, declare each value in a <code>android:name</code> attribute
in a separate <code>&lt;uses-feature&gt;</code> element. </p>
<table>
<tr>
<th>Feature</th>
<th>Attribute Value</th>
<th>Description</th>
<th>Comments</th>
</tr>
<tr>
<td>Live Wallpaper</td>
<td><code>android.software.live_wallpaper</code></td>
<td>The application uses or provides Live Wallpapers.</td>
<td></td>
</tr>
<tr>
<td rowspan="2">SIP/VOIP</td>
<td><code>android.software.sip</code></td>
<td>The application uses SIP service on the device.
</td>
<td></td>
</tr>
<tr>
<td><code>android.software.sip.voip</code></td>
<td>Subfeature. The application uses SIP-based VOIP service on the device.
</td>
<td>If declared with the <code>"android:required="true"</code> attribute, this
subfeature implicitly declares the <code>android.software.sip</code>
parent feature.</td>
</tr>
</table>
<h3 id="permissions">Permissions that Imply Feature Requirements</h3>
<p>Some feature constants listed in the tables above were made available to
applications <em>after</em> the corresponding API; for example, the
<code>android.hardware.bluetooth</code> feature was added in Android 2.2 (API
level 8), but the bluetooth API that it refers to was added in Android 2.0 (API
level 5). Because of this, some apps were able to use the API before they had
the ability to declare that they require the API via the
<code>&lt;uses-feature&gt;</code> system. </p>
<p>To prevent those apps from being made available unintentionally, Android
Market assumes that certain hardware-related permissions indicate that the
underlying hardware features are required by default. For instance, applications
that use Bluetooth must request the <code>BLUETOOTH</code> permission in a
<code>&lt;uses-permission&gt;</code> element &mdash; for legacy apps, Android
Market assumes that the permission declaration means that the underlying
<code>android.hardware.bluetooth</code> feature is required by the application
and sets up filtering based on that feature. </p>
<p>The table below lists permissions that imply feature requirements
equivalent to those declared in <code>&lt;uses-feature&gt;</code> elements. Note
that <code>&lt;uses-feature&gt;</code> declarations, including any declared
<code>android:required</code> attribute, always take precedence over features
implied by the permissions below. </p>
<p>For any of the permissions below, you can disable filtering based on the
implied feature by explicitly declaring the implied feature explicitly, in a
<code>&lt;uses-feature&gt;</code> element, with an
<code>android:required="false"</code> attribute. For example, to disable any
filtering based on the <code>CAMERA</code> permission, you would add this
<code>&lt;uses-feature&gt;</code> declaration to the manifest file:</p>
<pre>&lt;uses-feature android:name="android.hardware.camera" android:required="false" /&gt;</pre>
<table id="permissions-features" >
<tr>
<th>Category</th>
<th>This Permission...</th>
<th>Implies This Feature Requirement</th>
<!-- <th>Comments</th> -->
</tr>
<tr>
<td rowspan="2">Bluetooth</td>
<td><code>BLUETOOTH</code></td>
<td><code>android.hardware.bluetooth</code>
<p>(See <a href="#bt-permission-handling">Special handling for Bluetooth feature</a> for details.)</p></td>
<!-- <td></td> -->
</tr>
<tr>
<td><code>BLUETOOTH_ADMIN</code></td>
<td><code>android.hardware.bluetooth</code></td>
<!-- <td></td> -->
</tr>
<tr>
<td>Camera</td>
<td><code>CAMERA</code></td>
<td><code>android.hardware.camera</code> <em>and</em>
<br><code>android.hardware.camera.autofocus</code></td>
<!-- <td></td> -->
</tr>
<tr>
<td rowspan="5">Location</td>
<td><code>ACCESS_MOCK_LOCATION</code></td>
<td><code>android.hardware.location</code></td>
<!-- <td></td> -->
</tr>
<tr>
<td><code>ACCESS_LOCATION_EXTRA_COMMANDS</code></td>
<td><code>android.hardware.location</code></td>
<!-- <td></td> -->
</tr>
<tr>
<td><code>INSTALL_LOCATION_PROVIDER</code></td>
<td><code>android.hardware.location</code></td>
<!-- <td></td> -->
</tr>
<tr>
<td><code>ACCESS_COARSE_LOCATION</code></td>
<td><code>android.hardware.location.network</code> <em>and</em>
<br><code>android.hardware.location</code></td>
<!-- <td></td> -->
</tr>
<tr>
<td><code>ACCESS_FINE_LOCATION</code></td>
<td><code>android.hardware.location.gps</code> <em>and</em>
<br><code>android.hardware.location</code></td>
<!-- <td></td> -->
</tr>
<tr>
<td>Microphone</td>
<td><code>RECORD_AUDIO</code></td>
<td><code>android.hardware.microphone</code></td>
<!-- <td></td> -->
</tr>
<tr>
<td rowspan="11">Telephony</td>
<td><code>CALL_PHONE</code></td>
<td><code>android.hardware.telephony</code></td>
<!-- <td></td> -->
</tr>
<tr>
<td><code>CALL_PRIVILEGED</code></td>
<td><code>android.hardware.telephony</code></td>
<!-- <td></td> -->
</tr>
<tr>
<td><code>MODIFY_PHONE_STATE</code></td>
<td><code>android.hardware.telephony</code></td>
<!-- <td></td> -->
</tr>
<tr>
<td><code>PROCESS_OUTGOING_CALLS</code></td>
<td><code>android.hardware.telephony</code></td>
<!-- <td></td> -->
</tr>
<tr>
<td><code>READ_SMS</code></td>
<td><code>android.hardware.telephony</code></td>
<!-- <td></td> -->
</tr>
<tr>
<td><code>RECEIVE_SMS</code></td>
<td><code>android.hardware.telephony</code></td>
<!-- <td></td> -->
</tr>
<tr>
<td><code>RECEIVE_MMS</code></td>
<td><code>android.hardware.telephony</code></td>
<!-- <td></td> -->
</tr>
<tr>
<td><code>RECEIVE_WAP_PUSH</code></td>
<td><code>android.hardware.telephony</code></td>
<!-- <td></td> -->
</tr>
<tr>
<td><code>SEND_SMS</code></td>
<td><code>android.hardware.telephony</code></td>
<!-- <td></td> -->
</tr>
<tr>
<td><code>WRITE_APN_SETTINGS</code></td>
<td><code>android.hardware.telephony</code></td>
<!-- <td></td> -->
</tr>
<tr>
<td><code>WRITE_SMS</code></td>
<td><code>android.hardware.telephony</code></td>
<!-- <td></td> -->
</tr>
<tr>
<td rowspan="3">Wifi</td>
<td><code>ACCESS_WIFI_STATE</code></td>
<td><code>android.hardware.wifi</code></td>
<!-- <td></td> -->
</tr>
<tr>
<td><code>CHANGE_WIFI_STATE</code></td>
<td><code>android.hardware.wifi</code></td>
<!-- <td></td> -->
</tr>
<tr>
<td><code>CHANGE_WIFI_MULTICAST_STATE</code></td>
<td><code>android.hardware.wifi</code></td>
<!-- <td></td> -->
</tr>
</table>
@@ -0,0 +1,36 @@
page.title=&lt;uses-library&gt;
@jd:body
<dl class="xml">
<dt>syntax:</dt>
<dd><pre>&lt;uses-library android:<a href="#nm">name</a>="<i>string</i>" /&gt;</pre></dd>
<dt>contained in:</dt>
<dd><code><a href="{@docRoot}guide/topics/manifest/application-element.html">&lt;application&gt;</a></code></dd>
<dt>description:</dt>
<dd>Specifies a shared library that the application must be linked against.
This element tells the system to include the library's code in the class
loader for the package.
<p>
All of the {@code android} packages (such as {@link android.app},
{@link android.content}, {@link android.view}, and {@link android.widget})
are in the default library that all applications are automatically linked
against. However, some packages (such as {@code maps} and {@code awt} are
in separate libraries that are not automatically linked. Consult the
documentation for the packages you're using to determine which library
contains the package code.
</p></dd>
<dt>attributes:</dt>
<dd><dl class="attr">
<dt><a name="nm"></a>{@code android:name}</dt>
<dd>The name of the library.</dd>
</dl></dd>
<!-- ##api level indication## -->
<dt>introduced in:</dt>
<dd>API Level 1</dd>
</dl>
@@ -0,0 +1,80 @@
page.title=&lt;uses-permission&gt;
@jd:body
<dl class="xml">
<div class="sidebox-wrapper">
<img id="rule" src="{@docRoot}assets/images/grad-rule-qv.png">
<div id="qv-sub-rule">
<img src="{@docRoot}assets/images/icon_market.jpg" style="float:left;margin:0;padding:0;">
<p style="color:#669999;"><code style="color:#669999;">&lt;uses-permission&gt;</code> and filtering on Android Market. </p>
<p style="margin-top:1em;">In some cases, the permissions that you request
through <code>&lt;uses-permission&gt;</code> can affect how
your application is filtered by Android Market.</p>
<p style="margin-top:1em;">If you request a hardware-related permission &mdash;
<code>CAMERA</code>, for example &mdash; Android Market assumes that your
application requires the underlying hardware feature and filters the application
from devices that do not offer it.</p>
<p style="margin-top:1em;">To control filtering, always explicitly declare
hardware features in <code>&lt;uses-feature&gt;</code> elements, rather than
relying on Android Market to "discover" the requirements in
<code>&lt;uses-permission&gt;</code> elements. Then, if you want to disable
filtering for a particular feature, you can add a
<code>android:required="false"</code> attribute to the
<code>&lt;uses-feature&gt;</code> declaration.</p>
<p style="margin-top:1em;" class="caution">For a list of permissions that imply
hardware features, see the documentation for the <a
href="{@docRoot}guide/topics/manifest/uses-feature-element.html#permissions-features">
<code>&lt;uses-feature&gt;</code></a> element.</p>
</div>
</div>
<dt>syntax:</dt>
<dd><pre class="stx">&lt;uses-permission android:<a href="#nm">name</a>="<i>string</i>" /&gt;</pre></dd>
<dt>contained in:</dt>
<dd><code><a href="{@docRoot}guide/topics/manifest/manifest-element.html">&lt;manifest&gt;</a></code></dd>
<dt>description:</dt>
<dd>Requests a permission that the application must be granted in
order for it to operate correctly. Permissions are granted by the user when the
application is installed, not while it's running.
<p>
For more information on permissions, see the
<a href="{@docRoot}guide/topics/manifest/manifest-intro.html#perms">Permissions</a></code>
section in the introduction and the separate
<a href="{@docRoot}guide/topics/security/security.html">Security and Permissions</a> document.
A list of permissions defined by the base platform can be found at
{@link android.Manifest.permission android.Manifest.permission}.
<dt>attributes:</dt>
<dd><dl class="attr">
<dt><a name="nm"></a>{@code android:name}</dt>
<dd>The name of the permission. It can be a permission defined by the
application with the <code><a href="{@docRoot}guide/topics/manifest/permission-element.html">&lt;permission&gt;</a></code>
element, a permission defined by another application, or one of the
standard system permissions, such as "{@code android.permission.CAMERA}"
or "{@code android.permission.READ_CONTACTS}". As these examples show,
a permission name typically includes the package name as a prefix.</dd>
</dl></dd>
<!-- ##api level indication## -->
<dt>introduced in:</dt>
<dd>API Level 1</dd>
<dt>see also:</dt>
<dd>
<ul>
<li><code><a href="{@docRoot}guide/topics/manifest/permission-element.html">&lt;permission&gt;</a></code></li>
<li><code><a href="{@docRoot}guide/topics/manifest/uses-feature-element.html">&lt;uses-feature&gt;</a></code></li>
</ul>
</dd>
</dl>
@@ -0,0 +1,142 @@
page.title=&lt;uses-sdk&gt;
@jd:body
<dl class="xml">
<dt>syntax:</dt>
<dd><pre>
&lt;uses-sdk android:<a href="#min">minSdkVersion</a>="<i>integer</i>"
android:<a href="#target">targetSdkVersion</a>="<i>integer</i>"
android:<a href="#max">maxSdkVersion</a>="<i>integer</i>" /&gt;</pre></dd>
<dt>contained in:</dt>
<dd><code><a href="{@docRoot}guide/topics/manifest/manifest-element.html">&lt;manifest&gt;</a></code></dd>
<dt>description:</dt>
<dd>Lets you express an application's compatibility with one or more versions of the Android platform,
by means of an API Level integer. The API Level expressed by an application will be compared to the
API Level of a given Android system, which may vary among different Android devices.
</p>
<p>Despite its name, this element is used to specify the API Level, <em>not</em>
the version number of the SDK (software development kit) or Android platform.
The API Level is always a single integer. You cannot derive the API Level from
its associated Android version number (for example, it is not the same as the
major version or the sum of the major and minor versions).</p>
<p>For more information, read about
<a href="{@docRoot}guide/appendix/api-levels.html">Android API Levels</a> and
<a href="{@docRoot}guide/publishing/versioning.html">Versioning Your Applications</a>.
</p></dd>
<div class="sidebox-wrapper" xstyle="margin-bottom:2em;margin-top:.5em;width:90%;">
<img id="rule" src="{@docRoot}assets/images/grad-rule-qv.png">
<div id="qv-sub-rule">
<img src="{@docRoot}assets/images/icon_market.jpg" style="float:left;margin:0;padding:0;">
<p style="color:#669999;">Android Market and &lt;uses-sdk&gt; attributes</p>
<p>Android Market filters the applications that are visible to users, so
that users can only see and download applications that are compatible with their
devices. One of the ways Market filters applications is by Android
version-compatibility. To do this, Market checks the <code>&lt;uses-sdk&gt;</code>
attributes in each application's manifest to establish its version-compatibility
range, then shows or hides the application based on a comparison with the API
Level of the user's Android system version. For more information, see <a
href="{@docRoot}guide/appendix/market-filters.html">Market Filters</a>.</p>
</div>
</div>
<dt>attributes:</dt>
<dd>
<dl class="attr">
<dt><a name="min"></a>{@code android:minSdkVersion}</dt>
<dd>An integer designating the minimum API Level required
for the application to run. The Android system will prevent the user from installing
the application if the system's API Level is lower than the value specified in
this attribute. You should always declare this attribute.
<p class="caution"><strong>Caution:</strong> If you do not declare this
attribute, the system assumes a default value of "1", which indicates that your
application is compatible with all versions of Android. If your application is
<em>not</em> compatible with all versions (for instance, it uses APIs introduced
in API Level 3) and you have not declared the proper <code>android:minSdkVersion</code>,
then when installed on a system with an API Level less than 3, the application
will crash during runtime when attempting to access the unavailable APIs. For
this reason, be certain to declare the appropriate API Level in the
<code>minSdkVersion</code> attribute.</p>
</dd>
<dt><a name="target"></a>{@code android:targetSdkVersion}</dt>
<dd>An integer designating the API Level that the application is targetting.
<p>With this attribute set, the application says that it is able to run on
older versions (down to {@code minSdkVersion}), but was explicitly tested to
work with the version specified here. Specifying this target version allows the
platform to disable compatibility settings that are not required for the target
version (which may otherwise be turned on in order to maintain
forward-compatibility) or enable newer features that are not available to older
applications. This does not mean that you can program different features for
different versions of the platform&mdash;it simply informs the platform that you
have tested against the target version and the platform should not perform any
extra work to maintain forward-compatibility with the target version.</p>
<p>Introduced in: API Level 4</p>
</dd>
<dt><a name="max"></a>{@code android:maxSdkVersion}</dt>
<dd>An integer designating the maximum API Level on which the application is
designed to run.
<p>In Android 1.5, 1.6, 2.0, and 2.0.1, the system checks the value of this
attribute when installing an application and when revalidating the application
after a system update. In either case, if the application's
<code>android:maxSdkVersion</code> attribute is lower than the API Level used by
the system itself, then the system will not allow the application to be
installed. In the case of revalidation after system update, this effectively
removes your application from the device.
<p>To illustrate how this attribute can affect your application after system
updates, consider the following example: </p>
<p>An application declaring <code>android:maxSdkVersion="5"</code> in its
manifest is published on Android Market. A user whose device is running Android
1.6 (API Level 4) downloads and installs the app. After a few weeks, the user
receives an over-the-air system update to Android 2.0 (API Level 5). After the
update is installed, the system checks the application's
<code>android:maxSdkVersion</code> and successfully revalidates it. The
application functions as normal. However, some time later, the device receives
another system update, this time to Android 2.0.1 (API Level 6). After the
update, the system can no longer revalidate the application because the system's
own API Level (6) is now higher than the maximum supported by the application
(5). The system prevents the application from being visible to the user, in
effect removing it from the device.</p>
<p class="warning"><strong>Warning:</strong> Declaring this attribute is not
recommended. First, there is no need to set the attribute as means of blocking
deployment of your application onto new versions of the Android platform as they
are released. By design, new versions of the platform are fully
backward-compatible. Your application should work properly on new versions,
provided it uses only standard APIs and follows development best practices.
Second, note that in some cases, declaring the attribute can <strong>result in
your application being removed from users' devices after a system
update</strong> to a higher API Level. Most devices on which your appplication
is likely to be installed will receive periodic system updates over the air, so
you should consider their effect on your application before setting this
attribute.</p>
<p style="margin-bottom:1em;">Introduced in: API Level 4</p>
<div class="special">Future versions of Android (beyond Android 2.0.1) will no
longer check or enforce the <code>android:maxSdkVersion</code> attribute during
installation or revalidation. Android Market will continue to use the attribute
as a filter, however, when presenting users with applications available for
download. </div>
</dd>
</dl></dd>
<!-- ##api level indication## -->
<dt>introduced in:</dt>
<dd>API Level 1</dd>
</dl>
+218
View File
@@ -0,0 +1,218 @@
page.title=Audio and Video
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>Quickview</h2>
<ul>
<li>Audio playback and record</li>
<li>Video playback</li>
<li>Handles data from raw resources, files, streams</li>
<li>Built-in codecs for a variety of media. See <a href="{@docRoot}guide/appendix/media-formats.html">Android Supported Media Formats</a></li>
</ul>
<h2>In this document</h2>
<ol>
<li><a href="#playback">Audio and Video Playback</a>
<ol>
<li><a href="#playraw">Playing from a Raw Resource</li>
<li><a href="#playfile">Playing from a File or Stream</li>
<li><a href="#jet">Playing JET Content</li>
</ol>
</li>
<li><a href="#capture">Audio Capture</a></li>
</ol>
<h2>Key classes</h2>
<ol>
<li>{@link android.media.MediaPlayer MediaPlayer}</li>
<li>{@link android.media.MediaRecorder MediaRecorder}</li>
<li>{@link android.media.JetPlayer JetPlayer}</li>
<li>{@link android.media.SoundPool SoundPool}</li>
</ol>
<h2>See also</h2>
<ol>
<li><a href="{@docRoot}guide/topics/data/data-storage.html">Data Storage</a></li>
<li><a href="{@docRoot}guide/topics/media/jet/jetcreator_manual.html">JetCreator User Manual</a></li>
</ol>
</div>
</div>
<p>The Android platform offers built-in encoding/decoding for a variety of
common media types, so that you can easily integrate audio, video, and images into your
applications. Accessing the platform's media capabilities is fairly straightforward
&mdash; you do so using the same intents and activities mechanism that the rest of
Android uses.</p>
<p>Android lets you play audio and video from several types of data sources. You
can play audio or video from media files stored in the application's resources
(raw resources), from standalone files in the filesystem, or from a data stream
arriving over a network connection. To play audio or video from your
application, use the {@link android.media.MediaPlayer} class.</p>
<p>The platform also lets you record audio and video, where supported by the
mobile device hardware. To record audio or video, use the {@link
android.media.MediaRecorder} class. Note that the emulator doesn't have hardware
to capture audio or video, but actual mobile devices are likely to provide these
capabilities, accessible through the MediaRecorder class. </p>
<p>For a list of media formats for which Android offers built-in support,
see the <a href="{@docRoot}guide/appendix/media-formats.html">Android Media
Formats</a> appendix. </p>
<h2 id="playback">Audio and Video Playback</h2>
<p>Media can be played from anywhere: from a raw resource, from a file from the system,
or from an available network (URL).</p>
<p>You can play back the audio data only to the standard
output device; currently, that is the mobile device speaker or Bluetooth headset. You
cannot play sound files in the conversation audio. </p>
<h3 id="playraw">Playing from a Raw Resource</h3>
<p>Perhaps the most common thing to want to do is play back media (notably sound)
within your own applications. Doing this is easy:</p>
<ol>
<li>Put the sound (or other media resource) file into the <code>res/raw</code>
folder of your project, where the Eclipse plugin (or aapt) will find it and
make it into a resource that can be referenced from your R class</li>
<li>Create an instance of <code>MediaPlayer</code>, referencing that resource using
{@link android.media.MediaPlayer#create MediaPlayer.create}, and then call
{@link android.media.MediaPlayer#start() start()} on the instance:</li>
</ol>
<pre>
MediaPlayer mp = MediaPlayer.create(context, R.raw.sound_file_1);
mp.start();
</pre>
<p>To stop playback, call {@link android.media.MediaPlayer#stop() stop()}. If
you wish to later replay the media, then you must
{@link android.media.MediaPlayer#reset() reset()} and
{@link android.media.MediaPlayer#prepare() prepare()} the MediaPlayer object
before calling {@link android.media.MediaPlayer#start() start()} again.
(<code>create()</code> calls <code>prepare()</code> the first time.)</p>
<p>To pause playback, call {@link android.media.MediaPlayer#pause() pause()}.
Resume playback from where you paused with
{@link android.media.MediaPlayer#start() start()}.</p>
<h3 id="playfile">Playing from a File or Stream</h3>
<p>You can play back media files from the filesystem or a web URL:</p>
<ol>
<li>Create an instance of the <code>MediaPlayer</code> using <code>new</code></li>
<li>Call {@link android.media.MediaPlayer#setDataSource setDataSource()}
with a String containing the path (local filesystem or URL)
to the file you want to play</li>
<li>First {@link android.media.MediaPlayer#prepare prepare()} then
{@link android.media.MediaPlayer#start() start()} on the instance:</li>
</ol>
<pre>
MediaPlayer mp = new MediaPlayer();
mp.setDataSource(PATH_TO_FILE);
mp.prepare();
mp.start();
</pre>
<p>{@link android.media.MediaPlayer#stop() stop()} and
{@link android.media.MediaPlayer#pause() pause()} work the same as discussed
above.</p>
<p class="note"><strong>Note:</strong> It is possible that <code>mp</code> could be
null, so good code should <code>null</code> check after the <code>new</code>.
Also, <code>IllegalArgumentException</code> and <code>IOException</code> either
need to be caught or passed on when using <code>setDataSource()</code>, since
the file you are referencing may not exist.</p>
<p class="note"><strong>Note:</strong>
If you're passing a URL to an online media file, the file must be capable of
progressive download.</p>
<h3 id="jet">Playing JET content</h3>
<p>The Android platform includes a JET engine that lets you add interactive playback of JET audio content in your applications. You can create JET content for interactive playback using the JetCreator authoring application that ships with the SDK. To play and manage JET content from your application, use the {@link android.media.JetPlayer JetPlayer} class.</p>
<p>For a description of JET concepts and instructions on how to use the JetCreator authoring tool, see the <a href="{@docRoot}guide/topics/media/jet/jetcreator_manual.html">JetCreator User Manual</a>. The tool is available fully-featured on the OS X and Windows platforms and the Linux version supports all the content creation features, but not the auditioning of the imported assets. </p>
<p>Here's an example of how to set up JET playback from a .jet file stored on the SD card:</p>
<pre>
JetPlayer myJet = JetPlayer.getJetPlayer();
myJet.loadJetFile("/sdcard/level1.jet");
byte segmentId = 0;
// queue segment 5, repeat once, use General MIDI, transpose by -1 octave
myJet.queueJetSegment(5, -1, 1, -1, 0, segmentId++);
// queue segment 2
myJet.queueJetSegment(2, -1, 0, 0, 0, segmentId++);
myJet.play();
</pre>
<p>The SDK includes an example application &mdash; JetBoy &mdash; that shows how to use {@link android.media.JetPlayer JetPlayer} to create an interactive music soundtrack in your game. It also illustrates how to use JET events to synchronize music and game logic. The application is located at <code>&lt;sdk&gt;/platforms/android-1.5/samples/JetBoy</code>.
<h2 id="capture">Audio Capture</h2>
<p>Audio capture from the device is a bit more complicated than audio/video playback, but still fairly simple:</p>
<ol>
<li>Create a new instance of {@link android.media.MediaRecorder
android.media.MediaRecorder} using <code>new</code></li>
<li>Create a new instance of {@link android.content.ContentValues
android.content.ContentValues} and put in some standard properties like
<code>TITLE</code>, <code>TIMESTAMP</code>, and the all important
<code>MIME_TYPE</code></li>
<li>Create a file path for the data to go to (you can use {@link
android.content.ContentResolver android.content.ContentResolver} to
create an entry in the Content database and get it to assign a path
automatically which you can then use)</li>
<li>Set the audio source using {@link android.media.MediaRecorder#setAudioSource
MediaRecorder.setAudioSource()}. You will probably want to use
<code>MediaRecorder.AudioSource.MIC</code></li>
<li>Set output file format using {@link
android.media.MediaRecorder#setOutputFormat MediaRecorder.setOutputFormat()}
</li>
<li>Set the audio encoder using
{@link android.media.MediaRecorder#setAudioEncoder MediaRecorder.setAudioEncoder()}
</li>
<li>Call {@link android.media.MediaRecorder#prepare prepare()}
on the MediaRecorder instance.</li>
<li>To start audio capture, call
{@link android.media.MediaRecorder#start start()}. </li>
<li>To stop audio capture, call {@link android.media.MediaRecorder#stop stop()}.
<li>When you are done with the MediaRecorder instance, call
{@link android.media.MediaRecorder#release release()} on it. </li>
</ol>
<h3>Example: Audio Capture Setup and Start</h3>
<p>The example below illustrates how to set up, then start audio capture.</p>
<pre>
recorder = new MediaRecorder();
ContentValues values = new ContentValues(3);
values.put(MediaStore.MediaColumns.TITLE, SOME_NAME_HERE);
values.put(MediaStore.MediaColumns.TIMESTAMP, System.currentTimeMillis());
values.put(MediaStore.MediaColumns.MIME_TYPE, recorder.getMimeContentType());
ContentResolver contentResolver = new ContentResolver();
Uri base = MediaStore.Audio.INTERNAL_CONTENT_URI;
Uri newUri = contentResolver.insert(base, values);
if (newUri == null) {
// need to handle exception here - we were not able to create a new
// content entry
}
String path = contentResolver.getDataFilePath(newUri);
// could use setPreviewDisplay() to display a preview to suitable View here
recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
recorder.setOutputFile(path);
recorder.prepare();
recorder.start();
</pre>
<h3>Stop Recording</h3>
<p>Based on the example above, here's how you would stop audio capture. </p>
<pre>
recorder.stop();
recorder.release();
</pre>
File diff suppressed because it is too large Load Diff
+490
View File
@@ -0,0 +1,490 @@
page.title=Session Initiation Protocol
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>In this document</h2>
<ol>
<li><a href="#requirements">Requirements and Limitations</a></li>
<li><a href="#classes">Classes and Interfaces</a></li>
<li><a href="#manifest">Creating the Manifest</a></li>
<li><a href="#manager">Creating a SIP Manager</a></li>
<li><a href="#profiles">Registering with a SIP Server</a></li>
<li><a href="#audio">Making an Audio Call</a></li>
<li><a href="#receiving">Receiving Calls</a></li>
<li><a href="#testing">Testing SIP Applications</a></li>
</ol>
<h2>Key classes</h2>
<ol>
<li>{@link android.net.sip.SipManager}</li>
<li>{@link android.net.sip.SipProfile}</li>
<li>{@link android.net.sip.SipAudioCall}</li>
</ol>
<h2>Related samples</h2>
<ol>
<li> <a href="{@docRoot}resources/samples/SipDemo/index.html"> SipDemo</a></li>
</ol>
</div>
</div>
<p>Android provides an API that supports the Session Initiation Protocol (SIP).
This lets you add SIP-based internet telephony features to your applications.
Android includes a full SIP protocol stack and integrated call management
services that let applications easily set up outgoing and incoming voice calls,
without having to manage sessions, transport-level communication, or audio
record or playback directly.</p>
<p>Here are examples of the types of applications that might use the SIP API:</p>
<ul>
<li>Video conferencing.</li>
<li>Instant messaging.</li>
</ul>
<h2 id="requirements">Requirements and Limitations</h2>
<p>Here are the requirements for developing a SIP application:</p>
<ul>
<li>You must have a mobile device that is running Android 2.3 or higher. </li>
<li>SIP runs over a wireless data connection, so your device must have a data
connection (with a mobile data service or Wi-Fi)</span>. This means that you
can't test on AVD&#8212;you can only test on a physical device. For details, see
<a href="#testing">Testing SIP Applications</a>.</li>
<li>Each participant in the application's communication session must have a
SIP account. There are many different SIP providers that offer SIP accounts.</li>
</ul>
<h2 id="classes">SIP API Classes and Interfaces</h2>
<p>Here is a summary of the classes and one interface
(<code>SipRegistrationListener</code>) that are included in the Android SIP
API:</p>
<table>
<thead>
<tr>
<th>Class/Interface</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>{@link android.net.sip.SipAudioCall}</td>
<td>Handles an Internet audio call over SIP.</td>
</tr>
<tr>
<td>{@link android.net.sip.SipAudioCall.Listener}</td>
<td>Listener for events relating to a SIP call, such as when a call is being
received ("on ringing") or a call is outgoing ("on calling").</td>
</tr>
<tr>
<td>{@link android.net.sip.SipErrorCode}</td>
<td>Defines error codes returned during SIP actions.</td>
</tr>
<tr>
<td>{@link android.net.sip.SipManager}</td>
<td>Provides APIs for SIP tasks, such as initiating SIP connections, and provides access
to related SIP services.</td>
</tr>
<tr>
<td>{@link android.net.sip.SipProfile}</td>
<td>Defines a SIP profile, including a SIP account, domain and server information.
</td>
</tr>
<tr>
<td>{@link android.net.sip.SipProfile.Builder}</td>
<td>Helper class for creating a SipProfile.</td>
</tr>
<tr>
<td>{@link android.net.sip.SipSession}</td>
<td>Represents a SIP session that is associated with a SIP dialog or a standalone transaction
not within a dialog.</td>
</tr>
<tr>
<td>{@link android.net.sip.SipSession.Listener}</td>
<td>Listener for events relating to a SIP session, such as when a session is being registered
("on registering") or a call is outgoing ("on calling"). </td>
</tr>
<tr>
<td>{@link android.net.sip.SipSession.State}</td>
<td>Defines SIP session states, such as "registering", "outgoing call", and "in call". </td>
</tr>
<tr>
<td>{@link android.net.sip.SipRegistrationListener}</td>
<td>An interface that is a listener for SIP registration events.</td>
</tr>
</tbody>
</table>
<h2 id="manifest">Creating the Manifest</h2>
<p>If you are developing an application that uses the SIP API, remember that the
feature is supported only on Android 2.3 (API level 9) and higher versions of
the platform. Also, among devices running Android 2.3 (API level 9) or higher,
not all devices will offer SIP support.</p>
<p>To use SIP, add the following permissions to your application's manifest:</p>
<ul>
<li><code>android.permission.USE_SIP</code></li>
<li><code>android.permission.INTERNET</code></li>
</ul>
<p> To ensure that your application can only be installed on devices that are
capable of supporting SIP, add the following to your application's
manifest:</p>
<ul>
<li><code>&lt;uses-sdk android:minSdkVersion=&quot;9&quot; /&gt;</code>. This
indicates that your application requires Android 2.3 or higher. For more
information, see <a href="{@docRoot}guide/appendix/api-levels.html">API
Levels</a> and the documentation for the <a
href="{@docRoot}guide/topics/manifest/uses-sdk-element.html">&lt;uses-sdk&gt;</a
> element.</li>
</ul>
<p>To control how your application is filtered from devices that do not support
SIP (for example, in Android Market), add the following to your application's
manifest:</p>
<ul>
<li><code>&lt;uses-feature android:name=&quot;android.hardware.sip.voip&quot;
/&gt;</code>. This states that your application uses the SIP API. The
declaration should include an <code>android:required</code> attribute that
indicates whether you want the application to be filtered from devices that do
not offer SIP support. Other <code>&lt;uses-feature&gt;</code> declarations
may also be needed, depending on your implementation. For more information,
see the documentation for the <a
href="{@docRoot}guide/topics/manifest/uses-feature-element.html">&lt;uses-
feature&gt;</a> element.</li>
</ul>
<p>If your application is designed to receive calls, you must also define a receiver ({@link android.content.BroadcastReceiver} subclass) in the application's manifest: </p>
<ul>
<li><code>&lt;receiver android:name=&quot;.IncomingCallReceiver&quot; android:label=&quot;Call Receiver&quot;/&gt;</code></li>
</ul>
<p>Here are excerpts from the <strong>SipDemo</strong> manifest:</p>
<pre>&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;manifest xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
package=&quot;com.example.android.sip&quot;&gt;
...
&lt;receiver android:name=&quot;.IncomingCallReceiver&quot; android:label=&quot;Call Receiver&quot;/&gt;
...
&lt;uses-sdk android:minSdkVersion=&quot;9&quot; /&gt;
&lt;uses-permission android:name=&quot;android.permission.USE_SIP&quot; /&gt;
&lt;uses-permission android:name=&quot;android.permission.INTERNET&quot; /&gt;
...
&lt;uses-feature android:name=&quot;android.hardware.sip.voip&quot; android:required=&quot;true&quot; /&gt;
&lt;uses-feature android:name=&quot;android.hardware.wifi&quot; android:required=&quot;true&quot; /&gt;
&lt;uses-feature android:name=&quot;android.hardware.microphone&quot; android:required=&quot;true&quot; /&gt;
&lt;/manifest&gt;
</pre>
<h2 id="manager">Creating a SipManager</h2>
<p>To use the SIP API, your application must create a {@link
android.net.sip.SipManager} object. The {@link android.net.sip.SipManager} takes
care of the following in your application:</p>
<ul>
<li>Initiating SIP sessions.</li>
<li>Initiating and receiving calls.</li>
<li>Registering and unregistering with a SIP provider.</li>
<li>Verifying session connectivity.</li>
</ul>
<p>You instantiate a new {@link android.net.sip.SipManager} as follows:</p>
<pre>public SipManager mSipManager = null;
...
if(mSipManager == null) {
mSipManager = SipManager.newInstance(this);
}</pre>
<h2 id="profiles">Registering with a SIP Server</h2>
<p>A typical Android SIP application involves one or more users, each of whom
has a SIP account. In an Android SIP application, each SIP account is
represented by a {@link android.net.sip.SipProfile} object.</p>
<p>A {@link android.net.sip.SipProfile} defines a SIP profile, including a SIP
account, and domain and server information. The profile associated with the SIP
account on the device running the application is called the <em>local
profile</em>. The profile that the session is connected to is called the
<em>peer profile</em>. When your SIP application logs into the SIP server with
the local {@link android.net.sip.SipProfile}, this effectively registers the
device as the location to send SIP calls to for your SIP address.</p>
<p>This section shows how to create a {@link android.net.sip.SipProfile},
register it with a SIP server, and track registration events.</p>
<p>You create a {@link android.net.sip.SipProfile} object as follows:</p>
<pre>
public SipProfile mSipProfile = null;
...
SipProfile.Builder builder = new SipProfile.Builder(username, domain);
builder.setPassword(password);
mSipProfile = builder.build();</pre>
<p>The following code excerpt opens the local profile for making calls and/or
receiving generic SIP calls. The caller can make subsequent calls through
<code>mSipManager.makeAudioCall</code>. This excerpt also sets the action
<code>android.SipDemo.INCOMING_CALL</code>, which will be used by an intent
filter when the device receives a call (see <a href="#intent_filter">Setting up
an intent filter to receive calls</a>). This is the registration step:</p>
<pre>Intent intent = new Intent();
intent.setAction(&quot;android.SipDemo.INCOMING_CALL&quot;);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, intent, Intent.FILL_IN_DATA);
mSipManager.open(mSipProfile, pendingIntent, null);</pre>
<p>Finally, this code sets a <code>SipRegistrationListener</code> on the {@link
android.net.sip.SipManager}. This tracks whether the {@link
android.net.sip.SipProfile} was successfully registered with your SIP service
provider:<br>
</p>
<pre>mSipManager.setRegistrationListener(mSipProfile.getUriString(), new SipRegistrationListener() {
public void onRegistering(String localProfileUri) {
updateStatus(&quot;Registering with SIP Server...&quot;);
}
public void onRegistrationDone(String localProfileUri, long expiryTime) {
updateStatus(&quot;Ready&quot;);
}
public void onRegistrationFailed(String localProfileUri, int errorCode,
String errorMessage) {
updateStatus(&quot;Registration failed. Please check settings.&quot;);
}</pre>
<p>When your application is done using a profile, it should close it to free
associated objects into memory and unregister the device from the server. For
example:</p>
<pre>public void closeLocalProfile() {
if (mSipManager == null) {
return;
}
try {
if (mSipProfile != null) {
mSipManager.close(mSipProfile.getUriString());
}
} catch (Exception ee) {
Log.d(&quot;WalkieTalkieActivity/onDestroy&quot;, &quot;Failed to close local profile.&quot;, ee);
}
}</pre>
<h2 id="audio">Making an Audio Call</h2>
<p>To make an audio call, you must have the following in place:</p>
<ul>
<li>A {@link android.net.sip.SipProfile} that is making the call (the
&quot;local profile&quot;), and a valid SIP address to receive the call (the
&quot;peer profile&quot;).
<li>A {@link android.net.sip.SipManager} object. </li>
</ul>
<p>To make an audio call, you should set up a {@link
android.net.sip.SipAudioCall.Listener}. Much of the client's interaction with
the SIP stack happens through listeners. In this snippet, you see how the {@link
android.net.sip.SipAudioCall.Listener} sets things up after the call is
established:</p>
<pre>
SipAudioCall.Listener listener = new SipAudioCall.Listener() {
&#64;Override
public void onCallEstablished(SipAudioCall call) {
call.startAudio();
call.setSpeakerMode(true);
call.toggleMute();
...
}
&#64;Override
public void onCallEnded(SipAudioCall call) {
// Do something.
}
};</pre>
<p>Once you've set up the {@link android.net.sip.SipAudioCall.Listener}, you can
make the call. The {@link android.net.sip.SipManager} method
<code>makeAudioCall</code> takes the following parameters:</p>
<ul>
<li>A local SIP profile (the caller).</li>
<li>A peer SIP profile (the user being called).</li>
<li>A {@link android.net.sip.SipAudioCall.Listener} to listen to the call
events from {@link android.net.sip.SipAudioCall}. This can be <code>null</code>,
but as shown above, the listener is used to set things up once the call is
established.</li>
<li>The timeout value, in seconds.</li>
</ul>
<p>For example:</p>
<pre> call = mSipManager.makeAudioCall(mSipProfile.getUriString(), sipAddress, listener, 30);</pre>
<h2 id="receiving">Receiving Calls</h2>
<p>To receive calls, a SIP application must include a subclass of {@link
android.content.BroadcastReceiver} that has the ability to respond to an intent
indicating that there is an incoming call. Thus, you must do the following in
your application:</p>
<ul>
<li>In <code>AndroidManifest.xml</code>, declare a
<code>&lt;receiver&gt;</code>. In <strong>SipDemo</strong>, this is
<code>&lt;receiver android:name=&quot;.IncomingCallReceiver&quot;
android:label=&quot;Call Receiver&quot;/&gt;</code>.</li>
<li>Implement the receiver, which is a subclass of {@link
android.content.BroadcastReceiver}. In <strong>SipDemo</strong>, this is
<code>IncomingCallReceiver</code>.</li>
<li>Initialize the local profile ({@link android.net.sip.SipProfile}) with a
pending intent that fires your receiver when someone calls the local profile.
</li>
<li>Set up an intent filter that filters by the action that represents an
incoming call. In <strong>SipDemo</strong>, this action is
<code>android.SipDemo.INCOMING_CALL</code>. </li>
</ul>
<h4 id="BroadcastReceiver">Subclassing BroadcastReceiver</h4>
<p>To receive calls, your SIP application must subclass {@link
android.content.BroadcastReceiver}. <span id="internal-source-marker_0.">The
Android system handles incoming SIP calls and broadcasts an &quot;incoming
call&quot;<code></code> intent (as defined by the application) when it receives
a call.</span> Here is the subclassed {@link android.content.BroadcastReceiver}
code from <strong>SipDemo</strong>. To see the full example, go to <a
href="{@docRoot}resources/samples/SipDemo/index.html">SipDemo sample</a>, which
is included in the SDK samples. For information on downloading and installing
the SDK samples, see <a
href="{@docRoot}resources/samples/get.html">
Getting the Samples</a>. </p>
<pre>/*** Listens for incoming SIP calls, intercepts and hands them off to WalkieTalkieActivity.
*/
public class IncomingCallReceiver extends BroadcastReceiver {
/**
* Processes the incoming call, answers it, and hands it over to the
* WalkieTalkieActivity.
* @param context The context under which the receiver is running.
* @param intent The intent being received.
*/
&#64;Override
public void onReceive(Context context, Intent intent) {
SipAudioCall incomingCall = null;
try {
SipAudioCall.Listener listener = new SipAudioCall.Listener() {
&#64;Override
public void onRinging(SipAudioCall call, SipProfile caller) {
try {
call.answerCall(30);
} catch (Exception e) {
e.printStackTrace();
}
}
};
WalkieTalkieActivity wtActivity = (WalkieTalkieActivity) context;
incomingCall = wtActivity.mSipManager.takeAudioCall(intent, listener);
incomingCall.answerCall(30);
incomingCall.startAudio();
incomingCall.setSpeakerMode(true);
if(incomingCall.isMuted()) {
incomingCall.toggleMute();
}
wtActivity.call = incomingCall;
wtActivity.updateStatus(incomingCall);
} catch (Exception e) {
if (incomingCall != null) {
incomingCall.close();
}
}
}
}
</pre>
<h4 id="intent_filter">Setting up an intent filter to receive calls</h4>
<p>When the SIP service receives a new call, it sends out an intent with the
action string provided by the application. In SipDemo, this action string is
<code>android.SipDemo.INCOMING_CALL</code>. </p>
<p>This code excerpt from <strong>SipDemo</strong> shows how the {@link
android.net.sip.SipProfile} object gets created with a pending intent based on
the action string <code>android.SipDemo.INCOMING_CALL</code>. The
<code>PendingIntent</code> object will perform a broadcast when the {@link
android.net.sip.SipProfile} receives a call:</p>
<pre>
public SipManager mSipManager = null;
public SipProfile mSipProfile = null;
...
Intent intent = new Intent();
intent.setAction(&quot;android.SipDemo.INCOMING_CALL&quot;);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, intent, Intent.FILL_IN_DATA);
mSipManager.open(mSipProfile, pendingIntent, null);</pre>
<p>The broadcast will be intercepted by the intent filter, which will then fire
the receiver (<code>IncomingCallReceiver</code>). You can specify an intent
filter in your application's manifest file, or do it in code as in the <strong>SipDemo</strong>
sample application's <code>onCreate()</code> method
of the application's <code>Activity</code>:</p>
<pre>
public class WalkieTalkieActivity extends Activity implements View.OnTouchListener {
...
public IncomingCallReceiver callReceiver;
...
&#64;Override
public void onCreate(Bundle savedInstanceState) {
IntentFilter filter = new IntentFilter();
filter.addAction(&quot;android.SipDemo.INCOMING_CALL&quot;);
callReceiver = new IncomingCallReceiver();
this.registerReceiver(callReceiver, filter);
...
}
...
}
</pre>
<h2 id="testing">Testing SIP Applications</h2>
<p>To test SIP applications, you need the following:</p>
<ul>
<li>A mobile device that is running Android 2.3 or higher. SIP runs over
wireless, so you must test on an actual device. Testing on AVD won't work.</li>
<li>A SIP account. There are many different SIP providers that offer SIP accounts.</li>
<li>If you are placing a call, it must also be to a valid SIP account. </li>
</ul>
<p>To test a SIP application:</p>
<ol>
<li>On your device, connect to wireless (<strong>Settings > Wireless & networks
> Wi-Fi > Wi-Fi settings</strong>)</li>
<li>Set up your mobile device for testing, as described in <a
href="{@docRoot}guide/developing/device.html">Developing on a Device</a>.</li>
<li>Run your application on your mobile device, as described in <a
href="{@docRoot}guide/developing/device.html">Developing on a Device</a>.</li>
<li>If you are using Eclipse, you can view the application log output in Eclipse
using LogCat (<strong>Window > Show View > Other > Android >
LogCat</strong>).</li>
</ol>
+613
View File
@@ -0,0 +1,613 @@
page.title=Near Field Communication
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>Near Field Communication quickview</h2>
<ol>
<li><a href="#api">API Overview</a></li>
<li><a href="#manifest">Declaring Android Manifest Elements</a></li>
<li>
<a href="#dispatch">The Tag Dispatch System</a>
<ol>
<li><a href="#foreground-dispatch">Using the foreground dispatch system</a></li>
<li><a href="#intent-dispatch">Using the intent dispatch system</a></li>
</ol>
</li>
<li><a href="#ndef">NDEF messages</a></li>
<li><a href="#read">Reading an NFC tag</a></li>
<li><a href="#write">Writing to an NFC tag</a></li>
<li><a href="#p2p">Peer to Peer Data Exchange</a></li>
</ol>
</div>
</div>
<p>Near Field Communication (NFC) is a set of short-range wireless technologies, typically
requiring a distance of 4cm or less. NFC operates at 13.56mhz, and at rates ranging
from 106 kbit/s to 848 kbit/s. NFC communication always involves an initiator and a target.
The initiator actively generates an RF field that can power a passive target. This
enables NFC targets to take very simple form factors such as tags, stickers or cards that do
not require power. NFC peer-to-peer communication is also possible, where both devices
are powered.
<p>
Compared to other wireless technologies such as Bluetooth or WiFi, NFC provides much lower
bandwidth and range, but enables low-cost, un-powered targets
and does not require discovery or pairing. Interactions can be initiated with just a tap.
<p>
An Android device with NFC hardware will typically act as an initiator when the screen is
on. This mode is also known as NFC reader/writer. It will actively look for NFC tags and start
activities to handle them. Android 2.3.3 also has some limited P2P support.
<p>
Tags can range in complexity, simple tags just offer read/write semantics, sometimes
with one-time-programmable areas to make the card read-only. More complex tags offer
math operations, and have cryptographic hardware to authenticate access to a sector.
The most sophisticated tags contain operating environments, allowing
complex interactions with code executing on the tag.
<h2 id="api">API Overview</h2>
<p>The {@link android.nfc} package contains the high-level classes to interact
with the local device's NFC adapter, to represent discovered tags, and to use
the NDEF data format.
<table>
<tr>
<th>Class</th>
<th>Description</th>
</tr>
<tr>
<td>{@link android.nfc.NfcManager}</td>
<td>A high level manager class that enumerates the NFC adapters on this Android device.
Since most Android devices only have one NFC adapter, you can just use the static helper
{@link android.nfc.NfcAdapter#getDefaultAdapter(Context)} for most situations.</td>
</tr>
<tr>
<td>{@link android.nfc.NfcAdapter}</td>
<td>Represents the local NFC adapter. Defines the intent's used to request
tag dispatch to your activity, and provides methods to register for foreground
tag dispatch and foreground NDEF push. Foreground NDEF push is the only
peer-to-peer support that is currently provided in Android.</td>
</tr>
<tr>
<td>{@link android.nfc.NdefMessage} and {@link android.nfc.NdefRecord}</td>
<td>NDEF is an NFC Forum defined data structure, designed to efficiently
store data on NFC tags, such as text, URL's, and other MIME types. A
{@link android.nfc.NdefMessage} acts as a
container for the data that you want to transmit or read. One {@link android.nfc.NdefMessage}
object contains zero or more {@link android.nfc.NdefRecord}s. Each NDEF record
has a type such as text, URL, smart poster, or any MIME data. The type of the
first NDEF record in the NDEF message is used to dispatch a tag to an activity
on Android.</td>
</tr>
<tr>
<td>{@link android.nfc.Tag}</td>
<td>Represents a passive NFC target. These can come in many form factors such as
a tag, card, key fob, or even a phone doing card emulation. When a tag is
discovered, a {@link android.nfc.Tag} object is created and wrapped inside an
Intent. The NFC dispatch system sends the intent to a compatible actvitiy
using <code>startActivity()</code>. You can use the {@link
android.nfc.Tag#getTechList getTechList()} method to determine the technologies supported by
this tag and create the corresponding {@link android.nfc.tech.TagTechnology} object with one
of classes provided by {@link android.nfc.tech}.</td>
</tr>
</table>
<p>The {@link android.nfc.tech} package contains classes to query properties
and perform I/O operations on a tag. The classes are divided to represent different
NFC technologies that can be available on a tag.
<p>The {@link android.nfc.tech} package contains classes to query properties and perform I/O
operations on a tag. The classes are divided to represent different NFC technologies that can be
available on a Tag:</p>
<table>
<tr>
<th>Class</th>
<th>Description</th>
</tr>
<tr>
<td>{@link android.nfc.tech.TagTechnology}</td>
<td>The interface that all tag technology classes must implement.</td>
</tr>
<tr>
<td>{@link android.nfc.tech.NfcA}</td>
<td>Provides access to NFC-A (ISO 14443-3A) properties and I/O operations.</td>
</tr>
<tr>
<td>{@link android.nfc.tech.NfcB}</td>
<td>Provides access to NFC-B (ISO 14443-3B) properties and I/O operations.</td>
</tr>
<tr>
<td>{@link android.nfc.tech.NfcF}</td>
<td>Provides access to NFC-F (JIS 6319-4) properties and I/O operations.</td>
</tr>
<tr>
<td>{@link android.nfc.tech.NfcV}</td>
<td>Provides access to NFC-V (ISO 15693) properties and I/O operations.</td>
</tr>
<tr>
<td>{@link android.nfc.tech.IsoDep}</td>
<td>Provides access to ISO-DEP (ISO 14443-4) properties and I/O operations.</td>
</tr>
<tr>
<td>{@link android.nfc.tech.Ndef}</td>
<td>Provides access to NDEF data and operations on NFC tags that have been formatted as NDEF.
</td>
</tr>
<tr>
<td>{@link android.nfc.tech.NdefFormatable}</td>
<td>Provides a format operations for tags that may be NDEF formatable.</td>
</tr>
<tr>
<td>{@link android.nfc.tech.MifareClassic}</td>
<td>Provides access to MIFARE Classic properties and I/O operations, if this
Android device supports MIFARE.</td>
</tr>
<tr>
<td>{@link android.nfc.tech.MifareUltralight}</td>
<td>Provides access to MIFARE Ultralight properties and I/O operations, if this
Android device supports MIFARE.</td>
</tr>
</table>
<h2 id="manifest">Declaring Android Manifest elements</h2>
<p>Before you can access a device's NFC hardware and properly handle NFC intents, declare these
items in your <code>AndroidManifest.xml</code> file:</p>
<ol>
<li>The NFC <code>&lt;uses-permission&gt;</code> element to access the NFC hardware:
<pre>
&lt;uses-permission android:name="android.permission.NFC" /&gt;
</pre>
</li>
<li>The minimum SDK version that your application can support. API level 9 only supports
limited tag dispatch via {@link android.nfc.NfcAdapter#ACTION_TAG_DISCOVERED},
and only gives access to NDEF messages via the {@link android.nfc.NfcAdapter#EXTRA_NDEF_MESSAGES}
extra. No other tag properties or I/O operations are accessible. You probably want
to use API level 10 which includes comprehensive reader/writer support.
<pre class="pretty-print">
&lt;uses-sdk android:minSdkVersion="10"/&gt;
</pre>
</li>
<li>The uses-feature element so that your application can show up in the Android Market for
devices that have NFC hardware:
<pre>
&lt;uses-feature android:name="android.hardware.nfc" android:required="true" /&gt;
</pre>
</li>
<li>The NFC intent filter to tell the Android system your Activity can handle NFC data. Specify
one or more of these three intent filters:
<pre>
&lt;intent-filter&gt;
&lt;action android:name="android.nfc.action.NDEF_DISCOVERED"/&gt;
&lt;data android:mimeType="<em>mime/type</em>" /&gt;
&lt;/intent-filter&gt;
&lt;intent-filter&gt;
&lt;action android:name="android.nfc.action.TECH_DISCOVERED"/&gt;
&lt;meta-data android:name="android.nfc.action.TECH_DISCOVERED"
android:resource="@xml/<em>nfc_tech_filter</em>.xml" /&gt;
&lt;/intent-filter&gt;
&lt;intent-filter&gt;
&lt;action android:name="android.nfc.action.TAG_DISCOVERED"/&gt;
&lt;/intent-filter&gt;
</pre>
<p>The three intent filters are prioritized and behave in specific ways. Declare only the
ones that your Activity needs to handle. For more information on how to handle these filters,
see the section about <a href="#dispatch">The Tag Dispatch System</a>.</p>
</li>
</ol>
<p>View the <a href=
"../../../resources/samples/NFCDemo/AndroidManifest.html">AndroidManifest.xml</a> from the
NFCDemo sample to see a complete example.</p>
<h2 id="dispatch">The Tag Dispatch System</h2>
<p>When an Android device scans an NFC tag, the desired behavior is to have the most appropriate
Activity handle the intent without asking the user what appplication to use. Because devices scan
NFC tags at a very short range, it is likely that making users manually select an Activity forces
them to move the device away from the tag and break the connection. You should develop your
Activity to only handle the NFC tags that your Activity cares about to prevent the Activity
Chooser from appearing. Android provides two systems to help you correctly identify an NFC tag
that your Activity should handle: the Intent dispatch system and the foreground Activity dispatch
system.</p>
<p>The intent dispatch system checks the intent filters of all the Activities along with the
types of data that the Activities support to find the best Activity that can handle the NFC tag.
If multiple Activities specify the same intent filter and data to handle, then the Activity
Chooser is presented to the user as a last resort.</p>
<p>The foreground dispatch system allows an Activity application to override the intent dispatch
system and have priority when an NFC tag is scanned. The Activity handling the request must be
running in the foreground of the device. When an NFC tag is scanned and matches the intent and
data type that the foreground dispatch Activity defines, the intent is immediately sent to the
Activity even if another Activity can handle the intent. If the Activity cannot handle the
intent, the foreground dispatch system falls back to the intent dispatch system.</p>
<h3 id="intent-dispatch">Using the intent dispatch system</h3>
<p>The intent dispatch system specifies three intents that each have a priority. The intents that
start when a device scans a tag depend on the type of tag scanned. In general, the intents are
started in the following manner:</p>
<ul>
<li>
<code>android.nfc.action.NDEF_DISCOVERED</code>: This intent starts when a tag that contains
an NDEF payload is scanned. This is the highest priority intent. The Android system does not
let you specify this intent generically to handle all data types. You must specify
<code>&lt;data&gt;</code> elements in the <code>AndroidManifest.xml</code> along with this
intent to correctly handle NFC tags that start this intent. For example, to handle a
<code>NDEF_DISCOVERED</code> intent that contains plain text, specify the following filter in
your <code>AndroidManifest.xml</code> file:
<pre>
&lt;intent-filter&gt;
&lt;action android:name="android.nfc.action.NDEF_DISCOVERED"/&gt;
&lt;data android:mimeType="text/plain" /&gt;
&lt;/intent-filter&gt;
</pre>
<p>If the <code>NDEF_DISCOVERED</code> intent is started, the <code>TECH_DISCOVERED</code>
and <code>TAG_DISCOVERED</code> intents are not started. This intent does not start if an
unknown tag is scanned or if the tag does not contain an NDEF payload.</p>
</li>
<li><code>android.nfc.action.TECH_DISCOVERED</code>: If the <code>NDEF_DISCOVERED</code> intent
does not start or is not filtered by any Activity on the device, this intent starts if the tag
is known. The <code>TECH_DISCOVERED</code> intent requires that you specify the technologies
that you want to support in an XML resource file. For more information, see the section about
<a href="#technology-resources">Specifying tag technologies to handle</a>.</li>
<li><code>android.nfc.action.TAG_DISCOVERED</code>: This intent starts if no Activities handle
the <code>NDEF_DISCOVERED</code> and <code>TECH_DISCOVERED</code> intents or if the tag that is
scanned is unknown.</li>
</ul>
<h4 id="tech">Specifying tag technologies to handle</h4>
<p>If your Activity declares the <code>android.nfc.action.TECH_DISCOVERED</code> intent in your
<code>AndroidManifest.xml</code> file, you must create an XML resource file that specifies the
technologies that your Activity supports. The following sample defines all of the technologies.
Specifiying multiple technologies within the same list tells the system
to filter tags that support all of the technologies. The example below never filters a tag
because no tag supports all of the technologies at once.
You can remove the ones that you do not need. Save this file (you can name it anything you wish)
in the <code>&lt;project-root&gt;/res/xml</code> folder.</p>
<pre>
&lt;resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"&gt;
&lt;tech-list&gt;
&lt;tech&gt;android.nfc.tech.IsoDep&lt;/tech&gt;
&lt;tech&gt;android.nfc.tech.NfcA&lt;/tech&gt;
&lt;tech&gt;android.nfc.tech.NfcB&lt;/tech&gt;
&lt;tech&gt;android.nfc.tech.NfcF&lt;/tech&gt;
&lt;tech&gt;android.nfc.tech.NfcV&lt;/tech&gt;
&lt;tech&gt;android.nfc.tech.Ndef&lt;/tech&gt;
&lt;tech&gt;android.nfc.tech.NdefFormatable&lt;/tech&gt;
&lt;tech&gt;android.nfc.tech.MifareClassic&lt;/tech&gt;
&lt;tech&gt;android.nfc.tech.MifareUltralight&lt;/tech&gt;
&lt;/tech-list&gt;
&lt;/resources&gt;
</pre>
You can also specify multiple filter lists. In this case, a tag must match all of the
technologies within one of the lists. The following example filters for
cards that support the NfcA and Ndef technology or support the
NfcB and Ndef technology.
<pre>
&lt;resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"&gt;
&lt;tech-list&gt;
&lt;tech&gt;android.nfc.tech.NfcA&lt;/tech&gt;
&lt;tech&gt;android.nfc.tech.Ndef&lt;/tech&gt;
&lt;/tech-list&gt;
&lt;/resources&gt;
&lt;resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"&gt;
&lt;tech-list&gt;
&lt;tech&gt;android.nfc.tech.NfcB&lt;/tech&gt;
&lt;tech&gt;android.nfc.tech.Ndef&lt;/tech&gt;
&lt;/tech-list&gt;
&lt;/resources&gt;
</pre>
<p>In your <code>AndroidManifest.xml</code> file, specify the resource file that you just created
in the <code>&lt;meta-data&gt;</code> element inside the <code>&lt;intent-filter&gt;</code>
element like in the following example:</p>
<pre>
&lt;intent-filter&gt;
&lt;action android:name="android.nfc.action.TECH_DISCOVERED"/&gt;
&lt;meta-data android:name="android.nfc.action.TECH_DISCOVERED"
android:resource="@xml/nfc_tech_filter.xml" /&gt;
&lt;/intent-filter&gt;
</pre>
<h3 id="foreground-dispatch">Using the foreground dispatch system</h3>
<p>The foreground dispatch system allows an Activity to intercept an intent and claim priority
over other Activities that handle the same intent. The system is easy to use and involves
constructing a few data structures for the Android system to be able to send the appropriate
intents to your application. To enable the foreground dispatch system:</p>
<ol>
<li>Add the following code in the onCreate() method of your Activity:
<ol type="a">
<li>Create a {@link android.app.PendingIntent} object so the Android system can populate it
with the details of the tag when it is scanned
<pre>
PendingIntent pendingIntent = PendingIntent.getActivity(
this, 0, new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
</pre>
</li>
<li>Declare intent filters to handle the intents that you want to intercept. The foreground
dispatch system checks the specified intent filters with the intent that is received when
the device scans a tag. If they match, then your application handles the intent. If it does
not match, the foreground dispatch system falls back to the intent dispatch system.
Specifying a <code>null</code> array of intent filters and for the technology filters,
you receive a <code>TAG_DISCOVERED</code> intent for all tags discovered. Note that the
snippet below handles all MIME types. You should only handle the ones that you need.
<pre>
IntentFilter ndef = new IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED);
try {
ndef.addDataType("*/*"); /* Handles all MIME based dispatches.
You should specify only the ones that you need. */
}
catch (MalformedMimeTypeException e) {
throw new RuntimeException("fail", e);
}
intentFiltersArray = new IntentFilter[] {
ndef,
};
</pre>
</li>
<li>Set up an array of tag technologies that your application wants to handle. Call the
<code>Object.class.getName()</code> method to obtain the class of the technology that you
want to support.
<pre>
techListsArray = new String[][] { new String[] { NfcF.class.getName() } };
</pre>
</li>
</ol>
</li>
<li>Override the following Activity lifecycle callbacks and add logic to enable and disable the
foreground dispatch when the Activity loses ({@link android.app.Activity#onPause onPause()})
and regains ({@link android.app.Activity#onResume onResume()}) focus. {@link
android.nfc.NfcAdapter#enableForegroundDispatch} must best called from the main thread and only
when the activity is in the foreground (calling in {@link android.app.Activity#onResume
onResume()} guarantees this). You also need to implement the {@link
android.app.Activity#onNewIntent onNewIntent} callback to process the data from the scanned NFC
tag.
<pre>
public void onPause() {
super.onPause();
mAdapter.disableForegroundDispatch(this);
}
public void onResume() {
super.onResume();
mAdapter.enableForegroundDispatch(this, pendingIntent, intentFiltersArray, techListsArray);
}
public void onNewIntent(Intent intent) {
Tag tagFromIntent = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
//do something with tagFromIntent
}
</pre>
</li>
</ol>
<p>See the <a href=
"{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/nfc/ForegroundDispatch.html">ForegroundDispatch</a>
sample from API Demos for the complete sample.</p>
<h2 id="ndef">Working with Data on NFC tags</h2>
<p>Data on NFC tags are encoded in raw bytes, so you must convert the bytes to something human
readable if you are presenting the data to the user. When writing to NFC tags, you must write
them in bytes as well. Android provides APIs to help write messages that conform to the NDEF
standard, which was developed by the <a href="http://www.nfc-forum.org/specs/">NFC Forum</a> to
standardized data on tags. Using this standard ensures that your data will be supported by all
Android NFC devices if you are writing to tags. However, many tag technologies use their own
standard for storing data and are supported by Android as well, but you have to implement your
own protocol stack to read and write to these tags. You can find a full list of the supported
technologies in {@link android.nfc.tech} and an overview of the technolgies in the {@link
android.nfc.tech.TagTechnology} interface. This section is a brief overview of how to work with
NDEF messages in the context of the Android system. It is not meant to be a complete discussion
of the NDEF specification, but highlights the main things that you need to be aware of when
working with NDEF messages in Android.</p>
<p>To facilitate working with NDEF messages, Android provides the {@link android.nfc.NdefRecord}
and {@link android.nfc.NdefMessage} to encapsulate the raw bytes that represent NDEF messages. An
{@link android.nfc.NdefMessage} is the container for zero or more {@link
android.nfc.NdefRecord}s. Each {@link android.nfc.NdefRecord} has its own unique type name
format, record type, and ID to distinguish them from other records within the same {@link
android.nfc.NdefMessage}. You can store different types of records of varying length in a single
{@link android.nfc.NdefMessage}. The size constraint of the NFC tag determines how big your
{@link android.nfc.NdefMessage} can be.</p>
<p>Tags that support the {@link android.nfc.tech.Ndef} and {@link android.nfc.tech.NdefFormatable}
technologies return and accept {@link android.nfc.NdefMessage}
objects as parameters for read and write operations. You need to create your own logic to read
and write bytes for other tag technologies in {@link android.nfc.tech}.</p>
<p>You can download technical specifications for different types of NDEF message standards, such
as plain text and Smart Posters, at the <a href="http://www.nfc-forum.org/specs/">NFC Forum</a>
website. The NFCDemo sample application also declares sample <a href=
"{@docRoot}resources/samples/NFCDemo/src/com/example/android/nfc/simulator/MockNdefMessages.html">
plain text and SmartPoster NDEF messages.</a></p>
<h2 id="read">Reading an NFC tag</h2>
<p>When a device comes in proximity to an NFC tag, the appropriate intent is started on the
device, notifying interested applications that a NFC tag was scanned. By previously declaring the
appropriate intent filter in your <code>AndroidManifest.xml</code> file or using foreground
dispatching, your application can request to handle the intent.</p>
<p>The following method (slightly modified from the NFCDemo sample application), handles the
<code>TAG_DISCOVERED</code> intent and iterates through an array obtained from the intent that
contains the NDEF payload:</p>
<pre>
NdefMessage[] getNdefMessages(Intent intent) {
// Parse the intent
NdefMessage[] msgs = null;
String action = intent.getAction();
if (NfcAdapter.ACTION_TAG_DISCOVERED.equals(action)) {
Parcelable[] rawMsgs = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
if (rawMsgs != null) {
msgs = new NdefMessage[rawMsgs.length];
for (int i = 0; i &lt; rawMsgs.length; i++) {
msgs[i] = (NdefMessage) rawMsgs[i];
}
}
else {
// Unknown tag type
byte[] empty = new byte[] {};
NdefRecord record = new NdefRecord(NdefRecord.TNF_UNKNOWN, empty, empty, empty);
NdefMessage msg = new NdefMessage(new NdefRecord[] {record});
msgs = new NdefMessage[] {msg};
}
}
else {
Log.e(TAG, "Unknown intent " + intent);
finish();
}
return msgs;
}
</pre>
<p>Keep in mind that the data that the device reads is in bytes, so you must implement your own
logic if you need to present the data in a readable format to the user. The classes in
<code>com.example.android.nfc.record</code> of the NFCDemo sample show you how to parse some
common types of NDEF messages such as plain text or a SmartPoster.</p>
<h2 id="write">Writing to an NFC tag</h2>
<p>Writing to an NFC tag involves constructing your NDEF message in bytes and using the
appropriate tag technology for the tag that you are writing to. The following code sample shows
you how to write a simple text message to a {@link android.nfc.tech.NdefFormatable} tag:</p>
<pre>
NdefFormatable tag = NdefFormatable.get(t);
Locale locale = Locale.US;
final byte[] langBytes = locale.getLanguage().getBytes(Charsets.US_ASCII);
String text = "Tag, you're it!";
final byte[] textBytes = text.getBytes(Charsets.UTF_8);
final int utfBit = 0;
final char status = (char) (utfBit + langBytes.length);
final byte[] data = Bytes.concat(new byte[] {(byte) status}, langBytes, textBytes);
NdefRecord record = NdefRecord(NdefRecord.TNF_WELL_KNOWN, NdefRecord.RTD_TEXT, new byte[0], data);
try {
NdefRecord[] records = {text};
NdefMessage message = new NdefMessage(records);
tag.connect();
tag.format(message);
}
catch (Exception e){
//do error handling
}
</pre>
<h2 id="p2p">Peer-to-peer data exchange</h2>
<p>Support for simple peer-to-peer data exchange is supported by the foreground push feature,
which is enabled with the {@link android.nfc.NfcAdapter#enableForegroundNdefPush} method. To use
this feature:</p>
<ul>
<li>The Activity that is pushing the data must be in the foreground</li>
<li>You must encapsulate the data that you are sending in an {@link android.nfc.NdefMessage}
object</li>
<li>The NFC device that is receiving the pushed data (the scanned device) must support the
<code>com.android.npp</code> NDEF push protocol, which is optional for Android devices.</li>
</li>
</ul>
<p class="note">If your Activity enables the foreground push feature and is in the foreground,
the standard intent dispatch system is disabled. However, if your Activity also enables
foreground dispatching, then it can still scan tags that match the intent filters set in the
foreground dispatching.</p>
<p>To enable foreground dispatching:</p>
<ol>
<li>Create an NdefMessage that contains the NdefRecords that you want to push onto the other
device.</li>
<li>Implement the {@link android.app.Activity#onResume onResume()} and {@link
android.app.Activity#onPause onPause()} callbacks in your Activity to appropriately handle the
foreground pushing lifecycle. You must call {@link
android.nfc.NfcAdapter#enableForegroundNdefPush} from the main thread and only when the
activity is in the foreground (calling in {@link android.app.Activity#onResume onResume()}
guarantees this).
<pre>
public void onResume() {
super.onResume();
if (mAdapter != null)
mAdapter.enableForegroundNdefPush(this, myNdefMessage);
}
public void onPause() {
super.onPause();
if (mAdapter != null)
mAdapter.disableForegroundNdefPush(this);
}
</pre>
</li>
</ol>
<p>When the Activity is in the foreground, you can now tap the device to another device and push
the data to it. See the <a href=
"../../../resources/samples/ApiDemos/src/com/example/android/apis/nfc/ForegroundNdefPush.html">ForegroundNdefPush</a>
sample in API Demos for a simple example of peer-to-peer data exchange.</p>
@@ -0,0 +1,120 @@
page.title=Processes and Application Life Cycle
@jd:body
<p>In most cases, every Android application runs in its own Linux process.
This process is created for the application when some of its code needs to
be run, and will remain running until it is no longer needed <em>and</em>
the system needs to reclaim its memory for use by other applications.</p>
<p>An unusual and fundamental feature of Android is that an application process's
lifetime is <em>not</em> directly controlled by the application itself.
Instead, it is determined by the system through a combination of the parts of the application
that the system knows are running, how important these things are to the user,
and how much overall memory is available in the system.</p>
<p>It is important that
application developers understand how different application components
(in particular {@link android.app.Activity}, {@link android.app.Service},
and {@link android.content.BroadcastReceiver}) impact the lifetime
of the application's process. <strong>Not using these components correctly can
result in the system killing the application's process while it is doing
important work.</strong></p>
<p>A common example of a process life-cycle bug is a
{@link android.content.BroadcastReceiver} that starts a thread when it
receives an Intent in its {@link android.content.BroadcastReceiver#onReceive
BroadcastReceiver.onReceive()}
method, and then returns from the function. Once it returns, the system
considers the BroadcastReceiver to be no longer active, and thus, its hosting
process no longer needed (unless other application components are active in
it). So, the system may kill the process at any time to reclaim memory, and in doing so,
it terminates the spawned thread running in the process. The solution to this problem
is to start a {@link android.app.Service} from the BroadcastReceiver, so the
system knows that there is still active work being done in the process.</p>
<p>To determine which processes should be killed when low on memory, Android
places each process into an "importance hierarchy" based on the components running in
them and the state of those components. These process types are (in order of importance):</p>
<ol>
<li>A <strong>foreground process</strong> is one that is required for
what the user is currently doing. Various application components can
cause its containing process to be considered foreground in different
ways. A process is considered to be in the foreground if any of the
following conditions hold:
<ul>
<li> It is running an {@link android.app.Activity}
at the top of the screen that the user is interacting with (its
{@link android.app.Activity#onResume} method has been called).</li>
<li> It has a {@link android.content.BroadcastReceiver} that is currently running
(its {@link android.content.BroadcastReceiver#onReceive
BroadcastReceiver.onReceive()} method is executing).</li>
<li>It has a {@link android.app.Service} that is currently executing code
in one of its callbacks ({@link android.app.Service#onCreate Service.onCreate()},
{@link android.app.Service#onStart Service.onStart()}, or
{@link android.app.Service#onDestroy Service.onDestroy()}).</li>
</ul>
</li>
<p>There will only ever be a few such processes in the system, and these will only
be killed as a last resort if memory is so low that not even these processes
can continue to run. Generally, at this point, the device has
reached a memory paging state, so this action is required in order to keep the user
interface responsive.</p>
</li>
<li>A <strong>visible process</strong> is one holding an {@link android.app.Activity}
that is visible to the user on-screen but not in the foreground (its
{@link android.app.Activity#onPause} method has been called). This may
occur, for example, if the foreground Activity is displayed as a dialog
that allows the previous Activity to be seen behind it. Such a
process is considered extremely important and will not be killed unless doing so is
required to keep all foreground processes running.
</li>
<li>A <strong>service process</strong> is one holding a {@link android.app.Service}
that has been started with the
{@link android.content.Context#startService startService()} method. Though these
processes are not directly visible to the user, they are generally doing things
that the user cares about (such as background mp3 playback or background
network data upload or download), so the system will always keep such processes
running unless there is not enough memory to retain all foreground and visible process.
</li>
<li>A <strong>background process</strong> is one holding an {@link android.app.Activity}
that is not currently visible to the user (its
{@link android.app.Activity#onStop} method has been called). These processes
have no direct impact on the user experience. Provided they implement
their Activity life-cycle correctly
(see {@link android.app.Activity} for more details), the system
can kill such processes at any time to reclaim memory for one of the three
previous processes types. Usually there are many of these processes running,
so they are kept in an LRU list to ensure the process that was most recently seen
by the user is the last to be killed when running low on memory.
</li>
<li>An <strong>empty process</strong> is one that doesn't hold any active application
components. The only reason to keep such a process around is as a cache to
improve startup time the next time a component of its application needs to
run. As such, the system will often kill these processes in order to
balance overall system resources between these empty cached processes and the
underlying kernel caches.
</li>
</ol>
<p>When deciding how to classify a process, the system will base its decision on the most
important level found among all the components currently active in the process.
See the {@link android.app.Activity}, {@link android.app.Service}, and
{@link android.content.BroadcastReceiver} documentation for more detail on how
each of these components contribute to the overall life-cycle of a process.
The documentation for each of these classes describes in more detail how
they impact the overall life-cycle of their application.</p>
<p>A process's priority may also be increased based on other dependencies
a process has to it. For example, if process A has bound to a
{@link android.app.Service} with
the {@link android.content.Context#BIND_AUTO_CREATE Context.BIND_AUTO_CREATE}
flag or is using a
{@link android.content.ContentProvider} in process B, then process B's
classification will always be at least as important as process A's.</p>
@@ -0,0 +1,913 @@
page.title=Content Providers
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>In this document</h2>
<ol>
<li><a href="#basics">Content provider basics</a></li>
<li><a href="#querying">Querying a content provider</a></li>
<li><a href="#modifying">Modifying data in a provider</a></li>
<li><a href="#creating">Creating a content provider</a></li>
<li><a href="#urisum">Content URI summary</a></li>
</ol>
<h2>Key classes</h2>
<ol>
<li>{@link android.content.ContentProvider}</li>
<li>{@link android.content.ContentResolver}</li>
<li>{@link android.database.Cursor}</li>
</ol>
</div>
</div>
<p>
Content providers store and retrieve data and make it accessible to all
applications. They're the only way to share data across applications; there's
no common storage area that all Android packages can access.
</p>
<p>
Android ships with a number of content providers for common data types
(audio, video, images, personal contact information, and so on). You can
see some of them listed in the {@link android.provider android.provider}
package. You can query these providers for the data they contain (although,
for some, you must acquire the proper permission to read the data).
</p>
<p>
If you want to make your own data public, you have two options: You can
create your own content provider (a {@link android.content.ContentProvider}
subclass) or you can add the data to an existing provider &mdash; if there's
one that controls the same type of data and you have permission to write to it.
</p>
<p>
This document is an introduction to using content providers. After a
brief discussion of the fundamentals, it explores how to query a content
provider, how to modify data controlled by a provider, and how to create
a content provider of your own.
</p>
<h2><a name="basics"></a>Content Provider Basics</h2>
<p>
How a content provider actually stores its data under the covers is
up to its designer. But all content providers implement a common interface
for querying the provider and returning results &mdash; as well as for
adding, altering, and deleting data.
</p>
<p>
It's an interface that clients use indirectly, most generally through
{@link android.content.ContentResolver} objects. You get a ContentResolver
by calling <code>{@link android.content.Context#getContentResolver
getContentResolver()}</code> from within the implementation of an Activity
or other application component:
</p>
<pre>ContentResolver cr = getContentResolver();</pre>
<p>
You can then use the ContentResolver's methods to interact with whatever
content providers you're interested in.
</p>
<p>
When a query is initiated, the Android system identifies the content provider
that's the target of the query and makes sure that it is up and running.
The system instantiates all ContentProvider objects; you never need to do it
on your own. In fact, you never deal directly with ContentProvider objects
at all. Typically, there's just a single instance of each type of
ContentProvider. But it can communicate with multiple ContentResolver objects
in different applications and processes. The interaction between processes is
handled by the ContentResolver and ContentProvider classes.
</p>
<h3>The data model</h3>
<p>
Content providers expose their data as a simple table on a database model,
where each row is a record and each column is data of a particular type
and meaning. For example, information about people and their phone numbers
might be exposed as follows:
</p>
<table>
<tr>
<th scope="col">_ID</th>
<th scope="col">NUMBER</th>
<th scope="col">NUMBER_KEY</th>
<th scope="col">LABEL</th>
<th scope="col">NAME</th>
<th scope="col">TYPE</th>
</tr>
<tr>
<td>13</td>
<td>(425) 555 6677</td>
<td>425 555 6677</td>
<td>Kirkland office</td>
<td>Bully Pulpit</td>
<td>{@code TYPE_WORK}</td>
</tr>
<tr>
<td>44</td>
<td>(212) 555-1234</td>
<td>212 555 1234</td>
<td>NY apartment</td>
<td>Alan Vain</td>
<td>{@code TYPE_HOME}</td>
</tr>
<tr>
<td>45</td>
<td>(212) 555-6657</td>
<td>212 555 6657</td>
<td>Downtown office</td>
<td>Alan Vain</td>
<td>{@code TYPE_MOBILE}</td>
</tr>
<tr>
<td>53</td>
<td>201.555.4433</td>
<td>201 555 4433</td>
<td>Love Nest</td>
<td>Rex Cars</td>
<td>{@code TYPE_HOME}</td>
</tr>
</table>
<p>
Every record includes a numeric {@code _ID} field that uniquely identifies
the record within the table. IDs can be used to match records in related
tables &mdash; for example, to find a person's phone number in one table
and pictures of that person in another.
</p>
<p>
A query returns a {@link android.database.Cursor} object that can move from
record to record and column to column to read the contents of each field.
It has specialized methods for reading each type of data. So, to read a field,
you must know what type of data the field contains. (There's more on query
results and Cursor objects later.)
</p>
<h3><a name="uri"></a>URIs</h3>
<p>
Each content provider exposes a public URI (wrapped as a {@link android.net.Uri}
object) that uniquely identifies its data set. A content provider that controls
multiple data sets (multiple tables) exposes a separate URI for each one. All
URIs for providers begin with the string "{@code content://}". The {@code content:}
scheme identifies the data as being controlled by a content provider.
</p>
<p>
If you're defining a content provider, it's a good idea to also define a
constant for its URI, to simplify client code and make future updates cleaner.
Android defines {@code CONTENT_URI} constants for all the providers that come
with the platform. For example, the URI for the table that matches
phone numbers to people and the URI for the table that holds pictures of
people (both controlled by the Contacts content provider) are:
</p>
<p>
<p style="margin-left: 2em">{@code android.provider.Contacts.Phones.CONTENT_URI}
<br/>{@code android.provider.Contacts.Photos.CONTENT_URI}
</p>
<p>
The URI constant is used in all interactions with the content provider.
Every {@link android.content.ContentResolver} method takes the URI
as its first argument. It's what identifies which provider the ContentResolver
should talk to and which table of the provider is being targeted.
</p>
<h2><a name="querying"></a>Querying a Content Provider</h2>
<p>
You need three pieces of information to query a content provider:
</p>
<ul>
<li>The URI that identifies the provider</li>
<li>The names of the data fields you want to receive</li>
<li>The data types for those fields</li>
</ul>
<p>
If you're querying a particular record, you also need the ID for that record.
</p>
<h3>Making the query</h3>
<p>
To query a content provider, you can use either the
<code>{@link android.content.ContentResolver#query ContentResolver.query()}</code>
method or the <code>{@link android.app.Activity#managedQuery
Activity.managedQuery()}</code> method.
Both methods take the same set of arguments, and both return a
Cursor object. However, {@code managedQuery()}
causes the activity to manage the life cycle of the Cursor. A managed Cursor
handles all of the niceties, such as unloading itself when the activity pauses,
and requerying itself when the activity restarts. You can ask an Activity to
begin managing an unmanaged Cursor object for you by calling
<code>{@link android.app.Activity#startManagingCursor
Activity.startManagingCursor()}</code>.
</p>
<p>
The first argument to either <code>{@link android.content.ContentResolver#query query()}</code>
or <code>{@link android.app.Activity#managedQuery managedQuery()}</code> is the provider URI
&mdash; the {@code CONTENT_URI} constant that identifies a particular
ContentProvider and data set (see <a href="#uri">URIs</a> earlier).
</p>
<p>
To restrict a query to just one record, you can append the {@code _ID} value for
that record to the URI &mdash; that is, place a string matching the ID as the
last segment of the path part of the URI. For example, if the ID is 23,
the URI would be:
</p>
<p style="margin-left: 2em">{@code content://. . . ./23}</p>
<p>
There are some helper methods, particularly
<code>{@link android.content.ContentUris#withAppendedId
ContentUris.withAppendedId()}</code> and <code>{@link
android.net.Uri#withAppendedPath Uri.withAppendedPath()}</code>,
that make it easy to append an ID to a URI. Both are static methods that return
a Uri object with the ID added. So, for example, if you were looking for record
23 in the database of people contacts, you might construct a query as follows:
</p>
<pre>
import android.provider.Contacts.People;
import android.content.ContentUris;
import android.net.Uri;
import android.database.Cursor;
// Use the ContentUris method to produce the base URI for the contact with _ID == 23.
Uri myPerson = ContentUris.withAppendedId(People.CONTENT_URI, 23);
// Alternatively, use the Uri method to produce the base URI.
// It takes a string rather than an integer.
Uri myPerson = Uri.withAppendedPath(People.CONTENT_URI, "23");
// Then query for this specific record:
Cursor cur = managedQuery(myPerson, null, null, null, null);
</pre>
<p>
The other arguments to the <code>{@link android.content.ContentResolver#query query()}</code>
and <code>{@link android.app.Activity#managedQuery managedQuery()}</code> methods delimit
the query in more detail. They are:
</p>
<ul>
<li>The names of the data columns that should be returned. A {@code null}
value returns all columns. Otherwise, only columns that are listed by name
are returned. All the content providers that come with the platform define
constants for their columns. For example, the
{@link android.provider.Contacts.Phones android.provider.Contacts.Phones} class
defines constants for the names of the columns in the phone table illustrated
earlier &mdash {@code _ID}, {@code NUMBER}, {@code NUMBER_KEY}, {@code NAME},
and so on.</li>
<li><p>A filter detailing which rows to return, formatted as an SQL {@code WHERE}
clause (excluding the {@code WHERE} itself). A {@code null} value returns
all rows (unless the URI limits the query to a single record).</p></li>
<li><p>Selection arguments.</p></li>
<li><p>A sorting order for the rows that are returned, formatted as an SQL
{@code ORDER BY} clause (excluding the {@code ORDER BY} itself). A {@code null}
value returns the records in the default order for the table, which may be
unordered.</p></li>
</ul>
<p>
Let's look at an example query to retrieve a list of contact names and their
primary phone numbers:
</p>
<pre>
import android.provider.Contacts.People;
import android.database.Cursor;
// Form an array specifying which columns to return.
String[] projection = new String[] {
People._ID,
People._COUNT,
People.NAME,
People.NUMBER
};
// Get the base URI for the People table in the Contacts content provider.
Uri contacts = People.CONTENT_URI;
// Make the query.
Cursor managedCursor = managedQuery(contacts,
projection, // Which columns to return
null, // Which rows to return (all rows)
null, // Selection arguments (none)
// Put the results in ascending order by name
People.NAME + " ASC");
</pre>
<p>
This query retrieves data from the People table of the Contacts content
provider. It gets the name, primary phone number, and unique record ID for
each contact. It also reports the number of records that are returned as
the {@code _COUNT} field of each record.
</p>
<p>
The constants for the names of the columns are defined in various interfaces
&mdash; {@code _ID} and {@code _COUNT} in
{@link android.provider.BaseColumns BaseColumns}, {@code NAME} in {@link android.provider.Contacts.PeopleColumns PeopleColumns}, and {@code NUMBER}
in {@link android.provider.Contacts.PhonesColumns PhoneColumns}. The
{@link android.provider.Contacts.People Contacts.People} class implements
each of these interfaces, which is why the code example above could refer
to them using just the class name.
</p>
<h3>What a query returns</h3>
<p>
A query returns a set of zero or more database records. The names of the
columns, their default order, and their data types are specific to each
content provider.
But every provider has an {@code _ID} column, which holds a unique numeric
ID for each record. Every provider can also report the number
of records returned as the {@code _COUNT} column; its value
is the same for all rows.
</p>
<p>
Here is an example result set for the query in the previous section:
</p>
<table border="1">
<tbody>
<tr>
<th scope="col">_ID</th>
<th scope="col">_COUNT</th>
<th scope="col">NAME</th>
<th scope="col">NUMBER</th>
</tr>
<tr>
<td>44</td>
<td>3</td>
<td>Alan Vain</td>
<td>212 555 1234</td>
</tr>
<tr>
<td>13</td>
<td>3</td>
<td>Bully Pulpit</td>
<td>425 555 6677</td>
</tr>
<tr>
<td>53</td>
<td>3</td>
<td>Rex Cars</td>
<td>201 555 4433</td>
</tr>
</tbody>
</table>
<p>
The retrieved data is exposed by a {@link android.database.Cursor Cursor}
object that can be used to iterate backward or forward through the result
set. You can use this object only to read the data. To add, modify, or
delete data, you must use a ContentResolver object.
</p>
<h3>Reading retrieved data</h3>
<p>
The Cursor object returned by a query provides access to a recordset of
results. If you have queried for a specific record by ID, this set will
contain only one value. Otherwise, it can contain multiple values.
(If there are no matches, it can also be empty.) You
can read data from specific fields in the record, but you must know the
data type of the field, because the Cursor object has a separate method
for reading each type of data &mdash; such as <code>{@link
android.database.Cursor#getString getString()}</code>, <code>{@link
android.database.Cursor#getInt getInt()}</code>, and <code>{@link
android.database.Cursor#getFloat getFloat()}</code>.
(However, for most types, if you call the method for reading strings,
the Cursor object will give you the String representation of the data.)
The Cursor lets you request the column name from the index of the column,
or the index number from the column name.
</p>
<p>
The following snippet demonstrates reading names and phone numbers from
the query illustrated earlier:
</p>
<pre>
import android.provider.Contacts.People;
private void getColumnData(Cursor cur){
if (cur.moveToFirst()) {
String name;
String phoneNumber;
int nameColumn = cur.getColumnIndex(People.NAME);
int phoneColumn = cur.getColumnIndex(People.NUMBER);
String imagePath;
do {
// Get the field values
name = cur.getString(nameColumn);
phoneNumber = cur.getString(phoneColumn);
// Do something with the values.
...
} while (cur.moveToNext());
}
}
</pre>
<p>
If a query can return binary data, such as an image or sound, the data
may be directly entered in the table or the table entry for that data may be
a string specifying a {@code content:} URI that you can use to get the data.
In general, smaller amounts of data (say, from 20 to 50K or less) are most often
directly entered in the table and can be read by calling
<code>{@link android.database.Cursor#getBlob Cursor.getBlob()}</code>.
It returns a byte array.
</p>
<p>
If the table entry is a {@code content:} URI, you should never try to open
and read the file directly (for one thing, permissions problems can make this
fail). Instead, you should call
<code>{@link android.content.ContentResolver#openInputStream
ContentResolver.openInputStream()}</code> to get an
{@link java.io.InputStream} object that you can use to read the data.
</p>
<h2><a name="modifying"></a>Modifying Data</h2>
<p>
Data kept by a content provider can be modified by:
</p>
<ul>
<p><li>Adding new records</li>
<li>Adding new values to existing records</li>
<li>Batch updating existing records</li>
<li>Deleting records</li>
</ul>
<p>
All data modification is accomplished using {@link android.content.ContentResolver}
methods. Some content providers require a more restrictive permission for writing
data than they do for reading it. If you don't have permission to write to a
content provider, the ContentResolver methods will fail.
</p>
<h3>Adding records</h3>
<p>
To add a new record to a content provider, first set up a map of key-value pairs
in a {@link android.content.ContentValues} object, where each key matches
the name of a column in the content provider and the value is the desired
value for the new record in that column. Then call <code>{@link
android.content.ContentResolver#insert ContentResolver.insert()}</code> and pass
it the URI of the provider and the ContentValues map. This method returns
the full URI of the new record &mdash; that is, the provider's URI with
the appended ID for the new record. You can then use this URI to query and
get a Cursor over the new record, and to further modify the record.
Here's an example:
</p>
<pre>
import android.provider.Contacts.People;
import android.content.ContentResolver;
import android.content.ContentValues;
ContentValues values = new ContentValues();
// Add Abraham Lincoln to contacts and make him a favorite.
values.put(People.NAME, "Abraham Lincoln");
// 1 = the new contact is added to favorites
// 0 = the new contact is not added to favorites
values.put(People.STARRED, 1);
Uri uri = getContentResolver().insert(People.CONTENT_URI, values);
</pre>
<h3>Adding new values</h3>
<p>
Once a record exists, you can add new information to it or modify
existing information. For example, the next step in the example above would
be to add contact information &mdash; like a phone number or an IM or e-mail
address &mdash; to the new entry.
</p>
<p>
The best way to add to a record in the Contacts database is to append
the name of the table where the new data goes to the URI for the
record, then use the amended URI to add the new data values. Each
Contacts table exposes a name for this purpose as a {@code
CONTENT_DIRECTORY} constant. The following code continues the previous
example by adding a phone number and e-mail address for the record
just created:
</p>
<pre>
Uri phoneUri = null;
Uri emailUri = null;
// Add a phone number for Abraham Lincoln. Begin with the URI for
// the new record just returned by insert(); it ends with the _ID
// of the new record, so we don't have to add the ID ourselves.
// Then append the designation for the phone table to this URI,
// and use the resulting URI to insert the phone number.
phoneUri = Uri.withAppendedPath(uri, People.Phones.CONTENT_DIRECTORY);
values.clear();
values.put(People.Phones.TYPE, People.Phones.TYPE_MOBILE);
values.put(People.Phones.NUMBER, "1233214567");
getContentResolver().insert(phoneUri, values);
// Now add an email address in the same way.
emailUri = Uri.withAppendedPath(uri, People.ContactMethods.CONTENT_DIRECTORY);
values.clear();
// ContactMethods.KIND is used to distinguish different kinds of
// contact methods, such as email, IM, etc.
values.put(People.ContactMethods.KIND, Contacts.KIND_EMAIL);
values.put(People.ContactMethods.DATA, "test@example.com");
values.put(People.ContactMethods.TYPE, People.ContactMethods.TYPE_HOME);
getContentResolver().insert(emailUri, values);
</pre>
<p>
You can place small amounts of binary data into a table by calling
the version of <code>{@link android.content.ContentValues#put
ContentValues.put()}</code> that takes a byte array.
That would work for a small icon-like image or a short audio clip, for example.
However, if you have a large amount of binary data to add, such as a photograph
or a complete song, put a {@code content:} URI for the data in the table and call
<code>{@link android.content.ContentResolver#openOutputStream
ContentResolver.openOutputStream()}</code>
with the file's URI. (That causes the content provider to store the data
in a file and record the file path in a hidden field of the record.)
</p>
<p>
In this regard, the {@link android.provider.MediaStore} content
provider, the main provider that dispenses image, audio, and video
data, employs a special convention: The same URI that is used with
{@code query()} or {@code managedQuery()} to get meta-information
about the binary data (such as, the caption of a photograph or the
date it was taken) is used with {@code openInputStream()}
to get the data itself. Similarly, the same URI that is used with
{@code insert()} to put meta-information into a MediaStore record
is used with {@code openOutputStream()} to place the binary data there.
The following code snippet illustrates this convention:
</p>
<pre>
import android.provider.MediaStore.Images.Media;
import android.content.ContentValues;
import java.io.OutputStream;
// Save the name and description of an image in a ContentValues map.
ContentValues values = new ContentValues(3);
values.put(Media.DISPLAY_NAME, "road_trip_1");
values.put(Media.DESCRIPTION, "Day 1, trip to Los Angeles");
values.put(Media.MIME_TYPE, "image/jpeg");
// Add a new record without the bitmap, but with the values just set.
// insert() returns the URI of the new record.
Uri uri = getContentResolver().insert(Media.EXTERNAL_CONTENT_URI, values);
// Now get a handle to the file for that record, and save the data into it.
// Here, sourceBitmap is a Bitmap object representing the file to save to the database.
try {
OutputStream outStream = getContentResolver().openOutputStream(uri);
sourceBitmap.compress(Bitmap.CompressFormat.JPEG, 50, outStream);
outStream.close();
} catch (Exception e) {
Log.e(TAG, "exception while writing image", e);
}
</pre>
<h3>Batch updating records</h3>
<p>
To batch update a group of records (for example, to change "NY" to "New York"
in all fields), call the <code>{@link
android.content.ContentResolver#update ContentResolver.update()}</code>
method with the columns and values to change.
</p>
<h3><a name="deletingrecord"></a>Deleting a record</h3>
<p>
To delete a single record, call {<code>{@link
android.content.ContentResolver#delete ContentResolver.delete()}</code>
with the URI of a specific row.
</p>
<p>
To delete multiple rows, call <code>{@link
android.content.ContentResolver#delete ContentResolver.delete()}</code>
with the URI of the type of record to delete (for example, {@code android.provider.Contacts.People.CONTENT_URI}) and an SQL {@code WHERE}
clause defining which rows to delete. (<i><b>Caution</b>:
Be sure to include a valid {@code WHERE} clause if you're deleting a general
type, or you risk deleting more records than you intended!</i>).
</p>
<h2><a name="creating"></a>Creating a Content Provider</h2>
<p>
To create a content provider, you must:
</p>
<ul>
<li>Set up a system for storing the data. Most content providers
store their data using Android's file storage methods or SQLite databases,
but you can store your data any way you want. Android provides the
{@link android.database.sqlite.SQLiteOpenHelper SQLiteOpenHelper}
class to help you create a database and {@link
android.database.sqlite.SQLiteDatabase SQLiteDatabase} to manage it.</li>
<li><p>Extend the {@link android.content.ContentProvider} class to provide
access to the data.</p></li>
<li><p>Declare the content provider in the manifest file for your
application (AndroidManifest.xml).</p></li>
</ul>
<p>
The following sections have notes on the last two of these tasks.
</p>
<h3>Extending the ContentProvider class</h3>
<p>
You define a {@link android.content.ContentProvider} subclass to
expose your data to others using the conventions expected by
ContentResolver and Cursor objects. Principally, this means
implementing six abstract methods declared in the ContentProvider class:
</p>
<p style="margin-left: 2em">{@code query()}
<br/>{@code insert()}
<br/>{@code update()}
<br/>{@code delete()}
<br/>{@code getType()}
<br/>{@code onCreate()}</p>
<p>
The {@code query()} method must return a {@link android.database.Cursor} object
that can iterate over the requested data. Cursor itself is an interface, but
Android provides some ready-made Cursor objects that you can use. For example,
{@link android.database.sqlite.SQLiteCursor} can iterate over data stored in
an SQLite database. You get the Cursor object by calling any of the {@link
android.database.sqlite.SQLiteDatabase SQLiteDatabase} class's {@code query()}
methods. There are other Cursor implementations &mdash; such as {@link
android.database.MatrixCursor} &mdash; for data not stored in a database.
</p>
<p>
Because these ContentProvider methods can be called from
various ContentResolver objects in different processes and threads,
they must be implemented in a thread-safe manner.
</p>
<p>
As a courtesy, you might also want to call <code>{@link android.content.ContentResolver#notifyChange(android.net.Uri,android.database.ContentObserver)
ContentResolver.notifyChange()}</code> to notify listeners when there are
modifications to the data.
</p>
<p>
Beyond defining the subclass itself, there are other steps you should take
to simplify the work of clients and make the class more accessible:
</p>
<ul>
<li>Define a {@code public static final} {@link android.net.Uri}
named {@code CONTENT_URI}. This is the string that represents the full
{@code content:} URI that your content provider handles. You must define a
unique string for this value. The best solution is to use the fully-qualified
class name of the content provider (made lowercase). So, for example, the
URI for a TransportationProvider class could be defined as follows:
<pre>public static final Uri CONTENT_URI =
Uri.parse("content://com.example.codelab.transportationprovider");</pre>
<p>
If the provider has subtables, also define {@code CONTENT_URI} constants for
each of the subtables. These URIs should all have the same authority (since
that identifies the content provider), and be distinguished only by their paths.
For example:
</p>
<p style="margin-left: 2em">{@code content://com.example.codelab.transportationprovider/train}
<br/>{@code content://com.example.codelab.transportationprovider/air/domestic}
<br/>{@code content://com.example.codelab.transportationprovider/air/international}</p>
<p>
For an overview of {@code content:} URIs, see the <a href="#urisum">Content URI
Summary</a> at the end of this document.
</p></li>
<li><p>Define the column names that the content provider will return to clients.
If you are using an underlying database, these column names are typically
identical to the SQL database column names they represent. Also define
{@code public static} String constants that clients can use to specify
the columns in queries and other instructions.
</p>
<p>
Be sure to include an integer column named "{@code _id}"
(with the constant {@code _ID}) for
the IDs of the records. You should have this field whether or not you have
another field (such as a URL) that is also unique among all records. If
you're using the SQLite database, the {@code _ID} field should be the
following type:
</p>
<p style="margin-left: 2em">{@code INTEGER PRIMARY KEY AUTOINCREMENT}</p>
<p>
The {@code AUTOINCREMENT} descriptor is optional. But without it, SQLite
increments an ID counter field to the next number above the largest
existing number in the column. If you delete the last row, the next row added
will have the same ID as the deleted row. {@code AUTOINCREMENT} avoids this
by having SQLite increment to the next largest value whether deleted or not.
</p>
</li>
<li><p>Carefully document the data type of each column. Clients need this
information to read the data.</p></li>
<li><p>If you are handling a new data type, you must define a new MIME type
to return in your implementation of <code>{@link
android.content.ContentProvider#getType ContentProvider.getType()}</code>.
The type depends in part on whether or not the {@code content:} URI submitted
to {@code getType()} limits the request to a specific record. There's one
form of the MIME type for a single record and another for multiple records.
Use the {@link android.net.Uri Uri} methods to help determine what is being
requested. Here is the general format for each type:</p></li>
<ul>
<li><p>For a single record:&nbsp;&nbsp;&nbsp; {@code vnd.android.cursor.item/vnd.<em>yourcompanyname.contenttype</em>}</p>
<p>For example, a request for train record 122, like this URI,</p>
<p style="margin-left: 2em">{@code content://com.example.transportationprovider/trains/122}</p>
<p>might return this MIME type:</p>
<p style="margin-left: 2em">{@code vnd.android.cursor.item/vnd.example.rail}</p>
</li>
<li><p>For multiple records:&nbsp;&nbsp;&nbsp; {@code vnd.android.cursor.dir/vnd.<em>yourcompanyname.contenttype</em>}</p>
<p>For example, a request for all train records, like the following URI,</p>
<p style="margin-left: 2em">{@code content://com.example.transportationprovider/trains}</p>
<p>might return this MIME type:</p>
<p style="margin-left: 2em">{@code vnd.android.cursor.dir/vnd.example.rail}</p>
</li>
</ul>
<li><p>If you are exposing byte data that's too big to put in the table itself
&mdash; such as a large bitmap file &mdash; the field that exposes the
data to clients should actually contain a {@code content:} URI string.
This is the field that gives clients access to the data file. The record
should also have another field, named "{@code _data}" that lists the exact file
path on the device for that file. This field is not intended to be read by
the client, but by the ContentResolver. The client will call <code>{@link
android.content.ContentResolver#openInputStream ContentResolver.openInputStream()}</code>
on the user-facing field holding the URI for the item. The ContentResolver
will request the "{@code _data}" field for that record, and because
it has higher permissions than a client, it should be able to access
that file directly and return a read wrapper for the file to the client.</p></li>
</ul>
<p>
For an example of a private content provider implementation, see the
NodePadProvider class in the Notepad sample application that ships with the SDK.
</p>
<h3>Declaring the content provider</h3>
<p>
To let the Android system know about the content provider you've developed,
declare it with a {@code &lt;provider&gt;} element in the application's
AndroidManifest.xml file. Content providers that are not declared in the
manifest are not visible to the Android system
</p>
<p>
The {@code name} attribute is the fully qualified name of the ContentProvider
subclass. The {@code authorities} attribute is the authority part of the
{@code content:} URI that identifies the provider.
For example if the ContentProvider subclass is AutoInfoProvider, the
{@code &lt;provider&gt;} element might look like this:
</p>
<pre>
&lt;provider android:name="com.example.autos.AutoInfoProvider"
android:authorities="com.example.autos.autoinfoprovider"
. . . /&gt
&lt;/provider&gt;
</pre>
<p>
Note that the {@code authorities} attribute omits the path part of a
{@code content:} URI. For example, if AutoInfoProvider controlled subtables
for different types of autos or different manufacturers,
</p>
<p style="margin-left: 2em">{@code content://com.example.autos.autoinfoprovider/honda}
<br/>{@code content://com.example.autos.autoinfoprovider/gm/compact}
<br/>{@code content://com.example.autos.autoinfoprovider/gm/suv}</p>
<p>
those paths would not be declared in the manifest. The authority is what
identifies the provider, not the path; your provider can interpret the path
part of the URI in any way you choose.
</p>
<p>
Other {@code &lt;provider&gt;} attributes can set permissions to read and
write data, provide for an icon and text that can be displayed to users,
enable and disable the provider, and so on. Set the {@code multiprocess}
attribute to "{@code true}" if data does not need to be synchronized between
multiple running versions of the content provider. This permits an instance
of the provider to be created in each client process, eliminating the need
to perform IPC.
</p>
<h2><a name="urisum"></a>Content URI Summary</h2>
<p>
Here is a recap of the important parts of a content URI:
</p>
<p>
<img src="{@docRoot}images/content_uri.png" alt="Elements of a content URI"
height="80" width="528">
</p>
<ol type="A">
<li>Standard prefix indicating that the data is controlled by a
content provider. It's never modified.</li>
<li><p>The authority part of the URI; it identifies the content provider.
For third-party applications, this should be a fully-qualified class name
(reduced to lowercase) to ensure uniqueness. The authority is declared in
the {@code &lt;provider&gt;} element's {@code authorities} attribute:</p>
<pre>&lt;provider android:name=".TransportationProvider"
android:authorities="com.example.transportationprovider"
. . . &gt;</pre></li>
<li><p>The path that the content provider uses to determine what kind of data is
being requested. This can be zero or more segments long. If the content provider
exposes only one type of data (only trains, for example), it can be absent.
If the provider exposes several types, including subtypes, it can be several
segments long &mdash; for example, "{@code land/bus}", "{@code land/train}",
"{@code sea/ship}", and "{@code sea/submarine}" to give four possibilities.</p></li>
<li><p>The ID of the specific record being requested, if any. This is the
{@code _ID} value of the requested record. If the request is not limited to
a single record, this segment and the trailing slash are omitted:</p>
<p style="margin-left: 2em">{@code content://com.example.transportationprovider/trains}</p>
</li>
</ol>
@@ -0,0 +1,341 @@
page.title=Accessing Resources
parent.title=Application Resources
parent.link=index.html
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>Quickview</h2>
<ul>
<li>Resources can be referenced from code using integers from {@code R.java}, such as
{@code R.drawable.myimage}</li>
<li>Resources can be referenced from resources using a special XML syntax, such as {@code
&#64;drawable/myimage}</li>
<li>You can also access your app resources with methods in
{@link android.content.res.Resources}</li>
</ul>
<h2>Key classes</h2>
<ol>
<li>{@link android.content.res.Resources}</li>
</ol>
<h2>In this document</h2>
<ol>
<li><a href="#ResourcesFromCode">Accessing Resources from Code</a></li>
<li><a href="#ResourcesFromXml">Accessing Resources from XML</a>
<ol>
<li><a href="#ReferencesToThemeAttributes">Referencing style attributes</a></li>
</ol>
</li>
<li><a href="#PlatformResources">Accessing Platform Resources</a></li>
</ol>
<h2>See also</h2>
<ol>
<li><a href="providing-resources.html">Providing Resources</a></li>
<li><a href="available-resources.html">Resource Types</a></li>
</ol>
</div>
</div>
<p>Once you provide a resource in your application (discussed in <a
href="providing-resources.html">Providing Resources</a>), you can apply it by
referencing its resource ID. All resource IDs are defined in your project's {@code R} class, which
the {@code aapt} tool automatically generates.</p>
<p>When your application is compiled, {@code aapt} generates the {@code R} class, which contains
resource IDs for all the resources in your {@code
res/} directory. For each type of resource, there is an {@code R} subclass (for example,
{@code R.drawable} for all drawable resources) and for each resource of that type, there is a static
integer (for example, {@code R.drawable.icon}). This integer is the resource ID that you can use
to retrieve your resource.</p>
<p>Although the {@code R} class is where resource IDs are specified, you should never need to
look there to discover a resource ID. A resource ID is always composed of:</p>
<ul>
<li>The <em>resource type</em>: Each resource is grouped into a "type," such as {@code
string}, {@code drawable}, and {@code layout}. For more about the different types, see <a
href="available-resources.html">Resource Types</a>.
</li>
<li>The <em>resource name</em>, which is either: the filename,
excluding the extension; or the value in the XML {@code android:name} attribute, if the
resource is a simple value (such as a string).</li>
</ul>
<p>There are two ways you can access a resource:</p>
<ul>
<li><strong>In code:</strong> Using an static integer from a sub-class of your {@code R}
class, such as:
<pre class="classic no-pretty-print">R.string.hello</pre>
<p>{@code string} is the resource type and {@code hello} is the resource name. There are many
Android APIs that can access your resources when you provide a resource ID in this format. See
<a href="#ResourcesFromCode">Accessing Resources in Code</a>.</p>
</li>
<li><strong>In XML:</strong> Using a special XML syntax that also corresponds to
the resource ID defined in your {@code R} class, such as:
<pre class="classic no-pretty-print">&#64;string/hello</pre>
<p>{@code string} is the resource type and {@code hello} is the resource name. You can use this
syntax in an XML resource any place where a value is expected that you provide in a resource. See <a
href="#ResourcesFromXml">Accessing Resources from XML</a>.</p>
</li>
</ul>
<h2 id="ResourcesFromCode">Accessing Resources in Code </h2>
<p>You can use a resource in code by passing the resource ID as a method parameter. For
example, you can set an {@link android.widget.ImageView} to use the {@code res/drawable/myimage.png}
resource using {@link android.widget.ImageView#setImageResource(int) setImageResource()}:</p>
<pre>
ImageView imageView = (ImageView) findViewById(R.id.myimageview);
imageView.setImageResource(<strong>R.drawable.myimage</strong>);
</pre>
<p>You can also retrieve individual resources using methods in {@link
android.content.res.Resources}, which you can get an instance of
with {@link android.content.Context#getResources()}.</p>
<div class="sidebox-wrapper">
<div class="sidebox">
<h2>Access to Original Files</h2>
<p>While uncommon, you might need access your original files and directories. If you do, then
saving your files in {@code res/} won't work for you, because the only way to read a resource from
{@code res/} is with the resource ID. Instead, you can save your resources in the
{@code assets/} directory.</p>
<p>Files saved in the {@code assets/} directory are <em>not</em> given a resource
ID, so you can't reference them through the {@code R} class or from XML resources. Instead, you can
query files in the {@code assets/} directory like a normal file system and read raw data using
{@link android.content.res.AssetManager}.</p>
<p>However, if all you require is the ability to read raw data (such as a video or audio file),
then save the file in the {@code res/raw/} directory and read a stream of bytes using {@link
android.content.res.Resources#openRawResource(int) openRawResource()}.</p>
</div>
</div>
<h3>Syntax</h3>
<p>Here's the syntax to reference a resource in code:</p>
<pre class="classic no-pretty-print">
[<em>&lt;package_name&gt;</em>.]R.<em>&lt;resource_type&gt;</em>.<em>&lt;resource_name&gt;</em>
</pre>
<ul>
<li><em>{@code &lt;package_name&gt;}</em> is the name of the package in which the resource is located (not
required when referencing resources from your own package).</li>
<li><em>{@code &lt;resource_type&gt;}</em> is the {@code R} subclass for the resource type.</li>
<li><em>{@code &lt;resource_name&gt;}</em> is either the resource filename
without the extension or the {@code android:name} attribute value in the XML element (for simple
values).</li>
</ul>
<p>See <a href="available-resources.html">Resource Types</a> for
more information about each resource type and how to reference them.</p>
<h3>Use cases</h3>
<p>There are many methods that accept a resource ID parameter and you can retrieve resources using
methods in {@link android.content.res.Resources}. You can get an instance of {@link
android.content.res.Resources} with {@link android.content.Context#getResources
Context.getResources()}.</p>
<p>Here are some examples of accessing resources in code:</p>
<pre>
// Load a background for the current screen from a drawable resource
{@link android.app.Activity#getWindow()}.{@link
android.view.Window#setBackgroundDrawableResource(int)
setBackgroundDrawableResource}(<strong>R.drawable.my_background_image</strong>) ;
// Set the Activity title by getting a string from the Resources object, because
// this method requires a CharSequence rather than a resource ID
{@link android.app.Activity#getWindow()}.{@link android.view.Window#setTitle(CharSequence)
setTitle}(getResources().{@link android.content.res.Resources#getText(int)
getText}(<strong>R.string.main_title</strong>));
// Load a custom layout for the current screen
{@link android.app.Activity#setContentView(int)
setContentView}(<strong>R.layout.main_screen</strong>);
// Set a slide in animation by getting an Animation from the Resources object
mFlipper.{@link android.widget.ViewAnimator#setInAnimation(Animation)
setInAnimation}(AnimationUtils.loadAnimation(this,
<strong>R.anim.hyperspace_in</strong>));
// Set the text on a TextView object using a resource ID
TextView msgTextView = (TextView) findViewById(<strong>R.id.msg</strong>);
msgTextView.{@link android.widget.TextView#setText(int)
setText}(<strong>R.string.hello_message</strong>);
</pre>
<p class="caution"><strong>Caution:</strong> You should never modify the {@code
R.java} file by hand&mdash;it is generated by the {@code aapt} tool when your project is
compiled. Any changes are overridden next time you compile.</p>
<h2 id="ResourcesFromXml">Accessing Resources from XML</h2>
<p>You can define values for some XML attributes and elements using a
reference to an existing resource. You will often do this when creating layout files, to
supply strings and images for your widgets.</p>
<p>For example, if you add a {@link android.widget.Button} to your layout, you should use
a <a href="string-resource.html">string resource</a> for the button text:</p>
<pre>
&lt;Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="<strong>@string/submit</strong>" /&gt;
</pre>
<h3>Syntax</h3>
<p>Here is the syntax to reference a resource in an XML resource:</p>
<pre class="classic no-pretty-print">
&#64;[<em>&lt;package_name&gt;</em>:]<em>&lt;resource_type&gt;</em>/<em>&lt;resource_name&gt;</em>
</pre>
<ul>
<li>{@code &lt;package_name&gt;} is the name of the package in which the resource is located (not
required when referencing resources from the same package)</li>
<li>{@code &lt;resource_type&gt;} is the
{@code R} subclass for the resource type</li>
<li>{@code &lt;resource_name&gt;} is either the resource filename
without the extension or the {@code android:name} attribute value in the XML element (for simple
values).</li>
</ul>
<p>See <a href="available-resources.html">Resource Types</a> for
more information about each resource type and how to reference them.</p>
<h3>Use cases</h3>
<p>In some cases you must use a resource for a value in XML (for example, to apply a drawable image
to a widget), but you can also use a resource in XML any place that accepts a simple value. For
example, if you have the following resource file that includes a <a
href="more-resources.html#Color">color resource</a> and a <a
href="string-resource.html">string resource</a>:</p>
<pre>
&lt;?xml version="1.0" encoding="utf-8"?>
&lt;resources>
&lt;color name="opaque_red">#f00&lt;/color>
&lt;string name="hello">Hello!&lt;/string>
&lt;/resources>
</pre>
<p>You can use these resources in the following layout file to set the text color and
text string:</p>
<pre>
&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;EditText xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
android:layout_width=&quot;fill_parent&quot;
android:layout_height=&quot;fill_parent&quot;
android:textColor=&quot;<strong>&#64;color/opaque_red</strong>&quot;
android:text=&quot;<strong>&#64;string/hello</strong>&quot; /&gt;
</pre>
<p>In this case you don't need to specify the package name in the resource reference because the
resources are from your own package. To
reference a system resource, you would need to include the package name. For example:</p>
<pre>
&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;EditText xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
android:layout_width=&quot;fill_parent&quot;
android:layout_height=&quot;fill_parent&quot;
android:textColor=&quot;<strong>&#64;android:color/secondary_text_dark</strong>&quot;
android:text=&quot;&#64;string/hello&quot; /&gt;
</pre>
<p class="note"><strong>Note:</strong> You should use string resources at all times, so that your
application can be localized for other languages. For information about creating alternative
resources (such as localized strings), see <a
href="providing-resources.html#AlternativeResources">Providing Alternative
Resources</a>.</p>
<p>You can even use resources in XML to create aliases. For example, you can create a
drawable resource that is an alias for another drawable resource:</p>
<pre>
&lt;?xml version="1.0" encoding="utf-8"?>
&lt;bitmap xmlns:android="http://schemas.android.com/apk/res/android"
android:src="@drawable/other_drawable" />
</pre>
<p>This sounds redundant, but can be very useful when using alternative resource. Read more about
<a href="providing-resources.html#AliasResources">Creating alias resources</a>.</p>
<h3 id="ReferencesToThemeAttributes">Referencing style attributes</h3>
<p>A style attribute resource allows you to reference the value
of an attribute in the currently-applied theme. Referencing a style attribute allows you to
customize the look of UI elements by styling them to match standard variations supplied by the
current theme, instead of supplying a hard-coded value. Referencing a style attribute
essentially says, "use the style that is defined by this attribute, in the current theme."</p>
<p>To reference a style attribute, the name syntax is almost identical to the normal resource
format, but instead of the at-symbol ({@code &#64;}), use a question-mark ({@code ?}), and the
resource type portion is optional. For instance:</p>
<pre class="classic">
?[<em>&lt;package_name&gt;</em>:][<em>&lt;resource_type&gt;</em>/]<em>&lt;resource_name&gt;</em>
</pre>
<p>For example, here's how you can reference an attribute to set the text color to match the
"primary" text color of the system theme:</p>
<pre>
&lt;EditText id=&quot;text&quot;
android:layout_width=&quot;fill_parent&quot;
android:layout_height=&quot;wrap_content&quot;
android:textColor=&quot;<strong>?android:textColorSecondary</strong>&quot;
android:text=&quot;&#64;string/hello_world&quot; /&gt;
</pre>
<p>Here, the {@code android:textColor} attribute specifies the name of a style attribute
in the current theme. Android now uses the value applied to the {@code android:textColorSecondary}
style attribute as the value for {@code android:textColor} in this widget. Because the system
resource tool knows that an attribute resource is expected in this context,
you do not need to explicitly state the type (which would be
<code>?android:attr/textColorSecondary</code>)&mdash;you can exclude the {@code attr} type.</p>
<h2 id="PlatformResources">Accessing Platform Resources</h2>
<p>Android contains a number of standard resources, such as styles, themes, and layouts. To
access these resource, qualify your resource reference with the
<code>android</code> package name. For example, Android provides a layout resource you can use for
list items in a {@link android.widget.ListAdapter}:</p>
<pre>
{@link android.app.ListActivity#setListAdapter(ListAdapter)
setListAdapter}(new {@link
android.widget.ArrayAdapter}&lt;String&gt;(this, <strong>android.R.layout.simple_list_item_1</strong>, myarray));
</pre>
<p>In this example, {@link android.R.layout#simple_list_item_1} is a layout resource defined by the
platform for items in a {@link android.widget.ListView}. You can use this instead of creating
your own layout for list items. (For more about using {@link android.widget.ListView}, see the
<a href="{@docRoot}resources/tutorials/views/hello-listview.html">List View Tutorial</a>.)</p>
@@ -0,0 +1,568 @@
page.title=Animation Resources
parent.title=Resource Types
parent.link=available-resources.html
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>See also</h2>
<ol>
<li><a href="{@docRoot}guide/topics/graphics/2d-graphics.html#tween-animation">2D
Graphics</a></li>
</ol>
</div>
</div>
<p>An animation resource can define one of two types of animations:</p>
<dl>
<dt><a href="#Tween">Tween Animation</a></dt>
<dd>Creates an animation by performing a series of transformations on a single image.
An {@link android.view.animation.Animation}.</dd>
<dt><a href="#Frame">Frame Animation</a></dt>
<dd>Creates an animation by showing a sequence of images in order.
An {@link android.graphics.drawable.AnimationDrawable}.</dd>
</dl>
<h2 id="Tween">Tween Animation</h2>
<p>An animation defined in XML that performs transitions such as rotating,
fading, moving, and stretching on a graphic.
</p>
<dl class="xml">
<dt>file location:</dt>
<dd><code>res/anim/<em>filename</em>.xml</code><br/>
The filename will be used as the resource ID.</dd>
<dt>compiled resource datatype:</dt>
<dd>Resource pointer to an {@link android.view.animation.Animation}.</dd>
<dt>resource reference:</dt>
<dd>
In Java: <code>R.anim.<em>filename</em></code><br/>
In XML: <code>@[<em>package</em>:]anim/<em>filename</em></code>
</dd>
<dt>syntax:</dt>
<dd>
<pre class="stx">
&lt;?xml version="1.0" encoding="utf-8"?>
&lt;<a href="#set-element">set</a> xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@[package:]anim/<em>interpolator_resource</em>"
android:shareInterpolator=["true" | "false"] &gt;
&lt;<a href="#alpha-element">alpha</a>
android:fromAlpha="<em>float</em>"
android:toAlpha="<em>float</em>" /&gt;
&lt;<a href="#scale-element">scale</a>
android:fromXScale="<em>float</em>"
android:toXScale="<em>float</em>"
android:fromYScale="<em>float</em>"
android:toYScale="<em>float</em>"
android:pivotX="<em>float</em>"
android:pivotY="<em>float</em>" /&gt;
&lt;<a href="#translate-element">translate</a>
android:fromX="<em>float</em>"
android:toX="<em>float</em>"
android:fromY="<em>float</em>"
android:toY="<em>float</em>" /&gt;
&lt;<a href="#rotate-element">rotate</a>
android:fromDegrees="<em>float</em>"
android:toDegrees="<em>float</em>"
android:pivotX="<em>float</em>"
android:pivotY="<em>float</em>" /&gt;
&lt;<a href="#set-element">set</a>&gt;
...
&lt;/set&gt;
&lt;/set&gt;
</pre>
<p>The file must have a single root element: either an
<code>&lt;alpha&gt;</code>, <code>&lt;scale&gt;</code>, <code>&lt;translate&gt;</code>,
<code>&lt;rotate&gt;</code>, or <code>&lt;set&gt;</code> element that holds
a group (or groups) of other animation elements (even nested <code>&lt;set&gt;</code> elements).
</p>
</dd>
<dt>elements:</dt>
<dd>
<dl class="tag-list">
<dt id="set-element"><code>&lt;set&gt;</code></dt>
<dd>A container that holds other animation elements
(<code>&lt;alpha&gt;</code>, <code>&lt;scale&gt;</code>, <code>&lt;translate&gt;</code>,
<code>&lt;rotate&gt;</code>) or other <code>&lt;set&gt;</code> elements. Represents an {@link
android.view.animation.AnimationSet}.
<p class="caps">attributes:</p>
<dl class="atn-list">
<dt><code>android:interpolator</code></dt>
<dd><em>Interpolator resource</em>.
An {@link android.view.animation.Interpolator} to apply on the animation.
The value must be a reference to a resource that specifies an interpolator
(not an interpolator class name). There are default interpolator
resources available from the platform or you can create your own interpolator resource.
See the discussion below for more about <a href="#Interpolators">Interpolators</a>.</dd>
<dt><code>android:shareInterpolator</code></dt>
<dd><em>Boolean</em>. "true" if you want to share the same interpolator among all child
elements.</dd>
</dl>
</dd>
<dt id="alpha-element"><code>&lt;alpha&gt;</code></dt>
<dd>A fade-in or fade-out animation. Represents an {@link
android.view.animation.AlphaAnimation}.
<p class="caps">attributes:</p>
<dl class="atn-list">
<dt><code>android:fromAlpha</code></dt>
<dd><em>Float</em>. Starting opacity offset, where 0.0 is transparent and 1.0
is opaque.</dd>
<dt><code>android:toAlpha</code></dt>
<dd><em>Float</em>. Ending opacity offset, where 0.0 is transparent and 1.0
is opaque.</dd>
</dl>
<p>For more attributes supported by <code>&lt;alpha&gt;</code>, see the
{@link android.view.animation.Animation} class reference (of which, all XML attributes are
inherrited by this element).</p>
</dd>
<dt id="scale-element"><code>&lt;scale&gt;</code></dt>
<dd>A resizing animation. You can specify the center point of the image from which it grows
outward (or inward) by specifying {@code pivotX} and {@code pivotY}. For example, if these values
are 0, 0 (top-left corner), all growth will be down and to the right. Represents a {@link
android.view.animation.ScaleAnimation}.
<p class="caps">attributes:</p>
<dl class="atn-list">
<dt><code>android:fromXScale</code></dt>
<dd><em>Float</em>. Starting X size offset, where 1.0 is no change.</dd>
<dt><code>android:toXScale</code></dt>
<dd><em>Float</em>. Ending X size offset, where 1.0 is no change.</dd>
<dt><code>android:fromYScale</code></dt>
<dd><em>Float</em>. Starting Y size offset, where 1.0 is no change.</dd>
<dt><code>android:toYScale</code></dt>
<dd><em>Float</em>. Ending Y size offset, where 1.0 is no change.</dd>
<dt><code>android:pivotX</code></dt>
<dd><em>Float</em>. The X coordinate to remain fixed when the object is scaled.</dd>
<dt><code>android:pivotY</code></dt>
<dd><em>Float</em>. The Y coordinate to remain fixed when the object is scaled.</dd>
</dl>
<p>For more attributes supported by <code>&lt;scale&gt;</code>, see the
{@link android.view.animation.Animation} class reference (of which, all XML attributes are
inherrited by this element).</p>
</dd>
<dt id="translate-element"><code>&lt;translate&gt;</code></dt>
<dd>A vertical and/or horizontal motion. Supports the following attributes in any of
the following three formats: values from -100 to 100 ending with "%", indicating a percentage
relative to itself; values from -100 to 100 ending in "%p", indicating a percentage relative to its
parent; a float value with no suffix, indicating an absolute value. Represents a {@link
android.view.animation.TranslateAnimation}.
<p class="caps">attributes:</p>
<dl class="atn-list">
<dt><code>android:fromXDelta</code></dt>
<dd><em>Float or percentage</em>. Starting X offset. Expressed either: in pixels relative
to the normal position (such as {@code "5"}), in percentage relative to the element width (such as
{@code "5%"}), or in percentage relative to the parent width (such as {@code "5%p"}).</dd>
<dt><code>android:toXDelta</code></dt>
<dd><em>Float or percentage</em>. Ending X offset. Expressed either: in pixels relative
to the normal position (such as {@code "5"}), in percentage relative to the element width (such as
{@code "5%"}), or in percentage relative to the parent width (such as {@code "5%p"}).</dd>
<dt><code>android:fromYDelta</code></dt>
<dd><em>Float or percentage</em>. Starting Y offset. Expressed either: in pixels relative
to the normal position (such as {@code "5"}), in percentage relative to the element height (such as
{@code "5%"}), or in percentage relative to the parent height (such as {@code "5%p"}).</dd>
<dt><code>android:toYDelta</code></dt>
<dd><em>Float or percentage</em>. Ending Y offset. Expressed either: in pixels relative
to the normal position (such as {@code "5"}), in percentage relative to the element height (such as
{@code "5%"}), or in percentage relative to the parent height (such as {@code "5%p"}).</dd>
</dl>
<p>For more attributes supported by <code>&lt;translate&gt;</code>, see the
{@link android.view.animation.Animation} class reference (of which, all XML attributes are
inherrited by this element).</p>
</dd>
<dt id="rotate-element"><code>&lt;rotate&gt;</code></dt>
<dd>A rotation animation. Represents a {@link android.view.animation.RotateAnimation}.
<p class="caps">attributes:</p>
<dl class="atn-list">
<dt><code>android:fromDegrees</code></dt>
<dd><em>Float</em>. Starting angular position, in degrees.</dd>
<dt><code>android:toDegrees</code></dt>
<dd><em>Float</em>. Ending angular position, in degrees.</dd>
<dt><code>android:pivotX</code></dt>
<dd><em>Float or percentage</em>. The X coordinate of the center of rotation. Expressed
either: in pixels relative to the object's left edge (such as {@code "5"}), in percentage relative
to the object's left edge (such as {@code "5%"}), or in percentage relative to the parent
container's left edge (such as {@code "5%p"}).</dd>
<dt><code>android:pivotY</code></dt>
<dd><em>Float or percentage</em>. The Y coordinate of the center of rotation. Expressed
either: in pixels relative to the object's top edge (such as {@code "5"}), in percentage relative
to the object's top edge (such as {@code "5%"}), or in percentage relative to the parent
container's top edge (such as {@code "5%p"}).</dd>
</dl>
<p>For more attributes supported by <code>&lt;rotate&gt;</code>, see the
{@link android.view.animation.Animation} class reference (of which, all XML attributes are
inherrited by this element).</p>
</dd>
</dl>
</dd> <!-- end elements and attributes -->
<dt>example:</dt>
<dd>
<pp>XML file saved at <code>res/anim/hyperspace_jump.xml</code>:</p>
<pre>
&lt;set xmlns:android="http://schemas.android.com/apk/res/android"
android:shareInterpolator="false">
&lt;scale
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
android:fromXScale="1.0"
android:toXScale="1.4"
android:fromYScale="1.0"
android:toYScale="0.6"
android:pivotX="50%"
android:pivotY="50%"
android:fillAfter="false"
android:duration="700" />
&lt;set
android:interpolator="@android:anim/accelerate_interpolator"
android:startOffset="700">
&lt;scale
android:fromXScale="1.4"
android:toXScale="0.0"
android:fromYScale="0.6"
android:toYScale="0.0"
android:pivotX="50%"
android:pivotY="50%"
android:duration="400" />
&lt;rotate
android:fromDegrees="0"
android:toDegrees="-45"
android:toYScale="0.0"
android:pivotX="50%"
android:pivotY="50%"
android:duration="400" />
&lt;/set>
&lt;/set>
</pre>
<p>This application code will apply the animation to an {@link android.widget.ImageView} and
start the animation:</p>
<pre>
ImageView image = (ImageView) findViewById(R.id.image);
Animation hyperspaceJump = AnimationUtils.{@link android.view.animation.AnimationUtils#loadAnimation(Context,int) loadAnimation}(this, R.anim.hyperspace_jump);
image.{@link android.view.View#startAnimation(Animation) startAnimation}(hyperspaceJump);
</pre>
</dd> <!-- end example -->
<dt>see also:</dt>
<dd>
<ul>
<li><a href="{@docRoot}guide/topics/graphics/2d-graphics.html#tween-animation">2D
Graphics: Tween Animation</a></li>
</ul>
</dd>
</dl>
<h3 id="Interpolators">Interpolators</h3>
<p>An interpolator is an animation modifier defined in XML that affects the rate of change in an
animation. This allows your existing animation effects to be accelerated, decelerated, repeated,
bounced, etc.</p>
<p>An interpolator is applied to an animation element with the {@code android:interpolator}
attribute, the value of which is a reference to an interpolator resource.</p>
<p>All interpolators available in Android are subclasses of the {@link
android.view.animation.Interpolator} class. For each interpolator class, Android
includes a public resource you can reference in order to apply the interpolator to an animation
using the the {@code android:interpolator} attribute.
The following table specifies the resource to use for each interpolator:</p>
<table>
<tr><th>Interpolator class</th><th>Resource ID</th></tr>
<tr>
<td>{@link android.view.animation.AccelerateDecelerateInterpolator}</td>
<td>{@code @android:anim/accelerate_decelerate_interpolator}</td>
</tr>
<tr>
<td>{@link android.view.animation.AccelerateInterpolator}</td>
<td>{@code @android:anim/accelerate_interpolator}</td>
</tr>
<tr>
<td>{@link android.view.animation.AnticipateInterpolator}</td>
<td>{@code @android:anim/anticipate_interpolator}</td>
</tr>
<tr>
<td>{@link android.view.animation.AnticipateOvershootInterpolator}</td>
<td>{@code @android:anim/anticipate_overshoot_interpolator}</td>
</tr>
<tr>
<td>{@link android.view.animation.BounceInterpolator}</td>
<td>{@code @android:anim/bounce_interpolator}</td>
</tr>
<tr>
<td>{@link android.view.animation.CycleInterpolator}</td>
<td>{@code @android:anim/cycle_interpolator}</td>
</tr>
<tr>
<td>{@link android.view.animation.DecelerateInterpolator}</td>
<td>{@code @android:anim/decelerate_interpolator}</td>
</tr>
<tr>
<td>{@link android.view.animation.LinearInterpolator}</td>
<td>{@code @android:anim/linear_interpolator}</td>
</tr>
<tr>
<td>{@link android.view.animation.OvershootInterpolator}</td>
<td>{@code @android:anim/overshoot_interpolator}</td>
</tr>
</table>
<p>Here's how you can apply one of these with the {@code android:interpolator} attribute:</p>
<pre>
&lt;set android:interpolator="@android:anim/accelerate_interpolator"&gt;
...
&lt;/set&gt;
</pre>
<h4>Custom interpolators</h4>
<p>If you're not satisfied with the interpolators provided by the platform (listed in the
table above), you can create a custom interpolator resource with modified attributes.
For example, you can adjust the rate of
acceleration for the {@link android.view.animation.AnticipateInterpolator}, or adjust the number of
cycles for the {@link android.view.animation.CycleInterpolator}. In order to do so, you need to
create your own interpolator resource in an XML file.
</p>
<dl class="xml">
<dt>file location:</dt>
<dd><code>res/anim/<em>filename</em>.xml</code><br/>
The filename will be used as the resource ID.</dd>
<dt>compiled resource datatype:</dt>
<dd>Resource pointer to the corresponding interpolator object.</dd>
<dt>resource reference:</dt>
<dd>
In XML: <code>@[<em>package</em>:]anim/<em>filename</em></code>
</dd>
<dt>syntax:</dt>
<dd>
<pre class="stx">
&lt;?xml version="1.0" encoding="utf-8"?>
&lt;<em>InterpolatorName</em> xmlns:android="http://schemas.android.com/apk/res/android"
android:<em>attribute_name</em>="<em>value</em>"
/>
</pre>
<p>If you don't apply any attributes, then your interpolator will function exactly the same as
those provided by the platform (listed in the table above).</p>
</dd>
<dt>elements:</dt>
<dd>Notice that each {@link android.view.animation.Interpolator} implementation, when
defined in XML, begins its name in lowercase.</p>
<dl class="tag-list">
<dt><code>&lt;accelerateDecelerateInterpolator&gt;</code></dt>
<dd>The rate of change starts and ends slowly but accelerates through the
middle. <p>No attributes.</p></dd>
<dt><code>&lt;accelerateInterpolator&gt;</code></dt>
<dd>The rate of change starts out slowly, then accelerates.
<p class="caps">attributes:</p>
<dl class="atn-list">
<dt><code>android:factor</code></dt>
<dd><em>Float</em>. The acceleration rate (default is 1).</dd>
</dl>
</dd>
<dt><code>&lt;anticipateInterpolator&gt;</code></dt>
<dd>The change starts backward then flings forward.
<p class="caps">attributes:</p>
<dl class="atn-list">
<dt><code>android:tension</code></dt>
<dd><em>Float</em>. The amount of tension to apply (default is 2).</dd>
</dl>
</dd>
<dt><code>&lt;anticipateOvershootInterpolator&gt;</code></dt>
<dd>The change starts backward, flings forward and overshoots the target value, then
settles at the final value.
<p class="caps">attributes:</p>
<dl class="atn-list">
<dt><code>android:tension</code></dt>
<dd><em>Float</em>. The amount of tension to apply (default is 2).</dd>
<dt><code>android:extraTension</code></dt>
<dd><em>Float</em>. The amount by which to multiply the tension (default is
1.5).</dd>
</dl>
</dd>
<dt><code>&lt;bounceInterpolator&gt;</code></dt>
<dd>The change bounces at the end. <p>No attributes</p></dd>
<dt><code>&lt;cycleInterpolator&gt;</code></dt>
<dd>Repeats the animation for a specified number of cycles. The rate of change follows a
sinusoidal pattern.
<p class="caps">attributes:</p>
<dl class="atn-list">
<dt><code>android:cycles</code></dt>
<dd><em>Integer</em>. The number of cycles (default is 1).</dd>
</dl>
</dd>
<dt><code>&lt;decelerateInterpolator&gt;</code></dt>
<dd>The rate of change starts out quickly, then decelerates.
<p class="caps">attributes:</p>
<dl class="atn-list">
<dt><code>android:factor</code></dt>
<dd><em>Float</em>. The deceleration rate (default is 1).</dd>
</dl>
</dd>
<dt><code>&lt;linearInterpolator&gt;</code></dt>
<dd>The rate of change is constant. <p>No attributes.</p></dd>
<dt><code>&lt;overshootInterpolator&gt;</code></dt>
<dd>The change flings forward and overshoots the last value, then comes back.
<p class="caps">attributes:</p>
<dl class="atn-list">
<dt><code>android:tension</code></dt>
<dd><em>Float</em>. The amount of tension to apply (default is 2).</dd>
</dl>
</dd>
</dl>
<dt>example:</dt>
<dd>
<p>XML file saved at <code>res/anim/my_overshoot_interpolator.xml</code>:</p>
<pre>
&lt;?xml version="1.0" encoding="utf-8"?>
&lt;overshootInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
android:tension="7.0"
/>
</pre>
<p>This animation XML will apply the interpolator:</p>
<pre>
&lt;scale xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@anim/my_overshoot_interpolator"
android:fromXScale="1.0"
android:toXScale="3.0"
android:fromYScale="1.0"
android:toYScale="3.0"
android:pivotX="50%"
android:pivotY="50%"
android:duration="700" />
</pre>
</dd>
</dl>
<h2 id="Frame">Frame Animation</h2>
<p>An animation defined in XML that shows a sequence of images in order (like a film).
</p>
<dl class="xml">
<dt>file location:</dt>
<dd><code>res/drawable/<em>filename</em>.xml</code><br/>
The filename will be used as the resource ID.</dd>
<dt>compiled resource datatype:</dt>
<dd>Resource pointer to an {@link android.graphics.drawable.AnimationDrawable}.</dd>
<dt>resource reference:</dt>
<dd>
In Java: <code>R.drawable.<em>filename</em></code><br/>
In XML: <code>@[<em>package</em>:]drawable.<em>filename</em></code>
</dd>
<dt>syntax:</dt>
<dd>
<pre class="stx">
&lt;?xml version="1.0" encoding="utf-8"?>
&lt;<a href="#animation-list-element">animation-list</a> xmlns:android="http://schemas.android.com/apk/res/android"
android:oneshot=["true" | "false"] >
&lt;<a href="#item-element">item</a>
android:drawable="@[package:]drawable/<em>drawable_resource_name</em>"
android:duration="<em>integer</em>" />
&lt;/animation-list>
</pre>
</dd>
<dt>elements:</dt>
<dd>
<dl class="tag-list">
<dt id="animation-list-element"><code>&lt;animation-list&gt;</code></dt>
<dd><strong>Required</strong>. This must be the root element. Contains one or more
<code>&lt;item&gt;</code> elements.
<p class="caps">attributes:</p>
<dl class="atn-list">
<dt><code>android:oneshot</code></dt>
<dd><em>Boolean</em>. "true" if you want to perform the animation once; "false" to loop the
animation.</dd>
</dl>
</dd>
<dt id="item-element"><code>&lt;item&gt;</code></dt>
<dd>A single frame of animation. Must be a child of a <code>&lt;animation-list&gt;</code> element.
<p class="caps">attributes:</p>
<dl class="atn-list">
<dt><code>android:drawable</code></dt>
<dd><em>Drawable resource</em>. The drawable to use for this frame.</dd>
<dt><code>android:duration</code></dt>
<dd><em>Integer</em>. The duration to show this frame, in milliseconds.</dd>
</dl>
</dd>
</dl>
</dd> <!-- end elements and attributes -->
<dt>example:</dt>
<dd>
<dl>
<dt>XML file saved at <code>res/anim/rocket.xml</code>:</dt>
<dd>
<pre>
&lt;?xml version="1.0" encoding="utf-8"?>
&lt;animation-list xmlns:android="http://schemas.android.com/apk/res/android"
android:oneshot="false">
&lt;item android:drawable="@drawable/rocket_thrust1" android:duration="200" />
&lt;item android:drawable="@drawable/rocket_thrust2" android:duration="200" />
&lt;item android:drawable="@drawable/rocket_thrust3" android:duration="200" />
&lt;/animation-list>
</pre>
</dd>
<dt>This application code will set the animation as the background for a View,
then play the animation:</dt>
<dd>
<pre>
ImageView rocketImage = (ImageView) findViewById(R.id.rocket_image);
rocketImage.{@link android.view.View#setBackgroundResource(int) setBackgroundResource}(R.drawable.rocket_thrust);
rocketAnimation = (AnimationDrawable) rocketImage.{@link android.view.View#getBackground()};
rocketAnimation.{@link android.graphics.drawable.AnimationDrawable#start()};
</pre>
</dd>
</dl>
</dd> <!-- end example -->
</dl>
@@ -0,0 +1,59 @@
page.title=Resource Types
parent.title=Application Resources
parent.link=index.html
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>See also</h2>
<ol>
<li><a href="providing-resources.html">Providing Resources</a></li>
<li><a href="accessing-resources.html">Accessing Resources</a></li>
</ol>
</div>
</div>
<p>Each of the documents in this section describe the usage, format and syntax for a certain type
of application resource that you can provide in your resources directory ({@code res/}).</p>
<p>Here's a brief summary of each resource type:</p>
<dl>
<dt><a href="{@docRoot}guide/topics/resources/animation-resource.html">Animation Resources</a></dt>
<dd>Define pre-determined animations.<br/>
Tween animations are saved in {@code res/anim/} and accessed from the {@code R.anim} class.<br/>
Frame animations are saved in {@code res/drawable/} and accessed from the {@code R.drawable} class.</dd>
<dt><a href="{@docRoot}guide/topics/resources/color-list-resource.html">Color State List Resource</a></dt>
<dd>Define a color resources that changes based on the View state.<br/>
Saved in {@code res/color/} and accessed from the {@code R.color} class.</dd>
<dt><a href="{@docRoot}guide/topics/resources/drawable-resource.html">Drawable Resources</a></dt>
<dd>Define various graphics with bitmaps or XML.<br/>
Saved in {@code res/drawable/} and accessed from the {@code R.drawable} class.</dd>
<dt><a href="{@docRoot}guide/topics/resources/layout-resource.html">Layout Resource</a></dt>
<dd>Define the layout for your application UI.<br/>
Saved in {@code res/layout/} and accessed from the {@code R.layout} class.</dd>
<dt><a href="{@docRoot}guide/topics/resources/menu-resource.html">Menu Resource</a></dt>
<dd>Define the contents of your application menus.<br/>
Saved in {@code res/menu/} and accessed from the {@code R.menu} class.</dd>
<dt><a href="{@docRoot}guide/topics/resources/string-resource.html">String Resources</a></dt>
<dd>Define strings, string arrays, and plurals (and include string formatting and styling).<br/>
Saved in {@code res/values/} and accessed from the {@code R.string}, {@code R.array},
and {@code R.plurals} classes.</dd>
<dt><a href="{@docRoot}guide/topics/resources/style-resource.html">Style Resource</a></dt>
<dd>Define the look and format for UI elements.<br/>
Saved in {@code res/values/} and accessed from the {@code R.style} class.</dd>
<dt><a href="{@docRoot}guide/topics/resources/more-resources.html">More Resource Types</a></dt>
<dd>Define values such as booleans, integers, dimensions, colors, and other arrays.<br/>
Saved in {@code res/values/} but each accessed from unique {@code R} sub-classes (such as {@code
R.bool}, {@code R.integer}, {@code R.dimen}, etc.).</dd>
</dl>
@@ -0,0 +1,164 @@
page.title=Color State List Resource
parent.title=Resource Types
parent.link=available-resources.html
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>See also</h2>
<ol>
<li><a href="more-resources.html#Color">Color (simple value)</a></li>
</ol>
</div>
</div>
<p>A {@link android.content.res.ColorStateList} is an object you can define in XML
that you can apply as a color, but will actually change colors, depending on the state of
the {@link android.view.View} object to which it is applied. For example, a {@link
android.widget.Button} widget can exist in one of several different states (pressed, focused,
or niether) and, using a color state list, you can provide a different color during each state.</p>
<p>You can describe the state list in an XML file. Each color is defined in an {@code
&lt;item>} element inside a single {@code &lt;selector>} element. Each {@code &lt;item>}
uses various attributes to describe the state in which it should be used.</p>
<p>During each state change, the state list is traversed top to bottom and the first item that
matches the current state will be used&mdash;the selection is <em>not</em> based on the "best
match," but simply the first item that meets the minimum criteria of the state.</p>
<p class="note"><strong>Note:</strong> If you want to provide a static color resource, use a
simple <a href="more-resources.html#Color">Color</a> value.</p>
<dl class="xml">
<dt>file location:</dt>
<dd><code>res/color/<em>filename</em>.xml</code><br/>
The filename will be used as the resource ID.</dd>
<dt>compiled resource datatype:</dt>
<dd>Resource pointer to a {@link android.content.res.ColorStateList}.</dd>
<dt>resource reference:</dt>
<dd>
In Java: <code>R.color.<em>filename</em></code><br/>
In XML: <code>@[<em>package</em>:]color/<em>filename</em></code>
</dd>
<dt>syntax:</dt>
<dd>
<pre class="stx">
&lt;?xml version="1.0" encoding="utf-8"?>
&lt;<a href="#selector-element">selector</a> xmlns:android="http://schemas.android.com/apk/res/android" >
&lt;<a href="#item-element">item</a>
android:color="<em>hex_color</em>"
android:state_pressed=["true" | "false"]
android:state_focused=["true" | "false"]
android:state_selected=["true" | "false"]
android:state_checkable=["true" | "false"]
android:state_checked=["true" | "false"]
android:state_enabled=["true" | "false"]
android:state_window_focused=["true" | "false"] />
&lt;/selector>
</pre>
</dd>
<dt>elements:</dt>
<dd>
<dl class="tag-list">
<dt id="selector-element"><code>&lt;selector&gt;</code></dt>
<dd><strong>Required.</strong> This must be the root element. Contains one or more {@code
&lt;item>} elements.
<p class="caps">attributes:</p>
<dl class="atn-list">
<dt><code>xmlns:android</code></dt>
<dd><em>String</em>. <strong>Required.</strong> Defines the XML namespace, which must be
<code>"http://schemas.android.com/apk/res/android"</code>.
</dl>
</dd>
<dt id="item-element"><code>&lt;item&gt;</code></dt>
<dd>Defines a color to use during certain states, as described by its attributes. Must be a
child of a <code>&lt;selector&gt;</code> element.
<p class="caps">attributes:</p>
<dl class="atn-list">
<dt><code>android:color</code></dt>
<dd><em>Hexadeximal color</em>. <strong>Required</strong>. The color is specified with an
RGB value and optional alpha channel.
<p>The value always begins with a pound (#) character and then followed by the
Alpha-Red-Green-Blue information in one of the following formats:</p>
<ul>
<li>#<em>RGB</em></li>
<li>#<em>ARGB</em></li>
<li>#<em>RRGGBB</em></li>
<li>#<em>AARRGGBB</em></li>
</ul></dd>
<dt><code>android:state_pressed</code></dt>
<dd><em>Boolean</em>. "true" if this item should be used when the object is pressed (such as when a button
is touched/clicked); "false" if this item should be used in the default, non-pressed state.</dd>
<dt><code>android:state_focused</code></dt>
<dd><em>Boolean</em>. "true" if this item should be used when the object is focused (such as when a button
is highlighted using the trackball/d-pad); "false" if this item should be used in the default,
non-focused state.</dd>
<dt><code>android:state_selected</code></dt>
<dd><em>Boolean</em>. "true" if this item should be used when the object is selected (such as when a
tab is opened); "false" if this item should be used when the object is not selected.</dd>
<dt><code>android:state_checkable</code></dt>
<dd><em>Boolean</em>. "true" if this item should be used when the object is checkable; "false" if this
item should be used when the object is not checkable. (Only useful if the object can
transition between a checkable and non-checkable widget.)</dd>
<dt><code>android:state_checked</code></dt>
<dd><em>Boolean</em>. "true" if this item should be used when the object is checked; "false" if it
should be used when the object is un-checked.</dd>
<dt><code>android:state_enabled</code></dt>
<dd><em>Boolean</em>. "true" if this item should be used when the object is enabled (capable of
receiving touch/click events); "false" if it should be used when the object is disabled.</dd>
<dt><code>android:state_window_focused</code></dt>
<dd><em>Boolean</em>. "true" if this item should be used when the application window has focus (the
application is in the foreground), "false" if this item should be used when the application
window does not have focus (for example, if the notification shade is pulled down or a dialog appears).</dd>
</dl>
<p class="note"><strong>Note:</strong> Remember that the first item in the state list that
matches the current state of the object will be applied. So if the first item in the list contains
none of the state attributes above, then it will be applied every time, which is why your
default value should always be last (as demonstrated in the following example).</p>
</dd>
</dl>
</dd> <!-- end elements and attributes -->
<dt>example:</dt>
<dd>XML file saved at <code>res/color/button_text.xml</code>:
<pre>
&lt;?xml version="1.0" encoding="utf-8"?>
&lt;selector xmlns:android="http://schemas.android.com/apk/res/android">
&lt;item android:state_pressed="true"
android:color="#ffff0000"/> &lt;!-- pressed --&gt;
&lt;item android:state_focused="true"
android:color="#ff0000ff"/> &lt;!-- focused --&gt;
&lt;item android:color="#ff000000"/> &lt;!-- default --&gt;
&lt;/selector>
</pre>
<p>This layout XML will apply the color list to a View:</p>
<pre>
&lt;Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/button_text"
android:textColor="@color/button_text" />
</pre>
</dd> <!-- end example -->
<dt>see also:</dt>
<dd>
<ul>
<li><a href="more-resources.html#Color">Color (simple value)</a></li>
<li>{@link android.content.res.ColorStateList}</li>
<li><a href="drawable-resource.html#StateList">State List Drawable</a></li>
</ul>
</dd>
</dl>
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,105 @@
page.title=Application Resources
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>Topics</h2>
<ol>
<li><a href="providing-resources.html">Providing Resources</a></li>
<li><a href="accessing-resources.html">Accessing Resources</a></li>
<li><a href="runtime-changes.html">Handling Runtime Changes</a></li>
<li><a href="localization.html">Localization</a></li>
</ol>
<h2>Reference</h2>
<ol>
<li><a href="available-resources.html">Resource Types</a></li>
</ol>
</div>
</div>
<p>You should always externalize resources such as images and strings from your application
code, so that you can maintain them independently. Externalizing your
resources also allows you to provide alternative resources that support specific device
configurations such as different languages or screen sizes, which becomes increasingly
important as more Android-powered devices become available with different configurations. In order
to provide compatibility with different configurations, you must organize resources in your
project's {@code res/} directory, using various sub-directories that group resources by type and
configuration.</p>
<div class="figure" style="width:421px">
<img src="{@docRoot}images/resources/resource_devices_diagram1.png" height="137" alt="" />
<p class="img-caption">
<strong>Figure 1.</strong> Two different devices, both using default
resources.</p>
</div>
<div class="figure" style="width:421px">
<img src="{@docRoot}images/resources/resource_devices_diagram2.png" height="137" alt="" />
<p class="img-caption">
<strong>Figure 2.</strong> Two different devices, one using alternative
resources.</p>
</div>
<p>For any type of resource, you can specify <em>default</em> and multiple
<em>alternative</em> resources for your application:</p>
<ul>
<li>Default resources are those that should be used regardless of
the device configuration or when there are no alternative resources that match the current
configuration.</li>
<li>Alternative resources are those that you've designed for use with a specific
configuration. To specify that a group of resources are for a specific configuration,
append an appropriate configuration qualifier to the directory name.</li>
</ul>
<p>For example, while your default UI
layout is saved in the {@code res/layout/} directory, you might specify a different UI layout to
be used when the screen is in landscape orientation, by saving it in the {@code res/layout-land/}
directory. Android automatically applies the appropriate resources by matching the
device's current configuration to your resource directory names.</p>
<p>Figure 1 demonstrates how a collection of default resources from an application are applied
to two different devices when there are no alternative resources available. Figure 2 shows
the same application with a set of alternative resources that qualify for one of the device
configurations, thus, the two devices uses different resources.</p>
<p>The information above is just an introduction to how application resources work on Android.
The following documents provide a complete guide to how you can organize your application resources,
specify alternative resources, access them in your application, and more:</p>
<dl>
<dt><strong><a href="providing-resources.html">Providing Resources</a></strong></dt>
<dd>What kinds of resources you can provide in your app, where to save them, and how to create
alternative resources for specific device configurations.</dd>
<dt><strong><a href="accessing-resources.html">Accessing Resources</a></strong></dt>
<dd>How to use the resources you've provided, either by referencing them from your application
code or from other XML resources.</dd>
<dt><strong><a href="runtime-changes.html">Handling Runtime Changes</a></strong></dt>
<dd>How to manage configuration changes that occur while your Activity is running.</dd>
<dt><strong><a href="localization.html">Localization</a></strong></dt>
<dd>A bottom-up guide to localizing your application using alternative resources. While this is
just one specific use of alternative resources, it is very important in order to reach more
users.</dd>
<dt><strong><a href="available-resources.html">Resource Types</a></strong></dt>
<dd>A reference of various resource types you can provide, describing their XML elements,
attributes, and syntax. For example, this reference shows you how to create a resource for
application menus, drawables, animations, and more.</dd>
</dl>
<!--
<h2>Raw Assets</h2>
<p>An alternative to saving files in {@code res/} is to save files in the {@code
assets/} directory. This should only be necessary if you need direct access to original files and
directories by name. Files saved in the {@code assets/} directory will not be given a resource
ID, so you can't reference them through the {@code R} class or from XML resources. Instead, you can
query data in the {@code assets/} directory like an ordinary file system, search through the
directory and
read raw data using {@link android.content.res.AssetManager}. For example, this can be more useful
when dealing with textures for a game. However, if you only need to read raw data from a file
(such as a video or audio file), then you should save files into the {@code res/raw/} directory and
then read a stream of bytes using {@link android.content.res.Resources#openRawResource(int)}. This
is uncommon, but if you need direct access to original files in {@code assets/}, refer to the {@link
android.content.res.AssetManager} documentation.</p>
-->
@@ -0,0 +1,282 @@
page.title=Layout Resource
parent.title=Resource Types
parent.link=available-resources.html
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>See also</h2>
<ol>
<li><a href="{@docRoot}guide/topics/ui/declaring-layout.html">Declaring Layout</a></li>
</ol>
</div>
</div>
<p>A layout resource defines the architecture for the UI in an Activity or a component of a UI.</p>
<dl class="xml">
<dt>file location:</dt>
<dd><code>res/layout/<em>filename</em>.xml</code><br/>
The filename will be used as the resource ID.</dd>
<dt>compiled resource datatype:</dt>
<dd>Resource pointer to a {@link android.view.View} (or subclass) resource.</dd>
<dt>resource reference:</dt>
<dd>
In Java: <code>R.layout.<em>filename</em></code><br/>
In XML: <code>@[<em>package</em>:]layout/<em>filename</em></code>
</dd>
<dt>syntax:</dt>
<dd>
<pre class="stx">
&lt;?xml version="1.0" encoding="utf-8"?>
&lt;<a href="#viewgroup-element"><em>ViewGroup</em></a> xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@[+][<em>package</em>:]id/<em>resource_name</em>"
android:layout_height=["<em>dimension</em>" | "fill_parent" | "wrap_content"]
android:layout_width=["<em>dimension</em>" | "fill_parent" | "wrap_content"]
[<em>ViewGroup-specific attributes</em>] &gt;
&lt;<a href="#view-element"><em>View</em></a>
android:id="@[+][<em>package</em>:]id/<em>resource_name</em>"
android:layout_height=["<em>dimension</em>" | "fill_parent" | "wrap_content"]
android:layout_width=["<em>dimension</em>" | "fill_parent" | "wrap_content"]
[<em>View-specific attributes</em>] &gt;
&lt;<a href="#requestfocus-element">requestFocus</a>/&gt;
&lt;/<em>View</em>&gt;
&lt;<a href="#viewgroup-element"><em>ViewGroup</em></a> &gt;
&lt;<a href="#view-element"><em>View</em></a> /&gt;
&lt;/<em>ViewGroup</em>&gt;
&lt;<a href="#include-element">include</a> layout="@layout/<i>layout_resource</i>"/&gt;
&lt;/<em>ViewGroup</em>&gt;
</pre>
<p class="note"><strong>Note:</strong> The root element can be either a
{@link android.view.ViewGroup}, a {@link android.view.View}, or a <a
href="#merge-element">{@code &lt;merge&gt;}</a> element, but there must be only
one root element and it must contain the {@code xmlns:android} attribute with the {@code android}
namespace as shown.</p>
</dd>
<dt>elements:</dt>
<dd>
<dl class="tag-list">
<dt id="viewgroup-element"><code>&lt;ViewGroup&gt;</code></dt>
<dd>A container for other {@link android.view.View} elements. There are many
different kinds of {@link android.view.ViewGroup} objects and each one lets you
specify the layout of the child elements in different ways. Different kinds of
{@link android.view.ViewGroup} objects include {@link android.widget.LinearLayout},
{@link android.widget.RelativeLayout}, and {@link android.widget.FrameLayout}.
<p>You should not assume that any derivation of {@link android.view.ViewGroup}
will accept nested {@link android.view.View}s. Some {@link android.view.ViewGroup}s
are implementations of the {@link android.widget.AdapterView} class, which determines
its children only from an {@link android.widget.Adapter}.</p>
<p class="caps">attributes:</p>
<dl class="atn-list">
<dt><code>android:id</code></dt>
<dd><em>Resource ID</em>. A unique resource name for the element, which you can
use to obtain a reference to the {@link android.view.ViewGroup} from your application. See more
about the <a href="#idvalue">value for {@code android:id}</a> below.
</dd>
<dt><code>android:layout_height</code></dt>
<dd><em>Dimension or keyword</em>. <strong>Required</strong>. The height for the group, as a
dimension value (or <a
href="more-resources.html#Dimension">dimension resource</a>) or a keyword ({@code "fill_parent"}
or {@code "wrap_content"}). See the <a href="#layoutvalues">valid values</a> below.
</dd>
<dt><code>android:layout_width</code></dt>
<dd><em>Dimension or keyword</em>. <strong>Required</strong>. The width for the group, as a
dimension value (or <a
href="more-resources.html#Dimension">dimension resource</a>) or a keyword ({@code "fill_parent"}
or {@code "wrap_content"}). See the <a href="#layoutvalues">valid values</a> below.
</dd>
</dl>
<p>More attributes are supported by the {@link android.view.ViewGroup}
base class, and many more are supported by each implementation of
{@link android.view.ViewGroup}. For a reference of all available attributes,
see the corresponding reference documentation for the {@link android.view.ViewGroup} class
(for example, the <a
href="{@docRoot}reference/android/widget/LinearLayout.html#lattrs">LinearLayout XML
attributes</a>).</p>
</dd>
<dt id="view-element"><code>&lt;View&gt;</code></dt>
<dd>An individual UI component, generally referred to as a "widget". Different
kinds of {@link android.view.View} objects include {@link android.widget.TextView},
{@link android.widget.Button}, and {@link android.widget.CheckBox}.
<p class="caps">attributes:</p>
<dl class="atn-list">
<dt><code>android:id</code></dt>
<dd><em>Resource ID</em>. A unique resource name for the element, which you can use to
obtain a reference to the {@link android.view.View} from your application. See more about
the <a href="#idvalue">value for {@code android:id}</a> below.
</dd>
<dt><code>android:layout_height</code></dt>
<dd><em>Dimension or keyword</em>. <strong>Required</strong>. The height for the element, as
a dimension value (or <a
href="more-resources.html#Dimension">dimension resource</a>) or a keyword ({@code "fill_parent"}
or {@code "wrap_content"}). See the <a href="#layoutvalues">valid values</a> below.
</dd>
<dt><code>android:layout_width</code></dt>
<dd><em>Dimension or keyword</em>. <strong>Required</strong>. The width for the element, as
a dimension value (or <a
href="more-resources.html#Dimension">dimension resource</a>) or a keyword ({@code "fill_parent"}
or {@code "wrap_content"}). See the <a href="#layoutvalues">valid values</a> below.
</dd>
</dl>
<p>More attributes are supported by the {@link android.view.View}
base class, and many more are supported by each implementation of
{@link android.view.View}. Read <a href="{@docRoot}guide/topics/ui/declaring-layout.html">Declaring
Layout</a> for more information. For a reference of all available attributes,
see the corresponding reference documentation (for example, the <a
href="{@docRoot}reference/android/widget/TextView.html#lattrs">TextView XML attributes</a>).</p>
</dd>
<dt id="requestfocus-element"><code>&lt;requestFocus&gt;</code></dt>
<dd>Any element representing a {@link android.view.View} object can include this empty element,
which gives it's parent initial focus on the screen. You can have only one of these
elements per file.</dd>
<dt id="include-element"><code>&lt;include&gt;</code></dt>
<dd>Includes a layout file into this layout.
<p class="caps">attributes:</p>
<dl class="atn-list">
<dt><code>layout</code></dt>
<dd><em>Layout resource</em>. <strong>Required</strong>. Reference to a layout
resource.</dd>
<dt><code>android:id</code></dt>
<dd><em>Resource ID</em>. Overrides the ID given to the root view in the included layout.
</dd>
<dt><code>android:layout_height</code></dt>
<dd><em>Dimension or keyword</em>. Overrides the height given to the root view in the
included layout. Only effective if <code>android:layout_width</code> is also declared.
</dd>
<dt><code>android:layout_width</code></dt>
<dd><em>Dimension or keyword</em>. Overrides the width given to the root view in the
included layout. Only effective if <code>android:layout_height</code> is also declared.
</dd>
</dl>
<p>You can include any other layout attributes in the <code>&lt;include&gt;</code> that are
supported by the root element in the included layout and they will override those defined in the
root element.</p>
<p class="caution"><strong>Caution:</strong> If you want to override the layout dimensions,
you must override both <code>android:layout_height</code> and
<code>android:layout_width</code>&mdash;you cannot override only the height or only the width.
If you override only one, it will not take effect. (Other layout properties, such as weight,
are still inherited from the source layout.)</p>
<p>Another way to include a layout is to use {@link android.view.ViewStub}. It is a lightweight
View that consumes no layout space until you explicitly inflate it, at which point, it includes a
layout file defined by its {@code android:layout} attribute. For more information about using {@link
android.view.ViewStub}, read <a href="{@docRoot}resources/articles/layout-tricks-stubs.html">Layout
Tricks: ViewStubs</a>.</p>
</dd>
<dt id="merge-element"><code>&lt;merge&gt;</code></dt>
<dd>An alternative root element that is not drawn in the layout hierarchy. Using this as the
root element is useful when you know that this layout will be placed into a layout
that already contains the appropriate parent View to contain the children of the
<code>&lt;merge&gt;</code> element. This is particularly useful when you plan to include this layout
in another layout file using <a href="#include-element"><code>&lt;include&gt;</code></a> and
this layout doesn't require a different {@link android.view.ViewGroup} container. For more
information about merging layouts, read <a
href="{@docRoot}resources/articles/layout-tricks-merge.html">Layout
Tricks: Merging</a>.</dd>
</dl>
<h4 id="idvalue">Value for <code>android:id</code></h4>
<p>For the ID value, you should usually use this syntax form: <code>"@+id/<em>name</em>"</code>. The
plus symbol, {@code +}, indicates that this is a new resource ID and the <code>aapt</code> tool will
create a new resource integer in the {@code R.java} class, if it doesn't already exist. For
example:</p>
<pre>
&lt;TextView android:id="@+id/nameTextbox"/>
</pre>
<p>The <code>nameTextbox</code> name is now a resource ID attached to this element. You can then
refer to the {@link android.widget.TextView} to which the ID is associated in Java:</p>
<pre>
findViewById(R.id.nameTextbox);
</pre>
<p>This code returns the {@link android.widget.TextView} object.</p>
<p>However, if you have already defined an <a
href="{@docRoot}guide/topics/resources/drawable-resource.html#Id">ID resource</a> (and it is not
already used), then you can apply that ID to a {@link android.view.View} element by excluding the
plus symbol in the <code>android:id</code> value.</p>
<h4 id="layoutvalues">Value for <code>android:layout_height</code> and
<code>android:layout_width</code>:</h4>
<p>The height and width value can be expressed using any of the
<a href="more-resources.html#Dimension">dimension
units</a> supported by Android (px, dp, sp, pt, in, mm) or with the following keywords:</p>
<table><tr><th>Value</th><th>Description</th></tr>
<tr>
<td><code>match_parent</code></td>
<td>Sets the dimension to match that of the parent element. Added in API Level 8 to
deprecate <code>fill_parent</code>.</td>
</tr>
<tr>
<td><code>fill_parent</code></td>
<td>Sets the dimension to match that of the parent element.</td>
</tr><tr>
<td><code>wrap_content</code></td>
<td>Sets the dimension only to the size required to fit the content of this element.</td>
</tr>
</table>
<h4>Custom View elements</h4>
<p>You can create your own custom {@link android.view.View} and {@link android.view.ViewGroup}
elements and apply them to your layout the same as a standard layout
element. You can also specify the attributes supported in the XML element. To learn more,
read <a href="{@docRoot}guide/topics/ui/custom-components.html">Building Custom Components</a>.
</p>
</dd> <!-- end elements and attributes -->
<dt>example:</dt>
<dd>XML file saved at <code>res/layout/main_activity.xml</code>:
<pre>
&lt;?xml version="1.0" encoding="utf-8"?>
&lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
&lt;TextView android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello, I am a TextView" />
&lt;Button android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello, I am a Button" />
&lt;/LinearLayout>
</pre>
<p>This application code will load the layout for an {@link android.app.Activity}, in the
{@link android.app.Activity#onCreate(Bundle) onCreate()} method:</dt>
<dd>
<pre>
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView.(R.layout.main_activity);
}
</pre>
</dd> <!-- end example -->
<dt>see also:</dt>
<dd>
<ul>
<li><a href="{@docRoot}guide/topics/ui/declaring-layout.html">Declaring Layout</a></li>
<li>{@link android.view.View}</li>
<li>{@link android.view.ViewGroup}</li>
</ul>
</dd>
</dl>
+647
View File
@@ -0,0 +1,647 @@
page.title=Localization
parent.title=Application Resources
parent.link=index.html
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>Localization quickview</h2>
<ul>
<li>Android lets you create different resource sets for different locales.</li>
<li>When your application runs, Android will load the resource set
that match the device's locale.</li>
<li>If locale-specific resources are not available, Android falls back to
defaults.</li>
<li>The emulator has features for testing localized apps. </li>
</ul>
<h2>In this document</h2>
<ol>
<li><a href="#resource-switching">Overview: Resource-Switching in Android</a>
</li>
<ol><li><a href="#defaults-r-important">Why Default Resources Are Important</a></li></ol>
<li><a href="#using-framework">Using Resources for Localization</a>
<ol>
<li><a href="#creating-defaults">How to Create Default Resources</a></li>
<li><a href="#creating-alternatives">How to Create Alternative Resources</a></li>
<li><a href="#resource-precedence">Which Resources Take Precedence?</a></li>
<li><a href="#referring-to-resources">Referring to Resources in Java</a></li>
</ol>
</li>
<li><a href="#strategies">Localization Strategies</a></li>
<li><a href="#testing">Testing Localized Applications</a></li>
<ol>
<li><a href="#device">Testing on a Device</a></li>
<li><a href="#emulator">Testing on an Emulator</a></li>
<li><a href="#test-for-default">Testing for Default Resources</a></li>
</ol>
<li><a href="#publishing">Publishing</a></li>
<li><a href="#checklist">Localization Checklists</a></li>
<ol>
<li><a href="#planning-checklist">Planning and Design Checklist</a></li>
<li><a href="#content-checklist">Content Checklist</a></li>
<li><a href="#testing-checklist">Testing and Publishing Checklist</a></li>
</ol>
</ol>
<h2>See also</h2>
<ol>
<li><a
href="{@docRoot}resources/tutorials/localization/index.html">Hello, L10N Tutorial</a></li>
<li><a href="{@docRoot}guide/topics/resources/providing-resources.html">Providing Resources</a></li>
<li><a href="{@docRoot}guide/topics/ui/declaring-layout.html">Declaring Layout</a></li>
<li><a href="{@docRoot}reference/android/app/Activity.html#ActivityLifecycle">Activity Lifecycle</a></li>
</ol>
</div>
</div>
<p>Android will run on many devices in many regions. To reach the most users,
your application should handle text, audio files, numbers, currency, and
graphics in ways appropriate to the locales where your application will be used.
</p>
<p>This document describes best practices for localizing Android
applications. The principles apply whether you are developing your application
using ADT with Eclipse, Ant-based tools, or any other IDE. </p>
<p>You should already have a working knowledge of Java and be familiar with
Android resource loading, the declaration of user interface elements in XML,
development considerations such as Activity lifecycle, and general principles of
internationalization and localization. </p>
<p>It is good practice to use the Android resource framework to separate the
localized aspects of your application as much as possible from the core Java
functionality:</p>
<ul>
<li>You can put most or all of the <em>contents</em> of your application's
user interface into resource files, as described in this document and in <a
href="{@docRoot}guide/topics/resources/providing-resources.html">Providing Resources</a>.</li>
<li>The <em>behavior</em> of the user interface, on the other hand, is driven
by your Java code.
For example, if users input data that needs to be formatted or sorted
differently depending on locale, then you would use Java to handle the data
programmatically. This document does not cover how to localize your Java code.
</li>
</ul>
<p>The <a
href="{@docRoot}resources/tutorials/localization/index.html">Hello, L10N
</a> tutorial takes you through the steps of creating a simple localized
application that uses locale-specific resources in the way described in this
document. </p>
<h2 id="resource-switching">Overview: Resource-Switching in Android</h2>
<p>Resources are text strings, layouts, sounds, graphics, and any other static
data that your Android application needs. An application can include multiple
sets of resources, each customized for a different device configuration. When a
user runs the application, Android automatically selects and loads the
resources that best match the device.</p>
<p>(This document focuses on localization and locale. For a complete description
of resource-switching and all the types of configurations that you can
specify &#8212; screen orientation, touchscreen type, and so on &#8212; see <a
href="{@docRoot}guide/topics/resources/providing-resources.html#AlternativeResources">Providing
Alternative Resources</a>.)</p>
<table border="0" cellspacing="0" cellpadding="0">
<tr border="0">
<td width="180" style="border: 0pt none ;"><p class="special-note">
<strong>When you write your application:</strong>
<br><br>
You create a set of default resources, plus alternatives to be used in
different locales.</p></td>
<td style="border: 0pt none; padding:0">
<p style="border:0; padding:0"><img src="../../../images/resources/right-arrow.png" alt="right-arrow"
width="51" height="17"></p></td>
<td width="180" style="border: 0pt none ;"><p class="special-note">
<strong>When a user runs your application:</strong>
<br><br>The Android system selects which resources to load, based on the
device's locale.</p></td>
</tr>
</table>
<p>When you write your application, you create default and alternative resources
for your application to use. To create resources, you place files within
specially named subdirectories of the project's <code>res/</code> directory.
</p>
<h3 id="defaults-r-important">Why Default Resources Are Important</h3>
<p>Whenever the application runs in a locale for which you have not provided
locale-specific text, Android will load the default strings from
<code>res/values/strings.xml</code>. If this default file is absent, or if it
is missing a string that your application needs, then your application will not run
and will show an error.
The example below illustrates what can happen when the default text file is incomplete. </p>
<p><em>Example:</em>
<p>An application's Java code refers to just two strings, <code>text_a</code> and
<code>text_b</code>. This application includes a localized resource file
(<code>res/values-en/strings.xml</code>) that defines <code>text_a</code> and
<code>text_b</code> in English. This application also includes a default
resource file (<code>res/values/strings.xml</code>) that includes a
definition for <code>text_a</code>, but not for <code>text_b</code>:
<ul>
<li>This application might compile without a problem. An IDE such as Eclipse
will not highlight any errors if a resource is missing.</li>
<li>When this application is launched on a device with locale set to English,
the application might run without a problem, because
<code>res/values-en/strings.xml</code> contains both of the needed text
strings.</li>
<li>However, <strong>the user will see an error message and a Force Close
button</strong> when this application is launched on a device set to a
language other than English. The application will not load.</li>
</ul>
<p>To prevent this situation, make sure that a <code>res/values/strings.xml</code>
file exists and that it defines every needed string. The situation applies to
all types of resources, not just strings: You
need to create a set of default resource files containing all
the resources that your application calls upon &#8212; layouts, drawables,
animations, etc. For information about testing, see <a href="#test-for-default">
Testing for Default Resources</a>.</p>
<h2 id="using-framework">Using Resources for Localization</h2>
<h3 id="creating-defaults">How to Create Default Resources</h3>
<p>Put the application's default text in
a file with the following location and name:</p>
<p><code>&nbsp;&nbsp;&nbsp;&nbsp;res/values/strings.xml</code> (required directory)</p>
<p>The text strings in <code>res/values/strings.xml</code> should use the
default language, which is the language that you expect most of your application's users to
speak. </p>
<p>The default resource set must also include any default drawables and layouts,
and can include other types of resources such as animations.
<br>
<code>&nbsp;&nbsp;&nbsp;&nbsp;res/drawable/</code>(required directory holding at least
one graphic file, for the application's icon in the Market)<br>
<code>&nbsp;&nbsp;&nbsp;&nbsp;res/layout/</code> (required directory holding an XML
file that defines the default layout)<br>
<code>&nbsp;&nbsp;&nbsp;&nbsp;res/anim/</code> (required if you have any
<code>res/anim-<em>&lt;qualifiers&gt;</em></code> folders)<br>
<code>&nbsp;&nbsp;&nbsp;&nbsp;res/xml/</code> (required if you have any
<code>res/xml-<em>&lt;qualifiers&gt;</em></code> folders)<br>
<code>&nbsp;&nbsp;&nbsp;&nbsp;res/raw/</code> (required if you have any
<code>res/raw-<em>&lt;qualifiers&gt;</em></code> folders)
</p>
<p class="note"><strong>Tip:</strong> In your code, examine each reference to
an Android resource. Make sure that a default resource is defined for each
one. Also make sure that the default string file is complete: A <em>
localized</em> string file can contain a subset of the strings, but the
<em>default</em> string file must contain them all.
</p>
<h3 id="creating-alternatives">How to Create Alternative Resources</h3>
<p>A large part of localizing an application is providing alternative text for
different languages. In some cases you will also provide alternative graphics,
sounds, layouts, and other locale-specific resources. </p>
<p>An application can specify many <code>res/<em>&lt;qualifiers&gt;</em>/</code>
directories, each with different qualifiers. To create an alternative resource for
a different locale, you use a qualifier that specifies a language or a
language-region combination. (The name of a resource directory must conform
to the naming scheme described in
<a href="{@docRoot}guide/topics/resources/providing-resources.html#AlternativeResources">Providing
Alternative Resources</a>,
or else it will not compile.)</p>
<p><em>Example:</em></p>
<p>Suppose that your application's default language is English. Suppose also
that you want to localize all the text in your application to French, and most
of the text in your application (everything except the application's title) to
Japanese. In this case, you could create three alternative <code>strings.xml</code>
files, each stored in a locale-specific resource directory:</p>
<ol>
<li><code>res/values/strings.xml</code><br>
Contains English text for all the strings that the application uses,
including text for a string named <code>title</code>.</li>
<li><code>res/values-fr/strings.xml</code><br>
Contain French text for all the strings, including <code>title</code>.</li>
<li><code>res/values-ja/strings.xml</code><br>
Contain Japanese text for all the strings <em>except</em>
<code>title</code>.<br>
<code></code></li>
</ol>
<p>If your Java code refers to <code>R.string.title</code>, here is what will
happen at runtime:</p>
<ul>
<li>If the device is set to any language other than French, Android will load
<code>title</code> from the <code>res/values/strings.xml</code> file.</li>
<li>If the device is set to French, Android will load <code>title</code> from
the <code>res/values-fr/strings.xml</code> file.</li>
</ul>
<p>Notice that if the device is set to Japanese, Android will look for
<code>title</code> in the <code>res/values-ja/strings.xml</code> file. But
because no such string is included in that file, Android will fall back to the
default, and will load <code>title</code> in English from the
<code>res/values/strings.xml</code> file. </p>
<h3 id="resource-precedence">Which Resources Take Precedence?</h3>
<p> If multiple resource files match a device's configuration, Android follows a
set of rules in deciding which file to use. Among the qualifiers that can be
specified in a resource directory name, <strong>locale almost always takes
precedence</strong>. </p>
<p><em>Example:</em></p>
<p>Assume that an application includes a default set of graphics and two other
sets of graphics, each optimized for a different device setup:</p>
<ul>
<li><code>res/drawable/</code><br>
Contains
default graphics.</li>
<li><code>res/drawable-small-land-stylus/</code><br>
Contains graphics optimized for use with a device that expects input from a
stylus and has a QVGA low-density screen in landscape orientation.</li>
<li><code>res/drawable-ja/</code> <br>
Contains graphics optimized for use with Japanese.</li>
</ul>
<p>If the application runs on a device that is configured to use Japanese,
Android will load graphics from <code>res/drawable-ja/</code>, even if the
device happens to be one that expects input from a stylus and has a QVGA
low-density screen in landscape orientation.</p>
<p class="note"><strong>Exception:</strong> The only qualifiers that take
precedence over locale in the selection process are MCC and MNC (mobile country
code and mobile network code). </p>
<p><em>Example:</em></p>
<p>Assume that you have the following situation:</p>
<ul>
<li>The application code calls for <code>R.string.text_a</code></li>
<li>Two relevant resource files are available:
<ul>
<li><code>res/values-mcc404/strings.xml</code>, which includes
<code>text_a</code> in the application's default language, in this case
English.</li>
<li><code>res/values-hi/strings.xml</code>, which includes
<code>text_a</code> in Hindi.</li>
</ul>
</li>
<li>The application is running on a device that has the following
configuration:
<ul>
<li>The SIM card is connected to a mobile network in India (MCC 404).</li>
<li>The language is set to Hindi (<code>hi</code>).</li>
</ul>
</li>
</ul>
<p>Android will load <code>text_a</code> from
<code>res/values-mcc404/strings.xml</code> (in English), even if the device is
configured for Hindi. That is because in the resource-selection process, Android
will prefer an MCC match over a language match. </p>
<p>The selection process is not always as straightforward as these examples
suggest. Please read <a
href="{@docRoot}guide/topics/resources/providing-resources.html#BestMatch">How Android Finds
the Best-matching Resource</a> for a more nuanced description of the
process. All the qualifiers are described and listed in order of
precedence in <a
href="{@docRoot}guide/topics/resources/providing-resources.html#table2">Table 2 of Providing
Alternative Resources</a>.</p>
<h3 id="referring-to-resources">Referring to Resources in Java</h3>
<p>In your application's Java code, you refer to resources using the syntax
<code>R.<em>resource_type</em>.<em>resource_name</em></code> or
<code>android.R.<em>resource_type</em>.<em>resource_name</em></code><em>.</em>
For more about this, see <a
href="{@docRoot}guide/topics/resources/accessing-resources.html">Accessing Resources</a>.</p>
<h2 id="strategies">Localization Strategies</h2>
<h4 id="failing2">Design your application to work in any locale</h4>
<p>You cannot assume anything about the device on which a user will
run your application. The device might have hardware that you were not
anticipating, or it might be set to a locale that you did not plan for or that
you cannot test. Design your application so that it will function normally or fail gracefully no
matter what device it runs on.</p>
<p class="note"><strong>Important:</strong> Make sure that your application
includes a full set of default resources.</p> <p>Make sure to include
<code>res/drawable/</code> and a <code>res/values/</code> folders (without any
additional modifiers in the folder names) that contain all the images and text
that your application will need. </p>
<p>If an application is missing even one default resource, it will not run on a
device that is set to an unsupported locale. For example, the
<code>res/values/strings.xml</code> default file might lack one string that
the application needs: When the application runs in an unsupported locale and
attempts to load <code>res/values/strings.xml</code>, the user will see an
error message and a Force Close button. An IDE such as Eclipse will not
highlight this kind of error, and you will not see the problem when you
test the application on a device or emulator that is set to a supported locale.</p>
<p>For more information, see <a href="#test-for-default">Testing for Default Resources</a>.</p>
<h4>Design a flexible layout</h4>
<p> If you need to rearrange your layout to fit a certain language (for example
German with its long words), you can create an alternative layout for that
language (for example <code>res/layout-de/main.xml</code>). However, doing this
can make your application harder to maintain. It is better to create a single
layout that is more flexible.</p>
<p>Another typical situation is a language that requires something different in
its layout. For example, you might have a contact form that should include two
name fields when the application runs in Japanese, but three name fields when
the application runs in some other language. You could handle this in either of
two ways:</p>
<ul>
<li>Create one layout with a field that you can programmatically enable or
disable, based on the language, or</li>
<li>Have the main layout include another layout that includes the changeable
field. The second layout can have different configurations for different
languages.</li>
</ul>
<h4>Avoid creating more resource files and text strings than you need</h4>
<p>You probably do not need to create a locale-specific
alternative for every resource in your application. For example, the layout
defined in the <code>res/layout/main.xml</code> file might work in any locale,
in which case there would be no need to create any alternative layout files.
</p>
<p>Also, you might not need to create alternative text for every
string. For example, assume the following:</p>
<ul>
<li>Your application's default language is American
English. Every string that the application uses is defined, using American
English spellings, in <code>res/values/strings.xml</code>. </li>
<li>For a few important phrases, you want to provide
British English spelling. You want these alternative strings to be used when your
application runs on a device in the United Kingdom. </li>
</ul>
<p>To do this, you could create a small file called
<code>res/values-en-rGB/strings.xml</code> that includes only the strings that
should be different when the application runs in the U.K. For all the rest of
the strings, the application will fall back to the defaults and use what is
defined in <code>res/values/strings.xml</code>.</p>
<h4>Use the Android Context object for manual locale lookup</h4>
<p>You can look up the locale using the {@link android.content.Context} object
that Android makes available:</p>
<pre>String locale = context.getResources().getConfiguration().locale.getDisplayName();</pre>
<h2 id="testing">Testing Localized Applications</h2>
<h3 id="device">Testing on a Device</h3>
<p>Keep in mind that the device you are testing may be significantly different from
the devices available to consumers in other geographies. The locales available
on your device may differ from those available on other devices. Also, the
resolution and density of the device screen may differ, which could affect
the display of strings and drawables in your UI.</p>
<p>To change the locale on a device, use the Settings application (Home &gt;
Menu &gt; Settings &gt; Locale &amp; text &gt; Select locale). </p>
<h3 id="emulator">Testing on an Emulator</h3>
<p>For details about using the emulator, see See <a
href="{@docRoot}guide/developing/tools/emulator.html">Android Emulator</a>.</p>
<h4>Creating and using a custom locale</h4>
<p>A &quot;custom&quot; locale is a language/region combination that the Android
system image does not explicitly support. (For a list of supported locales in
Android platforms see the Version Notes in the <a
href="{@docRoot}sdk/index.html">SDK</a> tab). You can test
how your application will run in a custom locale by creating a custom locale in
the emulator. There are two ways to do this:</p>
<ul>
<li>Use the Custom Locale application, which is accessible from the
Application tab. (After you create a custom locale, switch to it by
pressing and holding the locale name.)</li>
<li>Change to a custom locale from the adb shell, as described below.</li>
</ul>
<p>When you set the emulator to a locale that is not available in the Android
system image, the system itself will display in its default language. Your
application, however, should localize properly.</p>
<h4>Changing the emulator locale from the adb shell</h4>
<p>To change the locale in the emulator by using the adb shell. </p>
<ol>
<li>Pick the locale you want to test and determine its language and region codes, for
example <code>fr</code> for French and <code>CA</code> for Canada.<br>
</li>
<li>Launch an emulator.</li>
<li>From a command-line shell on the host computer, run the following
command:<br>
<code>adb shell</code><br>
or if you have a device attached, specify that you want the emulator by adding
the <code>-e</code> option:<br>
<code>adb -e shell</code></li>
<li>At the adb shell prompt (<code>#</code>), run this command: <br>
<code>setprop persist.sys.language [<em>language code</em>];setprop
persist.sys.country [<em>country code</em>];stop;sleep 5;start <br>
</code>Replace bracketed sections with the appropriate codes from Step
1.</li>
</ol>
<p>For instance, to test in Canadian French:</p>
<p><code>setprop persist.sys.language fr;setprop persist.sys.country
CA;stop;sleep 5;start </code></p>
<p>This will cause the emulator to restart. (It will look like a full reboot,
but it is not.) Once the Home screen appears again, re-launch your application (for
example, click the Run icon in Eclipse), and the application will launch with
the new locale. </p>
<h3 id="test-for-default">Testing for Default Resources</h3>
<p>Here's how to test whether an application includes every string resource that it needs: </p>
<ol><li>Set the emulator or device to a language that your application does not
support. For example, if the application has French strings in
<code>res/values-fr/</code> but does not have any Spanish strings in
<code>res/values-es/</code>, then set the emulator's locale to Spanish.
(You can use the Custom Locale application to set the emulator to an
unsupported locale.)</li>
<li>Run the application.</li>
<li>If the application shows an error message and a Force Close button, it might
be looking for a string that is not available. Make sure that your
<code>res/values/strings.xml</code> file includes a definition for
every string that the application uses.</li>
</ol>
</p>
<p>If the test is successful, repeat it for other types of
configurations. For example, if the application has a layout file called
<code>res/layout-land/main.xml</code> but does not contain a file called
<code>res/layout-port/main.xml</code>, then set the emulator or device to
portrait orientation and see if the application will run.
<h2 id="publishing">Publishing Localized Applications</h2>
<p>The Android Market is
the main application distribution system for Android devices. To publish a
localized application, you need to sign your application, version it, and go
through all the other steps described in <a
href="{@docRoot}guide/publishing/preparing.html">Preparing to Publish</a>. </p>
<p>If you split your application in several .apk files, each targeted to a
different locale, follow these guidelines:</p>
<ul>
<li>Sign each .apk file with the same certificate. For more about this, see <a
href="{@docRoot}guide/publishing/app-signing.html#strategies">Signing
Strategies</a>. </li>
<li>Give each .apk file a different application name. Currently it is
impossible to put two applications into the Android Market that have exactly the
same name.</li>
<li>Include a complete set of default resources in each .apk file.</li>
</ul>
<h2 id="checklist">Localization Checklists</h2>
<p>These checklists summarize the process of localizing an Android application.
Not everything on these lists will apply to every application.</p>
<h3 id="planning-checklist">Planning and Design Checklist</h3>
<table width="100%" border="0" cellpadding="5" cellspacing="0">
<tr>
<td valign="top" align="center"><img src="../../../images/resources/arrow.png" alt="arrow" width="26"
border="0"></td>
<td>Choose a localization strategy. Which countries and which languages will
your application support? What is your application's default country and
language? How will your application behave when it does not have specific
resources available for a given locale?</td>
</tr>
<tr>
<td valign="top" align="center"><img src="../../../images/resources/arrow.png" alt="arrow" width="26"
border="0"></td>
<td><p>Identify everything in your application that will need to be
localized: </p>
<ul>
<li>Consider specific details of your application &#8212; text, images,
sounds, music, numbers, money, dates and times. You might not need to localize
everything. For example, you don't need to localize text that the user never
sees, or images that are culturally neutral, or icons that convey the same
meaning in every locale. </li>
<li>Consider broad themes. For example, if you hope to sell your
application in two very culturally different markets, you might want to design
your UI and present your application in an entirely different way for each
locale.</li>
</ul></td>
</tr>
<tr>
<td valign="top" align="center"><img src="../../../images/resources/arrow.png" alt="arrow" width="26"
border="0"></td>
<td><p>Design your Java code to externalize resources wherever possible:</p>
<ul>
<li>Use <code>R.string</code> and <code>strings.xml</code> files instead
of hard-coded strings or string constants. </li>
<li>Use <code>R.drawable</code> and <code>R.layout</code> instead of
hard-coded drawables or layouts. </li>
</ul></td>
</tr>
</table>
<h3 id="content-checklist">Content Checklist</h3>
<table border="0" cellspacing="0" cellpadding="5" width="100%">
<tr>
<td valign="top" align="center"><img src="../../../images/resources/arrow.png" alt="arrow" width="26"
border="0"></td>
<td>Create a full set of default resources in <code>res/values/</code> and
other <code>res/</code> folders, as described in <a
href="#creating-defaults">Creating Default Resources</a>.</td>
</tr>
<tr>
<td valign="top" align="center"><img src="../../../images/resources/arrow.png" alt="arrow" width="26"
border="0"></td>
<td>Obtain reliable translations of the static text, including menu text,
button names, error messages, and help text. Place the translated strings in
<code>res/values-<em>&lt;qualifiers&gt;</em>/strings.xml</code> files. </td>
</tr>
<tr>
<td valign="top" align="center"><img src="../../../images/resources/arrow.png" alt="arrow" width="26"
border="0"></td>
<td>Make sure that your application correctly formats dynamic text (for
example numbers and dates) for each supported locale. Make sure that your
application handles word breaks, punctuation, and alphabetical sorting correctly
for each supported language.</td>
</tr>
<tr>
<td valign="top" align="center"><img src="../../../images/resources/arrow.png" alt="arrow" width="26"
border="0"></td>
<td>If necessary, create locale-specific versions of your graphics and
layout, and place them in <code>res/drawable-<em>&lt;qualifiers&gt;</em>/</code> and
<code>res/layout-<em>&lt;qualifiers&gt;</em>/</code> folders.</td>
</tr>
<tr>
<td valign="top" align="center"><img src="../../../images/resources/arrow.png" alt="arrow" width="26"
border="0"></td>
<td>Create any other localized content that your application requires; for
example, create recordings of sound files for each language, as needed.</td>
</tr>
</table>
<h3 id="testing-checklist">Testing and Publishing Checklist</h3>
<table border="0" cellspacing="0" cellpadding="5" width="100%">
<tr>
<td valign="top" align="center"><img src="../../../images/resources/arrow.png" alt="arrow" width="26"
border="0"></td>
<td>Test your application for each supported locale. If possible, have a
person who is native to each locale test your application and give you
feedback.</td>
</tr>
<tr>
<td valign="top" align="center"><img src="../../../images/resources/arrow.png" alt="arrow" width="26"
border="0"></td>
<td>Test the default resources by loading a locale that is not available on
the device or emulator. For instructions, see <a href="#test-for-default">
Testing for Default Resources</a>. </td>
</tr>
<tr>
<td valign="top" align="center"><img src="../../../images/resources/arrow.png" alt="arrow" width="26"
border="0"></td>
<td>Test the localized strings in both landscape and portrait display modes.</td>
</tr>
<tr>
<td valign="top" align="center"><img src="../../../images/resources/arrow.png" alt="arrow" width="26"
border="0"></td>
<td>Sign your application and create your final build or builds.</td>
</tr>
<tr>
<td valign="top" align="center"><img src="../../../images/resources/arrow.png" alt="arrow" width="26"
border="0"></td>
<td>Upload your .apk file or files to Market, selecting the appropriate
languages as
you upload. (For more details, see <a
href="{@docRoot}guide/publishing/publishing.html">Publishing Your
Applications</a>.)</td>
</tr>
</table>
@@ -0,0 +1,207 @@
page.title=Menu Resource
parent.title=Resource Types
parent.link=available-resources.html
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>See also</h2>
<ol>
<li><a href="{@docRoot}guide/topics/ui/menus.html">Creating Menus</a></li>
</ol>
</div>
</div>
<p>A menu resource defines an application menu (Options Menu, Context Menu, or Sub Menu) that
can be inflated with {@link android.view.MenuInflater}.</p>
<dl class="xml">
<dt>file location:</dt>
<dd><code>res/menu/<em>filename</em>.xml</code><br/>
The filename will be used as the resource ID.</dd>
<dt>compiled resource datatype:</dt>
<dd>Resource pointer to a {@link android.view.Menu} (or subclass) resource.</dd>
<dt>resource reference:</dt>
<dd>
In Java: <code>R.menu.<em>filename</em></code><br/>
In XML: <code>@[<em>package</em>:]menu.<em>filename</em></code>
</dd>
<dt>syntax:</dt>
<dd>
<pre>
&lt;?xml version="1.0" encoding="utf-8"?>
&lt;<a href="#menu-element">menu</a> xmlns:android="http://schemas.android.com/apk/res/android">
&lt;<a href="#item-element">item</a> android:id="@[+][<em>package</em>:]id/<em>resource_name</em>"
android:menuCategory=["container" | "system" | "secondary" | "alternative"]
android:orderInCategory="<em>integer</em>"
android:title="<em>string</em>"
android:titleCondensed="<em>string</em>"
android:icon="@[package:]drawable/<em>drawable_resource_name</em>"
android:alphabeticShortcut="<em>string</em>"
android:numericShortcut="<em>string</em>"
android:checkable=["true" | "false"]
android:visible=["visible" | "invisible" | "gone"]
android:enabled=["enabled" | "disabled"] /&gt;
&lt;<a href="#group-element">group</a> android:id="@[+][<em>package</em>:]id/<em>resource name</em>"
android:menuCategory=["container" | "system" | "secondary" | "alternative"]
android:orderInCategory="<em>integer</em>"
android:checkableBehavior=["none" | "all" | "single"]
android:visible=["visible" | "invisible" | "gone"]
android:enabled=["enabled" | "disabled"] &gt;
&lt;<a href="#item-element">item</a> /&gt;
&lt;/group&gt;
&lt;<a href="#item-element">item</a> &gt;
&lt;<a href="#menu-element">menu</a>&gt;
&lt;<a href="#item-element">item</a> /&gt;
&lt;/menu&gt;
&lt;/item&gt;
&lt;/menu&gt;
</pre>
</dd>
<dt>elements:</dt>
<dd>
<dl class="tag-list">
<dt id="menu-element"><code>&lt;menu&gt;</code></dt>
<dd><strong>Required.</strong> This must be the root node. Contains <code>&lt;item></code> and/or
<code>&lt;group></code> elements.
<p class="caps">attributes:</p>
<dl class="atn-list">
<dt><code>xmlns:android</code></dt>
<dd><em>String</em>. <strong>Required.</strong> Defines the XML namespace, which must be
<code>"http://schemas.android.com/apk/res/android"</code>.
</dl>
</dd>
<dt id="group-element"><code>&lt;group&gt;</code></dt>
<dd>A menu group (to create a collection of items that share traits, such as whether they are
visible, enabled, or checkable). Contains one or more <code>&lt;item&gt;</code> elements. Must be a
child of a <code>&lt;menu&gt;</code> element.
<p class="caps">attributes:</p>
<dl class="atn-list">
<dt><code>android:id</code></dt>
<dd><em>Resource ID</em>. A unique resource ID. To create a new resource ID for this item, use the form:
<code>"@+id/<em>name</em>"</code>. The plus symbol indicates that this should be created as a new ID.</dd>
<dt><code>android:menuCategory</code></dt>
<dd><em>Keyword</em>. Value corresponding to {@link android.view.Menu} {@code CATEGORY_*}
constants, which define the group's priority. Valid values:
<table>
<tr><th>Value</th><th>Description</th></tr>
<tr><td><code>container</code></td><td>For groups that are part of a
container.</td></tr>
<tr><td><code>system</code></td><td>For groups that are provided by the
system.</td></tr>
<tr><td><code>secondary</code></td><td>For groups that are user-supplied secondary
(infrequently used) options.</td></tr>
<tr><td><code>alternative</code></td><td>For groups that are alternative actions
on the data that is currently displayed.</td></tr>
</table>
</dd>
<dt><code>android:orderInCategory</code></dt>
<dd><em>Integer</em>. The default order of the items within the category.</dd>
<dt><code>android:checkableBehavior</code></dt>
<dd><em>Keyword</em>. The type of checkable behavior for the group. Valid values:
<table>
<tr><th>Value</th><th>Description</th></tr>
<tr><td><code>none</code></td><td>Not checkable</td></tr>
<tr><td><code>all</code></td><td>All items can be checked (use checkboxes)</td></tr>
<tr><td><code>single</code></td><td>Only one item can be checked (use radio buttons)</td></tr>
</table>
</dd>
<dt><code>android:visible</code></dt>
<dd><em>Boolean</em>. "true" if the group is visible.</dd>
<dt><code>android:enabled</code></dt>
<dd><em>Boolean</em>. "true" if the group is enabled.</dd>
</dl>
</dd>
<dt id="item-element"><code>&lt;item&gt;</code></dt>
<dd>A menu item. May contain a <code>&lt;menu&gt;</code> element (for a Sub
Menu). Must be a child of a <code>&lt;menu&gt;</code> or <code>&lt;group&gt;</code> element.
<p class="caps">attributes:</p>
<dl class="atn-list">
<dt><code>android:id</code></dt>
<dd><em>Resource ID</em>. A unique resource ID. To create a new resource ID for this item, use the form:
<code>"@+id/<em>name</em>"</code>. The plus symbol indicates that this should be created as a new ID.</dd>
<dt><code>android:menuCategory</code></dt>
<dd><em>Keyword</em>. Value corresponding to {@link android.view.Menu} {@code CATEGORY_*}
constants, which define the item's priority. Valid values:
<table>
<tr><th>Value</th><th>Description</th></tr>
<tr><td><code>container</code></td><td>For items that are part of a
container.</td></tr>
<tr><td><code>system</code></td><td>For items that are provided by the
system.</td></tr>
<tr><td><code>secondary</code></td><td>For items that are user-supplied secondary
(infrequently used) options.</td></tr>
<tr><td><code>alternative</code></td><td>For items that are alternative actions
on the data that is currently displayed.</td></tr>
</table>
</dd>
<dt><code>android:orderInCategory</code></dt>
<dd><em>Integer</em>. The order of "importance" of the item, within a group.</dd>
<dt><code>android:title</code></dt>
<dd><em>String</em>. The menu title.</dd>
<dt><code>android:titleCondensed</code></dt>
<dd><em>String</em>. A condensed title, for situations in which the normal title is
too long.</dd>
<dt><code>android:icon</code></dt>
<dd><em>Drawable resource</em>. An image to be used as the menu item icon.</dd>
<dt><code>android:alphabeticShortcut</code></dt>
<dd><em>Char</em>. A character for the alphabetic shortcut key.</dd>
<dt><code>android:numericShortcut</code></dt>
<dd><em>Integer</em>. A number for the numeric shortcut key.</dd>
<dt><code>android:checkable</code></dt>
<dd><em>Boolean</em>. "true" if the item is checkable.</dd>
<dt><code>android:checked</code></dt>
<dd><em>Boolean</em>. "true" if the item is checked by default.</dd>
<dt><code>android:visible</code></dt>
<dd><em>Boolean</em>. "true" if the item is visible by default.</dd>
<dt><code>android:enabled</code></dt>
<dd><em>Boolean</em>. "true" if the item is enabled by default.</dd>
</dl>
</dd>
</dl>
</dd>
<dt>example:</dt>
<dd>XML file saved at <code>res/menu/example_menu.xml</code>:
<pre>
&lt;menu xmlns:android="http://schemas.android.com/apk/res/android">
&lt;item android:id="@+id/item1"
android:title="@string/item1"
android:icon="@drawable/group_item1_icon" />
&lt;group android:id="@+id/group">
&lt;item android:id="@+id/group_item1"
android:title="@string/group_item1"
android:icon="@drawable/group_item1_icon" />
&lt;item android:id="@+id/group_item2"
android:title="G@string/group_item2"
android:icon="@drawable/group_item2_icon" />
&lt;/group>
&lt;item android:id="@+id/submenu"
android:title="@string/submenu_title" >
&lt;menu>
&lt;item android:id="@+id/submenu_item1"
android:title="@string/submenu_item1" />
&lt;/menu>
&lt;/item>
&lt;/menu>
</pre>
<p>This application code will inflate the menu from the {@link
android.app.Activity#onCreateOptionsMenu(Menu)} callback:</p>
<pre>
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.example_menu, menu);
return true;
}
</pre>
</dd> <!-- end example -->
</dl>
@@ -0,0 +1,803 @@
page.title=More Resource Types
parent.title=Resource Types
parent.link=available-resources.html
@jd:body
<p>This page defines more types of resources you can externalize, including:</p>
<dl>
<dt><a href="#Bool">Bool</a></dt>
<dd>XML resource that carries a boolean value.</dd>
<dt><a href="#Color">Color</a></dt>
<dd>XML resource that carries a color value (a hexadecimal color).</dd>
<dt><a href="#Dimension">Dimension</a></dt>
<dd>XML resource that carries a dimension value (with a unit of measure).</dd>
<dt><a href="#Id">ID</a></dt>
<dd>XML resource that provides a unique identifier for application resources and
components.</dd>
<dt><a href="#Integer">Integer</a></dt>
<dd>XML resource that carries an integer value.</dd>
<dt><a href="#IntegerArray">Integer Array</a></dt>
<dd>XML resource that provides an array of integers.</dd>
<dt><a href="#TypedArray">Typed Array</a></dt>
<dd>XML resource that provides a {@link android.content.res.TypedArray} (which you can use
for an array of drawables).</dd>
</dl>
<h2 id="Bool">Bool</h2>
<p>A boolean value defined in XML.</p>
<p class="note"><strong>Note:</strong> A bool is a simple resource that is referenced
using the value provided in the {@code name} attribute (not the name of the XML file). As
such, you can combine bool resources with other simple resources in the one XML file,
under one {@code &lt;resources>} element.</p>
<dl class="xml">
<dt>file location:</dt>
<dd><code>res/values/<em>filename</em>.xml</code><br/>
The filename is arbitrary. The {@code &lt;bool>} element's {@code name} will be used as the resource
ID.</dd>
<dt>resource reference:</dt>
<dd>
In Java: <code>R.bool.<em>bool_name</em></code><br/>
In XML: <code>@[<em>package</em>:]bool/<em>bool_name</em></code>
</dd>
<dt>syntax:</dt>
<dd>
<pre class="stx">
&lt;?xml version="1.0" encoding="utf-8"?>
&lt;<a href="#bool-resources-element">resources</a>&gt;
&lt;<a href="#bool-element">bool</a>
name="<em>bool_name</em>"
&gt;[true | false]&lt;/bool>
&lt;/resources>
</pre>
</dd>
<dt>elements:</dt>
<dd>
<dl class="tag-list">
<dt id="bool-resources-element"><code>&lt;resources&gt;</code></dt>
<dd><strong>Required.</strong> This must be the root node.
<p>No attributes.</p>
</dd>
<dt id="bool-element"><code>&lt;bool&gt;</code></dt>
<dd>A boolean value: {@code true} or {@code false}.
<p class="caps">attributes:</p>
<dl class="atn-list">
<dt><code>name</code></dt>
<dd><em>String</em>. A name for the bool value. This will be used as the resource ID.</dd>
</dl>
</dd>
</dl>
</dd> <!-- end elements and attributes -->
<dt>example:</dt>
<dd>XML file saved at <code>res/values-small/bools.xml</code>:
<pre>
&lt;?xml version="1.0" encoding="utf-8"?>
&lt;resources&gt;
&lt;bool name="screen_small">true&lt;/bool>
&lt;bool name="adjust_view_bounds">true&lt;/bool>
&lt;/resources>
</pre>
<p>This application code retrieves the boolean:</p>
<pre>
Resources res = {@link android.content.Context#getResources()};
boolean screenIsSmall = res.{@link android.content.res.Resources#getBoolean(int) getBoolean}(R.bool.screen_small);
</pre>
<p>This layout XML uses the boolean for an attribute:</p>
<pre>
&lt;ImageView
android:layout_height="fill_parent"
android:layout_width="fill_parent"
android:src="@drawable/logo"
android:adjustViewBounds="@bool/adjust_view_bounds" />
</pre>
</dd> <!-- end example -->
</dl>
<h2 id="Color">Color</h2>
<p>A color value defined in XML.
The color is specified with an RGB value and alpha channel. You can use a color resource
any place that accepts a hexadecimal color value. You can also use a color resource when a
drawable resource is expected in XML (for example, {@code android:drawable="@color/green"}).</p>
<p>The value always begins with a pound (#) character and then followed by the
Alpha-Red-Green-Blue information in one of the following formats:</p>
<ul>
<li>#<em>RGB</em></li>
<li>#<em>ARGB</em></li>
<li>#<em>RRGGBB</em></li>
<li>#<em>AARRGGBB</em></li>
</ul>
<p class="note"><strong>Note:</strong> A color is a simple resource that is referenced
using the value provided in the {@code name} attribute (not the name of the XML file). As
such, you can combine color resources with other simple resources in the one XML file,
under one {@code &lt;resources>} element.</p>
<dl class="xml">
<dt>file location:</dt>
<dd><code>res/values/colors.xml</code><br/>
The filename is arbitrary. The {@code &lt;color>} element's {@code name} will be used as the
resource ID.</dd>
<dt>resource reference:</dt>
<dd>
In Java: <code>R.color.<em>color_name</em></code><br/>
In XML: <code>@[<em>package</em>:]color/<em>color_name</em></code>
</dd>
<dt>syntax:</dt>
<dd>
<pre class="stx">
&lt;?xml version="1.0" encoding="utf-8"?>
&lt;<a href="#color-resources-element">resources</a>>
&lt;<a href="#color-element">color</a>
name="<em>color_name</em>"
&gt;<em>hex_color</em>&lt;/color>
&lt;/resources>
</pre>
</dd>
<dt>elements:</dt>
<dd>
<dl class="tag-list">
<dt id="color-resources-element"><code>&lt;resources&gt;</code></dt>
<dd><strong>Required.</strong> This must be the root node.
<p>No attributes.</p>
</dd>
<dt id="color-element"><code>&lt;color&gt;</code></dt>
<dd>A color expressed in hexadecimal, as described above.
<p class="caps">attributes:</p>
<dl class="atn-list">
<dt><code>name</code></dt>
<dd><em>String</em>. A name for the color. This will be used as the resource ID.
</dd>
</dl>
</dd>
</dl>
</dd> <!-- end elements and attributes -->
<dt>example:</dt>
<dd>XML file saved at <code>res/values/colors.xml</code>:
<pre>
&lt;?xml version="1.0" encoding="utf-8"?>
&lt;resources>
&lt;color name="opaque_red">#f00&lt;/color>
&lt;color name="translucent_red">#80ff0000&lt;/color>
&lt;/resources>
</pre>
<p>This application code retrieves the color resource:</p>
<pre>
Resources res = {@link android.content.Context#getResources()};
int color = res.{@link android.content.res.Resources#getColor(int) getColor}(R.color.opaque_red);
</pre>
<p>This layout XML applies the color to an attribute:</p>
<pre>
&lt;TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textColor="@color/translucent_red"
android:text="Hello"/>
</pre>
</dd> <!-- end example -->
</dl>
<h2 id="Dimension">Dimension</h2>
<p>A dimension value defined in XML. A dimension
is specified with a number followed by a unit of measure.
For example: 10px, 2in, 5sp. The following units of measure are supported by Android:</p>
<dl>
<dt>{@code dp}</dt>
<dd>Density-independent Pixels - an abstract unit that is based on the physical density of the
screen. These units are relative to a 160 dpi (dots per inch) screen, so <em>{@code 160dp} is
always one inch</em> regardless of the screen density. The ratio of dp-to-pixel will change with the
screen density, but not necessarily in direct proportion. You should use these units when specifying
view dimensions in your layout, so the UI properly scales to render at the same actual size on
different screens. (The compiler accepts both "dip" and "dp", though "dp" is more consistent with
"sp".)</dd>
<dt>{@code sp}</dt>
<dd>Scale-independent Pixels - this is like the dp unit, but it is also scaled by the user's font
size preference. It is recommend you use this unit when specifying font sizes, so they will be adjusted
for both the screen density and the user's preference.</dd>
<dt>{@code pt}</dt>
<dd>Points - 1/72 of an inch based on the physical size of the screen.</dd>
<dt>{@code px}</dt>
<dd>Pixels - corresponds to actual pixels on the screen. This unit of measure is not recommended because
the actual representation can vary across devices; each devices may have a different number of pixels
per inch and may have more or fewer total pixels available on the screen.</dd>
<dt>{@code mm}</dt>
<dd>Millimeters - based on the physical size of the screen.</dd>
<dt>{@code in}</dt>
<dd>Inches - based on the physical size of the screen.</dd>
</dl>
<p class="note"><strong>Note:</strong> A dimension is a simple resource that is referenced
using the value provided in the {@code name} attribute (not the name of the XML file). As
such, you can combine dimension resources with other simple resources in the one XML file,
under one {@code &lt;resources>} element.</p>
<dl class="xml">
<dt>file location:</dt>
<dd><code>res/values/<em>filename</em>.xml</code><br/>
The filename is arbitrary. The {@code &lt;dimen>} element's {@code name} will be used as the
resource ID.</dd>
<dt>resource reference:</dt>
<dd>
In Java: <code>R.dimen.<em>dimension_name</em></code><br/>
In XML: <code>@[<em>package</em>:]dimen/<em>dimension_name</em></code>
</dd>
<dt>syntax:</dt>
<dd>
<pre class="stx">
&lt;?xml version="1.0" encoding="utf-8"?>
&lt;<a href="#dimen-resources-element">resources</a>>
&lt;<a href="#dimen-element">dimen</a>
name="<em>dimension_name</em>"
&gt;<em>dimension</em>&lt;/dimen&gt;
&lt;/resources&gt;
</pre>
</dd>
<dt>elements:</dt>
<dd>
<dl class="tag-list">
<dt id="dimen-resources-element"><code>&lt;resources&gt;</code></dt>
<dd><strong>Required.</strong> This must be the root node.
<p>No attributes.</p>
</dd>
<dt id="dimen-element"><code>&lt;dimen&gt;</code></dt>
<dd>A dimension, represented by a float, followed by a unit of measurement (dp, sp, pt, px, mm, in),
as described above.
<p class="caps">attributes:</p>
<dl class="atn-list">
<dt><code>name</code></dt>
<dd><em>String</em>. A name for the dimension. This will be used as the resource ID.
</dd>
</dl>
</dd>
</dl>
</dd> <!-- end elements and attributes -->
<dt>example:</dt>
<dd>XML file saved at <code>res/values/dimens.xml</code>:
<pre>
&lt;?xml version="1.0" encoding="utf-8"?>
&lt;resources>
&lt;dimen name="textview_height">25dp&lt;/dimen>
&lt;dimen name="textview_width">150dp&lt;/dimen>
&lt;dimen name="ball_radius">30dp&lt;/dimen>
&lt;dimen name="font_size">16sp&lt;/dimen>
&lt;/resources>
</pre>
<p>This application code retrieves a dimension:</p>
<pre>
Resources res = {@link android.content.Context#getResources()};
float fontSize = res.{@link android.content.res.Resources#getDimension(int) getDimension}(R.dimen.font_size);
</pre>
<p>This layout XML applies dimensions to attributes:</p>
<pre>
&lt;TextView
android:layout_height="@dimen/textview_height"
android:layout_width="@dimen/textview_width"
android:textSize="@dimen/font_size"/>
</pre>
</dl>
</dd> <!-- end example -->
</dl>
<h2 id="Id">ID</h2>
<p>A unique resource ID defined in XML. Using the name you provide in the {@code &lt;item&gt;}
element, the Android developer tools create a unique integer in your project's {@code
R.java} class, which you can use as an
identifier for an application resources (for example, a {@link android.view.View} in your UI layout)
or a unique integer for use in your application code (for example, as an ID for a dialog or a
result code).</p>
<p class="note"><strong>Note:</strong> An ID is a simple resource that is referenced
using the value provided in the {@code name} attribute (not the name of the XML file). As
such, you can combine ID resources with other simple resources in the one XML file,
under one {@code &lt;resources&gt;} element. Also, remember that an ID resources does not reference
an actual resource item; it is simply a unique ID that you can attach to other resources or use
as a unique integer in your application.</p>
<dl class="xml">
<dt>file location:</dt>
<dd><code>res/values/<em>filename.xml</em></code><br/>
The filename is arbitrary.</dd>
<dt>resource reference:</dt>
<dd>
In Java: <code>R.id.<em>name</em></code><br/>
In XML: <code>@[<em>package</em>:]id/<em>name</em></code>
</dd>
<dt>syntax:</dt>
<dd>
<pre class="stx">
&lt;?xml version="1.0" encoding="utf-8"?>
&lt;<a href="#id-resources-element">resources</a>&gt;
&lt;<a href="#id-item-element">item</a>
type="id"
name="<em>id_name</em>" /&gt;
&lt;/resources&gt;
</pre>
</dd>
<dt>elements:</dt>
<dd>
<dl class="tag-list">
<dt id="id-resources-element"><code>&lt;resources&gt;</code></dt>
<dd><strong>Required.</strong> This must be the root node.
<p>No attributes.</p>
</dd>
<dt id="id-item-element"><code>&lt;item&gt;</code></dt>
<dd>Defines a unique ID. Takes no value, only attributes.
<p class="caps">attributes:</p>
<dl class="atn-list">
<dt><code>type</code></dt>
<dd>Must be "id".</dd>
<dt><code>name</code></dt>
<dd><em>String</em>. A unique name for the ID.</dd>
</dl>
</dd>
</dl>
</dd> <!-- end elements and attributes -->
<dt>example:</dt>
<dd>
<p>XML file saved at <code>res/values/ids.xml</code>:</p>
<pre>
&lt;?xml version="1.0" encoding="utf-8"?>
&lt;resources>
&lt;item type="id" name="button_ok" /&gt;
&lt;item type="id" name="dialog_exit" /&gt;
&lt;/resources>
</pre>
<p>Then, this layout snippet uses the "button_ok" ID for a Button widget:</p>
<pre>
&lt;Button android:id="<b>@id/button_ok</b>"
style="@style/button_style" /&gt;
</pre>
<p>Notice that the {@code android:id} value does not include the plus sign in the ID reference,
because the ID already exists, as defined in the {@code ids.xml} example above. (When you specify an
ID to an XML resource using the plus sign&mdash;in the format {@code
android:id="@+id/name"}&mdash;it means that the "name" ID does not exist and should be created.)</p>
<p>As another example, the following code snippet uses the "dialog_exit" ID as a unique identifier
for a dialog:</p>
<pre>
{@link android.app.Activity#showDialog(int) showDialog}(<b>R.id.dialog_exit</b>);
</pre>
<p>In the same application, the "dialog_exit" ID is compared when creating a dialog:</p>
<pre>
protected Dialog {@link android.app.Activity#onCreateDialog(int)}(int id) {
Dialog dialog;
switch(id) {
case <b>R.id.dialog_exit</b>:
...
break;
default:
dialog = null;
}
return dialog;
}
</pre>
</dd> <!-- end example -->
</dl>
<h2 id="Integer">Integer</h2>
<p>An integer defined in XML.</p>
<p class="note"><strong>Note:</strong> An integer is a simple resource that is referenced
using the value provided in the {@code name} attribute (not the name of the XML file). As
such, you can combine integer resources with other simple resources in the one XML file,
under one {@code &lt;resources>} element.</p>
<dl class="xml">
<dt>file location:</dt>
<dd><code>res/values/<em>filename.xml</em></code><br/>
The filename is arbitrary. The {@code &lt;integer>} element's {@code name} will be used as the
resource ID.</dd>
<dt>resource reference:</dt>
<dd>
In Java: <code>R.integer.<em>integer_name</em></code><br/>
In XML: <code>@[<em>package</em>:]integer/<em>integer_name</em></code>
</dd>
<dt>syntax:</dt>
<dd>
<pre class="stx">
&lt;?xml version="1.0" encoding="utf-8"?>
&lt;<a href="#integer-resources-element">resources</a>>
&lt;<a href="#integer-element">integer</a>
name="<em>integer_name</em>"
&gt;<em>integer</em>&lt;/integer&gt;
&lt;/resources&gt;
</pre>
</dd>
<dt>elements:</dt>
<dd>
<dl class="tag-list">
<dt id="integer-resources-element"><code>&lt;resources&gt;</code></dt>
<dd><strong>Required.</strong> This must be the root node.
<p>No attributes.</p>
</dd>
<dt id="integer-element"><code>&lt;integer&gt;</code></dt>
<dd>An integer.
<p class="caps">attributes:</p>
<dl class="atn-list">
<dt><code>name</code></dt>
<dd><em>String</em>. A name for the integer. This will be used as the resource ID.
</dd>
</dl>
</dd>
</dl>
</dd> <!-- end elements and attributes -->
<dt>example:</dt>
<dd>
<p>XML file saved at <code>res/values/integers.xml</code>:</p>
<pre>
&lt;?xml version="1.0" encoding="utf-8"?>
&lt;resources>
&lt;integer name="max_speed">75&lt;/integer>
&lt;integer name="min_speed">5&lt;/integer>
&lt;/resources>
</pre>
<p>This application code retrieves an integer:</p>
<pre>
Resources res = {@link android.content.Context#getResources()};
int maxSpeed = res.{@link android.content.res.Resources#getInteger(int) getInteger}(R.integer.max_speed);
</pre>
</dd> <!-- end example -->
</dl>
<h2 id="IntegerArray">Integer Array</h2>
<p>An array of integers defined in XML.</p>
<p class="note"><strong>Note:</strong> An integer array is a simple resource that is referenced
using the value provided in the {@code name} attribute (not the name of the XML file). As
such, you can combine integer array resources with other simple resources in the one XML file,
under one {@code &lt;resources>} element.</p>
<dl class="xml">
<dt>file location:</dt>
<dd><code>res/values/<em>filename</em>.xml</code><br/>
The filename is arbitrary. The {@code &lt;integer-array>} element's {@code name} will be used as the
resource ID.</dd>
<dt>compiled resource datatype:</dt>
<dd>Resource pointer to an array of integers.</dd>
<dt>resource reference:</dt>
<dd>
In Java: <code>R.array.<em>string_array_name</em></code><br/>
In XML: <code>@[<em>package</em>:]array.<em>integer_array_name</em></code>
</dd>
<dt>syntax:</dt>
<dd>
<pre class="stx">
&lt;?xml version="1.0" encoding="utf-8"?>
&lt;<a href="#integer-array-resources-element">resources</a>>
&lt;<a href="#integer-array-element">integer-array</a>
name="<em>integer_array_name</em>">
&lt;<a href="#integer-array-item-element">item</a>
&gt;<em>integer</em>&lt;/item&gt;
&lt;/integer-array>
&lt;/resources>
</pre>
</dd>
<dt>elements:</dt>
<dd>
<dl class="tag-list">
<dt id="integer-array-resources-element"><code>&lt;resources&gt;</code></dt>
<dd><strong>Required.</strong> This must be the root node.
<p>No attributes.</p>
</dd>
<dt id="integer-array-element"><code>&lt;string-array&gt;</code></dt>
<dd>Defines an array of integers. Contains one or more child {@code &lt;item>} elements.
<p class="caps">attributes:</p>
<dl class="atn-list">
<dt><code>android:name</code></dt>
<dd><em>String</em>. A name for the array. This name will be used as the resource
ID to reference the array.</dd>
</dl>
</dd>
<dt id="integer-array-item-element"><code>&lt;item&gt;</code></dt>
<dd>An integer. The value can be a referenced to another
integer resource. Must be a child of a {@code &lt;integer-array&gt;} element.
<p>No attributes.</p>
</dd>
</dl>
</dd> <!-- end elements -->
<dt>example:</dt>
<dd>XML file saved at <code>res/values/integers.xml</code>:
<pre>
&lt;?xml version="1.0" encoding="utf-8"?>
&lt;resources>
&lt;integer-array name="bits">
&lt;item>4&lt;/item>
&lt;item>8&lt;/item>
&lt;item>16&lt;/item>
&lt;item>32&lt;/item>
&lt;/integer-array>
&lt;/resources>
</pre>
<p>This application code retrieves the integer array:</p>
<pre>
Resources res = {@link android.content.Context#getResources()};
int[] bits = res.{@link android.content.res.Resources#getIntArray(int) getIntArray}(R.array.bits);
</pre>
</dd> <!-- end example -->
</dl>
<h2 id="TypedArray">Typed Array</h2>
<p>A {@link android.content.res.TypedArray} defined in XML. You can use
this to create an array of other resources, such as drawables. Note that the array
is not required to be homogeneous, so you can create an array of mixed resource types, but
you must be aware of what and where the data types are in the array so that you can properly obtain
each item with the {@link android.content.res.TypedArray}'s {@code get...()} methods.</p>
<p class="note"><strong>Note:</strong> A typed array is a simple resource that is referenced
using the value provided in the {@code name} attribute (not the name of the XML file). As
such, you can combine typed array resources with other simple resources in the one XML file,
under one {@code &lt;resources&gt;} element.</p>
<dl class="xml">
<dt>file location:</dt>
<dd><code>res/values/<em>filename</em>.xml</code><br/>
The filename is arbitrary. The {@code &lt;array>} element's {@code name} will be used as the
resource ID.</dd>
<dt>compiled resource datatype:</dt>
<dd>Resource pointer to a {@link android.content.res.TypedArray}.</dd>
<dt>resource reference:</dt>
<dd>
In Java: <code>R.array.<em>array_name</em></code><br/>
In XML: <code>@[<em>package</em>:]array.<em>array_name</em></code>
</dd>
<dt>syntax:</dt>
<dd>
<pre class="stx">
&lt;?xml version="1.0" encoding="utf-8"?>
&lt;<a href="#array-resources-element">resources</a>>
&lt;<a href="#array-element">array</a>
name="<em>integer_array_name</em>">
&lt;<a href="#array-item-element">item</a>&gt;<em>resource</em>&lt;/item&gt;
&lt;/array>
&lt;/resources>
</pre>
</dd>
<dt>elements:</dt>
<dd>
<dl class="tag-list">
<dt id="array-resources-element"><code>&lt;resources&gt;</code></dt>
<dd><strong>Required.</strong> This must be the root node.
<p>No attributes.</p>
</dd>
<dt id="array-element"><code>&lt;array&gt;</code></dt>
<dd>Defines an array. Contains one or more child {@code &lt;item>} elements.
<p class="caps">attributes:</p>
<dl class="atn-list">
<dt><code>android:name</code></dt>
<dd><em>String</em>. A name for the array. This name will be used as the resource
ID to reference the array.</dd>
</dl>
</dd>
<dt id="array-item-element"><code>&lt;item&gt;</code></dt>
<dd>A generic resource. The value can be a reference to a resource or a simple data type.
Must be a child of an {@code &lt;array&gt;} element.
<p>No attributes.</p>
</dd>
</dl>
</dd> <!-- end elements -->
<dt>example:</dt>
<dd>XML file saved at <code>res/values/arrays.xml</code>:
<pre>
&lt;?xml version="1.0" encoding="utf-8"?>
&lt;resources>
&lt;array name="icons">
&lt;item>@drawable/home&lt;/item>
&lt;item>@drawable/settings&lt;/item>
&lt;item>@drawable/logout&lt;/item>
&lt;/array>
&lt;array name="colors">
&lt;item>#FFFF0000&lt;/item>
&lt;item>#FF00FF00&lt;/item>
&lt;item>#FF0000FF&lt;/item>
&lt;/array>
&lt;/resources>
</pre>
<p>This application code retrieves each array and then obtains the first entry in each array:</p>
<pre>
Resources res = {@link android.content.Context#getResources()};
TypedArray icons = res.{@link android.content.res.Resources#obtainTypedArray(int) obtainTypedArray}(R.array.icons);
Drawable drawable = icons.{@link android.content.res.TypedArray#getDrawable(int) getDrawable}(0);
TypedArray colors = res.{@link android.content.res.Resources#obtainTypedArray(int) obtainTypedArray}(R.array.icons);
int color = colors.{@link android.content.res.TypedArray#getColor(int,int) getColor}(0,0);
</pre>
</dd> <!-- end example -->
</dl>
<!-- TODO
<h2>Styleable Attribute</h2>
<dl class="xml">
<dt>syntax:</dt>
<dd>
<pre class="stx">
</pre>
</dd>
<dt>file location:</dt>
<dd><code>res/</code></dd>
<dt>compiled resource datatype:</dt>
<dd>Resource pointer to a {@link android.view.Menu} (or subclass) resource.</dd>
<dt>resource reference:</dt>
<dd>Java: <code>R.</code><br/>
XML:
</dd>
<dt>elements and attributes:</dt>
<dd>
<dl class="attr">
<dt><code></code></dt>
<dd></dd>
<dt><code></code></dt>
<dd>Valid attributes:
<dl>
<dt><code></code></dt>
<dd>
</dd>
<dt><code></code></dt>
<dd>
</dd>
</dl>
</dd>
</dl>
</dd>
<dt>example:</dt>
<dd>
<dl>
<dt>XML file saved at <code>res/</code>:</dt>
<dd>
<pre>
</pre>
</dd>
<dt>Java code :</dt>
<dd>
<pre>
</pre>
</dd>
</dl>
</dd>
<dt>see also:</dt>
<dd>
<ul>
<li></li>
</ul>
</dd>
</dl>
-->
@@ -0,0 +1,992 @@
page.title=Providing Resources
parent.title=Application Resources
parent.link=index.html
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>Quickview</h2>
<ul>
<li>Different types of resources belong in different subdirectories of {@code res/}</li>
<li>Alternative resources provide configuration-specific resource files</li>
<li>Always include default resources so your app does not depend on specific
device configurations</li>
</ul>
<h2>In this document</h2>
<ol>
<li><a href="#ResourceTypes">Grouping Resource Types</a></li>
<li><a href="#AlternativeResources">Providing Alternative Resources</a>
<ol>
<li><a href="#QualifierRules">Qualifier name rules</a></li>
<li><a href="#AliasResources">Creating alias resources</a></li>
</ol>
</li>
<li><a href="#Compatibility">Providing the Best Device Compatibility with Resources</a>
<ol>
<li><a href="#ScreenCompatibility">Providing screen resource compatibility for Android
1.5</a></li>
</ol>
</li>
<li><a href="#BestMatch">How Android Finds the Best-matching Resource</a></li>
<li><a href="#KnownIssues">Known Issues</a></li>
</ol>
<h2>See also</h2>
<ol>
<li><a href="accessing-resources.html">Accessing Resources</a></li>
<li><a href="available-resources.html">Resource Types</a></li>
<li><a href="{@docRoot}guide/practices/screens_support.html">Supporting Multiple
Screens</a></li>
</ol>
</div>
</div>
<p>You should always externalize application resources such as images and strings from your
code, so that you can maintain them independently. You should also provide alternative resources for
specific device configurations, by grouping them in specially-named resource directories. At
runtime, Android uses uses the appropriate resource based on the current configuration. For
example, you might want to provide a different UI layout depending on the screen size or different
strings depending on the language setting.</p>
<p>Once you externalize your application resources, you can access them
using resource IDs that are generated in your project's {@code R} class. How to use
resources in your application is discussed in <a href="accessing-resources.html">Accessing
Resources</a>. This document shows you how to group your resources in your Android project and
provide alternative resources for specific device configurations.</p>
<h2 id="ResourceTypes">Grouping Resource Types</h2>
<p>You should place each type of resource in a specific subdirectory of your project's
{@code res/} directory. For example, here's the file hierarchy for a simple project:</p>
<pre class="classic no-pretty-print">
MyProject/
src/ <span style="color:black">
MyActivity.java </span>
res/
drawable/ <span style="color:black">
icon.png </span>
layout/ <span style="color:black">
main.xml
info.xml</span>
values/ <span style="color:black">
strings.xml </span>
</pre>
<p>As you can see in this example, the {@code res/} directory contains all the resources (in
subdirectories): an image resource, two layout resources, and a string resource file. The resource
directory names are important and are described in table 1.</p>
<p class="table-caption" id="table1"><strong>Table 1.</strong> Resource directories
supported inside project {@code res/} directory.</p>
<table>
<tr>
<th scope="col">Directory</th>
<th scope="col">Resource Type</th>
</tr>
<tr>
<td><code>anim/</code></td>
<td>XML files that define tween animations. See <a
href="animation-resource.html">Animation Resources</a>.</td>
</tr>
<tr>
<td><code>color/</code></td>
<td>XML files that define a state list of colors. See <a href="color-list-resource.html">Color
State List Resource</a></td>
</tr>
<tr>
<td><code>drawable/</code></td>
<td><p>Bitmap files ({@code .png}, {@code .9.png}, {@code .jpg}, {@code .gif}) or XML files that
are compiled into the following drawable resource subtypes:</p>
<ul>
<li>Bitmap files</li>
<li>Nine-Patches (re-sizable bitmaps)</li>
<li>State lists</li>
<li>Shapes</li>
<li>Animation drawables</li>
<li>Other drawables</li>
</ul>
<p>See <a href="drawable-resource.html">Drawable Resources</a>.</p>
</td>
</tr>
<tr>
<td><code>layout/</code></td>
<td>XML files that define a user interface layout.
See <a href="layout-resource.html">Layout Resource</a>.</td>
</tr>
<tr>
<td><code>menu/</code></td>
<td>XML files that define application menus, such as an Options Menu, Context Menu, or Sub
Menu. See <a href="menu-resource.html">Menu Resource</a>.</td>
</tr>
<tr>
<td><code>raw/</code></td>
<td><p>Arbitrary files to save in their raw form. To open these resources with a raw
{@link java.io.InputStream}, call {@link android.content.res.Resources#openRawResource(int)
Resources.openRawResource()} with the resource ID, which is {@code R.raw.<em>filename</em>}.</p>
<p>However, if you need access to original file names and file hierarchy, you might consider
saving some resources in the {@code
assets/} directory (instead of {@code res/raw/}). Files in {@code assets/} are not given a
resource ID, so you can read them only using {@link android.content.res.AssetManager}.</p></td>
</tr>
<tr>
<td><code>values/</code></td>
<td><p>XML files that contain simple values, such as strings, integers, and colors.</p>
<p>Whereas XML resource files in other {@code res/} subdirectories define a single resource
based on the XML filename, files in the {@code values/} directory describe multiple resources.
For a file in this directory, each child of the {@code &lt;resources&gt;} element defines a single
resource. For example, a {@code &lt;string&gt;} element creates an
{@code R.string} resource and a {@code &lt;color&gt;} element creates an {@code R.color}
resource.</p>
<p>Because each resource is defined with its own XML element, you can name the file
whatever you want and place different resource types in one file. However, for clarity, you might
want to place unique resource types in different files. For example, here are some filename
conventions for resources you can create in this directory:</p>
<ul>
<li>arrays.xml for resource arrays (<a
href="more-resources.html#TypedArray">typed arrays</a>).</li>
<li>colors.xml for <a
href="more-resources.html#Color">color values</a></li>
<li>dimens.xml for <a
href="more-resources.html#Dimension">dimension values</a>.</li>
<li>strings.xml for <a href="string-resource.html">string
values</a>.</li>
<li>styles.xml for <a href="style-resource.html">styles</a>.</li>
</ul>
<p>See <a href="string-resource.html">String Resources</a>,
<a href="style-resource.html">Style Resource</a>, and
<a href="more-resources.html">More Resource Types</a>.</p>
</td>
</tr>
<tr>
<td><code>xml/</code></td>
<td>Arbitrary XML files that can be read at runtime by calling {@link
android.content.res.Resources#getXml(int) Resources.getXML()}. Various XML configuration files
must be saved here, such as a <a
href="{@docRoot}guide/topics/search/searchable-config.html">searchable configuration</a>.
<!-- or preferences configuration. --></td>
</tr>
</table>
<p class="caution"><strong>Caution:</strong> Never save resource files directly inside the
{@code res/} directory&mdash;it will cause a compiler error.</p>
<p>For more information about certain types of resources, see the <a
href="available-resources.html">Resource Types</a> documentation.</p>
<p>The resources that you save in the subdirectories defined in table 1 are your "default"
resources. That is, these resources define the default design and content for your application.
However, different types of Android-powered devices might call for different types of resources.
For example, if a device has a larger than normal screen, then you should provide
different layout resources that take advantage of the extra screen space. Or, if a device has a
different language setting, then you should provide different string resources that translate the
text in your user interface. To provide these different resources for different device
configurations, you need to provide alternative resources, in addition to your default
resources.</p>
<h2 id="AlternativeResources">Providing Alternative Resources</h2>
<div class="figure" style="width:421px">
<img src="{@docRoot}images/resources/resource_devices_diagram2.png" height="137" alt="" />
<p class="img-caption">
<strong>Figure 1.</strong> Two different devices, one using alternative resources.</p>
</div>
<p>Almost every application should provide alternative resources to support specific device
configurations. For instance, you should include alternative drawable resources for different
screen densities and alternative string resources for different languages. At runtime, Android
detects the current device configuration and loads the appropriate
resources for your application.</p>
<p>To specify configuration-specific alternatives for a set of resources:</p>
<ol>
<li>Create a new directory in {@code res/} named in the form {@code
<em>&lt;resources_name&gt;</em>-<em>&lt;config_qualifier&gt;</em>}.
<ul>
<li><em>{@code &lt;resources_name&gt;}</em> is the directory name of the corresponding default
resources (defined in table 1).</li>
<li><em>{@code &lt;qualifier&gt;}</em> is a name that specifies an individual configuration
for which these resources are to be used (defined in table 2).</li>
</ul>
<p>You can append more than one <em>{@code &lt;qualifier&gt;}</em>. Separate each
one with a dash.</p>
</li>
<li>Save the respective alternative resources in this new directory. The resource files must be
named exactly the same as the default resource files.</li>
</ol>
<p>For example, here are some default and alternative resources:</p>
<pre class="classic no-pretty-print">
res/
drawable/ <span style="color:black">
icon.png
background.png </span>
drawable-hdpi/ <span style="color:black">
icon.png
background.png </span>
</pre>
<p>The {@code hdpi} qualifier indicates that the resources in that directory are for devices with a
high-density screen. The images in each of these drawable directories are sized for a specific
screen density, but the filenames are exactly
the same. This way, the resource ID that you use to reference the {@code icon.png} or {@code
background.png} image is always the same, but Android selects the
version of each resource that best matches the current device, by comparing the device
configuration information with the qualifiers in the alternative resource directory name.</p>
<p>Android supports several configuration qualifiers and you can
add multiple qualifiers to one directory name, by separating each qualifier with a dash. Table 2
lists the valid configuration qualifiers, in order of precedence&mdash;if you use multiple
qualifiers for one resource directory, they must be added to the directory name in the order they
are listed in the table.</p>
<p class="note"><strong>Note:</strong> Some configuration qualifiers were added after Android 1.0,
so not
all versions of Android support all the qualifiers listed in table 2. New qualifiers
indicate the version in which they were added. To avoid any issues, always include a set of default
resources for resources that your application uses. For more information, see the section about <a
href="#Compatibility">Providing the Best Device Compatibility with Resources</a>.</p>
<p class="table-caption" id="table2"><strong>Table 2.</strong> Configuration qualifier
names.</p>
<table>
<tr>
<th>Qualifier</th>
<th>Values</th>
<th>Description</th>
</tr>
<tr id="MccQualifier">
<td>MCC and MNC</td>
<td>Examples:<br/>
<code>mcc310</code><br/>
<code><nobr>mcc310-mnc004</nobr></code><br/>
<code>mcc208-mnc00</code><br/>
etc.
</td>
<td>
<p>The mobile country code (MCC), optionally followed by mobile network code (MNC)
from the SIM card in the device. For example, <code>mcc310</code> is U.S. on any carrier,
<code>mcc310-mnc004</code> is U.S. on Verizon, and <code>mcc208-mnc00</code> is France on
Orange.</p>
<p>If the device uses a radio connection (GSM phone), the MCC comes
from the SIM, and the MNC comes from the network to which the
device is connected.</p>
<p>You can also use the MCC alone (for example, to include country-specific legal
resources in your application). If you need to specify based on the language only, then use the
<em>language and region</em> qualifier instead (discussed next). If you decide to use the MCC and
MNC qualifier, you should do so with care and test that it works as expected.</p>
<p>Also see the configuration fields {@link
android.content.res.Configuration#mcc}, and {@link
android.content.res.Configuration#mnc}, which indicate the current mobile country code
and mobile network code, respectively.</p>
</td>
</tr>
<tr id="LocaleQualifier">
<td>Language and region</td>
<td>Examples:<br/>
<code>en</code><br/>
<code>fr</code><br/>
<code>en-rUS</code><br/>
<code>fr-rFR</code><br/>
<code>fr-rCA</code><br/>
etc.
</td>
<td><p>The language is defined by a two-letter <a
href="http://www.loc.gov/standards/iso639-2/php/code_list.php">ISO
639-1</a> language code, optionally followed by a two letter
<a
href="http://www.iso.org/iso/en/prods-services/iso3166ma/02iso-3166-code-lists/list-en1.html">ISO
3166-1-alpha-2</a> region code (preceded by lowercase &quot;{@code r}&quot;).
</p><p>
The codes are <em>not</em> case-sensitive; the {@code r} prefix is used to
distinguish the region portion.
You cannot specify a region alone.</p>
<p>This can change during the life
of your application if the user changes his or her language in the system settings. See <a
href="runtime-changes.html">Handling Runtime Changes</a> for information about
how this can affect your application during runtime.</p>
<p>See <a href="localization.html">Localization</a> for a complete guide to localizing
your application for other languages.</p>
<p>Also see the {@link android.content.res.Configuration#locale} configuration field, which
indicates the current locale.</p>
</td>
</tr>
<tr id="ScreenSizeQualifier">
<td>Screen size</td>
<td>
<code>small</code><br/>
<code>normal</code><br/>
<code>large</code><br/>
<code>xlarge</code>
</td>
<td>
<ul class="nolist">
<li>{@code small}: Screens based on the space available on a
low-density QVGA screen. Considering a portrait HVGA display, this has
the same available width but less height&mdash;it is 3:4 vs. HVGA's
2:3 aspect ratio. Examples are QVGA low density and VGA high
density.</li>
<li>{@code normal}: Screens based on the traditional
medium-density HVGA screen. A screen is considered to be normal if it is
at least this size (independent of density) and not larger. Examples
of such screens a WQVGA low density, HVGA medium density, WVGA
high density.</li>
<li>{@code large}: Screens based on the space available on a
medium-density VGA screen. Such a screen has significantly more
available space in both width and height than an HVGA display.
Examples are VGA and WVGA medium density screens.</li>
<li>{@code xlarge}: Screens that are considerably larger than the traditional
medium-density HVGA screen. In most cases, devices with extra large screens would be too
large to carry in a pocket and would most likely be tablet-style devices. <em>Added in API Level
9.</em></li>
</ul>
<p><em>Added in API Level 4.</em></p>
<p>See <a href="{@docRoot}guide/practices/screens_support.html">Supporting Multiple
Screens</a> for more information.</p>
<p>Also see the {@link android.content.res.Configuration#screenLayout} configuration field,
which indicates whether the screen is small, normal,
or large.</p>
</td>
</tr>
<tr id="ScreenAspectQualifier">
<td>Screen aspect</td>
<td>
<code>long</code><br/>
<code>notlong</code>
</td>
<td>
<ul class="nolist">
<li>{@code long}: Long screens, such as WQVGA, WVGA, FWVGA</li>
<li>{@code notlong}: Not long screens, such as QVGA, HVGA, and VGA</li>
</ul>
<p><em>Added in API Level 4.</em></p>
<p>This is based purely on the aspect ratio of the screen (a "long" screen is wider). This
is not related to the screen orientation.</p>
<p>Also see the {@link android.content.res.Configuration#screenLayout} configuration field,
which indicates whether the screen is long.</p>
</td>
</tr>
<tr id="OrientationQualifier">
<td>Screen orientation</td>
<td>
<code>port</code><br/>
<code>land</code> <!-- <br/>
<code>square</code> -->
</td>
<td>
<ul class="nolist">
<li>{@code port}: Device is in portrait orientation (vertical)</li>
<li>{@code land}: Device is in landscape orientation (horizontal)</li>
<!-- Square mode is currently not used. -->
</ul>
<p>This can change during the life of your application if the user rotates the
screen. See <a href="runtime-changes.html">Handling Runtime Changes</a> for information about
how this affects your application during runtime.</p>
<p>Also see the {@link android.content.res.Configuration#orientation} configuration field,
which indicates the current device orientation.</p>
</td>
</tr>
<tr id="DockQualifier">
<td>Dock mode</td>
<td>
<code>car</code><br/>
<code>desk</code>
</td>
<td>
<ul class="nolist">
<li>{@code car}: Device is in a car dock</li>
<li>{@code desk}: Device is in a desk dock</li>
</ul>
<p><em>Added in API Level 8.</em></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 this mode using {@link
android.app.UiModeManager}. See <a href="runtime-changes.html">Handling Runtime Changes</a> for
information about how this affects your application during runtime.</p>
</td>
</tr>
<tr id="NightQualifier">
<td>Night mode</td>
<td>
<code>night</code><br/>
<code>notnight</code>
</td>
<td>
<ul class="nolist">
<li>{@code night}: Night time</li>
<li>{@code notnight}: Day time</li>
</ul>
<p><em>Added in API Level 8.</em></p>
<p>This can change during the life of your application if night mode is left in
auto mode (default), in which case the mode changes based on the time of day. You can enable
or disable this mode using {@link android.app.UiModeManager}. See <a
href="runtime-changes.html">Handling Runtime Changes</a> for information about how this affects your
application during runtime.</p>
</td>
</tr>
<tr id="DensityQualifier">
<td>Screen pixel density (dpi)</td>
<td>
<code>ldpi</code><br/>
<code>mdpi</code><br/>
<code>hdpi</code><br/>
<code>xhdpi</code><br/>
<code>nodpi</code>
</td>
<td>
<ul class="nolist">
<li>{@code ldpi}: Low-density screens; approximately 120dpi.</li>
<li>{@code mdpi}: Medium-density (on traditional HVGA) screens; approximately
160dpi.</li>
<li>{@code hdpi}: High-density screens; approximately 240dpi.</li>
<li>{@code xhdpi}: Extra high-density screens; approximately 320dpi. <em>Added in API
Level 8</em></li>
<li>{@code nodpi}: This can be used for bitmap resources that you do not want to be scaled
to match the device density.</li>
</ul>
<p><em>Added in API Level 4.</em></p>
<p>There is thus a 3:4:6 scaling ratio between the three densities, so a 9x9 bitmap
in ldpi is 12x12 in mdpi and 18x18 in hdpi.</p>
<p>When Android selects which resource files to use,
it handles screen density differently than the other qualifiers.
In step 1 of <a href="#BestMatch">How Android finds the best
matching directory</a> (below), screen density is always considered to
be a match. In step 4, if the qualifier being considered is screen
density, Android selects the best final match at that point,
without any need to move on to step 5.
</p>
<p>See <a href="{@docRoot}guide/practices/screens_support.html">Supporting Multiple
Screens</a> for more information about how to handle screen sizes and how Android might scale
your bitmaps.</p>
</td>
</tr>
<tr id="TouchscreenQualifier">
<td>Touchscreen type</td>
<td>
<code>notouch</code><br/>
<code>stylus</code><br/>
<code>finger</code>
</td>
<td>
<ul class="nolist">
<li>{@code notouch}: Device does not have a touchscreen.</li>
<li>{@code stylus}: Device has a resistive touchscreen that's suited for use with a
stylus.</li>
<li>{@code finger}: Device has a touchscreen.</li>
</ul>
<p>Also see the {@link android.content.res.Configuration#touchscreen} configuration field,
which indicates the type of touchscreen on the device.</p>
</td>
</tr>
<tr id="KeyboardAvailQualifier">
<td>Keyboard availability</td>
<td>
<code>keysexposed</code><br/>
<code>keyssoft</code>
</td>
<td>
<ul class="nolist">
<li>{@code keysexposed}: Device has a keyboard available. If the device has a
software keyboard enabled (which is likely), this may be used even when the hardware keyboard is
<em>not</em> exposed to the user, even if the device has no hardware keyboard. If no software
keyboard is provided or it's disabled, then this is only used when a hardware keyboard is
exposed.</li>
<li>{@code keyshidden}: Device has a hardware keyboard available but it is
hidden <em>and</em> the device does <em>not</em> have a software keyboard enabled.</li>
<li>{@code keyssoft}: Device has a software keyboard enabled, whether it's
visible or not.</li>
</ul>
<p>If you provide <code>keysexposed</code> resources, but not <code>keyssoft</code>
resources, the system uses the <code>keysexposed</code> resources regardless of whether a
keyboard is visible, as long as the system has a software keyboard enabled.</p>
<p>This can change during the life of your application if the user opens a hardware
keyboard. See <a href="runtime-changes.html">Handling Runtime Changes</a> for information about how
this affects your application during runtime.</p>
<p>Also see the configuration fields {@link
android.content.res.Configuration#hardKeyboardHidden} and {@link
android.content.res.Configuration#keyboardHidden}, which indicate the visibility of a hardware
keyboard and and the visibility of any kind of keyboard (including software), respectively.</p>
</td>
</tr>
<tr id="ImeQualifier">
<td>Primary text input method</td>
<td>
<code>nokeys</code><br/>
<code>qwerty</code><br/>
<code>12key</code>
</td>
<td>
<ul class="nolist">
<li>{@code nokeys}: Device has no hardware keys for text input.</li>
<li>{@code qwerty}: Device has a hardware qwerty keyboard, whether it's visible to the
user
or not.</li>
<li>{@code 12key}: Device has a hardware 12-key keyboard, whether it's visible to the user
or not.</li>
</ul>
<p>Also see the {@link android.content.res.Configuration#keyboard} configuration field,
which indicates the primary text input method available.</p>
</td>
</tr>
<tr id="NavAvailQualifier">
<td>Navigation key availability</td>
<td>
<code>navexposed</code><br/>
<code>navhidden</code>
</td>
<td>
<ul class="nolist">
<li>{@code navexposed}: Navigation keys are available to the user.</li>
<li>{@code navhidden}: Navigation keys are not available (such as behind a closed
lid).</li>
</ul>
<p>This can change during the life of your application if the user reveals the navigation
keys. See <a href="runtime-changes.html">Handling Runtime Changes</a> for
information about how this affects your application during runtime.</p>
<p>Also see the {@link android.content.res.Configuration#navigationHidden} configuration
field, which indicates whether navigation keys are hidden.</p>
</td>
</tr>
<tr id="TouchQualifier">
<td>Primary non-touch navigation method</td>
<td>
<code>nonav</code><br/>
<code>dpad</code><br/>
<code>trackball</code><br/>
<code>wheel</code>
</td>
<td>
<ul class="nolist">
<li>{@code nonav}: Device has no navigation facility other than using the
touchscreen.</li>
<li>{@code dpad}: Device has a directional-pad (d-pad) for navigation.</li>
<li>{@code trackball}: Device has a trackball for navigation.</li>
<li>{@code wheel}: Device has a directional wheel(s) for navigation (uncommon).</li>
</ul>
<p>Also see the {@link android.content.res.Configuration#navigation} configuration field,
which indicates the type of navigation method available.</p>
</td>
</tr>
<!-- DEPRECATED
<tr>
<td>Screen dimensions</td>
<td>Examples:<br/>
<code>320x240</code><br/>
<code>640x480</code><br/>
etc.
</td>
<td>
<p>The larger dimension must be specified first. <strong>This configuration is deprecated
and should not be used</strong>. Instead use "screen size," "wider/taller screens," and "screen
orientation" described above.</p>
</td>
</tr>
-->
<tr id="VersionQualifier">
<td>System Version (API Level)</td>
<td>Examples:<br/>
<code>v3</code><br/>
<code>v4</code><br/>
<code>v7</code><br/>
etc.</td>
<td>
<p>The API Level supported by the device. For example, <code>v1</code> for API Level
1 (devices with Android 1.0 or higher) and <code>v4</code> for API Level 4 (devices with Android
1.6 or higher). See the <a
href="{@docRoot}guide/appendix/api-levels.html">Android API Levels</a> document for more information
about these values.</p>
<p class="caution"><strong>Caution:</strong> Android 1.5 and 1.6 only match resources
with this qualifier when it exactly matches the system version. See the section below about <a
href="#KnownIssues">Known Issues</a> for more information.</p>
</td>
</tr>
</table>
<h3 id="QualifierRules">Qualifier name rules</h3>
<p>Here are some rules about using configuration qualifier names:</p>
<ul>
<li>You can specify multiple qualifiers for a single set of resources, separated by dashes. For
example, <code>drawable-en-rUS-land</code> applies to US-English devices in landscape
orientation.</li>
<li>The qualifiers must be in the order listed in <a href="#table2">table 2</a>. For
example:
<ul>
<li>Wrong: <code>drawable-hdpi-port/</code></li>
<li>Correct: <code>drawable-port-hdpi/</code></li>
</ul>
</li>
<li>Alternative resource directories cannot be nested. For example, you cannot have
<code>res/drawable/drawable-en/</code>.</li>
<li>Values are case-insensitive. The resource compiler converts directory names
to lower case before processing to avoid problems on case-insensitive
file systems. Any capitalization in the names is only to benefit readability.</li>
<li>Only one value for each qualifier type is supported. For example, if you want to use
the same drawable files for Spain and France, you <em>cannot</em> have a directory named
<code>drawable-rES-rFR/</code>. Instead you need two resource directories, such as
<code>drawable-rES/</code> and <code>drawable-rFR/</code>, which contain the appropriate files.
However, you are not required to actually duplicate the same files in both locations. Instead, you
can create an alias to a resource. See <a href="#AliasResources">Creating
alias resources</a> below.</li>
</ul>
<p>After you save alternative resources into directories named with
these qualifiers, Android automatically applies the resources in your application based on the
current device configuration. Each time a resource is requested, Android checks for alternative
resource directories that contain the requested resource file, then <a href="#BestMatch">finds the
best-matching resource</a> (discussed below). If there are no alternative resources that match
a particular device configuration, then Android uses the corresponding default resources (the
set of resources for a particular resource type that does not include a configuration
qualifier).</p>
<h3 id="AliasResources">Creating alias resources</h3>
<p>When you have a resource that you'd like to use for more than one device
configuration (but do not want to provide as a default resource), you do not need to put the same
resource in more than one alternative resource directory. Instead, you can (in some cases) create an
alternative
resource that acts as an alias for a resource saved in your default resource directory.</p>
<p class="note"><strong>Note:</strong> Not all resources offer a mechanism by which you can
create an alias to another resource. In particular, animation, menu, raw, and other unspecified
resources in the {@code xml/} directory do not offer this feature.</p>
<p>For example, imagine you have an application icon, {@code icon.png}, and need unique version of
it for different locales. However, two locales, English-Canadian and French-Canadian, need to
use the same version. You might assume that you need to copy the same image
into the resource directory for both English-Canadian and French-Canadian, but it's
not true. Instead, you can save the image that's used for both as {@code icon_ca.png} (any
name other than {@code icon.png}) and put
it in the default {@code res/drawable/} directory. Then create an {@code icon.xml} file in {@code
res/drawable-en-rCA/} and {@code res/drawable-fr-rCA/} that refers to the {@code icon_ca.png}
resource using the {@code &lt;bitmap&gt;} element. This allows you to store just one version of the
PNG file and two small XML files that point to it. (An example XML file is shown below.)</p>
<h4>Drawable</h4>
<p>To create an alias to an existing drawable, use the {@code &lt;bitmap&gt;} element.
For example:</p>
<pre>
&lt;?xml version="1.0" encoding="utf-8"?>
&lt;bitmap xmlns:android="http://schemas.android.com/apk/res/android"
android:src="@drawable/icon_ca" />
</pre>
<p>If you save this file as {@code icon.xml} (in an alternative resource directory, such as
{@code res/drawable-en-rCA/}), it is compiled into a resource that you
can reference as {@code R.drawable.icon}, but is actually an alias for the {@code
R.drawable.icon_ca} resource (which is saved in {@code res/drawable/}).</p>
<h4>Layout</h4>
<p>To create an alias to an existing layout, use the {@code &lt;include&gt;}
element, wrapped in a {@code &lt;merge&gt;}. For example:</p>
<pre>
&lt;?xml version="1.0" encoding="utf-8"?>
&lt;merge>
&lt;include layout="@layout/main_ltr"/>
&lt;/merge>
</pre>
<p>If you save this file as {@code main.xml}, it is compiled into a resource you can reference
as {@code R.layout.main}, but is actually an alias for the {@code R.layout.main_ltr}
resource.</p>
<h4>Strings and other simple values</h4>
<p>To create an alias to an existing string, simply use the resource ID of the desired
string as the value for the new string. For example:</p>
<pre>
&lt;?xml version="1.0" encoding="utf-8"?>
&lt;resources>
&lt;string name="hello">Hello&lt;/string>
&lt;string name="hi">@string/hello&lt;/string>
&lt;/resources>
</pre>
<p>The {@code R.string.hi} resource is now an alias for the {@code R.string.hello}.</p>
<p> <a href="{@docRoot}guide/topics/resources/more-resources.html">Other simple values</a> work the
same way. For example, a color:</p>
<pre>
&lt;?xml version="1.0" encoding="utf-8"?>
&lt;resources>
&lt;color name="yellow">#f00&lt;/color>
&lt;color name="highlight">@color/red&lt;/color>
&lt;/resources>
</pre>
<h2 id="Compatibility">Providing the Best Device Compatibility with Resources</h2>
<p>In order for your application to support multiple device configurations, it's very important that
you always provide default resources for each type of resource that your application uses.</p>
<p>For example, if your application supports several languages, always include a {@code
values/} directory (in which your strings are saved) <em>without</em> a <a
href="#LocaleQualifier">language and region qualifier</a>. If you instead put all your string files
in directories that have a language and region qualifier, then your application will crash when run
on a device set to a language that your strings do not support. But, as long as you provide default
{@code values/} resources, then your application will run properly (even if the user doesn't
understand that language&mdash;it's better than crashing).</p>
<p>Likewise, if you provide different layout resources based on the screen orientation, you should
pick one orientation as your default. For example, instead of providing layout resources in {@code
layout-land/} for landscape and {@code layout-port/} for portrait, leave one as the default, such as
{@code layout/} for landscape and {@code layout-port/} for portrait.</p>
<p>Providing default resources is important not only because your application might run on a
configuration you had not anticipated, but also because new versions of Android sometimes add
configuration qualifiers that older versions do not support. If you use a new resource qualifier,
but maintain code compatibility with older versions of Android, then when an older version of
Android runs your application, it will crash if you do not provide default resources, because it
cannot use the resources named with the new qualifier. For example, if your <a
href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code
minSdkVersion}</a> is set to 4, and you qualify all of your drawable resources using <a
href="#NightQualifier">night mode</a> ({@code night} or {@code notnight}, which were added in API
Level 8), then an API Level 4 device cannot access your drawable resources and will crash. In this
case, you probably want {@code notnight} to be your default resources, so you should exclude that
qualifier so your drawable resources are in either {@code drawable/} or {@code drawable-night/}.</p>
<p>So, in order to provide the best device compatibility, always provide default
resources for the resources your application needs to perform properly. Then create alternative
resources for specific device configurations using the configuration qualifiers.</p>
<p>There is one exception to this rule: If your application's <a
href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code minSdkVersion}</a> is 4 or
greater, you <em>do not</em> need default drawable resources when you provide alternative drawable
resources with the <a href="#DensityQualifier">screen density</a> qualifier. Even without default
drawable resources, Android can find the best match among the alternative screen densities and scale
the bitmaps as necessary. However, for the best experience on all types of devices, you should
provide alternative drawables for all three types of density. If your <a
href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code minSdkVersion}</a> is
<em>less than</em> 4 (Android 1.5 or lower), be aware that the screen size, density, and aspect
qualifiers are not supported on Android 1.5 or lower, so you might need to perform additional
compatibility for these versions.</p>
<h3 id="ScreenCompatibility">Providing screen resource compatibility for Android 1.5</h3>
<p>Android 1.5 (and lower) does not support the following configuration qualifers:</p>
<dl>
<dt><a href="#DensityQualifier">Density</a></dt>
<dd>{@code ldpi}, {@code mdpi}, {@code ldpi}, and {@code nodpi}</dd>
<dt><a href="#ScreenSizeQualifier">Screen size</a></dt>
<dd>{@code small}, {@code normal}, and {@code large}</dd>
<dt><a href="#ScreenAspectQualifier">Screen aspect</a></dt>
<dd>{@code long} and {@code notlong}</dd>
</dl>
<p>These configuration qualifiers were introduced in Android 1.6, so Android 1.5 (API Level 3) and
lower does not support them. If you use these configuration qualifiers and do not provide
corresponding default resources, then an Android 1.5 device might use any one of the resource
directories named with the above screen configuration qualifiers, because it ignores these
qualifiers and uses whichever otherwise-matching drawable resource it finds first.</p>
<p>For example, if your application supports Android 1.5 and includes drawable resources for
each density type ({@code drawable-ldpi/}, {@code drawable-mdpi/}, and {@code drawable-ldpi/}),
and does <em>not</em> include default drawable resources ({@code drawable/}), then
an Android 1.5 will use drawables from any one of the alternative resource directories, which
can result in a user interface that's less than ideal.<p>
<p>So, to provide compatibility with Android 1.5 (and lower) when using the screen configuration
qualifiers:</p>
<ol>
<li>Provide default resources that are for medium-density, normal, and notlong screens.
<p>Because all Android 1.5 devices have medium-density, normal, not-long screens, you can
place these kinds of resources in the corresponding default resource directory. For example, put all
medium density drawable resources in {@code drawable/} (instead of {@code drawable-mdpi/}),
put {@code normal} size resources in the corresponding default resource directory, and {@code
notlong} resources in the corresponding default resource directory.</p>
</li>
<li>Ensure that your <a href="{@docRoot}sdk/tools-notes.html">SDK Tools</a> version
is r6 or greater.
<p>You need SDK Tools, Revision 6 (or greater), because it includes a new packaging tool that
automatically applies an appropriate <a href="#VersionQualifier">version qualifier</a> to any
resource directory named with a qualifier that does not exist in Android 1.0. For example, because
the density qualifier was introduced in Android 1.6 (API Level 4), when the packaging tool
encounters a resource directory using the density qualifier, it adds {@code v4} to the directory
name to ensure that older versions do not use those resources (only API Level 4 and higher support
that qualifier). Thus, by putting your medium-density resources in a directory <em>without</em> the
{@code mdpi} qualifier, they are still accessible by Android 1.5, and any device that supports the
density qualifer and has a medium-density screen also uses the default resources (which are mdpi)
because they are the best match for the device (instead of using the {@code ldpi} or {@code hdpi}
resources).</p>
</li>
</ol>
<p class="note"><strong>Note:</strong> Later versions of Android, such as API Level 8,
introduce other configuration qualifiers that older version do not support. To provide the best
compatibility, you should always include a set of default resources for each type of resource
that your application uses, as discussed above to provide the best device compatibility.</p>
<h2 id="BestMatch">How Android Finds the Best-matching Resource</h2>
<p>When you request a resource for which you provide alternatives, Android selects which
alternative resource to use at runtime, depending on the current device configuration. To
demonstrate how Android selects an alternative resource, assume the following drawable directories
each contain different versions of the same images:</p>
<pre class="classic no-pretty-print">
drawable/
drawable-en/
drawable-fr-rCA/
drawable-en-port/
drawable-en-notouch-12key/
drawable-port-ldpi/
drawable-port-notouch-12key/
</pre>
<p>And assume the following is the device configuration:</p>
<p style="margin-left:1em;">
Locale = <code>en-GB</code> <br/>
Screen orientation = <code>port</code> <br/>
Screen pixel density = <code>hdpi</code> <br/>
Touchscreen type = <code>notouch</code> <br/>
Primary text input method = <code>12key</code>
</p>
<p>By comparing the device configuration to the available alternative resources, Android selects
drawables from {@code drawable-en-port}. It arrives at this decision using the following logic:</p>
<div class="figure" style="width:280px">
<img src="{@docRoot}images/resources/res-selection-flowchart.png" alt="" height="590" />
<p class="img-caption"><strong>Figure 2.</strong> Flowchart of how Android finds the
best-matching resource.</p>
</div>
<ol>
<li>Eliminate resource files that contradict the device configuration.
<p>The <code>drawable-fr-rCA/</code> directory is eliminated, because it
contradicts the <code>en-GB</code> locale.</p>
<pre class="classic no-pretty-print">
drawable/
drawable-en/
<strike>drawable-fr-rCA/</strike>
drawable-en-port/
drawable-en-notouch-12key/
drawable-port-ldpi/
drawable-port-notouch-12key/
</pre>
<p class="note"><strong>Exception:</strong> Screen pixel density is the one qualifier that is not
eliminated due to a contradiction. Even though the screen density of the device is hdpi,
<code>drawable-port-ldpi/</code> is not eliminated because every screen density is
considered to be a match at this point. More information is available in the <a
href="{@docRoot}guide/practices/screens_support.html">Supporting Multiple
Screens</a> document.</p></li>
<li>Pick the (next) highest-precedence qualifier in the list (<a href="#table2">table 2</a>).
(Start with MCC, then move down.) </li>
<li>Do any of the resource directories include this qualifier? </li>
<ul>
<li>If No, return to step 2 and look at the next qualifier. (In the example,
the answer is &quot;no&quot; until the language qualifier is reached.)</li>
<li>If Yes, continue to step 4.</li>
</ul>
</li>
<li>Eliminate resource directories that do not include this qualifier. In the example, the system
eliminates all the directories that do not include a language qualifier:</li>
<pre class="classic no-pretty-print">
<strike>drawable/</strike>
drawable-en/
drawable-en-port/
drawable-en-notouch-12key/
<strike>drawable-port-ldpi/</strike>
<strike>drawable-port-notouch-12key/</strike>
</pre>
<p class="note"><strong>Exception:</strong> If the qualifier in question is screen pixel density,
Android selects the option that most closely matches the device screen density.
In general, Android prefers scaling down a larger original image to scaling up a smaller
original image. See <a href="{@docRoot}guide/practices/screens_support.html">Supporting Multiple
Screens</a>.</p>
</li>
<li>Go back and repeat steps 2, 3, and 4 until only one directory remains. In the example, screen
orientation is the next qualifier for which there are any matches.
So, resources that do not specify a screen orientation are eliminated:
<pre class="classic no-pretty-print">
<strike>drawable-en/</strike>
drawable-en-port/
<strike>drawable-en-notouch-12key/</strike>
</pre>
<p>The remaining directory is {@code drawable-en-port}.</p>
</li>
</ol>
<p>Though this procedure is executed for each resource requested, the system further optimizes
some aspects. One such optimization is that once the device configuration is known, it might
eliminate alternative resources that can never match. For example, if the configuration
language is English ("en"), then any resource directory that has a language qualifier set to
something other than English is never included in the pool of resources checked (though a
resource directory <em>without</em> the language qualifier is still included).</p>
<p class="note"><strong>Note:</strong> The <em>precedence</em> of the qualifier (in <a
href="#table2">table 2</a>) is more important
than the number of qualifiers that exactly match the device. For example, in step 4 above, the last
choice on the list includes three qualifiers that exactly match the device (orientation, touchscreen
type, and input method), while <code>drawable-en</code> has only one parameter that matches
(language). However, language has a higher precedence than these other qualifiers, so
<code>drawable-port-notouch-12key</code> is out.</p>
<p>To learn more about how to use resources in your application, continue to <a
href="accessing-resources.html">Accessing Resources</a>.</p>
<h2 id="KnownIssues">Known Issues</h2>
<h3>Android 1.5 and 1.6: Version qualifier performs exact match, instead of best match</h3>
<p>The correct behavior is for the system to match resources marked with a <a
href="#VersionQualifier">version qualifier</a> equal
to or less than the system version on the device, but on Android 1.5 and 1.6, (API Level 3 and 4),
there is a bug that causes the system to match resources marked with the version qualifier
only when it exactly matches the version on the device.</p>
<p><b>The workaround:</b> To provide version-specific resources, abide by this behavior. However,
because this bug is fixed in versions of Android available after 1.6, if
you need to differentiate resources between Android 1.5, 1.6, and later versions, then you only need
to apply the version qualifier to the 1.6 resources and one to match all later versions. Thus, this
is effectively a non-issue.</p>
<p>For example, if you want drawable resources that are different on each Android 1.5, 1.6,
and 2.0.1 (and later), create three drawable directories: {@code drawable/} (for 1.5 and lower),
{@code drawable-v4} (for 1.6), and {@code drawable-v6} (for 2.0.1 and later&mdash;version 2.0, v5,
is no longer available).</p>
+8
View File
@@ -0,0 +1,8 @@
page.title=Application Resources
@jd:body
<script type="text/javascript">
window.location = toRoot + "guide/topics/resources/index.html";
</script>
<p><strong>This document has moved. Please see <a href="index.html">Application Resources</a>.</strong></p>
@@ -0,0 +1,247 @@
page.title=Handling Runtime Changes
parent.title=Application Resources
parent.link=index.html
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>In this document</h2>
<ol>
<li><a href="#RetainingAnObject">Retaining an Object During a Configuration Change</a></li>
<li><a href="#HandlingTheChange">Handling the Configuration Change Yourself</a>
</ol>
<h2>See also</h2>
<ol>
<li><a href="providing-resources.html">Providing Resources</a></li>
<li><a href="accessing-resources.html">Accessing Resources</a></li>
<li><a href="{@docRoot}resources/articles/faster-screen-orientation-change.html">Faster Screen
Orientation Change</a></li>
</ol>
</div>
</div>
<p>Some device configurations can change during runtime
(such as screen orientation, keyboard availability, and language). When such a change occurs,
Android restarts the running
Activity ({@link android.app.Activity#onDestroy()} is called, followed by {@link
android.app.Activity#onCreate(Bundle) onCreate()}). The restart behavior is designed to help your
application adapt to new configurations by automatically reloading your application with
alternative resources.</p>
<p>To properly handle a restart, it is important that your Activity restores its previous
state through the normal <a href="{@docRoot}guide/topics/fundamentals.html#lcycles">Activity
lifecycle</a>, in which Android calls
{@link android.app.Activity#onSaveInstanceState(Bundle) onSaveInstanceState()} before it destroys
your Activity so that you can save data about the application state. You can then restore the state
during {@link android.app.Activity#onCreate(Bundle) onCreate()} or {@link
android.app.Activity#onRestoreInstanceState(Bundle) onRestoreInstanceState()}. To test
that your application restarts itself with the application state intact, you should
invoke configuration changes (such as changing the screen orientation) while performing various
tasks in your application.</p>
<p>Your application should be able to restart at any time without loss of user data or
state in order to handle events such as when the user receives an incoming phone call and then
returns to your application (read about the
<a href="{@docRoot}guide/topics/fundamentals.html#lcycles">Activity lifecycle</a>).</p>
<p>However, you might encounter a situation in which restarting your application and
restoring significant amounts of data can be costly and create a poor user experience. In such a
situation, you have two options:</p>
<ol type="a">
<li><a href="#RetainingAnObject">Retain an object during a configuration change</a>
<p>Allow your Activity to restart when a configuration changes, but carry a stateful
{@link java.lang.Object} to the new instance of your Activity.</p>
</li>
<li><a href="#HandlingTheChange">Handle the configuration change yourself</a>
<p>Prevent the system from restarting your Activity during certain configuration
changes and receive a callback when the configurations do change, so that you can manually update
your Activity as necessary.</p>
</li>
</ol>
<h2 id="RetainingAnObject">Retaining an Object During a Configuration Change</h2>
<p>If restarting your Activity requires that you recover large sets of data, re-establish a
network connection, or perform other intensive operations, then a full restart due to a
configuration change might
be an unpleasant user experience. Also, it may not be possible for you to completely
maintain your Activity state with the {@link android.os.Bundle} that the system saves for you during
the Activity lifecycle&mdash;it is not designed to carry large objects (such as bitmaps) and the
data within it must be serialized then deserialized, which can consume a lot of memory and make the
configuration change slow. In such a situation, you can alleviate the burden of reinitializing
your Activity by retaining a stateful Object when your Activity is restarted due to a configuration
change.</p>
<p>To retain an Object during a runtime configuration change:</p>
<ol>
<li>Override the {@link android.app.Activity#onRetainNonConfigurationInstance()} method to return
the Object you would like to retain.</li>
<li>When your Activity is created again, call {@link
android.app.Activity#getLastNonConfigurationInstance()} to recover your Object.</li>
</ol>
<p>Android calls {@link android.app.Activity#onRetainNonConfigurationInstance()} between {@link
android.app.Activity#onStop()} and {@link
android.app.Activity#onDestroy()} when it shuts down your Activity due to a configuration
change. In your implementation of {@link
android.app.Activity#onRetainNonConfigurationInstance()}, you can return any {@link
java.lang.Object} that you need in order to efficiently restore your state after the configuration
change.</p>
<p>A scenario in which this can be valuable is if your application loads a lot of data from the
web. If the user changes the orientation of the device and the Activity restarts, your application
must re-fetch the data, which could be slow. What you can do instead is implement
{@link android.app.Activity#onRetainNonConfigurationInstance()} to return an object carrying your
data and then retrieve the data when your Activity starts again with {@link
android.app.Activity#getLastNonConfigurationInstance()}. For example:</p>
<pre>
&#64;Override
public Object onRetainNonConfigurationInstance() {
final MyDataObject data = collectMyLoadedData();
return data;
}
</pre>
<p class="caution"><strong>Caution:</strong> While you can return any object, you
should never pass an object that is tied to the {@link android.app.Activity}, such as a {@link
android.graphics.drawable.Drawable}, an {@link android.widget.Adapter}, a {@link android.view.View}
or any other object that's associated with a {@link android.content.Context}. If you do, it will
leak all the Views and resources of the original Activity instance. (To leak the resources
means that your application maintains a hold on them and they cannot be garbage-collected, so
lots of memory can be lost.)</p>
<p>Then retrieve the {@code data} when your Activity starts again:</p>
<pre>
&#64;Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
final MyDataObject data = (MyDataObject) getLastNonConfigurationInstance();
if (data == null) {
data = loadMyData();
}
...
}
</pre>
<p>In this case, {@link android.app.Activity#getLastNonConfigurationInstance()} retrieves
the data saved by {@link android.app.Activity#onRetainNonConfigurationInstance()}. If {@code data}
is null (which happens when the
Activity starts due to any reason other than a configuration change) then the data object is loaded
from the original source.</p>
<h2 id="HandlingTheChange">Handling the Configuration Change Yourself</h2>
<p>If your application doesn't need to update resources during a specific configuration
change <em>and</em> you have a performance limitation that requires you to
avoid the Activity restart, then you can declare that your Activity handles the configuration change
itself, which prevents the system from restarting your Activity.</p>
<p class="note"><strong>Note:</strong> Handling the configuration change yourself can make it much
more difficult to use alternative resources, because the system does not automatically apply them
for you. This technique should be considered a last resort and is not recommended for most
applications.</p>
<p>To declare that your Activity handles a configuration change, edit the appropriate <a
href="{@docRoot}guide/topics/manifest/activity-element.html">{@code &lt;activity&gt;}</a> element
in your manifest file to include the <a
href="{@docRoot}guide/topics/manifest/activity-element.html#config">{@code
android:configChanges}</a> attribute with a string value that represents the configuration that you
want to handle. Possible values are listed in the documentation for
the <a href="{@docRoot}guide/topics/manifest/activity-element.html#config">{@code
android:configChanges}</a> attribute (the most commonly used values are {@code orientation} to
handle when the screen orientation changes and {@code keyboardHidden} to handle when the
keyboard availability changes). You can declare multiple configuration values in the attribute
by separating them with a pipe character ("|").</p>
<p>For example, the following manifest snippet declares an Activity that handles both the
screen orientation change and keyboard availability change:</p>
<pre>
&lt;activity android:name=".MyActivity"
android:configChanges="orientation|keyboardHidden"
android:label="@string/app_name">
</pre>
<p>Now when one of these configurations change, {@code MyActivity} is not restarted.
Instead, the Activity receives a call to {@link
android.app.Activity#onConfigurationChanged(Configuration) onConfigurationChanged()}. This method
is passed a {@link android.content.res.Configuration} object that specifies
the new device configuration. By reading fields in the {@link android.content.res.Configuration},
you can determine the new configuration and make appropriate changes by updating
the resources used in your interface. At the
time this method is called, your Activity's {@link android.content.res.Resources} object is updated
to return resources based on the new configuration, so you can easily
reset elements of your UI without the system restarting your Activity.</p>
<p>For example, the following {@link
android.app.Activity#onConfigurationChanged(Configuration) onConfigurationChanged()} implementation
checks the availability of a hardware keyboard and the current device orientation:</p>
<pre>
&#64;Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
// Checks the orientation of the screen
if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
Toast.makeText(this, "landscape", Toast.LENGTH_SHORT).show();
} else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT){
Toast.makeText(this, "portrait", Toast.LENGTH_SHORT).show();
}
// Checks whether a hardware keyboard is available
if (newConfig.hardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_NO) {
Toast.makeText(this, "keyboard visible", Toast.LENGTH_SHORT).show();
} else if (newConfig.hardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_YES) {
Toast.makeText(this, "keyboard hidden", Toast.LENGTH_SHORT).show();
}
}
</pre>
<p>The {@link android.content.res.Configuration} object represents all of the current
configurations, not just the ones that have changed. Most of the time, you won't care exactly how
the configuration has changed and can simply re-assign all your resources that provide alternatives
to the configuration that you're handling. For example, because the {@link
android.content.res.Resources} object is now updated, you can reset
any {@link android.widget.ImageView}s with {@link android.widget.ImageView#setImageResource(int)}
and the appropriate resource for the new configuration is used (as described in <a
href="providing-resources.html#AlternateResources">Providing Resources</a>).</p>
<p>Notice that the values from the {@link
android.content.res.Configuration} fields are integers that are matched to specific constants
from the {@link android.content.res.Configuration} class. For documentation about which constants
to use with each field, refer to the appropriate field in the {@link
android.content.res.Configuration} reference.</p>
<p class="note"><strong>Remember:</strong> When you declare your Activity to handle a configuration
change, you are responsible for resetting any elements for which you provide alternatives. If you
declare your Activity to handle the orientation change and have images that should change
between landscape and portrait, you must re-assign each resource to each element during {@link
android.app.Activity#onConfigurationChanged(Configuration) onConfigurationChanged()}.</p>
<p>If you don't need to update your application based on these configuration
changes, you can instead <em>not</em> implement {@link
android.app.Activity#onConfigurationChanged(Configuration) onConfigurationChanged()}. In
which case, all of the resources used before the configuration change are still used
and you've only avoided the restart of your Activity. However, your application should always be
able to shutdown and restart with its previous state intact. Not only because
there are other configuration changes that you cannot prevent from restarting your application but
also in order to handle events such as when the user receives an incoming phone call and then
returns to your application.</p>
<p>For more about which configuration changes you can handle in your Activity, see the <a
href="{@docRoot}guide/topics/manifest/activity-element.html#config">{@code
android:configChanges}</a> documentation and the {@link android.content.res.Configuration}
class.</p>
@@ -0,0 +1,444 @@
page.title=String Resources
parent.title=Resource Types
parent.link=available-resources.html
@jd:body
<p>A string resource provides text strings for your application
with optional text styling and formatting. There are three types of resources that can provide
your application with strings:</p>
<dl>
<dt><a href="#String">String</a></dt>
<dd>XML resource that provides a single string.</dd>
<dt><a href="#StringArray">String Array</a></dt>
<dd>XML resource that provides an array of strings.</dd>
<dt><a href="#Plurals">Plurals</a></dt>
<dd>XML resource that carries different strings for different pluralizations
of the same word or phrase.</dd>
</dl>
<p>All strings are capable of applying some styling markup and formatting arguments. For
information about styling and formatting strings, see the section about <a
href="#FormattingAndStyling">Formatting and Styling</a>.</p>
<h2 id="String">String</h2>
<p>A single string that can be referenced from the application or from other resource files (such
as an XML layout).</p>
<p class="note"><strong>Note:</strong> A string is a simple resource that is referenced
using the value provided in the {@code name} attribute (not the name of the XML file). So, you can
combine string resources with other simple resources in the one XML file,
under one {@code &lt;resources>} element.</p>
<dl class="xml">
<dt>file location:</dt>
<dd><code>res/values/<em>filename</em>.xml</code><br/>
The filename is arbitrary. The {@code &lt;string>} element's {@code name} will be used as the
resource ID.</dd>
<dt>compiled resource datatype:</dt>
<dd>Resource pointer to a {@link java.lang.String}.</dd>
<dt>resource reference:</dt>
<dd>
In Java: <code>R.string.<em>string_name</em></code><br/>
In XML:<code>@string/<em>string_name</em></code>
</dd>
<dt>syntax:</dt>
<dd>
<pre class="stx">
&lt;?xml version="1.0" encoding="utf-8"?>
&lt;<a href="#string-resources-element">resources</a>>
&lt;<a href="#string-element">string</a>
name="<em>string_name</em>"
&gt;<em>text_string</em>&lt;/string&gt;
&lt;/resources>
</pre>
</dd>
<dt>elements:</dt>
<dd>
<dl class="tag-list">
<dt id="string-resources-element"><code>&lt;resources&gt;</code></dt>
<dd><strong>Required.</strong> This must be the root node.
<p>No attributes.</p>
</dd>
<dt id="string-element"><code>&lt;string&gt;</code></dt>
<dd>A string, which can include styling tags. Beware that you must escape apostrophes and
quotation marks. For more information about how to properly style and format your strings see <a
href="#FormattingAndStyling">Formatting and Styling</a>, below.
<p class="caps">attributes:</p>
<dl class="atn-list">
<dt><code>name</code></dt>
<dd><em>String</em>. A name for the string. This name will be used as the resource
ID.</dd>
</dl>
</dd>
</dl>
</dd> <!-- end elements and attributes -->
<dt>example:</dt>
<dd>XML file saved at <code>res/values/strings.xml</code>:
<pre>
&lt;?xml version="1.0" encoding="utf-8"?>
&lt;resources>
&lt;string name="hello">Hello!&lt;/string>
&lt;/resources>
</pre>
<p>This layout XML applies a string to a View:</p>
<pre>
&lt;TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
<strong>android:text="@string/hello"</strong> />
</pre>
<p>This application code retrieves a string:</p>
<pre>
String string = {@link android.content.Context#getString(int) getString}(R.string.hello);
</pre>
<p>You can use either {@link android.content.Context#getString(int)} or
{@link android.content.Context#getText(int)} to retieve a string. {@link
android.content.Context#getText(int)} will retain any rich text styling applied to the string.</p>
</dd> <!-- end example -->
</dl>
<h2 id="StringArray">String Array</h2>
<p>An array of strings that can be referenced from the application.</p>
<p class="note"><strong>Note:</strong> A string array is a simple resource that is referenced
using the value provided in the {@code name} attribute (not the name of the XML file). As
such, you can combine string array resources with other simple resources in the one XML file,
under one {@code &lt;resources>} element.</p>
<dl class="xml">
<dt>file location:</dt>
<dd><code>res/values/<em>filename</em>.xml</code><br/>
The filename is arbitrary. The {@code &lt;string-array>} element's {@code name} will be used as the
resource ID.</dd>
<dt>compiled resource datatype:</dt>
<dd>Resource pointer to an array of {@link java.lang.String}s.</dd>
<dt>resource reference:</dt>
<dd>
In Java: <code>R.array.<em>string_array_name</em></code>
</dd>
<dt>syntax:</dt>
<dd>
<pre class="stx">
&lt;?xml version="1.0" encoding="utf-8"?>
&lt;<a href="#string-array-resources-element">resources</a>>
&lt;<a href="#string-array-element">string-array</a>
name="<em>string_array_name</em>">
&lt;<a href="#string-array-item-element">item</a>
&gt;<em>text_string</em>&lt;/item&gt;
&lt;/string-array>
&lt;/resources>
</pre>
</dd>
<dt>elements:</dt>
<dd>
<dl class="tag-list">
<dt id="string-array-resources-element"><code>&lt;resources&gt;</code></dt>
<dd><strong>Required.</strong> This must be the root node.
<p>No attributes.</p>
</dd>
<dt id="string-array-element"><code>&lt;string-array&gt;</code></dt>
<dd>Defines an array of strings. Contains one or more {@code &lt;item>} elements.
<p class="caps">attributes:</p>
<dl class="atn-list">
<dt><code>name</code></dt>
<dd><em>String</em>. A name for the array. This name will be used as the resource
ID to reference the array.</dd>
</dl>
</dd>
<dt id="string-array-item-element"><code>&lt;item&gt;</code></dt>
<dd>A string, which can include styling tags. The value can be a referenced to another
string resource. Must be a child of a {@code &lt;string-array&gt;} element. Beware that you
must escape apostrophes and
quotation marks. See <a href="#FormattingAndStyling">Formatting and Styling</a>, below, for
information about to properly style and format your strings.
<p>No attributes.</p>
</dd>
</dl>
</dd> <!-- end elements -->
<dt>example:</dt>
<dd>XML file saved at <code>res/values/strings.xml</code>:
<pre>
&lt;?xml version="1.0" encoding="utf-8"?>
&lt;resources>
&lt;string-array name="planets_array">
&lt;item>Mercury&lt;/item>
&lt;item>Venus&lt;/item>
&lt;item>Earth&lt;/item>
&lt;item>Mars&lt;/item>
&lt;/string-array>
&lt;/resources>
</pre>
<p>This application code retrieves a string array:</p>
<pre>
Resources res = {@link android.content.Context#getResources()};
String[] planets = res.{@link android.content.res.Resources#getStringArray(int)
getStringArray}(R.array.planets_array);
</pre>
</dd> <!-- end example -->
</dl>
<h2 id="Plurals">Plurals</h2>
<p>A pair of strings that each provide a different plural form of the same word or phrase,
which you can collectively reference from the application. When you request the plurals
resource using a method such as {@link android.content.res.Resources#getQuantityString(int,int)
getQuantityString()}, you must pass a "count", which will determine the plural form you
require and return that string to you.</p>
<p class="note"><strong>Note:</strong> A plurals collection is a simple resource that is
referenced using the value provided in the {@code name} attribute (not the name of the XML
file). As such, you can combine plurals resources with other simple resources in the one
XML file, under one {@code &lt;resources>} element.</p>
<dl class="xml">
<dt>file location:</dt>
<dd><code>res/values/<em>filename</em>.xml</code><br/>
The filename is arbitrary. The {@code &lt;plurals>} element's {@code name} will be used as the
resource ID.</dd>
<dt>resource reference:</dt>
<dd>
In Java: <code>R.plurals.<em>plural_name</em></code>
</dd>
<dt>syntax:</dt>
<dd>
<pre class="stx">
&lt;?xml version="1.0" encoding="utf-8"?>
&lt;<a href="#plurals-resources-element">resources</a>>
&lt;<a href="#plurals-element">plurals</a>
name="<em>plural_name</em>">
&lt;<a href="#plurals-item-element">item</a>
quantity=["one" | "other"]
&gt;<em>text_string</em>&lt;/item>
&lt;/plurals>
&lt;/resources>
</pre>
</dd>
<dt>elements:</dt>
<dd>
<dl class="tag-list">
<dt id="plurals-resources-element"><code>&lt;resources&gt;</code></dt>
<dd><strong>Required.</strong> This must be the root node.
<p>No attributes.</p>
</dd>
<dt id="plurals-element"><code>&lt;plurals&gt;</code></dt>
<dd>A collection of strings, of which, one string is provided depending on the amount of
something. Contains one or more {@code &lt;item>} elements.
<p class="caps">attributes:</p>
<dl class="atn-list">
<dt><code>name</code></dt>
<dd><em>String</em>. A name for the pair of strings. This name will be used as the
resource ID.</dd>
</dl>
</dd>
<dt id="plurals-item-element"><code>&lt;item&gt;</code></dt>
<dd>A plural or singular string. The value can be a referenced to another
string resource. Must be a child of a {@code &lt;plurals&gt;} element. Beware that you must
escape apostrophes and quotation marks. See <a href="#FormattingAndStyling">Formatting and
Styling</a>, below, for information about to properly style and format your strings.
<p class="caps">attributes:</p>
<dl class="atn-list">
<dt><code>quantity</code></dt>
<dd><em>Keyword</em>. A value indicating the case in which this string should be used. Valid
values:
<table>
<tr><th>Value</th><th>Description</th></tr>
<tr>
<td>{@code one}</td><td>When there is one (a singular string).</td>
</tr>
<tr>
<td>{@code other}</td><td>When the quantity is anything other than one (a plural
string, but also used when the count is zero).</td>
</tr>
</table>
</dd>
</dl>
</dd>
</dl>
</dd> <!-- end elements -->
<dt>example:</dt>
<dd>XML file saved at {@code res/values/strings.xml}:</p>
<pre>
&lt;?xml version="1.0" encoding="utf-8"?>
&lt;resources>
&lt;plurals name="numberOfSongsAvailable">
&lt;item quantity="one">One song found.&lt;/item>
&lt;item quantity="other">%d songs found.&lt;/item>
&lt;/plurals>
&lt;/resources>
</pre>
<p>Java code:</p>
<pre>
int count = getNumberOfsongsAvailable();
Resources res = {@link android.content.Context#getResources()};
String songsFound = res.{@link android.content.res.Resources#getQuantityString(int,int)
getQuantityString}(R.plurals.numberOfSongsAvailable, count);
</pre>
</dd> <!-- end example -->
</dl>
<h2 id="FormattingAndStyling">Formatting and Styling</h2>
<p>Here are a few important things you should know about how to properly
format and style your string resources.</p>
<h3>Escaping apostrophes and quotes</h3>
<p>If you have an apostrophe or a quote in your string, you must either escape it or enclose the
whole string in the other type of enclosing quotes. For example, here are some stings that
do and don't work:</p>
<pre>
&lt;string name="good_example">"This'll work"&lt;/string>
&lt;string name="good_example_2">This\'ll also work&lt;/string>
&lt;string name="bad_example">This doesn't work&lt;/string>
&lt;string name="bad_example_2">XML encodings don&amp;apos;t work&lt;/string>
</pre>
<h3>Formatting strings</h3>
<p>If you need to format your strings using <a
href="{@docRoot}reference/java/lang/String.html#format(java.lang.String,
java.lang.Object...)">{@code String.format(String, Object...)}</a>,
then you can do so by putting
your format arguments in the string resource. For example, with the following resource:</p>
<pre>
&lt;string name="welcome_messages">Hello, %1$s! You have %2$d new messages.&lt;/string>
</pre>
<p>In this example, the format string has two arguments: {@code %1$s} is a string and {@code %2$d}
is a decimal number. You can format the string with arguements from your application like this:</p>
<pre>
Resources res = {@link android.content.Context#getResources()};
String text = String.<a href="{@docRoot}reference/java/lang/String.html#format(java.lang.String,
java.lang.Object...)">format</a>(res.getString(R.string.welcome_messages), username, mailCount);
</pre>
<h3>Styling with HTML markup</h3>
<p>You can add styling to your strings with HTML markup. For example:</p>
<pre>
&lt;?xml version="1.0" encoding="utf-8"?>
&lt;resources>
&lt;string name="welcome">Welcome to &lt;b>Android&lt;/b>!&lt;/string>
&lt;/resources>
</pre>
<p>Supported HTML elements include:</p>
<ul>
<li>{@code &lt;b>} for <b>bold</b> text.</li>
<li>{@code &lt;i>} for <i>italic</i> text.</li>
<li>{@code &lt;u>} for <u>underline</u> text.</li>
</ul>
<p>Sometimes you may want to create a styled text resource that is also used as a format
string. Normally, this won't work because the <a
href="{@docRoot}reference/java/lang/String.html#format(java.lang.String,
java.lang.Object...)">{@code String.format(String, Object...)}</a>
method will strip all the style
information from the string. The work-around to this is to write the HTML tags with escaped
entities, which are then recovered with {@link android.text.Html#fromHtml(String)},
after the formatting takes place. For example:</p>
<ol>
<li>Store your styled text resource as an HTML-escaped string:
<pre>
&lt;resources&gt;
&lt;string name="welcome_messages"&gt;Hello, %1$s! You have &amp;lt;b>%2$d new messages&amp;lt;/b>.&lt;/string>
&lt;/resources&gt;
</pre>
<p>In this formatted string, a {@code &lt;b>} element is added. Notice that the opening bracket is
HTML-escaped, using the {@code &amp;lt;} notation.</p>
</li>
<li>Then format the string as usual, but also call {@link android.text.Html#fromHtml} to
convert the HTML text into styled text:
<pre>
Resources res = {@link android.content.Context#getResources()};
String text = String.<a
href="{@docRoot}reference/java/lang/String.html#format(java.lang.String,
java.lang.Object...)">format</a>(res.getString(R.string.welcome_messages), username, mailCount);
CharSequence styledText = Html.fromHtml(text);
</pre>
</li>
</ol>
<p>Because the {@link android.text.Html#fromHtml} method will format all HTML entities, be sure to
escape any possible HTML characters in the strings you use with the formatted text, using
{@link android.text.TextUtils#htmlEncode}. For instance, if you'll be passing a string argument to
<a href="{@docRoot}reference/java/lang/String.html#format(java.lang.String,
java.lang.Object...)">{@code String.format()}</a> that may contain characters such as
"&lt;" or "&amp;", then they must be escaped before formatting, so that when the formatted string
is passed through {@link android.text.Html#fromHtml}, the characters come out the way they were
originally written. For example:</p>
<pre>
String escapedUsername = TextUtil.{@link android.text.TextUtils#htmlEncode htmlEncode}(username);
Resources res = {@link android.content.Context#getResources()};
String text = String.<a href="{@docRoot}reference/java/lang/String.html#format(java.lang.String,
java.lang.Object...)">format</a>(res.getString(R.string.welcome_messages), escapedUsername, mailCount);
CharSequence styledText = Html.fromHtml(text);
</pre>
@@ -0,0 +1,128 @@
page.title=Style Resource
parent.title=Resource Types
parent.link=available-resources.html
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>See also</h2>
<ol>
<li><a href="{@docRoot}guide/topics/ui/themes.html">Applying Styles and Themes</a></li>
</ol>
</div>
</div>
<p>A style resource defines the format and look for a UI.
A style can be applied to an individual {@link android.view.View} (from within a layout file) or to
an entire {@link android.app.Activity} or application (from within the manifest file).</p>
<p>For more information about creating and applying styles, please read
<a href="{@docRoot}guide/topics/ui/themes.html">Applying Styles and Themes</a>.</p>
<p class="note"><strong>Note:</strong> A style is a simple resource that is referenced
using the value provided in the {@code name} attribute (not the name of the XML file). As
such, you can combine style resources with other simple resources in the one XML file,
under one {@code &lt;resources>} element.</p>
<dl class="xml">
<dt>file location:</dt>
<dd><code>res/values/<em>filename</em>.xml</code><br/>
The filename is arbitrary. The element's {@code name} will be used as the resource ID.</dd>
<dt>resource reference:</dt>
<dd>
In XML: <code>@[package:]style/<em>style_name</em></code>
</dd>
<dt>syntax:</dt>
<dd>
<pre class="stx">
&lt;?xml version="1.0" encoding="utf-8"?>
&lt;<a href="#resources-element">resources</a>>
&lt;<a href="#style-element">style</a>
name="<em>style_name</em>"
parent="@[package:]style/<em>style_to_inherit</em>">
&lt;<a href="#item-element">item</a>
name="<em>[package:]style_property_name</em>"
&gt;<em>style_value</em>&lt;/item>
&lt;/style>
&lt;/resources>
</pre>
</dd>
<dt>elements:</dt>
<dd>
<dl class="tag-list">
<dt id="resources-element"><code>&lt;resources&gt;</code></dt>
<dd><strong>Required.</strong> This must be the root node.
<p>No attributes.</p>
</dd>
<dt id="style-element"><code>&lt;style&gt;</code></dt>
<dd>Defines a single style. Contains {@code &lt;item&gt;} elements.
<p class="caps">attributes:</p>
<dl class="atn-list">
<dt><code>name</code></dt>
<dd><em>String</em>. <strong>Required</strong>. A name for the style, which is used as the
resource ID to apply the style to a View, Activity, or application.
</dd>
<dt><code>parent</code></dt>
<dd><em>Style resource</em>. Reference to a style from which this
style should inherit style properties.
</dd>
</dl>
</dd>
<dt id="item-element"><code>&lt;item&gt;</code></dt>
<dd>Defines a single property for the style. Must be a child of a
<code>&lt;style&gt;</code> element.</p>
<p class="caps">attributes:</p>
<dl class="atn-list">
<dt><code>name</code></dt>
<dd><em>Attribute resource</em>. <strong>Required</strong>. The name of the style property
to be defined, with a package prefix if necessary (for example {@code android:textColor}).
</dd>
</dl>
</dd>
</dl>
</dd> <!-- end elements and attributes -->
<dt>example:</dt>
<dd>
<dl>
<dt>XML file for the style (saved in <code>res/values/</code>):</dt>
<dd>
<pre>
&lt;?xml version="1.0" encoding="utf-8"?>
&lt;resources>
&lt;style name="CustomText" parent="@style/Text">
&lt;item name="android:textSize">20sp&lt;/item>
&lt;item name="android:textColor">#008&lt;/item>
&lt;/style>
&lt;/resources>
</pre>
</dd>
<dt>XML file that applies the style to a {@link android.widget.TextView}
(saved in <code>res/layout/</code>):</dt>
<dd>
<pre>
&lt;?xml version="1.0" encoding="utf-8"?>
&lt;EditText
style="@style/CustomText"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Hello, World!" />
</pre>
</dd>
</dl>
</dd> <!-- end example -->
</dl>
@@ -0,0 +1,748 @@
page.title=Adding Custom Suggestions
parent.title=Search
parent.link=index.html
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>In this document</h2>
<ol>
<li><a href="#TheBasics">The Basics</a></li>
<li><a href="#CustomSearchableConfiguration">Modifying the Searchable Configuration</a></li>
<li><a href="#CustomContentProvider">Creating a Content Provider</a>
<ol>
<li><a href="#HandlingSuggestionQuery">Handling a suggestion query</a></li>
<li><a href="#SuggestionTable">Building a suggestion table</a></li>
</ol>
</li>
<li><a href="#IntentForSuggestions">Declaring an Intent for Suggestions</a>
<ol>
<li><a href="#IntentAction">Declaring the Intent action</a></li>
<li><a href="#IntentData">Declaring the Intent data</a></li>
</ol>
</li>
<li><a href="#HandlingIntent">Handling the Intent</a></li>
<li><a href="#RewritingQueryText">Rewriting the Query Text</a></li>
<li><a href="#QSB">Exposing Search Suggestions to Quick Search Box</a></li>
</ol>
<h2>Key classes</h2>
<ol>
<li>{@link android.app.SearchManager}</li>
<li>{@link android.content.SearchRecentSuggestionsProvider}</li>
<li>{@link android.content.ContentProvider}</li>
</ol>
<h2>Related samples</h2>
<ol>
<li><a href="{@docRoot}resources/samples/SearchableDictionary/index.html">Searchable
Dictionary</a></li>
</ol>
<h2>See also</h2>
<ol>
<li><a href="searchable-config.html">Searchable Configuration</a></li>
<li><a href="{@docRoot}guide/topics/providers/content-providers.html">Content Providers</a></li>
</ol>
</div>
</div>
<p>When using the Android search dialog, you can provide custom search suggestions that are
created from data in your application. For example, if your application is a word
dictionary, you can suggest words from the
dictionary that match the text entered so far. These are the most valuable suggestions, because you
can effectively predict what the user wants and provide instant access to it. Figure 1 shows
an example of a search dialog with custom suggestions.</p>
<p>Once you provide custom suggestions, you can also make them available to the system-wide Quick
Search Box, providing access to your content from outside your application.</p>
<p>Before you begin with this guide to add custom suggestions, you need to have implemented the
Android search dialog for searches in your
application. If you haven't, see <a href="search-dialog.html">Using the Android Search
Dialog</a>.</p>
<h2 id="TheBasics">The Basics</h2>
<div class="figure" style="width:250px">
<img src="{@docRoot}images/search/search-suggest-custom.png" alt="" height="417" />
<p class="img-caption"><strong>Figure 1.</strong> Screenshot of a search dialog with custom
search suggestions.</p>
</div>
<p>When the user selects a custom suggestion, the Search Manager sends an {@link
android.content.Intent} to
your searchable Activity. Whereas a normal search query sends an Intent with the {@link
android.content.Intent#ACTION_SEARCH} action, you can instead define your custom suggestions to use
{@link android.content.Intent#ACTION_VIEW} (or any other Intent action), and also include data
that's relevant to the selected suggestion. Continuing
the dictionary example, when the user selects a suggestion, your application can immediately
open the definition for that word, instead of searching the dictionary for matches.</p>
<p>To provide custom suggestions, do the following:</p>
<ul>
<li>Implement a basic searchable Activity, as described in <a
href="search-dialog.html">Using the Android Search Dialog</a>.</li>
<li>Modify the searchable configuration with information about the content provider that
provides custom suggestions.</li>
<li>Build a table (such as in an {@link android.database.sqlite.SQLiteDatabase}) for your
suggestions and format the table with required columns.</li>
<li>Create a <a href="{@docRoot}guide/topics/providers/content-providers.html">Content
Provider</a> that has access to your suggestions table and declare the provider
in your manifest.</li>
<li>Declare the type of {@link android.content.Intent} to be sent when the user selects a
suggestion (including a custom action and custom data). </li>
</ul>
<p>Just like the Search Manager displays the search dialog, it also displays your search
suggestions. All you need is a content provider from which the Search Manager can retrieve your
suggestions. If you're not familiar with creating content
providers, read the <a href="{@docRoot}guide/topics/providers/content-providers.html">Content
Providers</a> developer guide before you continue.</p>
<p>When the Search Manager identifies that your Activity is searchable and provides search
suggestions, the following procedure takes place as soon as the user enters text into the
search dialog:</p>
<ol>
<li>Search Manager takes the search query text (whatever has been typed so far) and performs a
query to your content provider that manages your suggestions.</li>
<li>Your content provider returns a {@link android.database.Cursor} that points to all
suggestions that are relevant to the search query text.</li>
<li>Search Manager displays the list of suggestions provided by the Cursor.</li>
</ol>
<p>Once the custom suggestions are displayed, the following might happen:</p>
<ul>
<li>If the user types another key, or changes the query in any way, the above steps are repeated
and the suggestion list is updated as appropriate. </li>
<li>If the user executes the search, the suggestions are ignored and the search is delivered
to your searchable Activity using the normal {@link android.content.Intent#ACTION_SEARCH}
Intent.</li>
<li>If the user selects a suggestion, an Intent is sent to your searchable Activity, carrying a
custom action and custom data so that your application can open the suggested content.</li>
</ul>
<h2 id="CustomSearchableConfiguration">Modifying the searchable configuration</h2>
<p>To add support for custom suggestions, add the {@code android:searchSuggestAuthority} attribute
to the {@code &lt;searchable&gt;} element in your searchable configuration file. For example:</p>
<pre>
&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;searchable xmlns:android="http://schemas.android.com/apk/res/android"
android:label="@string/app_label"
android:hint="@string/search_hint"
<b>android:searchSuggestAuthority="com.example.MyCustomSuggestionProvider"</b>&gt;
&lt;/searchable&gt;
</pre>
<p>You might need some additional attributes, depending on the type of Intent you attach
to each suggestion and how you want to format queries to your content provider. The other optional
attributes are discussed in the following sections.</p>
<h2 id="CustomContentProvider">Creating a Content Provider</h2>
<p>Creating a content provider for custom suggestions requires previous knowledge about content
providers that's covered in the <a
href="{@docRoot}guide/topics/providers/content-providers.html">Content Provider</a> developer
guide. For the most part, a content provider for custom suggestions is the
same as any other content provider. However, for each suggestion you provide, the respective row in
the {@link android.database.Cursor} must include specific columns that the Search Manager
understands and uses to format the suggestions.</p>
<p>When the user starts typing into the search dialog, the Search Manager queries your content
provider for suggestions by calling {@link
android.content.ContentProvider#query(Uri,String[],String,String[],String) query()} each time
a letter is typed. In your implementation of {@link
android.content.ContentProvider#query(Uri,String[],String,String[],String) query()}, your
content provider must search your suggestion data and return a {@link
android.database.Cursor} that points to the rows you have determined to be good suggestions.</p>
<p>Details about creating a content provider for custom suggestions are discussed in the following
two sections:</p>
<dl>
<dt><a href="#HandlingSuggestionQuery">Handling the suggestion query</a></dt>
<dd>How the Search Manager sends requests to your content provider and how to handle them</dd>
<dt><a href="#SuggestionTable">Building a suggestion table</a></dt>
<dd>How to define the columns that the Search Manager expects in the {@link
android.database.Cursor} returned with each query</dd>
</dl>
<h3 id="HandlingSuggestionQuery">Handling the suggestion query</h3>
<p>When the Search Manager requests suggestions from your content provider, it calls your content
provider's {@link android.content.ContentProvider#query(Uri,String[],String,String[],String)
query()} method. You must
implement this method to search your suggestion data and return a
{@link android.database.Cursor} pointing to the suggestions you deem relevant.</p>
<p>Here's a summary of the parameters that the Search Manager passes to your {@link
android.content.ContentProvider#query(Uri,String[],String,String[],String) query()} method
(listed in order):</p>
<dl>
<dt><code>uri</code></dt>
<dd>Always a content {@link android.net.Uri}, formatted as:
<pre class="no-pretty-print">
content://<em>your.authority</em>/<em>optional.suggest.path</em>/<em>{@link
android.app.SearchManager#SUGGEST_URI_PATH_QUERY}</em>
</pre>
<p>The default behavior is for Search Manager to pass this URI and append it with the query text.
For example:</p>
<pre class="no-pretty-print">
content://<em>your.authority</em>/<em>optional.suggest.path</em>/<em>{@link
android.app.SearchManager#SUGGEST_URI_PATH_QUERY}</em>/puppies
</pre>
<p>The query text on the end is encoded using URI encoding rules, so you might need to decode
it before performing a search.</p>
<p>The <em>{@code optional.suggest.path}</em> portion is only included in the URI if you have set
such a path in your searchable configuration file with the {@code android:searchSuggestPath}
attribute. This is only needed if you use the same content provider for multiple searchable
activities, in which case, you need to disambiguate the source of the suggestion query.</p>
<p class="note"><strong>Note:</strong> {@link
android.app.SearchManager#SUGGEST_URI_PATH_QUERY} is not the literal
string provided in the URI, but a constant that you should use if you need to refer to this
path.</p>
</dd>
<dt><code>projection</code></dt>
<dd>Always null</dd>
<dt><code>selection</code></dt>
<dd>The value provided in the {@code android:searchSuggestSelection} attribute of
your searchable configuration file, or null if you have not declared the {@code
android:searchSuggestSelection} attribute. More about using this to <a href="#GetTheQuery">get the
query</a> below.</dd>
<dt><code>selectionArgs</code></dt>
<dd>Contains the search query as the first (and only) element of the array if you have
declared the {@code android:searchSuggestSelection} attribute in your searchable configuration. If
you have not declared {@code android:searchSuggestSelection}, then this parameter is null. More
about using this to <a href="#GetTheQuery">get the query</a> below.</dd>
<dt><code>sortOrder</code></dt>
<dd>Always null</dd>
</dl>
<p>The Search Manager can send you the search query text in two ways. The
default manner is for the query text to be included as the last path of the content
URI passed in the {@code uri} parameter. However, if you include a selection value in your
searchable configuration's {@code
android:searchSuggestSelection} attribute, then the query text is instead passed as the first
element of the {@code selectionArgs} string array. Both options are summarized next.</p>
<h4 id="GetTheQueryUri">Get the query in the Uri</h4>
<p>By default, the query is appended as the last segment of the {@code uri}
parameter (a {@link android.net.Uri} object). To retrieve the query text in this case, simply use
{@link android.net.Uri#getLastPathSegment()}. For example:</p>
<pre>
String query = uri.getLastPathSegment().toLowerCase();
</pre>
<p>This returns the last segment of the {@link android.net.Uri}, which is the query text entered in
the search dialog.</p>
<h4 id="GetTheQuery">Get the query in the selection arguments</h4>
<p>Instead of using the URI, you might decide it makes more sense for your {@link
android.content.ContentProvider#query(Uri,String[],String,String[],String) query()} method to
receive everything it needs to perform the look-up and you want the
{@code selection} and {@code selectionArgs} parameters to carry the appropriate values. In such a
case, add the {@code android:searchSuggestSelection} attribute to your searchable configuration with
your SQLite selection string. In the selection string, include a question mark ("?") as
a placeholder for the actual search query. The Search Manager calls {@link
android.content.ContentProvider#query(Uri,String[],String,String[],String) query()} with the
selection string as the {@code selection} parameter and the search query as the first
element in the {@code selectionArgs} array.</p>
<p>For example, here's how you might form the {@code android:searchSuggestSelection} attribute to
create a full-text search statement:</p>
<pre>
&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;searchable xmlns:android="http://schemas.android.com/apk/res/android"
android:label="@string/app_label"
android:hint="@string/search_hint"
android:searchSuggestAuthority="com.example.MyCustomSuggestionProvider"
android:searchSuggestIntentAction="android.Intent.action.VIEW"
<b>android:searchSuggestSelection="word MATCH ?"</b>&gt;
&lt;/searchable&gt;
</pre>
<p>With this configuration, your {@link
android.content.ContentProvider#query(Uri,String[],String,String[],String) query()} method
delivers the {@code selection} parameter as "word MATCH ?" and the {@code selectionArgs}
parameter as whatever the user entered in the search dialog. When you pass these to an SQLite
{@link android.database.sqlite.SQLiteDatabase#query(String,String[],String,String[],String,String,
String) query()} method, as their respective arguments, they are synthesized together (the
question mark is replaced with the query
text). If you chose to receive suggestion queries this way and need to add wildcards to
the query text, append (and/or prefix) them to the {@code selectionArgs}
parameter, because this value is wrapped in quotes and inserted in place of the
question mark.</p>
<p>Another new attribute in the example above is {@code android:searchSuggestIntentAction}, which
defines the Intent action sent with each Intent when the user selects a suggestion. It is
discussed further in the section about <a href="#IntentForSuggestions">Declaring an Intent for
suggestions</a>.</p>
<p class="note"><strong>Tip:</strong> If you don't want to define a selection clause in
the {@code android:searchSuggestSelection} attribute, but would still like to receive the query
text in the {@code selectionArgs} parameter, simply provide a non-null value for the {@code
android:searchSuggestSelection} attribute. This triggers the query to be passed in {@code
selectionArgs} and you can ignore the {@code selection} parameter. In this way, you can instead
define the actual selection clause at a lower level so that your content provider doesn't have to
handle it.</p>
<h3 id="SuggestionTable">Building a suggestion table</h3>
<div class="sidebox-wrapper">
<div class="sidebox">
<h2>Creating a Cursor without a table</h2>
<p>If your search suggestions are not stored in a table format (such as an SQLite table) using the
columns required by the
Search Manager, then you can search your suggestion data for matches and then format them
into the necessary table on each request. To do so, create a {@link android.database.MatrixCursor}
using the required column names and then add a row for each suggestion using {@link
android.database.MatrixCursor#addRow(Object[])}. Return the final product from your Content
Provider's {@link
android.content.ContentProvider#query(Uri,String[],String,String[],String) query()} method.</p>
</div>
</div>
<p>When you return suggestions to the Search Manager with a {@link android.database.Cursor}, the
Search Manager expects specific columns in each row. So, regardless of whether you
decide to store
your suggestion data in an SQLite database on the device, a database on a web server, or another
format on the device or web, you must format the suggestions as rows in a table and
present them with a {@link android.database.Cursor}. The Search
Manager understands several columns, but only two are required:</p>
<dl>
<dt>{@link android.provider.BaseColumns#_ID}</dt>
<dd>A unique integer row ID for each suggestion. The search dialog requires this in order
to present suggestions in a ListView.</dd>
<dt>{@link android.app.SearchManager#SUGGEST_COLUMN_TEXT_1}</dt>
<dd>The string that is presented as a suggestion.</dd>
</dl>
<p>The following columns are all optional (and most are discussed further in the following
sections):</p>
<dl>
<dt>{@link android.app.SearchManager#SUGGEST_COLUMN_TEXT_2}</dt>
<dd>A string. If your Cursor includes this column, then all suggestions are provided in a
two-line format. The string in this column is displayed as a second, smaller line of text below the
primary suggestion text. It can be null or empty to indicate no secondary text.</dd>
<dt>{@link android.app.SearchManager#SUGGEST_COLUMN_ICON_1}</dt>
<dd>A drawable resource, content, or file URI string. If your Cursor includes this column, then
all suggestions are provided in an icon-plus-text format with the drawable icon on the left side.
This can be null or zero to indicate no icon in this row.</dd>
<dt>{@link android.app.SearchManager#SUGGEST_COLUMN_ICON_2}</dt>
<dd>A drawable resource, content, or file URI string. If your Cursor includes this column, then
all suggestions are provided in an icon-plus-text format with the icon on the right side. This can
be null or zero to indicate no icon in this row.</dd>
<dt>{@link android.app.SearchManager#SUGGEST_COLUMN_INTENT_ACTION}</dt>
<dd>An Intent action string. If this column exists and contains a value at the given row, the
action defined here is used when forming the suggestion's Intent. If the element is not
provided, the action is taken from the {@code android:searchSuggestIntentAction} field in your
searchable configuration. If your action is the same for all
suggestions, it is more efficient to specify the action using {@code
android:searchSuggestIntentAction} and omit this column.</dd>
<dt>{@link android.app.SearchManager#SUGGEST_COLUMN_INTENT_DATA}</dt>
<dd>A data URI string. If this column exists and contains a value at the given row, this is the
data that is used when forming the suggestion's Intent. If the element is not provided, the data is
taken from the {@code android:searchSuggestIntentData} field in your searchable configuration. If
neither source is provided,
the Intent's data field is null. If your data is the same for all suggestions, or can be
described using a constant part and a specific ID, it is more efficient to specify it using {@code
android:searchSuggestIntentData} and omit this column.
</dd>
<dt>{@link android.app.SearchManager#SUGGEST_COLUMN_INTENT_DATA_ID}</dt>
<dd>A URI path string. If this column exists and contains a value at the given row, then "/" and
this value is appended to the data field in the Intent. This should only be used if the data field
specified
by the {@code android:searchSuggestIntentData} attribute in the searchable configuration has already
been set to an appropriate base string.</dd>
<dt>{@link android.app.SearchManager#SUGGEST_COLUMN_INTENT_EXTRA_DATA}</dt>
<dd>Arbitrary data. If this column exists and contains a value at a given row, this is the
<em>extra</em> data used when forming the suggestion's Intent. If not provided, the
Intent's extra data field is null. This column allows suggestions to provide additional data that is
included as an extra in the Intent's {@link android.app.SearchManager#EXTRA_DATA_KEY} key.</dd>
<dt>{@link android.app.SearchManager#SUGGEST_COLUMN_QUERY}</dt>
<dd>If this column exists and this element exists at the given row, this is the data that is
used when forming the suggestion's query, included as an extra in the Intent's {@link
android.app.SearchManager#QUERY} key. Required if suggestion's action is {@link
android.content.Intent#ACTION_SEARCH}, optional otherwise.</dd>
<dt>{@link android.app.SearchManager#SUGGEST_COLUMN_SHORTCUT_ID}</dt>
<dd>Only used when providing suggestions for Quick Search Box. This column indicates
whether a search suggestion should be stored as a
shortcut and whether it should be validated. Shortcuts are usually formed when the user clicks a
suggestion from Quick Search Box. If missing, the result is stored as a shortcut and never
refreshed. If set to {@link android.app.SearchManager#SUGGEST_NEVER_MAKE_SHORTCUT}, the result is
not stored as a shortcut.
Otherwise, the shortcut ID is used to check back for an up to date suggestion using
{@link android.app.SearchManager#SUGGEST_URI_PATH_SHORTCUT}.</dd>
<dt>{@link android.app.SearchManager#SUGGEST_COLUMN_SPINNER_WHILE_REFRESHING}</dt>
<dd>Only used when providing suggestions for Quick Search Box. This column specifies that
a spinner should be shown instead of an icon from {@link
android.app.SearchManager#SUGGEST_COLUMN_ICON_2}
while the shortcut of this suggestion is being refreshed in Quick Search Box.</dd>
</dl>
<p>Some of these columns are discussed more in the following sections.</p>
<h2 id="IntentForSuggestions">Declaring an Intent for suggestions</h2>
<p>When the user selects a suggestion from the list that appears below the search dialog, the Search
Manager sends a custom {@link android.content.Intent} to your searchable Activity. You must define
the action and data for the Intent.</p>
<h3 id="IntentAction">Declaring the Intent action</h3>
<p>The most common Intent action for a custom suggestion is {@link
android.content.Intent#ACTION_VIEW}, which is appropriate when
you want to open something, like the definition for a word, a person's contact information, or a web
page. However, the Intent action can be any other action and can even be different for each
suggestion.</p>
<p>Depending on whether you want all suggestions to use the same Intent action, you
can define the action in two ways:</p>
<ol type="a">
<li>Use the {@code android:searchSuggestIntentAction} attribute of your searchable configuration
file to define the action for all suggestions. <p>For example:</p>
<pre>
&lt;?xml version="1.0" encoding="utf-8"?>
&lt;searchable xmlns:android="http://schemas.android.com/apk/res/android"
android:label="@string/app_label"
android:hint="@string/search_hint"
android:searchSuggestAuthority="com.example.MyCustomSuggestionProvider"
<b>android:searchSuggestIntentAction="android.Intent.action.VIEW"</b> >
&lt;/searchable>
</pre>
</li>
<li>Use the {@link android.app.SearchManager#SUGGEST_COLUMN_INTENT_ACTION} column to define the
action for individual suggestions.
<p>Add the {@link android.app.SearchManager#SUGGEST_COLUMN_INTENT_ACTION} column to
your suggestions table and, for each suggestion, place in it the action to use (such as
{@code "android.Intent.action.VIEW"}).</p>
</li>
</ol>
<p>You can also combine these two techniques. For instance, you can include the {@code
android:searchSuggestIntentAction} attribute with an action to be used with all suggestions by
default, then override this action for some suggestions by declaring a different action in the
{@link android.app.SearchManager#SUGGEST_COLUMN_INTENT_ACTION} column. If you do not include
a value in the {@link android.app.SearchManager#SUGGEST_COLUMN_INTENT_ACTION} column, then the
Intent provided in the {@code android:searchSuggestIntentAction} attribute is used.</p>
<p class="note"><strong>Note</strong>: If you do not include the
{@code android:searchSuggestIntentAction} attribute in your searchable configuration, then you
<em>must</em> include a value in the {@link android.app.SearchManager#SUGGEST_COLUMN_INTENT_ACTION}
column for every suggestion, or the Intent will fail.</p>
<h3 id="IntentData">Declaring Intent data</h3>
<p>When the user selects a suggestion, your searchable Activity receives the Intent with the
action you've defined (as discussed in the previous section), but the Intent must also carry
data in order for your Activity to identify which suggestion was selected. Specifically,
the data should be something unique for each suggestion, such as the row ID for the suggestion in
your SQLite table. When the Intent is received,
you can retrieve the attached data with {@link android.content.Intent#getData()} or {@link
android.content.Intent#getDataString()}.</p>
<p>You can define the data included with the Intent in two ways:</p>
<ol type="a">
<li>Define the data for each suggestion inside the {@link
android.app.SearchManager#SUGGEST_COLUMN_INTENT_DATA} column of your suggestions table.
<p>Provide all necessary data information for each Intent in the suggestions table by including the
{@link android.app.SearchManager#SUGGEST_COLUMN_INTENT_DATA} column and then populating it with
unique data for each row. The data from this column is attached to the Intent exactly as you
define it in this column. You can then retrieve it with with {@link
android.content.Intent#getData()} or {@link android.content.Intent#getDataString()}.</p>
<p class="note"><strong>Tip</strong>: It's usually easiest to use the table's row ID as the
Intent data, because it's always unique. And the easiest way to do that is by using the
{@link android.app.SearchManager#SUGGEST_COLUMN_INTENT_DATA} column name as an alias for the row ID
column. See the <a
href="{@docRoot}resources/samples/SearchableDictionary/index.html">Searchable Dictionary sample
app</a> for an example in which {@link android.database.sqlite.SQLiteQueryBuilder} creates a
projection map of column names to aliases.</p>
</li>
<li>Fragment a data URI into two pieces: the portion common to all suggestions and the portion
unique to each suggestion. Place these parts into the {@code android:searchSuggestIntentData}
attribute of the searchable configuration and the {@link
android.app.SearchManager#SUGGEST_COLUMN_INTENT_DATA_ID} column of your
suggestions table, respectively.
<p>Declare the piece of the URI that is common to all suggestions in the {@code
android:searchSuggestIntentData} attribute of your searchable configuration. For example:</p>
<pre>
&lt;?xml version="1.0" encoding="utf-8"?>
&lt;searchable xmlns:android="http://schemas.android.com/apk/res/android"
android:label="@string/app_label"
android:hint="@string/search_hint"
android:searchSuggestAuthority="com.example.MyCustomSuggestionProvider"
android:searchSuggestIntentAction="android.Intent.action.VIEW"
<b>android:searchSuggestIntentData="content://com.example/datatable"</b> >
&lt;/searchable>
</pre>
<p>Then include the final path for each suggestion (the unique part) in the {@link
android.app.SearchManager#SUGGEST_COLUMN_INTENT_DATA_ID}
column of your suggestions table. When the user selects a suggestion, the Search Manager takes
the string from {@code android:searchSuggestIntentData}, appends a slash ("/") and then adds the
respective value from the {@link android.app.SearchManager#SUGGEST_COLUMN_INTENT_DATA_ID} column to
form a complete content URI. You can then retrieve the {@link android.net.Uri} with with {@link
android.content.Intent#getData()}.</p>
</li>
</ol>
<h4>Add more data</h4>
<p>If you need to express even more information with your Intent, you can add another table column,
{@link android.app.SearchManager#SUGGEST_COLUMN_INTENT_EXTRA_DATA}, which can store additional
information about the suggestion. The data saved in this column is placed in {@link
android.app.SearchManager#EXTRA_DATA_KEY} of the Intent's extra Bundle.</p>
<h2 id="HandlingIntent">Handling the Intent</h2>
<p>Now that your search dialog provides custom search suggestions with custom Intents, you
need your searchable Activity to handle these Intents when the user selects a
suggestion. This is in addition to handling the {@link
android.content.Intent#ACTION_SEARCH} Intent, which your searchable Activity already does.
Here's an example of how you can handle the Intents during your Activity {@link
android.app.Activity#onCreate(Bundle) onCreate()} callback:</p>
<pre>
Intent intent = getIntent();
if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
// Handle the normal search query case
String query = intent.getStringExtra(SearchManager.QUERY);
doSearch(query);
} else if (Intent.ACTION_VIEW.equals(intent.getAction())) {
// Handle a suggestions click (because the suggestions all use ACTION_VIEW)
Uri data = intent.getData();
showResult(data);
}
</pre>
<p>In this example, the Intent action is {@link
android.content.Intent#ACTION_VIEW} and the data carries a complete URI pointing to the suggested
item, as synthesized by the {@code android:searchSuggestIntentData} string and {@link
android.app.SearchManager#SUGGEST_COLUMN_INTENT_DATA_ID} column. The URI is then passed to the local
{@code showResult()} method that queries the content provider for the item specified by the URI.</p>
<p class="note"><strong>Note:</strong> You do <em>not</em> need to add an Intent filter to your
Android manifest file for the Intent action you defined with the {@code
android:searchSuggestIntentAction} attribute or {@link
android.app.SearchManager#SUGGEST_COLUMN_INTENT_ACTION} column. The Search Manager opens your
searchable Activity by name to deliver the suggestion's Intent, so the Activity does not need to
declare the accepted action.</p>
<h2 id="RewritingQueryText">Rewriting the query text</h2>
<p>If the user navigates through the suggestions list using the directional controls (trackball or
d-pad), the text in the search dialog won't change, by default. However, you can temporarily rewrite
the user's query text as it appears in the text box with
a query that matches the suggestion currently in focus. This enables the user to see what query is
being suggested (if appropriate) and then select the search box and edit the query before
dispatching it as a search.</p>
<p>You can rewrite the query text in the following ways:</p>
<ol type="a">
<li>Add the {@code android:searchMode} attribute to your searchable configuration with the
"queryRewriteFromText" value. In this case, the content from the suggestion's {@link
android.app.SearchManager#SUGGEST_COLUMN_TEXT_1}
column is used to rewrite the query text.</li>
<li>Add the {@code android:searchMode} attribute to your searchable configuration with the
"queryRewriteFromData" value. In this case, the content from the suggestion's
{@link android.app.SearchManager#SUGGEST_COLUMN_INTENT_DATA} column is used to rewrite the
query text. This should only
be used with URI's or other data formats that are intended to be user-visible, such as HTTP URLs.
Internal URI schemes should not be used to rewrite the query in this way.</li>
<li>Provide a unique query text string in the {@link
android.app.SearchManager#SUGGEST_COLUMN_QUERY} column of your suggestions table. If this column is
present and contains a value for the current suggestion, it is used to rewrite the query text
(and override either of the previous implementations).</li>
</ol>
<h2 id="QSB">Exposing search suggestions to Quick Search Box</h2>
<p>Once you configure your application to provide custom search suggestions, making them available
to the globally accessible Quick Search Box is as easy as modifying your searchable configuration to
include {@code android:includeInGlobalSearch} as "true".</p>
<p>The only scenario in which additional work is necessary is when your content provider demands a
read permission. In which case, you need to add a special
{@code &lt;path-permission&gt;} element for the provider to grant Quick Search Box read access to
your content provider. For example:</p>
<pre>
&lt;provider android:name="MySuggestionProvider"
android:authorities="com.example.MyCustomSuggestionProvider"
android:readPermission="com.example.provider.READ_MY_DATA"
android:writePermission="com.example.provider.WRITE_MY_DATA"&gt;
&lt;path-permission android:pathPrefix="/search_suggest_query"
android:readPermission="android.permission.GLOBAL_SEARCH" /&gt;
&lt;/provider&gt;
</pre>
<p>In this example, the provider restricts read and write access to the content. The
{@code &lt;path-permission>} element amends the restriction by granting read access to content
inside the {@code "/search_suggest_query"} path prefix when the {@code
"android.permission.GLOBAL_SEARCH"} permission exists. This grants access to Quick Search Box
so that it may query your content provider for suggestions.</p>
<p>If your content provider does not enforce read permissions, then Quick Search Box can read
it by default.</p>
<h3 id="EnablingSuggestions">Enabling suggestions on a device</h3>
<p>When your application is configured to provide suggestions in Quick Search Box, it is not
actually enabled to provide suggestions in Quick Search Box, by default. It is the user's choice
whether to include suggestions from your application in the Quick Search Box. To enable search
suggestions from your application, the user must open "Searchable items" (in Settings > Search) and
enable your application as a searchable item.</p>
<p>Each application that is available to Quick Search Box has an entry in the Searchable items
settings page. The entry includes the name of the application and a short description of what
content can be searched from the application and made available for suggestions in Quick Search Box.
To define the description text for your searchable application, add the {@code
android:searchSettingsDescription} attribute to your searchable configuration. For example:</p>
<pre>
&lt;?xml version="1.0" encoding="utf-8"?>
&lt;searchable xmlns:android="http://schemas.android.com/apk/res/android"
android:label="@string/app_label"
android:hint="@string/search_hint"
android:searchSuggestAuthority="com.example.MyCustomSuggestionProvider"
android:searchSuggestIntentAction="android.Intent.action.VIEW"
android:includeInGlobalSearch="true"
<b>android:searchSettingsDescription="@string/search_description"</b> >
&lt;/searchable>
</pre>
<p>The string for {@code android:searchSettingsDescription} should be as concise as possible and
state the content that is searchable. For example, "Artists, albums, and tracks" for a music
application, or "Saved notes" for a notepad application. Providing this description is important so
the user knows what kind of suggestions are provided. You should always include this attribute
when {@code android:includeInGlobalSearch} is "true".</p>
<p>Remember that the user must visit the settings menu to enable search suggestions for your
application before your search suggestions appear in Quick Search Box. As such, if search is an
important aspect of your application, then you might want to consider a way to convey that to
your users &mdash; you might provide a note the first time they launch the app that instructs
them how to enable search suggestions for Quick Search Box.</p>
<h3 id="ManagingShortcuts">Managing Quick Search Box suggestion shortcuts</h3>
<p>Suggestions that the user selects from Quick Search Box can be automatically made into shortcuts.
These are suggestions that the Search Manager has copied from your content provider so it can
quickly access the suggestion without the need to re-query your content provider. </p>
<p>By default, this is enabled for all suggestions retrieved by Quick Search Box, but if your
suggestion data changes over time, then you can request that the shortcuts be refreshed. For
instance, if your suggestions refer to dynamic data, such as a contact's presence status, then you
should request that the suggestion shortcuts be refreshed when shown to the user. To do so,
include the {@link android.app.SearchManager#SUGGEST_COLUMN_SHORTCUT_ID} in your suggestions table.
Using this column, you can
configure the shortcut behavior for each suggestion in one of the following ways:</p>
<ol type="a">
<li>Have Quick Search Box re-query your content provider for a fresh version of the suggestion
shortcut.
<p>Provide a value in the {@link android.app.SearchManager#SUGGEST_COLUMN_SHORTCUT_ID} column
and the suggestion is
re-queried for a fresh version each time the shortcut is displayed. The shortcut
is quickly displayed with whatever data was most recently available until the refresh query
returns, at which point the suggestion is refreshed with the new information. The
refresh query is sent to your content provider with a URI path of {@link
android.app.SearchManager#SUGGEST_URI_PATH_SHORTCUT}
(instead of {@link android.app.SearchManager#SUGGEST_URI_PATH_QUERY}).</p>
<p>The {@link android.database.Cursor} you return should contain one suggestion using the
same columns as the original suggestion, or be empty, indicating that the shortcut is no
longer valid (in which case, the suggestion disappears and the shortcut is removed).</p>
<p>If a suggestion refers to data that could take longer to refresh, such as a network-based
refresh, you can also add the {@link
android.app.SearchManager#SUGGEST_COLUMN_SPINNER_WHILE_REFRESHING} column to your suggestions
table with a value
of "true" in order to show a progress spinner for the right hand icon until the refresh is complete.
Any value other than "true" does not show the progress spinner.</p>
</li>
<li>Prevent the suggestion from being copied into a shortcut at all.
<p>Provide a value of {@link android.app.SearchManager#SUGGEST_NEVER_MAKE_SHORTCUT} in the
{@link android.app.SearchManager#SUGGEST_COLUMN_SHORTCUT_ID} column. In
this case, the suggestion is never copied into a shortcut. This should only be necessary if you
absolutely do not want the previously copied suggestion to appear. (Recall that if you
provide a normal value for the column, then the suggestion shortcut appears only until the
refresh query returns.)</p></li>
<li>Allow the default shortcut behavior to apply.
<p>Leave the {@link android.app.SearchManager#SUGGEST_COLUMN_SHORTCUT_ID} empty for each
suggestion that will not change and can be saved as a shortcut.</p></li>
</ol>
<p>If none of your suggestions ever change, then you do not need the
{@link android.app.SearchManager#SUGGEST_COLUMN_SHORTCUT_ID} column at all.</p>
<p class="note"><strong>Note</strong>: Quick Search Box ultimately decides whether or not to create
a shortcut for a suggestion, considering these values as a strong request from your
application&mdash;there is no guarantee that the behavior you have requested for your suggestion
shortcuts will be honored.</p>
<h3 id="AboutRanking">About Quick Search Box suggestion ranking</h3>
<p>Once you make your application's search suggestions available to Quick Search Box, the Quick
Search Box ranking determines how the suggestions are surfaced to the user for a particular query.
This might depend on how many other apps have results for that query, and how often the user has
selected your results compared to those from other apps. There is no guarantee about how your
suggestions are ranked, or whether your app's suggestions show at all for a given query. In
general, you can expect that providing quality results increases the likelihood that your app's
suggestions are provided in a prominent position and apps that provide low quality suggestions
are more likely to be ranked lower or not displayed.</p>
<div class="special">
<p>See the <a href="{@docRoot}resources/samples/SearchableDictionary/index.html">Searchable
Dictionary sample app</a> for a complete demonstration of custom search suggestions.</p>
</div>
@@ -0,0 +1,235 @@
page.title=Adding Recent Query Suggestions
parent.title=Search
parent.link=index.html
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>In this document</h2>
<ol>
<li><a href="#TheBasics">The Basics</a></li>
<li><a href="#RecentQueryContentProvider">Creating a Content Provider</a></li>
<li><a href="#RecentQuerySearchableConfiguration">Modifying the Searchable
Configuration</a></li>
<li><a href="#SavingQueries">Saving Queries</a></li>
<li><a href="#ClearingSuggestionData">Clearing the Suggestion Data</a></li>
</ol>
<h2>Key classes</h2>
<ol>
<li>{@link android.provider.SearchRecentSuggestions}</li>
<li>{@link android.content.SearchRecentSuggestionsProvider}</li>
</ol>
<h2>See also</h2>
<ol>
<li><a href="searchable-config.html">Searchable Configuration</a></li>
</ol>
</div>
</div>
<p>When using the Android search dialog, you can provide search suggestions based on recent search
queries. For example, if a user previously searched for "puppies," then that query appears as a
suggestion once he or she begins typing the same query. Figure 1 shows an example of a search dialog
with recent query suggestions.</p>
<p>Before you begin, you need to implement the search dialog for basic searches in your application.
If you haven't, see <a href="search-dialog.html">Using the Android Search Dialog</a>.</p>
<h2 id="TheBasics">The Basics</h2>
<div class="figure" style="width:250px">
<img src="{@docRoot}images/search/search-suggest-recent-queries.png" alt="" height="417" />
<p class="img-caption"><strong>Figure 1.</strong> Screenshot of a search dialog with recent query
suggestions.</p>
</div>
<p>Recent query suggestions are simply saved searches. When the user selects one of
the suggestions, your searchable Activity receives a {@link
android.content.Intent#ACTION_SEARCH} Intent with the suggestion as the search query, which your
searchable Activity already handles (as described in <a href="search-dialog.html">Using the Android
Search Dialog</a>).</p>
<p>To provide recent queries suggestions, you need to:</p>
<ul>
<li>Implement a searchable Activity, <a
href="{@docRoot}guide/topics/search/search-dialog.html">using the Android Search Dialog</a>.</li>
<li>Create a content provider that extends {@link
android.content.SearchRecentSuggestionsProvider} and declare it in your application manifest.</li>
<li>Modify the searchable configuration with information about the content provider that
provides search suggestions.</li>
<li>Save queries to your content provider each time a search is executed.</li>
</ul>
<p>Just as the Search Manager displays the search dialog, it also displays the
search suggestions. All you need to do is provide a source from which the suggestions can be
retrieved.</p>
<p>When the Search Manager identifies that your Activity is searchable and provides search
suggestions, the following procedure takes place as soon as the user types into the search
dialog:</p>
<ol>
<li>Search Manager takes the search query text (whatever has been typed so far) and performs a
query to the content provider that contains your suggestions.</li>
<li>Your content provider returns a {@link android.database.Cursor} that points to all
suggestions that match the search query text.</li>
<li>Search Manager displays the list of suggestions provided by the Cursor.</li>
</ol>
<p>Once the recent query suggestions are displayed, the following might happen:</p>
<ul>
<li>If the user types another key, or changes the query in any way, the aforementioned steps are
repeated and the suggestion list is updated.</li>
<li>If the user executes the search, the suggestions are ignored and the search is delivered
to your searchable Activity using the normal {@link android.content.Intent#ACTION_SEARCH}
Intent.</li>
<li>If the user selects a suggestion, an
{@link android.content.Intent#ACTION_SEARCH} Intent is delivered to your searchable Activity using
the suggested text as the query.</li>
</ul>
<p>The {@link android.content.SearchRecentSuggestionsProvider} class that
you extend for your content provider automatically does the work described above, so there's
actually very little code to write.</p>
<h2 id="RecentQueryContentProvider">Creating a Content Provider</h2>
<p>The content provider that you need for recent query suggestions must be an implementation
of {@link android.content.SearchRecentSuggestionsProvider}. This class does practically everything
for you. All you have to do is write a class constructor that executes one line of code.</p>
<p>For example, here's a complete implementation of a content provider for recent query
suggestions:</p>
<pre>
public class MySuggestionProvider extends SearchRecentSuggestionsProvider {
public final static String AUTHORITY = "com.example.MySuggestionProvider";
public final static int MODE = DATABASE_MODE_QUERIES;
public MySuggestionProvider() {
setupSuggestions(AUTHORITY, MODE);
}
}
</pre>
<p>The call to {@link android.content.SearchRecentSuggestionsProvider#setupSuggestions(String,int)
setupSuggestions()} passes the name of the search authority and a
database mode. The search authority can be any unique string, but the best practice is to use a
fully qualified name for your content provider
(package name followed by the provider's class name; for example,
"com.example.MySuggestionProvider"). The database mode must include {@link
android.content.SearchRecentSuggestionsProvider#DATABASE_MODE_QUERIES} and can optionally include
{@link
android.content.SearchRecentSuggestionsProvider#DATABASE_MODE_2LINES}, which adds another column
to the suggestions table that allows you to provide a second line of text with each suggestion. For
example, if you want to provide two lines in each suggestion:</p>
<pre>
public final static int MODE = DATABASE_MODE_QUERIES | DATABASE_MODE_2LINES;
</pre>
<p>Now declare the content provider in your application manifest with the same authority
string used in your {@link android.content.SearchRecentSuggestionsProvider} class (and in the
searchable configuration). For example:</p>
<pre>
&lt;application>
&lt;provider android:name=".MySuggestionProvider"
android:authorities="com.example.MySuggestionProvider" />
...
&lt;/application>
</pre>
<h2 id="RecentQuerySearchableConfiguration">Modifying the Searchable Configuration</h2>
<p>To configure your search dialog to use your suggestions provider, you need to add
the {@code android:searchSuggestAuthority} and {@code android:searchSuggestSelection} attributes to
the {@code &lt;searchable&gt;} element in your searchable configuration file. For example:</p>
<pre>
&lt;?xml version="1.0" encoding="utf-8"?>
&lt;searchable xmlns:android="http://schemas.android.com/apk/res/android"
android:label="@string/app_label"
android:hint="@string/search_hint"
<b>android:searchSuggestAuthority="com.example.MySuggestionProvider"
android:searchSuggestSelection=" ?"</b> >
&lt;/searchable>
</pre>
<p>The value for {@code android:searchSuggestAuthority} should be a fully qualified name for
your content provider that exactly matches the authority used in the content provider (the {@code
AUTHORITY} string in the above example).
</p>
<p>The value for {@code android:searchSuggestSelection} must be a single question mark, preceded by
a space ({@code " ?"}), which is simply a placeholder for the SQLite selection argument (which is
automatically replaced by the query text entered by the user).</p>
<h2 id="SavingQueries">Saving Queries</h2>
<p>To populate your collection of recent queries, add each query
received by your searchable Activity to your {@link
android.content.SearchRecentSuggestionsProvider}. To do this, create an instance of {@link
android.provider.SearchRecentSuggestions} and call {@link
android.provider.SearchRecentSuggestions#saveRecentQuery(String,String) saveRecentQuery()} each time
your searchable Activity receives a query. For example, here's how you can save the query during
your Activity's {@link android.app.Activity#onCreate(Bundle) onCreate()} method:</p>
<pre>
&#64;Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Intent Intent = getIntent();
if (Intent.ACTION_SEARCH.equals(Intent .getAction())) {
String query = Intent .getStringExtra(SearchManager.QUERY);
SearchRecentSuggestions suggestions = new SearchRecentSuggestions(this,
MySuggestionProvider.AUTHORITY, MySuggestionProvider.MODE);
suggestions.saveRecentQuery(query, null);
}
}
</pre>
<p>The {@link android.content.SearchRecentSuggestionsProvider} constructor requires the
same authority and database mode declared by your content provider.</p>
<p>The {@link android.provider.SearchRecentSuggestions#saveRecentQuery(String,String)
saveRecentQuery()} method takes
the search query string as the first parameter and, optionally, a second string to include as the
second line of the suggestion (or null). The second parameter is only used if you've enabled
two-line mode for the search suggestions with {@link
android.content.SearchRecentSuggestionsProvider#DATABASE_MODE_2LINES}. If you have enabled
two-line mode, then the query text is also matched against this second line when the Search Manager
looks for matching suggestions.</p>
<h2 id="ClearingSuggestionData">Clearing the Suggestion Data</h2>
<p>To protect the user's privacy, you should always provide a way for the user to clear the recent
query suggestions. To clear the query history, call {@link
android.provider.SearchRecentSuggestions#clearHistory()}. For example:</p>
<pre>
SearchRecentSuggestions suggestions = new SearchRecentSuggestions(this,
HelloSuggestionProvider.AUTHORITY, HelloSuggestionProvider.MODE);
suggestions.clearHistory();
</pre>
<p>Execute this from your choice of a "Clear Search History" menu item,
preference item, or button. You should also provide a confirmation dialog to
verify that the user wants to delete their search history.</p>
+109
View File
@@ -0,0 +1,109 @@
page.title=Search
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>Topics</h2>
<ol>
<li><a href="search-dialog.html">Using the Android Search Dialog</a></li>
<li><a href="adding-recent-query-suggestions.html">Adding Recent Query Suggestions</a></li>
<li><a href="adding-custom-suggestions.html">Adding Custom Suggestions</a></li>
</ol>
<h2>Reference</h2>
<ol>
<li><a href="searchable-config.html">Searchable Configuration</a></li>
</ol>
<h2>Related samples</h2>
<ol>
<li><a href="{@docRoot}resources/samples/SearchableDictionary/index.html">Searchable
Dictionary</a></li>
</ol>
</div>
</div>
<p>Search is a core user feature on Android. Users should be able
to search any data that is available to them, whether the content is located on the device or
the Internet. The search experience should be seamless and consistent across the entire
system, which is why Android provides a search framework to help you provide users with
a familiar search dialog and a great search experience.</p>
<div class="figure" style="width:250px">
<img src="{@docRoot}images/search/search-suggest-custom.png" alt="" height="417" />
<p class="img-caption"><strong>Figure 1.</strong> Screenshot of a search dialog with custom
search suggestions.</p>
</div>
<p>Android's search framework provides a user interface in which users can perform a search and
an interaction layer that communicates with your application, so you don't have to build
your own search Activity. Instead, a search dialog appears at the top of the screen at the user's
command without interrupting the current Activity.</p>
<p>The search framework manages the life of the search dialog. When users execute a search, the
search framework passes the query text to your application so your application can perform a
search. Figure 1 shows an example of the search dialog with optional search suggestions.</p>
<p>Once your application is set up to use the search dialog, you can:</p>
<ul>
<li>Enable voice search</li>
<li>Provide search suggestions based on recent user queries</li>
<li>Provide custom search suggestions that match actual results in your application data</li>
<li>Offer your application's search suggestions in the system-wide Quick Search Box</li>
</ul>
<p class="note"><strong>Note</strong>: The search framework does <em>not</em> provide APIs to
search your data. To perform a search, you need to use APIs appropriate for your data. For example,
if your data is stored in an SQLite database, you should use the {@link android.database.sqlite}
APIs to perform searches.</p>
<p>The following documents show you how to use the search dialog in your application:</p>
<dl>
<dt><strong><a href="search-dialog.html">Using the Android Search Dialog</a></strong></dt>
<dd>How to set up your application to use the search dialog. </dd>
<dt><strong><a href="adding-recent-query-suggestions.html">Adding Recent Query
Suggestions</a></strong></dt>
<dd>How to show suggestions based on queries previously used in the search dialog.</dd>
<dt><strong><a href="adding-custom-suggestions.html">Adding Custom Suggestions</a></strong></dt>
<dd>How to show suggestions based on custom data from your application and offer your suggestions
in the system-wide Quick Search Box.</dd>
<dt><strong><a href="searchable-config.html">Searchable Configuration</a></strong></dt>
<dd>A reference for the searchable configuration file (though the other
documents also discuss the configuration file in terms of specific behaviors).</dd>
</dl>
<h2>Protecting User Privacy</h2>
<p>When you implement search in your application, take steps to protect the user's
privacy. Many users consider their activities on the phone&mdash;including searches&mdash;to
be private information. To protect each user's privacy, you should abide by the following
principles:</p>
<ul>
<li><strong>Don't send personal information to servers, but if you must, do not log it.</strong>
<p>Personal information is any information that can personally identify your users, such as their
names, email addresses, billing information, or other data that can be reasonably linked to such
information. If your application implements search with the assistance of a server, avoid sending
personal information along with the search queries. For example, if you are searching for businesses
near a zip code,
you don't need to send the user ID as well; send only the zip code to the server. If you must
send the personal information, you should not log it. If you must log it, protect that data
very carefully and erase it as soon as possible.</p>
</li>
<li><strong>Provide the user with a way to clear their search history.</strong>
<p>The search framework helps your application provide context-specific suggestions while the user
types. Sometimes these
suggestions are based on previous searches or other actions taken by the user in an earlier
session. A user might not wish for previous searches to be revealed to other device users, for
instance, if they share their phone with a friend. If your application provides suggestions that can
reveal previous activities, you should implement the ability for the user to clear the search
history. If you are using {@link android.provider.SearchRecentSuggestions}, you can simply call the
{@link android.provider.SearchRecentSuggestions#clearHistory()} method. If you are implementing
custom suggestions, you'll need to provide a similar "clear history" method in your provider that
the user can execute.</p>
</li>
</ul>
@@ -0,0 +1,576 @@
page.title=Using the Android Search Dialog
parent.title=Search
parent.link=index.html
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>In this document</h2>
<ol>
<li><a href="#TheBasics">The Basics</a></li>
<li><a href="#SearchableConfiguration">Creating a Searchable Configuration</a></li>
<li><a href="#SearchableActivity">Creating a Searchable Activity</a>
<ol>
<li><a href="#DeclaringSearchableActivity">Declaring a searchable Activity</a></li>
<li><a href="#PerformingSearch">Performing a search</a></li>
</ol>
</li>
<li><a href="#InvokingTheSearchDialog">Invoking the Search Dialog</a>
<ol>
<li><a href="#LifeCycle">The impact of the search dialog on your Activity life-cycle</a></li>
</ol>
</li>
<li><a href="#SearchContextData">Passing Search Context Data</a></li>
<li><a href="#VoiceSearch">Adding Voice Search</a></li>
</ol>
<h2>Key classes</h2>
<ol>
<li>{@link android.app.SearchManager}</li>
</ol>
<h2>Related samples</h2>
<ol>
<li><a href="{@docRoot}resources/samples/SearchableDictionary/index.html">Searchable
Dictionary</a></li>
</ol>
<h2>Downloads</h2>
<ol>
<li><a href="{@docRoot}shareables/search_icons.zip">search_icons.zip</a></li>
</ol>
<h2>See also</h2>
<ol>
<li><a href="adding-recent-query-suggestions.html">Adding Recent Query Suggestions</a></li>
<li><a href="adding-custom-suggestions.html">Adding Custom Suggestions</a></li>
<li><a href="searchable-config.html">Searchable Configuration</a></li>
</ol>
</div>
</div>
<p>When you want to implement search in your application, the last thing you should have to worry
about is where to put the search box. When you implement search with the Android search framework,
you don't have to. When the user invokes search, a search dialog appears at the top of the screen
with your application icon to the left of the search box. When the user executes the search, your
application receives the query so it can search your application's data. An example of the search
dialog is shown in figure 1.</p>
<p>This guide shows you how to set up your application to provide search in the search
dialog. When you use the search dialog, you provide a standardized search
experience and can add features such as voice search and search suggestions.</p>
<h2 id="TheBasics">The Basics</h2>
<div class="figure" style="width:250px">
<img src="{@docRoot}images/search/search-ui.png" alt="" height="417" />
<p class="img-caption"><strong>Figure 1.</strong> Screenshot of an application's search dialog.</p>
</div>
<p>The Android search framework manages the search dialog for your application. You never need
to draw it or worry about where it is, and your Activity is not interrupted when the search dialog
appears. The Search Manager ({@link android.app.SearchManager}) is the component that does this work
for you. It manages the life of the search dialog and sends your application the user's search
query.</p>
<p>When the user executes a search, the Search Manager creates an {@link android.content.Intent} to
pass the search query to the Activity that you've declared to handle searches. Basically, all you
need is an Activity that receives the search Intent, performs the search, and presents the results.
Specifically, you need the following:</p>
<dl>
<dt>A searchable configuration</dt>
<dd>An XML file that configures the search dialog and includes settings for features such as voice
search, search suggestion, and the hint text.</dd>
<dt>A searchable Activity</dt>
<dd>The {@link android.app.Activity} that receives the search query, then searches your data and
displays the search results.</dd>
<dt>A mechanism by which the user can invoke search</dt>
<dd>The device search key invokes the search dialog, by default. However, a dedicated search key
is not guaranteed on all devices, so provide another means by which the user can invoke a search,
such as a search button in the Options Menu or elsewhere in the Activity UI.</dd>
</dl>
<h2 id="SearchableConfiguration">Creating a Searchable Configuration</h2>
<p>The searchable configuration is an XML file that defines several settings for the search
dialog in your application. This file is traditionally named {@code searchable.xml} and must be
saved in the {@code res/xml/} project directory.</p>
<p>The file must consist of the {@code &lt;searchable&gt;} element as the root node and specify one
or more attributes that configure your search dialog. For example:</p>
<pre>
&lt;?xml version="1.0" encoding="utf-8"?>
&lt;searchable xmlns:android="http://schemas.android.com/apk/res/android"
android:label="@string/app_label"
android:hint="@string/search_hint" >
&lt;/searchable>
</pre>
<p>The {@code android:label} attribute is the only required attribute and points to a string
resource, which should be the same as the application name. This label isn't actually visible to the
user until you enable suggestions for Quick Search Box, at which point, this label is visible in the
list of Searchable items in the system Settings.</p>
<p>Though it's not required, we recommend that you always include the {@code android:hint}
attribute, which provides a hint string in the search dialog's text box before the user
enters their query. The hint is important because it provides important clues to users about what
they can search.</p>
<p class="note"><strong>Tip:</strong> For consistency among other
Android applications, you should format the string for {@code android:hint} as "Search
<em>&lt;content-or-product&gt;</em>". For example, "Search songs and artists" or "Search
YouTube".</p>
<p>The {@code &lt;searchable&gt;} element accepts several other attributes. Most attributes apply
only when configuring features such as search suggestions and voice search.</p>
<p>For more details about the searchable configuration file, see the <a
href="{@docRoot}guide/topics/search/searchable-config.html">Searchable Configuration</a>
reference.</p>
<h2 id="SearchableActivity">Creating a Searchable Activity</h2>
<p>When the user executes a search from the search dialog, the Search Manager takes the query
and sends it to your searchable {@link android.app.Activity} in the {@link
android.content.Intent#ACTION_SEARCH} {@link android.content.Intent}. Your searchable Activity
then searches your data using the query and presents the results to the user.</p>
<p>In order for the Search Manager to know where to deliver the search query, you must declare your
searchable Activity in the Android manifest file.</p>
<h3 id="DeclaringSearchableActivity">Declaring a searchable Activity</h3>
<p>If you don't have one already, create an {@link android.app.Activity} that performs
searches and present search results. To set up this Activity as your searchable Activity:</p>
<ol>
<li>Declare the Activity to accept the {@link android.content.Intent#ACTION_SEARCH} {@link
android.content.Intent}, in an <a
href="{@docRoot}guide/topics/manifest/intent-filter-element.html">{@code &lt;intent-filter&gt;}</a>
element.</li>
<li>Apply the searchable configuration, in a <a
href="{@docRoot}guide/topics/manifest/meta-data-element.html">{@code &lt;meta-data&gt;}</a>
element.</li>
</ol>
<p>For example:</p>
<pre>
&lt;application ... >
&lt;activity android:name=".MySearchableActivity" >
&lt;intent-filter>
&lt;action android:name="android.intent.action.SEARCH" />
&lt;/intent-filter>
&lt;meta-data android:name="android.app.searchable"
android:resource="@xml/searchable"/>
&lt;/activity>
...
&lt;/application>
</pre>
<p>The {@code &lt;meta-data&gt;} element must include the {@code android:name} attribute with a
value of {@code "android.app.searchable"} and the {@code android:resource} attribute with a
reference to the searchable configuration file (in this example, it
refers to the {@code res/xml/searchable.xml} file).</p>
<p class="note"><strong>Note:</strong> The {@code &lt;intent-filter&gt;} does not need a <a
href="{@docRoot}guide/topics/manifest/category-element.html">{@code &lt;category&gt;}</a> with the
{@code DEFAULT} value, because the Search Manager delivers the {@link
android.content.Intent#ACTION_SEARCH} Intent explicitly to your searchable Activity by name.</p>
<p>The search dialog is not, by default, available from every Activity of your
application. Rather, the search dialog is presented to users only when they
invoke search from a searchable context of your application. A searchable context is any Activity
for which you have
declared searchable meta-data in the manifest file. For example, the searchable Activity itself
(declared in the manifest snippet above) is
a searchable context because it includes meta-data that defines the
searchable configuration. Any other Activity in your application is not a searchable context, by
default, and thus, does not reveal the search dialog. However, you probably do want the search
dialog available from your other activities (and to launch the searchable Activity when the user
executes a search). You can do exactly that.</p>
<p>If you want all of your activities to provide the search dialog, add another {@code
&lt;meta-data&gt;} element inside the {@code
&lt;application&gt;} element. Use this element to declare the existing searchable Activity as the
default searchable Activity. For example:</p>
<pre>
&lt;application ... >
&lt;activity android:name=".MySearchableActivity" >
&lt;intent-filter>
&lt;action android:name="android.intent.action.SEARCH" />
&lt;/intent-filter>
&lt;meta-data android:name="android.app.searchable"
android:resource="@xml/searchable"/>
&lt;/activity>
&lt;activity android:name=".AnotherActivity" ... >
&lt;/activity>
&lt;!-- declare the default searchable Activity for the whole app --&gt;
<b>&lt;meta-data android:name="android.app.default_searchable"
android:value=".MySearchableActivity" /&gt;</b>
...
&lt;/application>
</pre>
<p>The {@code &lt;meta-data&gt;} element with the {@code android:name} attribute value of
{@code "android.app.default_searchable"} specifies a default searchable Activity for the context in
which it is placed (which, in this case, is the entire application). The searchable Activity to
use is specified with the {@code android:value} attribute. All other activities in the
application, such as {@code AnotherActivity}, are now considered a searchable context and can invoke
the search dialog. When a search is executed, {@code MySearchableActivity} is launched to handle
the search query.</p>
<p>You can also control which activities provide search at a more granular level.
To specify only an individual Activity as a searchable context, place the {@code
&lt;meta-data&gt;} with the {@code
"android.app.default_searchable"} name inside the respective {@code &lt;activity&gt;}
element (rather than inside the {@code &lt;application&gt;} element). While uncommon, you
can also create more than one searchable Activity and provide each one in different contexts of your
application, either by declaring a different searchable Activity in each {@code &lt;activity&gt;}
element, or by declaring a default searchable Activity for the entire application and then
overriding it with a {@code &lt;meta-data&gt;} element inside certain activities. (You might do
this if you want to search different sets of data that cannot be handled by the same
searchable Activity, depending on the currently open Activity.)</p>
<h3 id="PerformingSearch">Performing a search</h3>
<p>Once you have declared your searchable Activity, performing a search for the user involves
three steps:</p>
<ol>
<li><a href="#ReceivingTheQuery">Receiving the query</a></li>
<li><a href="#SearchingYourData">Searching your data</a></li>
<li><a href="#PresentingTheResults">Presenting the results</a></li>
</ol>
<p>Traditionally, your search results should be presented in a {@link android.widget.ListView}, so
you might want your searchable Activity to extend {@link android.app.ListActivity}, which
provides easy access to {@link android.widget.ListView} APIs. (See the <a
href="{@docRoot}resources/tutorials/views/hello-listview.html">List View Tutorial</a> for a simple
{@link android.app.ListActivity} sample.)</p>
<h4 id="ReceivingTheQuery">Receiving the query</h4>
<p>When a user executes a search from the search dialog, the Search Manager sends the {@link
android.content.Intent#ACTION_SEARCH} {@link android.content.Intent} to your searchable Activity.
This Intent carries the search query in the
{@link android.app.SearchManager#QUERY QUERY} string extra. You must check for
this Intent when the Activity starts and extract the string. For example, here's how you can get the
query when your Activity starts:</p>
<pre>
&#64;Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.search);
Intent intent = getIntent();
if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
String query = intent.getStringExtra(SearchManager.QUERY);
doMySearch(query);
}
}
</pre>
<p>The {@link android.app.SearchManager#QUERY QUERY} string is always included with
the {@link android.content.Intent#ACTION_SEARCH} Intent. In this example, the query is
retrieved and passed to a local {@code doMySearch()} method where the actual search operation
is done.</p>
<h4 id="SearchingYourData">Searching your data</h4>
<p>The process of storing and searching your data is unique to your application.
You can store and search your data in many ways, but this guide does not show you how to store your
data and search it. Storing and searching your data is something you should carefully consider in
terms of your needs and your data. However, here are some tips you might be able to apply:</p>
<ul>
<li>If your data is stored in a SQLite database on the device, performing a full-text search
(using FTS3, rather than a LIKE query) can provide a more robust search across text data and can
produce results significantly faster. See <a href="http://sqlite.org/fts3.html">sqlite.org</a>
for information about FTS3 and the {@link android.database.sqlite.SQLiteDatabase} class for
information about SQLite on Android. Also look at the <a
href="{@docRoot}resources/samples/SearchableDictionary/index.html">Searchable Dictionary</a> sample
application to see a complete SQLite implementation that performs searches with FTS3.</li>
<li>If your data is stored online, then the perceived search performance might be
inhibited by the user's data connection. You might want to display a spinning progress wheel until
your search returns. See {@link android.net} for a reference of network APIs and <a
href="{@docRoot}guide/topics/ui/dialogs.html#ProgressDialog">Creating a Progress Dialog</a> to see
how you can display a progress wheel.</li>
</ul>
<div class="sidebox-wrapper">
<div class="sidebox">
<h2>About Adapters</h2>
<p>An Adapter binds individual items from a set of data into individual {@link
android.view.View} objects. When the Adapter
is applied to a {@link android.widget.ListView}, the Views are injected as individual items of the
list. {@link
android.widget.Adapter} is simply an interface, so implementations such as {@link
android.widget.CursorAdapter} (for binding data from a {@link android.database.Cursor}) are needed.
If none of the existing implementations work for your data, then you should implement your own from
{@link android.widget.BaseAdapter}. Install the SDK Samples package for API Level 4 to see the
original version of the Searchable Dictionary, which creates a custom BaseAdapter.</p>
</div>
</div>
<p>Regardless of where your data lives and how you search it, we recommend that you return search
results to your searchable Activity with an {@link android.widget.Adapter}. This way, you can easily
present all the search results in a {@link android.widget.ListView}. If your data comes from a
SQLite database query, then you can apply your results to a {@link android.widget.ListView}
using a {@link android.widget.CursorAdapter}. If your data comes in some other type of format, then
you can create an extension of the {@link android.widget.BaseAdapter}.</p>
<h4 id="PresentingTheResults">Presenting the results</h4>
<p>Presenting your search results is mostly a UI detail that is not handled by the search APIs.
However, one option is to create your searchable Activity to extend {@link
android.app.ListActivity} and call {@link
android.app.ListActivity#setListAdapter(ListAdapter)}, passing it an {@link
android.widget.Adapter} that is bound to your data. This injects all the
results into the Activity {@link android.widget.ListView}.</p>
<p>For more help presenting your results, see the {@link android.app.ListActivity}
documentation.</p>
<p>Also see the <a
href="{@docRoot}resources/samples/SearchableDictionary/index.html">Searchable Dictionary</a> sample
for an a complete demonstration of how to search an SQLite database and use an
{@link android.widget.Adapter} to provide results in a {@link android.widget.ListView}.</p>
<h2 id="InvokingTheSearchDialog">Invoking the Search Dialog</h2>
<p>Once you have a searchable Activity, invoking the search dialog is easy. Many Android
devices provide a dedicated SEARCH key, which reveals the search dialog when the user presses it
from a searchable context of your application. However, you should not assume that a SEARCH
key is available on the user's device and should always provide a search button in your UI that
invokes search.</p>
<p>To invoke search from your Activity, call {@link android.app.Activity#onSearchRequested()}.</p>
<p>For instance, you should provide a menu item in your <a
href="{@docRoot}guide/topics/ui/menus.html#options-menu">Options Menu</a> or a button in your UI to
invoke search with this method. The <a
href="{@docRoot}shareables/search_icons.zip">search_icons.zip</a> file includes icons for
medium and high density screens, which you can use for your search menu item or button (low density
screens automatically scale-down the hdpi image by one half). </p>
<!-- ... maybe this should go into the Creating Menus document ....
<p>If you chose to provide a shortcut key for the menu item, using {@link
android.view.MenuItem#setAlphabeticShortcut(char)}, then SearchManager.MENU_KEY is the recommended
key character, representing the default search key.</p>
-->
<p>You can also enable "type-to-search" functionality, which reveals the search dialog when the
user starts typing on the keyboard and the keystrokes are inserted into the search dialog. You can
enable type-to-search in your Activity by calling
{@link android.app.Activity#setDefaultKeyMode(int) setDefaultKeyMode}({@link
android.app.Activity#DEFAULT_KEYS_SEARCH_LOCAL}) during your Activity's
{@link android.app.Activity#onCreate(Bundle) onCreate()} method.</p>
<h3 id="LifeCycle">The impact of the search dialog on your Activity lifecycle</h3>
<p>The search dialog is a {@link android.app.Dialog} that floats at the top of the
screen. It does not cause any change in the Activity stack, so when the search dialog appears, no
lifecycle methods for the currently open Activity (such as {@link
android.app.Activity#onPause()}) are called. Your Activity just loses input focus as it is given to
the search dialog.
</p>
<p>If you want to be notified when search is invoked, override the {@link
android.app.Activity#onSearchRequested()} method. When the system calls this method, you can do any
work you want to when your Activity looses input focus to the search dialog (such as pause
animations). Unless you are <a href="#SearchContextData">passing search context data</a>
(discussed below), you should end the method by calling the super class implementation. For
example:</p>
<pre>
&#64;Override
public boolean onSearchRequested() {
pauseSomeStuff();
return super.onSearchRequested();
}
</pre>
<p>If the user cancels search by pressing the BACK key, the Activity in which search was
invoked re-gains input focus. You can register to be notified when the search dialog is
closed with {@link android.app.SearchManager#setOnDismissListener(SearchManager.OnDismissListener)
setOnDismissListener()}
and/or {@link android.app.SearchManager#setOnCancelListener(SearchManager.OnCancelListener)
setOnCancelListener()}. You
should need to register only the {@link android.app.SearchManager.OnDismissListener
OnDismissListener}, because it is called every time the search dialog closes. The {@link
android.app.SearchManager.OnCancelListener OnCancelListener} only pertains to events in which the
user explicitly exited the search dialog, so it is not called when a search is executed (in which
case, the search dialog naturally disappears).</p>
<p>If the current Activity is not the searchable Activity, then the normal Activity lifecycle
events are triggered once the user executes a search (the current Activity receives {@link
android.app.Activity#onPause()} and so forth, as
described in <a href="{@docRoot}guide/topics/fundamentals.html#lcycles">Application
Fundamentals</a>). If, however, the current Activity is the searchable Activity, then one of two
things happens:</p>
<ol type="a">
<li>By default, the searchable Activity receives the {@link
android.content.Intent#ACTION_SEARCH} Intent with a call to {@link
android.app.Activity#onCreate(Bundle) onCreate()} and a new instance of the
Activity is brought to the top of the Activity stack. There are now two instances of your
searchable Activity in the Activity stack (so pressing the BACK key goes back to the previous
instance of the searchable Activity, rather than exiting the searchable Activity).</li>
<li>If you set {@code android:launchMode} to "singleTop", then the
searchable Activity receives the {@link android.content.Intent#ACTION_SEARCH} Intent with a call
to {@link android.app.Activity#onNewIntent(Intent)}, passing the new {@link
android.content.Intent#ACTION_SEARCH} Intent here. For example, here's how you might handle
this case, in which the searchable Activity's launch mode is "singleTop":
<pre>
&#64;Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.search);
handleIntent(getIntent());
}
&#64;Override
protected void onNewIntent(Intent intent) {
setIntent(intent);
handleIntent(intent);
}
private void handleIntent(Intent intent) {
if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
String query = intent.getStringExtra(SearchManager.QUERY);
doMySearch(query);
}
}
</pre>
<p>Compared to the example code in the section about <a href="#PerformingSearch">Performing a
Search</a>, all the code to handle the
search Intent is now in the {@code handleIntent()} method, so that both {@link
android.app.Activity#onCreate(Bundle)
onCreate()} and {@link android.app.Activity#onNewIntent(Intent) onNewIntent()} can execute it.</p>
<p>When the system calls {@link android.app.Activity#onNewIntent(Intent)}, the Activity has
not been restarted, so the {@link android.app.Activity#getIntent()} method
returns the same Intent that was received with {@link
android.app.Activity#onCreate(Bundle) onCreate()}. This is why you should call {@link
android.app.Activity#setIntent(Intent)} inside {@link
android.app.Activity#onNewIntent(Intent)} (so that the Intent saved by the Activity is updated in
case you call {@link android.app.Activity#getIntent()} in the future).</p>
</li>
</ol>
<p>The second scenario using "singleTop" launch mode is usually ideal, because chances are good that
once a search is done, the user will perform additional searches and it's a bad experience if your
application creates multiple instances of the searchable Activity. So, we recommend that you set
your searchable Activity to "singleTop" launch mode in the application
manifest. For example:</p>
<pre>
&lt;activity android:name=".MySearchableActivity"
<b>android:launchMode="singleTop"</b> >
&lt;intent-filter>
&lt;action android:name="android.intent.action.SEARCH" />
&lt;/intent-filter>
&lt;meta-data android:name="android.app.searchable"
android:resource="@xml/searchable"/>
&lt;/activity>
</pre>
<h2 id="SearchContextData">Passing Search Context Data</h2>
<p>To refine your search criteria from the current Activity instead of depending only on the user's
search query, you can provide additional data in the Intent that the Search Manager sends to your
searchable Activity. In a simple case, you can make your refinements inside the searchable
Activity, for every search made, but if your
search criteria varies from one searchable context to another, then you can pass whatever data
is necessary to refine your search in the {@link android.app.SearchManager#APP_DATA} {@link
android.os.Bundle}, which is included in the {@link android.content.Intent#ACTION_SEARCH}
Intent.</p>
<p>To pass this kind of data to your searchable Activity, override {@link
android.app.Activity#onSearchRequested()} method for the Activity in which search can be invoked.
For example:</p>
<pre>
&#64;Override
public boolean onSearchRequested() {
Bundle appData = new Bundle();
appData.putBoolean(MySearchableActivity.JARGON, true);
startSearch(null, false, appData, false);
return true;
}
</pre>
<p>Returning "true" indicates that you have successfully handled this callback event. Then in your
searchable Activity, you can extract the data placed inside {@code appdata} from the {@link
android.app.SearchManager#APP_DATA} {@link android.os.Bundle} to refine the search. For example:</p>
<pre>
Bundle appData = getIntent().getBundleExtra(SearchManager.APP_DATA);
if (appData != null) {
boolean jargon = appData.getBoolean(MySearchableActivity.JARGON);
}
</pre>
<p class="caution"><strong>Caution:</strong> Never call the {@link
android.app.Activity#startSearch(String,boolean,Bundle,boolean) startSearch()} method from outside
the {@link android.app.Activity#onSearchRequested()} callback method. To invoke the search dialog
in your Activity, always call {@link android.app.Activity#onSearchRequested()}. Otherwise, {@link
android.app.Activity#onSearchRequested()} is not called and customizations (such as the addition of
{@code appData} in the above example) are missed.</p>
<h2 id="VoiceSearch">Adding Voice Search</h2>
<p>You can add voice search functionality to your search dialog by adding the {@code
android:voiceSearchMode} attribute to your searchable configuration. This adds a voice search
button in the search dialog that launches a voice prompt. When the user
has finished speaking, the transcribed search query is sent to your searchable
Activity.</p>
<p>For example:</p>
<pre>
&lt;?xml version="1.0" encoding="utf-8"?>
&lt;searchable xmlns:android="http://schemas.android.com/apk/res/android"
android:label="@string/search_label"
android:hint="@string/search_hint"
<b>android:voiceSearchMode="showVoiceSearchButton|launchRecognizer"</b> >
&lt;/searchable>
</pre>
<p>The value {@code showVoiceSearchButton} is required to enable voice
search, while the second value, {@code launchRecognizer}, specifies that the voice search button
should launch a recognizer that returns the transcribed text to the searchable Activity.</p>
<p>You can provide additional attributes to specify the voice search behavior, such
as the language to be expected and the maximum number of results to return. See the <a
href="searchable-config.html">Searchable Configuration</a> reference for more information about the
available attributes.</p>
<p class="note"><strong>Note:</strong> Carefully consider whether voice search is appropriate for
your application. All searches performed with the voice search button are immediately sent to
your searchable Activity without a chance for the user to review the transcribed query. Sufficiently
test the voice recognition and ensure that it understands the types of queries that
the user might submit inside your application.</p>
@@ -0,0 +1,381 @@
page.title=Searchable Configuration
parent.title=Search
parent.link=index.html
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>See also</h2>
<ol>
<li><a href="search-dialog.html">Using the Android Search Dialog</a></li>
<li><a href="adding-recent-query-suggestions.html">Adding Recent Query Suggestions</a></li>
<li><a href="adding-custom-suggestions.html">Adding Custom Suggestions</a></li>
</ol>
</div>
</div>
<p>To utilize the Android search framework and provide a custom search dialog, your
application must provide a search
configuration in the form of an XML resource. This document describes the search configuration XML
in terms of its syntax and usage. For more information about how to implement search
features for your application, see the developer guide about <a
href="index.html">Search</a>.</p>
<dl class="xml">
<dt>file location:</dt>
<dd><code>res/xml/<em>filename</em>.xml</code><br/>
Android uses the filename as the resource ID.</dd>
<dt>syntax:</dt>
<dd>
<pre class="stx">
&lt;?xml version="1.0" encoding="utf-8"?>
&lt;<a href="#searchable-element">searchable</a> xmlns:android="http://schemas.android.com/apk/res/android"
android:label="<em>string resource</em>"
android:hint="<em>string resource</em>"
android:searchMode=["queryRewriteFromData" | "queryRewriteFromText"]
android:searchButtonText="<em>string resource</em>"
android:inputType="<em>{@link android.R.attr#inputType}</em>"
android:imeOptions="<em>{@link android.R.attr#imeOptions}</em>"
android:searchSuggestAuthority="<em>string</em>"
android:searchSuggestPath="<em>string</em>"
android:searchSuggestSelection="<em>string</em>"
android:searchSuggestIntentAction="<em>string</em>"
android:searchSuggestIntentData="<em>string</em>"
android:searchSuggestThreshold="<em>int</em>"
android:includeInGlobalSearch=["true" | "false"]
android:searchSettingsDescription="<em>string resource</em>"
android:queryAfterZeroResults=["true" | "false"]
android:voiceSearchMode=["showVoiceSearchButton" | "launchWebSearch" | "launchRecognizer"]
android:voiceLanguageModel=["free-form" | "web_search"]
android:voicePromptText="<em>string resource</em>"
android:voiceLanguage="<em>string</em>"
android:voiceMaxResults="<em>int</em>"
&gt;
&lt;<a href="#actionkey-element">actionkey</a>
android:keycode="<em>{@link android.view.KeyEvent KEYCODE}</em>"
android:queryActionMsg="<em>string</em>"
android:suggestActionMsg="<em>string</em>"
android:suggestActionMsgColumn="<em>string</em>" &gt;
&lt;/searchable&gt;
</pre>
</dd>
<dt>elements:</dt>
<dd>
<dl class="tag-list">
<dt id="searchable-element"><code>&lt;searchable&gt;</code></dt>
<dd>Defines all search configurations used with the search dialog.
<p class="caps">attributes:</p>
<dl class="atn-list">
<dt><code>android:label</code></dt>
<dd><em>String resource</em>. (Required.) The name of your application.
It should be the same as the name applied to the {@code android:label} attribute of your <a
href="{@docRoot}guide/topics/manifest/activity-element.html#label">{@code &lt;activity&gt;}</a> or
<a href="{@docRoot}guide/topics/manifest/application-element.html#label">{@code
&lt;application&gt;}</a> manifest element. This label is only visible to the user when you set
<code>android:includeInGlobalSearch</code> to "true", in which case, this label is used to identify
your application as a searchable item in the system's search settings.</dd>
<dt><code>android:hint</code></dt>
<dd><em>String resource</em>. (Recommended.) The text to display in the search text field when
no text has been entered. It provides a hint to the user about what
content is searchable. For consistency with other Android applications, you should format the
string for {@code android:hint} as "Search <em>&lt;content-or-product&gt;</em>". For example,
"Search songs and artists" or "Search YouTube".</dd>
<dt><code>android:searchMode</code></dt>
<dd><em>Keyword</em>. Sets additional modes that control the search dialog presentation.
Currently available modes define how the query text that appears in the search dialog
should be rewritten when a custom suggestion receives focus. The following mode values are accepted:
<table>
<tr><th>Value</th><th>Description</th></tr>
<tr>
<td><code>"queryRewriteFromText"</code></td>
<td>Use the value from the {@link android.app.SearchManager#SUGGEST_COLUMN_TEXT_1}
colum to rewrite the query text in the search dialog.</td>
</tr>
<tr>
<td><code>"queryRewriteFromData"</code></td>
<td>Use the value from the
{@link android.app.SearchManager#SUGGEST_COLUMN_INTENT_DATA} column to rewrite the
query text in the search dialog. This should only be used when the values in
{@link android.app.SearchManager#SUGGEST_COLUMN_INTENT_DATA} are suitable for user
inspection and editing, typically HTTP URI's.</td>
</tr>
</table>
<p>For more information, see the discussion about rewriting the query text in <a
href="adding-custom-suggestions.html#RewritingQueryText">Adding Custom Suggestions</a>.</p>
</dd>
<dt><code>android:searchButtonText</code></dt>
<dd><em>String resource</em>. The text to display in the button that executes search. By
default, the button shows a search icon (a magnifying glass), which is ideal for
internationalization, so you should not use this attribute to change the button unless the
behavior is something other than a search (such as a URL request in a web browser).</dd>
<dt><code>android:inputType</code></dt>
<dd><em>Keyword</em>. Defines the type of input method (such as the type of soft keyboard)
to use with the search dialog. For most searches, in which free-form text is expected, you don't
need this attribute. See {@link android.R.attr#inputType} for a list of suitable values for this
attribute.</dd>
<dt><code>android:imeOptions</code></dt>
<dd><em>Keyword</em>. Supplies additional options for the input method.
For most searches, in which free-form text is expected, you don't need this attribute. The
default IME is "actionSearch" (provides the "search" button instead of a carriage
return in the soft keyboard). See {@link android.R.attr#imeOptions} for a list of suitable values
for this attribute.
</dd>
</dl>
<h4>Search suggestion attributes</h4>
<p>If you have defined a content provider to generate search suggestions, you need to
define additional attributes that configure communications with the content
provider. When providing search suggestions, you need some of the following
{@code &lt;searchable>} attributes:</p><br/>
<dl class="atn-list">
<dt><code>android:searchSuggestAuthority</code></dt>
<dd><em>String</em>. (Required to provide search suggestions.)
This value must match the authority string provided in the {@code android:authorities}
attribute of the Android manifest {@code &lt;provider>} element.</dd>
<dt><code>android:searchSuggestPath</code></dt>
<dd><em>String</em>. This path is used as a portion of the suggestions
query {@link android.net.Uri}, after the prefix and authority, but before
the standard suggestions path.
This is only required if you have a single content provider issuing different types
of suggestions (such as for different data types) and you need
a way to disambiguate the suggestions queries when you receive them.</dd>
<dt><code>android:searchSuggestSelection</code></dt>
<dd><em>String</em>. This value is passed into your
query function as the {@code selection} parameter. Typically this is a WHERE clause
for your database, and should contain a single question mark, which is a placeholder for the
actual query string that has been typed by the user (for example, {@code "query=?"}). However, you
can also use any non-null value to trigger the delivery of the query text via the {@code
selectionArgs} parameter (and then ignore the {@code selection} parameter).</dd>
<dt><code>android:searchSuggestIntentAction</code></dt>
<dd><em>String</em>. The default Intent action to be used when a user
clicks on a custom search suggestion (such as {@code "android.intent.action.VIEW"}).
If this is not overridden by the selected suggestion (via the {@link
android.app.SearchManager#SUGGEST_COLUMN_INTENT_ACTION} column), this value is placed in the action
field of the {@link android.content.Intent} when the user clicks a suggestion.</dd>
<dt><code>android:searchSuggestIntentData</code></dt>
<dd><em>String</em>. The default Intent data to be used when a user
clicks on a custom search suggestion.
If not overridden by the selected suggestion (via the {@link
android.app.SearchManager#SUGGEST_COLUMN_INTENT_DATA} column), this value is
placed in the data field of the {@link android.content.Intent} when the user clicks
a suggestion.</dd>
<dt><code>android:searchSuggestThreshold</code></dt>
<dd><em>Integer</em>. The minimum number of characters needed to
trigger a suggestion look-up. Only guarantees that the Search Manager will not query your
content provider for anything shorter than the threshold. The default value is 0.</dd>
</dl>
<p>For more information about the above attributes for search suggestions, see the guides for
<a href="adding-recent-query-suggestions.html">Adding Recent Query Suggestions</a> and
<a href="adding-custom-suggestions.html">Adding Custom Suggestions</a>.</p>
<h4>Quick Search Box attributes</h4>
<p>To make your custom search suggestions available to Quick Search Box, you need some of the
following {@code &lt;searchable>} attributes:</p><br/>
<dl class="atn-list">
<dt><code>android:includeInGlobalSearch</code></dt>
<dd><em>Boolean</em>. (Required to provide search suggestions in
Quick Search Box.) Set to "true" if you want your suggestions to be
included in the globally accessible Quick Search Box. The user must
still enable your application as a searchable item in the system search settings before
your suggestions will appear in Quick Search Box.</dd>
<dt><code>android:searchSettingsDescription</code></dt>
<dd><em>String</em>. Provides a brief description of the search suggestions that you provide
to Quick Search Box, which is displayed in the searchable items entry for your application.
Your description should concisely describe the content that is searchable. For example, "Artists,
albums, and tracks" for a music application, or "Saved notes" for a notepad application.</dd>
<dt><code>android:queryAfterZeroResults</code></dt>
<dd><em>Boolean</em>. Set to "true" if you want your content provider to be invoked for
supersets of queries that have returned zero results in the past. For example, if
your content provider returned zero results for "bo", it should be requiried for "bob". If set to
"false", supersets are ignored for a single session ("bob" does not invoke a requery). This lasts
only for the life of the search dialog (when the search dialog is reopened, "bo" queries your
content provider again). The default value is false.</dd>
</dl>
<h4>Voice search attributes</h4>
<p>To enable voice search for your search dialog, you'll need some of the
following {@code &lt;searchable>} attributes:</p><br/>
<dl class="atn-list">
<dt><code>android:voiceSearchMode</code></dt>
<dd><em>Keyword</em>. (Required to provide voice search capabilities.)
Enables voice search for the search dialog, with a specific mode for voice search.
(Voice search may not be provided by the device, in which case these flags
have no effect.) The following mode values are accepted:
<table>
<tr><th>Value</th><th>Description</th></tr>
<tr>
<td><code>"showVoiceSearchButton"</code></td>
<td>Display a voice search button, if voice search is available on the device. If set,
then either {@code "launchWebSearch"} or {@code "launchRecognizer"} must also be set
(separated by the pipe | character).</td>
</tr>
<tr>
<td><code>"launchWebSearch"</code></td>
<td>The voice search button takes the user directly
to a built-in voice web search activity. Most applications don't need this flag, as
it takes the user away from the Activity in which search was invoked.</td>
</tr>
<tr>
<td><code>"launchRecognizer"</code></td>
<td>The voice search button takes
the user directly to a built-in voice recording activity. This Activity
prompts the user to speak, transcribes the spoken text, and forwards the resulting
query text to the searchable Activity, just as if the user typed it into the
search UI and clicked the search button.</td>
</tr>
</table>
</dd>
<dt><code>android:voiceLanguageModel</code></dt>
<dd><em>Keyword</em>. The language model that
should be used by the voice recognition system. The following values are accepted:
<table>
<tr><th>Value</th><th>Description</th></tr>
<tr>
<td><code>"free_form"</code></td>
<td>Use free-form speech recognition for dictating queries. This is primarily
optimized for English. This is the default.</td>
</tr>
<tr>
<td><code>"web_search"</code></td>
<td>Use web-search-term recognition for shorter, search-like phrases. This is
available in more languages than "free_form".</td>
</tr>
</table>
<p>Also see
{@link android.speech.RecognizerIntent#EXTRA_LANGUAGE_MODEL} for more
information.</p></dd>
<dt><code>android:voicePromptText</code></dt>
<dd><em>String</em>. An additional message to display in the voice input dialog.</dd>
<dt><code>android:voiceLanguage</code></dt>
<dd><em>String</em>. The spoken language to be expected, expressed as the string value of
a constants in {@link java.util.Locale} (such as {@code "de"} for German or {@code "fr"} for
French). This is needed only if it is different from the current value of {@link
java.util.Locale#getDefault() Locale.getDefault()}.</dd>
<dt><code>android:voiceMaxResults</code></dt>
<dd><em>Integer</em>. Forces the maximum number of results to return,
including the "best" result which is always provided as the {@link
android.content.Intent#ACTION_SEARCH} Intent's primary
query. Must be 1 or greater. Use {@link android.speech.RecognizerIntent#EXTRA_RESULTS} to
get the results from the Intent.
If not provided, the recognizer chooses how many results to return.</dd>
</dl>
</dd> <!-- end searchable element -->
<dt id="actionkey-element"><code>&lt;actionkey&gt;</code></dt>
<dd>Defines a device key and behavior for a search action. A search action provides a
special behavior at the touch of a button on the device, based on the current query or focused
suggestion. For example, the Contacts application provides a search action to initiate a phone call
to the currenly focused contact suggestion at the press of the CALL button.
<p>Not all action keys are available on every device, and not
all keys are allowed to be overriden in this way. For example, the "Home" key cannot be used and
must always return to the home screen. Also be sure not to define an action
key for a key that's needed for typing a search query. This essentially limits the
available and reasonable action keys to the call button and menu button. Also note that action
keys are not generally discoverable, so you should not provide them as a core user feature.</p>
<p>You must define the <code>android:keycode</code> to define the key and at least one of the
other three attributes in order to define the search action.</p>
<p class="caps">attributes:</p>
<dl class="atn-list">
<dt><code>android:keycode</code></dt>
<dd><em>String</em>. (Required.) A key code from {@link
android.view.KeyEvent} that represents the action key
you wish to respond to (for example {@code "KEYCODE_CALL"}). This is added to the
{@link android.content.Intent#ACTION_SEARCH ACTION_SEARCH} Intent that is passed to your
searchable Activity. To examine the key code, use
{@link android.content.Intent#getIntExtra getIntExtra(SearchManager.ACTION_KEY)}. Not all
keys are supported for a search action, as many of them are used for typing, navigation, or system
functions.</dd>
<dt><code>android:queryActionMsg</code></dt>
<dd><em>String</em>. An action message to be sent if the action key is pressed while the
user is entering query text. This is added to the
{@link android.content.Intent#ACTION_SEARCH ACTION_SEARCH} Intent that the Search Manager
passes to your searchable Activity. To examine the string, use
{@link android.content.Intent#getStringExtra
getStringExtra(SearchManager.ACTION_MSG)}.</dd>
<dt><code>android:suggestActionMsg</code></dt>
<dd><em>String</em>. An action message to be sent if the action key is pressed while a
suggestion is in focus. This is added to the
Intent that that the Search Manager passes to your searchable Activity (using the action
you've defined for the suggestion). To examine the string,
use {@link android.content.Intent#getStringExtra
getStringExtra(SearchManager.ACTION_MSG)}. This should only be used if all your
suggestions support this action key. If not all suggestions can handle the same action key, then
you must instead use the following {@code android:suggestActionMsgColumn} attribute.</dd>
<dt><code>android:suggestActionMsgColumn</code></dt>
<dd><em>String</em>. The name of the column in your content provider that defines the
action message for this action key, which is to be sent if the user presses the action key while a
suggestion is in focus. This attribute lets you control the
action key on a suggestion-by-suggestion basis, because, instead of using the {@code
android:suggestActionMsg} attribute to define the action message for all suggestions, each entry in
your content provider provides its own action message.
<p>First, you must define a column in your
content provider for each suggestion to provide an action message, then provide the name of that
column in this attribute. The Search Manager looks at your suggestion cursor,
using the string provided here to select your action message column, and
then select the action message string from the Cursor. That string is added to the
Intent that the Search Manager passes to your searchable Activity (using the action you've
defined for suggestions). To examine the string, use {@link
android.content.Intent#getStringExtra getStringExtra(SearchManager.ACTION_MSG)}. If the data
does not exist for the selected suggestion, the action key is ignored.</dd>
</dl>
</dd><!-- end action key -->
</dl>
</dd><!-- end elements -->
<dt>example:</dt>
<dd>XML file saved at <code>res/xml/searchable.xml</code>:
<pre>
&lt;?xml version="1.0" encoding="utf-8"?>
&lt;searchable xmlns:android="http://schemas.android.com/apk/res/android"
android:label="@string/search_label"
android:hint="@string/search_hint"
android:searchSuggestAuthority="dictionary"
android:searchSuggestIntentAction="android.intent.action.VIEW"
android:includeInGlobalSearch="true"
android:searchSettingsDescription="@string/settings_description" >
&lt;/searchable>
</pre>
</dd> <!-- end example -->
</dl>
@@ -0,0 +1,402 @@
page.title=Security and Permissions
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>In this document</h2>
<ol>
<li><a href="#arch">Security Architecture</a></li>
<li><a href="#signing">Application Signing</a></li>
<li><a href="#userid">User IDs and File Access</a></li>
<li><a href="#permissions">Using Permissions</a></li>
<li><a href="#declaring">Declaring and Enforcing Permissions</a>
<ol>
<li><a href="#manifest">...in AndroidManifest.xml</a></li>
<li><a href="#broadcasts">...when Sending Broadcasts</a></li>
<li><a href="#enforcement">Other Permission Enforcement</a></li>
</ol></li>
<li><a href="#uri">URI Permissions</a></li>
</ol>
</div>
</div>
<p>Android is a privilege-separated operating system, in which each
application runs with a distinct system identity (Linux user ID and group
ID). Parts of the system are also separated into distinct identities.
Linux thereby isolates applications from each other and from the system.</p>
<p>Additional finer-grained security features are provided through a
"permission" mechanism that enforces restrictions on the specific operations
that a particular process can perform, and per-URI permissions for granting
ad-hoc access to specific pieces of data.</p>
<a name="arch"></a>
<h2>Security Architecture</h2>
<p>A central design point of the Android security architecture is that no
application, by default, has permission to perform any operations that would
adversely impact other applications, the operating system, or the user. This
includes reading or writing the user's private data (such as contacts or
e-mails), reading or writing another application's files, performing
network access, keeping the device awake, etc.</p>
<p>Because the kernel sandboxes applications from each other, applications
must explicitly share resources and data. They do this by declaring the
<em>permissions</em> they need for additional capabilities not provided by
the basic sandbox. Applications statically declare the permissions they
require, and the Android system prompts the user for consent at the time the
application is installed. Android has no mechanism for granting permissions
dynamically (at run-time) because it complicates the user experience to the
detriment of security.</p>
<p>The kernel is solely responsible for sandboxing applications from each
other. In particular the Dalvik VM is not a security boundary, and any app
can run native code (see <a href="/sdk/ndk/index.html">the Android NDK</a>).
All types of applications &mdash; Java, native, and hybrid &mdash; are
sandboxed in the same way and have the same degree of security from each
other.</p>
<a name="signing"></a>
<h2>Application Signing</h2>
<p>All Android applications (.apk files) must be signed with a certificate
whose private key is held by their developer. This certificate identifies
the author of the application. The certificate does <em>not</em> need to be
signed by a certificate authority: it is perfectly allowable, and typical,
for Android applications to use self-signed certificates. The purpose of
certificates in Android is to distinguish application authors. This allows
the system to grant or deny applications access to <a
href="/guide/topics/manifest/permission-element.html#plevel">signature-level
permissions</a> and to grant or deny an application's <a
href="/guide/topics/manifest/manifest-element.html#uid">request to be given
the same Linux identity</a> as another application.</p>
<a name="userid"></a>
<h2>User IDs and File Access</h2>
<p>At install time, Android gives each package a distinct Linux user ID. The
identity remains constant for the duration of the package's life on that
device. On a different device, the same package may have a different UID;
what matters is that each package has a distinct UID on a given device.</p>
<p>Because security enforcement happens at the
process level, the code of any two packages can not normally
run in the same process, since they need to run as different Linux users.
You can use the {@link android.R.attr#sharedUserId} attribute in the
<code>AndroidManifest.xml</code>'s
{@link android.R.styleable#AndroidManifest manifest} tag of each package to
have them assigned the same user ID. By doing this, for purposes of security
the two packages are then treated as being the same application, with the same
user ID and file permissions. Note that in order to retain security, only two applications
signed with the same signature (and requesting the same sharedUserId) will
be given the same user ID.</p>
<p>Any data stored by an application will be assigned that application's user
ID, and not normally accessible to other packages. When creating a new file
with {@link android.content.Context#getSharedPreferences},
{@link android.content.Context#openFileOutput}, or
{@link android.content.Context#openOrCreateDatabase},
you can use the
{@link android.content.Context#MODE_WORLD_READABLE} and/or
{@link android.content.Context#MODE_WORLD_WRITEABLE} flags to allow any other
package to read/write the file. When setting these flags, the file is still
owned by your application, but its global read and/or write permissions have
been set appropriately so any other application can see it.</p>
<a name="permissions"></a>
<h2>Using Permissions</h2>
<p>A basic Android application has no permissions associated with it,
meaning it can not do anything that would adversely impact the user experience
or any data on the device. To make use of protected features of the device,
you must include in your <code>AndroidManifest.xml</code> one or more
<code>{@link android.R.styleable#AndroidManifestUsesPermission &lt;uses-permission&gt;}</code>
tags declaring the permissions that your application needs.</p>
<p>For example, an application that needs to monitor incoming SMS messages would
specify:</p>
<pre>&lt;manifest xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
package=&quot;com.android.app.myapp&quot; &gt;
&lt;uses-permission android:name=&quot;android.permission.RECEIVE_SMS&quot; /&gt;
...
&lt;/manifest&gt;</pre>
<p>At application install time, permissions requested by the application are
granted to it by the package installer, based on checks against the
signatures of the applications declaring those permissions and/or interaction
with the user. <em>No</em> checks with the user
are done while an application is running: it either was granted a particular
permission when installed, and can use that feature as desired, or the
permission was not granted and any attempt to use the feature will fail
without prompting the user.</p>
<p>Often times a permission failure will result in a {@link
java.lang.SecurityException} being thrown back to the application. However,
this is not guaranteed to occur everywhere. For example, the {@link
android.content.Context#sendBroadcast} method checks permissions as data is
being delivered to each receiver, after the method call has returned, so you
will not receive an exception if there are permission failures. In almost all
cases, however, a permission failure will be printed to the system log.</p>
<p>The permissions provided by the Android system can be found at {@link
android.Manifest.permission}. Any application may also define and enforce its
own permissions, so this is not a comprehensive list of all possible
permissions.</p>
<p>A particular permission may be enforced at a number of places during your
program's operation:</p>
<ul>
<li>At the time of a call into the system, to prevent an application from
executing certain functions.</li>
<li>When starting an activity, to prevent applications from launching
activities of other applications.</li>
<li>Both sending and receiving broadcasts, to control who can receive
your broadcast or who can send a broadcast to you.</li>
<li>When accessing and operating on a content provider.</li>
<li>Binding to or starting a service.</li>
</ul>
<a name="declaring"></a>
<h2>Declaring and Enforcing Permissions</h2>
<p>To enforce your own permissions, you must first declare them in your
<code>AndroidManifest.xml</code> using one or more
<code>{@link android.R.styleable#AndroidManifestPermission &lt;permission&gt;}</code>
tags.</p>
<p>For example, an application that wants to control who can start one
of its activities could declare a permission for this operation as follows:</p>
<pre>&lt;manifest xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
package=&quot;com.me.app.myapp&quot; &gt;
&lt;permission android:name=&quot;com.me.app.myapp.permission.DEADLY_ACTIVITY&quot;
android:label=&quot;&#64;string/permlab_deadlyActivity&quot;
android:description=&quot;&#64;string/permdesc_deadlyActivity&quot;
android:permissionGroup=&quot;android.permission-group.COST_MONEY&quot;
android:protectionLevel=&quot;dangerous&quot; /&gt;
...
&lt;/manifest&gt;</pre>
<p>The {@link android.R.styleable#AndroidManifestPermission_protectionLevel
&lt;protectionLevel&gt;} attribute is required, telling the system how the
user is to be informed of applications requiring the permission, or who is
allowed to hold that permission, as described in the linked documentation.</p>
<p>The {@link android.R.styleable#AndroidManifestPermission_permissionGroup
&lt;permissionGroup&gt;} attribute is optional, and only used to help the system display
permissions to the user. You will usually want to set this to either a standard
system group (listed in {@link android.Manifest.permission_group
android.Manifest.permission_group}) or in more rare cases to one defined by
yourself. It is preferred to use an existing group, as this simplifies the
permission UI shown to the user.</p>
<p>Note that both a label and description should be supplied for the
permission. These are string resources that can be displayed to the user when
they are viewing a list of permissions
(<code>{@link android.R.styleable#AndroidManifestPermission_label android:label}</code>)
or details on a single permission (
<code>{@link android.R.styleable#AndroidManifestPermission_description android:description}</code>).
The label should be short, a few words
describing the key piece of functionality the permission is protecting. The
description should be a couple sentences describing what the permission allows
a holder to do. Our convention for the description is two sentences, the first
describing the permission, the second warning the user of what bad things
can happen if an application is granted the permission.</p>
<p>Here is an example of a label and description for the CALL_PHONE
permission:</p>
<pre>
&lt;string name=&quot;permlab_callPhone&quot;&gt;directly call phone numbers&lt;/string&gt;
&lt;string name=&quot;permdesc_callPhone&quot;&gt;Allows the application to call
phone numbers without your intervention. Malicious applications may
cause unexpected calls on your phone bill. Note that this does not
allow the application to call emergency numbers.&lt;/string&gt;
</pre>
<p>You can look at the permissions currently defined in the system with the
shell command <code>adb shell pm list permissions</code>. In particular,
the '-s' option displays the permissions in a form roughly similar to how the
user will see them:</p>
<pre>
$ adb shell pm list permissions -s
All Permissions:
Network communication: view Wi-Fi state, create Bluetooth connections, full
Internet access, view network state
Your location: access extra location provider commands, fine (GPS) location,
mock location sources for testing, coarse (network-based) location
Services that cost you money: send SMS messages, directly call phone numbers
...</pre>
<a name="manifest"></a>
<h3>Enforcing Permissions in AndroidManifest.xml</h3>
<p>High-level permissions restricting access to entire components of the
system or application can be applied through your
<code>AndroidManifest.xml</code>. All that this requires is including an {@link
android.R.attr#permission android:permission} attribute on the desired
component, naming the permission that will be used to control access to
it.</p>
<p><strong>{@link android.app.Activity}</strong> permissions
(applied to the
{@link android.R.styleable#AndroidManifestActivity &lt;activity&gt;} tag)
restrict who can start the associated
activity. The permission is checked during
{@link android.content.Context#startActivity Context.startActivity()} and
{@link android.app.Activity#startActivityForResult Activity.startActivityForResult()};
if the caller does not have
the required permission then {@link java.lang.SecurityException} is thrown
from the call.</p>
<p><strong>{@link android.app.Service}</strong> permissions
(applied to the
{@link android.R.styleable#AndroidManifestService &lt;service&gt;} tag)
restrict who can start or bind to the
associated service. The permission is checked during
{@link android.content.Context#startService Context.startService()},
{@link android.content.Context#stopService Context.stopService()} and
{@link android.content.Context#bindService Context.bindService()};
if the caller does not have
the required permission then {@link java.lang.SecurityException} is thrown
from the call.</p>
<p><strong>{@link android.content.BroadcastReceiver}</strong> permissions
(applied to the
{@link android.R.styleable#AndroidManifestReceiver &lt;receiver&gt;} tag)
restrict who can send broadcasts to the associated receiver.
The permission is checked <em>after</em>
{@link android.content.Context#sendBroadcast Context.sendBroadcast()} returns,
as the system tries
to deliver the submitted broadcast to the given receiver. As a result, a
permission failure will not result in an exception being thrown back to the
caller; it will just not deliver the intent. In the same way, a permission
can be supplied to
{@link android.content.Context#registerReceiver(android.content.BroadcastReceiver, android.content.IntentFilter, String, android.os.Handler)
Context.registerReceiver()}
to control who can broadcast to a programmatically registered receiver.
Going the other way, a permission can be supplied when calling
{@link android.content.Context#sendBroadcast(Intent, String) Context.sendBroadcast()}
to restrict which BroadcastReceiver objects are allowed to receive the broadcast (see
below).</p>
<p><strong>{@link android.content.ContentProvider}</strong> permissions
(applied to the
{@link android.R.styleable#AndroidManifestProvider &lt;provider&gt;} tag)
restrict who can access the data in
a {@link android.content.ContentProvider}. (Content providers have an important
additional security facility available to them called
<a href="#uri">URI permissions</a> which is described later.)
Unlike the other components,
there are two separate permission attributes you can set:
{@link android.R.attr#readPermission android:readPermission} restricts who
can read from the provider, and
{@link android.R.attr#writePermission android:writePermission} restricts
who can write to it. Note that if a provider is protected with both a read
and write permission, holding only the write permission does not mean
you can read from a provider. The permissions are checked when you first
retrieve a provider (if you don't have either permission, a SecurityException
will be thrown), and as you perform operations on the provider. Using
{@link android.content.ContentResolver#query ContentResolver.query()} requires
holding the read permission; using
{@link android.content.ContentResolver#insert ContentResolver.insert()},
{@link android.content.ContentResolver#update ContentResolver.update()},
{@link android.content.ContentResolver#delete ContentResolver.delete()}
requires the write permission.
In all of these cases, not holding the required permission results in a
{@link java.lang.SecurityException} being thrown from the call.</p>
<a name="broadcasts"></a>
<h3>Enforcing Permissions when Sending Broadcasts</h3>
<p>In addition to the permission enforcing who can send Intents to a
registered {@link android.content.BroadcastReceiver} (as described above), you
can also specify a required permission when sending a broadcast. By calling {@link
android.content.Context#sendBroadcast(android.content.Intent,String)
Context.sendBroadcast()} with a
permission string, you require that a receiver's application must hold that
permission in order to receive your broadcast.</p>
<p>Note that both a receiver and a broadcaster can require a permission. When
this happens, both permission checks must pass for the Intent to be delivered
to the associated target.</p>
<a name="enforcement"></a>
<h3>Other Permission Enforcement</h3>
<p>Arbitrarily fine-grained permissions can be enforced at any call into a
service. This is accomplished with the {@link
android.content.Context#checkCallingPermission Context.checkCallingPermission()}
method. Call with a desired
permission string and it will return an integer indicating whether that
permission has been granted to the current calling process. Note that this can
only be used when you are executing a call coming in from another process,
usually through an IDL interface published from a service or in some other way
given to another process.</p>
<p>There are a number of other useful ways to check permissions. If you have
the pid of another process, you can use the Context method {@link
android.content.Context#checkPermission(String, int, int) Context.checkPermission(String, int, int)}
to check a permission against that pid. If you have the package name of another
application, you can use the direct PackageManager method {@link
android.content.pm.PackageManager#checkPermission(String, String)
PackageManager.checkPermission(String, String)}
to find out whether that particular package has been granted a specific permission.</p>
<a name="uri"></a>
<h2>URI Permissions</h2>
<p>The standard permission system described so far is often not sufficient
when used with content providers. A content provider may want to
protect itself with read and write permissions, while its direct clients
also need to hand specific URIs to other applications for them to operate on.
A typical example is attachments in a mail application. Access to the mail
should be protected by permissions, since this is sensitive user data. However,
if a URI to an image attachment is given to an image viewer, that image viewer
will not have permission to open the attachment since it has no reason to hold
a permission to access all e-mail.</p>
<p>The solution to this problem is per-URI permissions: when starting an
activity or returning a result to an activity, the caller can set
{@link android.content.Intent#FLAG_GRANT_READ_URI_PERMISSION
Intent.FLAG_GRANT_READ_URI_PERMISSION} and/or
{@link android.content.Intent#FLAG_GRANT_WRITE_URI_PERMISSION
Intent.FLAG_GRANT_WRITE_URI_PERMISSION}. This grants the receiving activity
permission access the specific data URI in the Intent, regardless of whether
it has any permission to access data in the content provider corresponding
to the Intent.</p>
<p>This mechanism allows a common capability-style model where user interaction
(opening an attachment, selecting a contact from a list, etc) drives ad-hoc
granting of fine-grained permission. This can be a key facility for reducing
the permissions needed by applications to only those directly related to their
behavior.</p>
<p>The granting of fine-grained URI permissions does, however, require some
cooperation with the content provider holding those URIs. It is strongly
recommended that content providers implement this facility, and declare that
they support it through the
{@link android.R.styleable#AndroidManifestProvider_grantUriPermissions
android:grantUriPermissions} attribute or
{@link android.R.styleable#AndroidManifestGrantUriPermission
&lt;grant-uri-permissions&gt;} tag.</p>
<p>More information can be found in the
{@link android.content.Context#grantUriPermission Context.grantUriPermission()},
{@link android.content.Context#revokeUriPermission Context.revokeUriPermission()}, and
{@link android.content.Context#checkUriPermission Context.checkUriPermission()}
methods.</p>
@@ -0,0 +1,18 @@
page.title=Accelerometer
parent.title=Sensors
parent.link=index.html
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>In this document</h2>
<ol>
</ol>
</div>
</div>
TODO
@@ -0,0 +1,18 @@
page.title=Camera
parent.title=Sensors
parent.link=index.html
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>Key class</h2>
<ol>
<li>{@link android.hardware.Camera android.hardware.Camera}</li>
</ol>
<h2>In this document</h2>
<ol>
<li>TODO</li>
</ol>
</div>
</div>
@@ -0,0 +1,18 @@
page.title=Compass
parent.title=Sensors
parent.link=index.html
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>In this document</h2>
<ol>
</ol>
</div>
</div>
TODO
@@ -0,0 +1,13 @@
page.title=Sensors
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>Accelerometer</h2>
<p>The accelerometer sensors allow you to detect the various movements of the device.</p>
<h2>Compass</h2>
<p>The compass provides data on the devices current polar orientation.</p>
@@ -0,0 +1,392 @@
page.title=Activity Testing
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>In this document</h2>
<ol>
<li>
<a href="#ActivityTestAPI">The Activity Testing API</a>
<ol>
<li>
<a href="#ActivityInstrumentationTestCase2">ActivityInstrumentationTestCase2</a>
</li>
<li>
<a href="#ActivityUnitTestCase">ActivityUnitTestCase</a>
</li>
<li>
<a href="#SingleLaunchActivityTestCase">SingleLaunchActivityTestCase</a>
</li>
<li>
<a href="#MockObjectNotes">Mock objects and activity testing</a>
</li>
<li>
<a href="#AssertionNotes">Assertions for activity testing</a>
</li>
</ol>
</li>
<li>
<a href="#WhatToTest">What to Test</a>
</li>
<li>
<a href="#NextSteps">Next Steps</a>
</li>
<li>
<a href="#UITesting">Appendix: UI Testing Notes</a>
<ol>
<li>
<a href="#RunOnUIThread">Testing on the UI thread</a>
</li>
<li>
<a href="#NotouchMode">Turning off touch mode</a>
</li>
<li>
<a href="#UnlockDevice">Unlocking the Emulator or Device</a>
</li>
<li>
<a href="#UITestTroubleshooting">Troubleshooting UI tests</a>
</li>
</ol>
</li>
</ol>
<h2>Key Classes</h2>
<ol>
<li>{@link android.test.InstrumentationTestRunner}</li>
<li>{@link android.test.ActivityInstrumentationTestCase2}</li>
<li>{@link android.test.ActivityUnitTestCase}</li>
</ol>
<h2>Related Tutorials</h2>
<ol>
<li>
<a href="{@docRoot}resources/tutorials/testing/helloandroid_test.html">
Hello, Testing</a>
</li>
<li>
<a href="{@docRoot}resources/tutorials/testing/activity_test.html">Activity Testing</a>
</li>
</ol>
<h2>See Also</h2>
<ol>
<li>
<a href="{@docRoot}guide/developing/testing/testing_eclipse.html">
Testing in Eclipse, with ADT</a>
</li>
<li>
<a href="{@docRoot}guide/developing/testing/testing_otheride.html">
Testing in Other IDEs</a>
</li>
</ol>
</div>
</div>
<p>
Activity testing is particularly dependent on the the Android instrumentation framework.
Unlike other components, activities have a complex lifecycle based on callback methods; these
can't be invoked directly except by instrumentation. Also, the only way to send events to the
user interface from a program is through instrumentation.
</p>
<p>
This document describes how to test activities using instrumentation and other test
facilities. The document assumes you have already read
<a href="{@docRoot}guide/topics/testing/testing_android.html">Testing Fundamentals</a>,
the introduction to the Android testing and instrumentation framework.
</p>
<h2 id="ActivityTestAPI">The Activity Testing API</h2>
<p>
The activity testing API base class is {@link android.test.InstrumentationTestCase},
which provides instrumentation to the test case subclasses you use for Activities.
</p>
<p>
For activity testing, this base class provides these functions:
</p>
<ul>
<li>
Lifecycle control: With instrumentation, you can start the activity under test, pause it,
and destroy it, using methods provided by the test case classes.
</li>
<li>
Dependency injection: Instrumentation allows you to create mock system objects such as
Contexts or Applications and use them to run the activity under test. This
helps you control the test environment and isolate it from production systems. You can
also set up customized Intents and start an activity with them.
</li>
<li>
User interface interaction: You use instrumentation to send keystrokes or touch events
directly to the UI of the activity under test.
</li>
</ul>
<p>
The activity testing classes also provide the JUnit framework by extending
{@link junit.framework.TestCase} and {@link junit.framework.Assert}.
</p>
<p>
The two main testing subclasses are {@link android.test.ActivityInstrumentationTestCase2} and
{@link android.test.ActivityUnitTestCase}. To test an Activity that is launched in a mode
other than <code>standard</code>, you use {@link android.test.SingleLaunchActivityTestCase}.
</p>
<h3 id="ActivityInstrumentationTestCase2">ActivityInstrumentationTestCase2</h3>
<p>
The {@link android.test.ActivityInstrumentationTestCase2} test case class is designed to do
functional testing of one or more Activities in an application, using a normal system
infrastructure. It runs the Activities in a normal instance of the application under test,
using a standard system Context. It allows you to send mock Intents to the activity under
test, so you can use it to test an activity that responds to multiple types of intents, or
an activity that expects a certain type of data in the intent, or both. Notice, though, that it
does not allow mock Contexts or Applications, so you can not isolate the test from the rest of
a production system.
</p>
<h3 id="ActivityUnitTestCase">ActivityUnitTestCase</h3>
<p>
The {@link android.test.ActivityUnitTestCase} test case class tests a single activity in
isolation. Before you start the activity, you can inject a mock Context or Application, or both.
You use it to run activity tests in isolation, and to do unit testing of methods
that do not interact with Android. You can not send mock Intents to the activity under test,
although you can call
{@link android.app.Activity#startActivity(Intent) Activity.startActivity(Intent)} and then
look at arguments that were received.
</p>
<h3 id="SingleLaunchActivityTestCase">SingleLaunchActivityTestCase</h3>
<p>
The {@link android.test.SingleLaunchActivityTestCase} class is a convenience class for
testing a single activity in an environment that doesn't change from test to test.
It invokes {@link junit.framework.TestCase#setUp() setUp()} and
{@link junit.framework.TestCase#tearDown() tearDown()} only once, instead of once per
method call. It does not allow you to inject any mock objects.
</p>
<p>
This test case is useful for testing an activity that runs in a mode other than
<code>standard</code>. It ensures that the test fixture is not reset between tests. You
can then test that the activity handles multiple calls correctly.
</p>
<h3 id="MockObjectNotes">Mock objects and activity testing</h3>
<p>
This section contains notes about the use of the mock objects defined in
{@link android.test.mock} with activity tests.
</p>
<p>
The mock object {@link android.test.mock.MockApplication} is only available for activity
testing if you use the {@link android.test.ActivityUnitTestCase} test case class.
By default, <code>ActivityUnitTestCase</code>, creates a hidden <code>MockApplication</code>
object that is used as the application under test. You can inject your own object using
{@link android.test.ActivityUnitTestCase#setApplication(Application) setApplication()}.
</p>
<h3 id="AssertionNotes">Assertions for activity testing</h3>
<p>
{@link android.test.ViewAsserts} defines assertions for Views. You use it to verify the
alignment and position of View objects, and to look at the state of ViewGroup objects.
</p>
<h2 id="WhatToTest">What To Test</h2>
<ul>
<li>
Input validation: Test that an activity responds correctly to input values in an
EditText View. Set up a keystroke sequence, send it to the activity, and then
use {@link android.view.View#findViewById(int)} to examine the state of the View. You can
verify that a valid keystroke sequence enables an OK button, while an invalid one leaves the
button disabled. You can also verify that the Activity responds to invalid input by
setting error messages in the View.
</li>
<li>
Lifecycle events: Test that each of your application's activities handles lifecycle events
correctly. In general, lifecycle events are actions, either from the system or from the
user, that trigger a callback method such as <code>onCreate()</code> or
<code>onClick()</code>. For example, an activity should respond to pause or destroy events
by saving its state. Remember that even a change in screen orientation causes the current
activity to be destroyed, so you should test that accidental device movements don't
accidentally lose the application state.
</li>
<li>
Intents: Test that each activity correctly handles the intents listed in the intent
filter specified in its manifest. You can use
{@link android.test.ActivityInstrumentationTestCase2} to send mock Intents to the
activity under test.
</li>
<li>
Runtime configuration changes: Test that each activity responds correctly to the
possible changes in the device's configuration while your application is running. These
include a change to the device's orientation, a change to the current language, and so
forth. Handling these changes is described in detail in the topic
<a href="{@docRoot}guide/topics/resources/runtime-changes.html">Handling Runtime
Changes</a>.
</li>
<li>
Screen sizes and resolutions: Before you publish your application, make sure to test it on
all of the screen sizes and densities on which you want it to run. You can test the
application on multiple sizes and densities using AVDs, or you can test your application
directly on the devices that you are targeting. For more information, see the topic
<a href="{@docRoot}guide/practices/screens_support.html">Supporting Multiple Screens</a>.
</li>
</ul>
<h2 id="NextSteps">Next Steps</h2>
<p>
To learn how to set up and run tests in Eclipse, please refer to <a
href="{@docRoot}guide/developing/testing/testing_eclipse.html">Testing in
Eclipse, with ADT</a>. If you're not working in Eclipse, refer to <a
href="{@docRoot}guide/developing/testing/testing_otheride.html">Testing in Other
IDEs</a>.
</p>
<p>
If you want a step-by-step introduction to testing activities, try one of the
testing tutorials:
</p>
<ul>
<li>
The <a
href="{@docRoot}resources/tutorials/testing/helloandroid_test.html">Hello,
Testing</a> tutorial introduces basic testing concepts and procedures in the
context of the Hello, World application.
</li>
<li>
The <a
href="{@docRoot}resources/tutorials/testing/activity_test.html">Activity
Testing</a> tutorial is an excellent follow-up to the Hello, Testing tutorial.
It guides you through a more complex testing scenario that you develop against a
more realistic activity-oriented application.
</li>
</ul>
<h2 id="UITesting">Appendix: UI Testing Notes</h2>
<p>
The following sections have tips for testing the UI of your Android application, specifically
to help you handle actions that run in the UI thread, touch screen and keyboard events, and home
screen unlock during testing.
</p>
<h3 id="RunOnUIThread">Testing on the UI thread</h3>
<p>
An application's activities run on the application's <strong>UI thread</strong>. Once the
UI is instantiated, for example in the activity's <code>onCreate()</code> method, then all
interactions with the UI must run in the UI thread. When you run the application normally, it
has access to the thread and does not have to do anything special.
</p>
<p>
This changes when you run tests against the application. With instrumentation-based classes,
you can invoke methods against the UI of the application under test. The other test classes
don't allow this. To run an entire test method on the UI thread, you can annotate the thread
with <code>@UIThreadTest</code>. Notice that this will run <em>all</em> of the method statements
on the UI thread. Methods that do not interact with the UI are not allowed; for example, you
can't invoke <code>Instrumentation.waitForIdleSync()</code>.
</p>
<p>
To run a subset of a test method on the UI thread, create an anonymous class of type
<code>Runnable</code>, put the statements you want in the <code>run()</code> method, and
instantiate a new instance of the class as a parameter to the method
<code><em>appActivity</em>.runOnUiThread()</code>, where <code><em>appActivity</em></code> is
the instance of the application you are testing.
</p>
<p>
For example, this code instantiates an activity to test, requests focus (a UI action) for the
Spinner displayed by the activity, and then sends a key to it. Notice that the calls to
<code>waitForIdleSync</code> and <code>sendKeys</code> aren't allowed to run on the UI thread:
</p>
<pre>
private MyActivity mActivity; // MyActivity is the class name of the app under test
private Spinner mSpinner;
...
protected void setUp() throws Exception {
super.setUp();
mInstrumentation = getInstrumentation();
mActivity = getActivity(); // get a references to the app under test
/*
* Get a reference to the main widget of the app under test, a Spinner
*/
mSpinner = (Spinner) mActivity.findViewById(com.android.demo.myactivity.R.id.Spinner01);
...
public void aTest() {
/*
* request focus for the Spinner, so that the test can send key events to it
* This request must be run on the UI thread. To do this, use the runOnUiThread method
* and pass it a Runnable that contains a call to requestFocus on the Spinner.
*/
mActivity.runOnUiThread(new Runnable() {
public void run() {
mSpinner.requestFocus();
}
});
mInstrumentation.waitForIdleSync();
this.sendKeys(KeyEvent.KEYCODE_DPAD_CENTER);
</pre>
<h3 id="NotouchMode">Turning off touch mode</h3>
<p>
To control the emulator or a device with key events you send from your tests, you must turn off
touch mode. If you do not do this, the key events are ignored.
</p>
<p>
To turn off touch mode, you invoke
<code>ActivityInstrumentationTestCase2.setActivityTouchMode(false)</code>
<em>before</em> you call <code>getActivity()</code> to start the activity. You must invoke the
method in a test method that is <em>not</em> running on the UI thread. For this reason, you
can't invoke the touch mode method from a test method that is annotated with
<code>@UIThread</code>. Instead, invoke the touch mode method from <code>setUp()</code>.
</p>
<h3 id="UnlockDevice">Unlocking the emulator or device</h3>
<p>
You may find that UI tests don't work if the emulator's or device's home screen is disabled with
the keyguard pattern. This is because the application under test can't receive key events sent
by <code>sendKeys()</code>. The best way to avoid this is to start your emulator or device
first and then disable the keyguard for the home screen.
</p>
<p>
You can also explicitly disable the keyguard. To do this,
you need to add a permission in the manifest file (<code>AndroidManifest.xml</code>) and
then disable the keyguard in your application under test. Note, though, that you either have to
remove this before you publish your application, or you have to disable it with code in
the published application.
</p>
<p>
To add the the permission, add the element
<code>&lt;uses-permission android:name="android.permission.DISABLE_KEYGUARD"/&gt;</code>
as a child of the <code>&lt;manifest&gt;</code> element. To disable the KeyGuard, add the
following code to the <code>onCreate()</code> method of activities you intend to test:
</p>
<pre>
mKeyGuardManager = (KeyguardManager) getSystemService(KEYGUARD_SERVICE);
mLock = mKeyGuardManager.newKeyguardLock("<em>activity_classname</em>");
mLock.disableKeyguard();
</pre>
<p>where <code><em>activity_classname</em></code> is the class name of the activity.</p>
<h3 id="UITestTroubleshooting">Troubleshooting UI tests</h3>
<p>
This section lists some of the common test failures you may encounter in UI testing, and their
causes:
</p>
<dl>
<dt><code>WrongThreadException</code></dt>
<dd>
<p><strong>Problem:</strong></p>
For a failed test, the Failure Trace contains the following error message:
<code>
android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created
a view hierarchy can touch its views.
</code>
<p><strong>Probable Cause:</strong></p>
This error is common if you tried to send UI events to the UI thread from outside the UI
thread. This commonly happens if you send UI events from the test application, but you don't
use the <code>@UIThread</code> annotation or the <code>runOnUiThread()</code> method. The
test method tried to interact with the UI outside the UI thread.
<p><strong>Suggested Resolution:</strong></p>
Run the interaction on the UI thread. Use a test class that provides instrumentation. See
the previous section <a href="#RunOnUIThread">Testing on the UI Thread</a>
for more details.
</dd>
<dt><code>java.lang.RuntimeException</code></dt>
<dd>
<p><strong>Problem:</strong></p>
For a failed test, the Failure Trace contains the following error message:
<code>
java.lang.RuntimeException: This method can not be called from the main application thread
</code>
<p><strong>Probable Cause:</strong></p>
This error is common if your test method is annotated with <code>@UiThreadTest</code> but
then tries to do something outside the UI thread or tries to invoke
<code>runOnUiThread()</code>.
<p><strong>Suggested Resolution:</strong></p>
Remove the <code>@UiThreadTest</code> annotation, remove the <code>runOnUiThread()</code>
call, or re-factor your tests.
</dd>
</dl>
@@ -0,0 +1,223 @@
page.title=Content Provider Testing
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>In this document</h2>
<ol>
<li>
<a href="#DesignAndTest">Content Provider Design and Testing</a>
</li>
<li>
<a href="#ContentProviderTestAPI">The Content Provider Testing API</a>
<ol>
<li>
<a href="#ProviderTestCase2">ProviderTestCase2 </a>
</li>
<li>
<a href="#MockObjects">Mock object classes</a>
</li>
</ol>
</li>
<li>
<a href="#WhatToTest">What To Test</a>
</li>
<li>
<a href="#NextSteps">Next Steps</a>
</li>
</ol>
<h2>Key Classes</h2>
<ol>
<li>{@link android.test.InstrumentationTestRunner}</li>
<li>{@link android.test.ProviderTestCase2}</li>
<li>{@link android.test.IsolatedContext}</li>
<li>{@link android.test.mock.MockContentResolver}</li>
</ol>
<h2>See Also</h2>
<ol>
<li>
<a
href="{@docRoot}guide/topics/testing/testing_android.html">
Testing Fundamentals</a>
</li>
<li>
<a href="{@docRoot}guide/developing/testing/testing_eclipse.html">
Testing in Eclipse, with ADT</a>
</li>
<li>
<a href="{@docRoot}guide/developing/testing/testing_otheride.html">
Testing in Other IDEs</a>
</li>
</ol>
</div>
</div>
<p>
Content providers, which store and retrieve data and make it accessible across applications,
are a key part of the Android API. As an application developer you're allowed to provide your
own public providers for use by other applications. If you do, then you should test them
using the API you publish.
</p>
<p>
This document describes how to test public content providers, although the information is
also applicable to providers that you keep private to your own application. If you aren't
familiar with content providers or the Android testing framework, please read
<a href="{@docRoot}guide/topics/providers/content-providers.html">Content Providers</a>,
the guide to developing content providers, and
<a href="{@docRoot}guide/topics/testing/testing_android.html">Testing Fundamentals</a>,
the introduction to the Android testing and instrumentation framework.
</p>
<h2 id="DesignAndTest">Content Provider Design and Testing</h2>
<p>
In Android, content providers are viewed externally as data APIs that provide
tables of data, with their internals hidden from view. A content provider may have many
public constants, but it usually has few if any public methods and no public variables.
This suggests that you should write your tests based only on the provider's public members.
A content provider that is designed like this is offering a contract between itself and its
users.
</p>
<p>
The base test case class for content providers,
{@link android.test.ProviderTestCase2}, allows you to test your content provider in an
isolated environment. Android mock objects such as {@link android.test.IsolatedContext} and
{@link android.test.mock.MockContentResolver} also help provide an isolated test environment.
</p>
<p>
As with other Android tests, provider test packages are run under the control of the test
runner {@link android.test.InstrumentationTestRunner}. The section
<a href="{@docRoot}guide/topics/testing/testing_android.html#InstrumentationTestRunner">
Running Tests With InstrumentationTestRunner</a> describes the test runner in
more detail. The topic <a href="{@docRoot}guide/developing/testing/testing_eclipse.html">
Testing in Eclipse, with ADT</a> shows you how to run a test package in Eclipse, and the
topic <a href="{@docRoot}guide/developing/testing/testing_otheride.html">
Testing in Other IDEs</a>
shows you how to run a test package from the command line.
</p>
<h2 id="ContentProviderTestAPI">Content Provider Testing API</h2>
<p>
The main focus of the provider testing API is to provide an isolated testing environment. This
ensures that tests always run against data dependencies set explicitly in the test case. It
also prevents tests from modifying actual user data. For example, you want to avoid writing
a test that fails because there was data left over from a previous test, and you want to
avoid adding or deleting contact information in a actual provider.
</p>
<p>
The test case class and mock object classes for provider testing set up this isolated testing
environment for you.
</p>
<h3 id="ProviderTestCase2">ProviderTestCase2</h3>
<p>
You test a provider with a subclass of {@link android.test.ProviderTestCase2}. This base class
extends {@link android.test.AndroidTestCase}, so it provides the JUnit testing framework as well
as Android-specific methods for testing application permissions. The most important
feature of this class is its initialization, which creates the isolated test environment.
</p>
<p>
The initialization is done in the constructor for {@link android.test.ProviderTestCase2}, which
subclasses call in their own constructors. The {@link android.test.ProviderTestCase2}
constructor creates an {@link android.test.IsolatedContext} object that allows file and
database operations but stubs out other interactions with the Android system.
The file and database operations themselves take place in a directory that is local to the
device or emulator and has a special prefix.
</p>
<p>
The constructor then creates a {@link android.test.mock.MockContentResolver} to use as the
resolver for the test. The {@link android.test.mock.MockContentResolver} class is described in
detail in the section
<a href="{@docRoot}guide/topics/testing/testing_android.html#MockObjectClasses">Mock object
classes</a>.
</p>
<p>
Lastly, the constructor creates an instance of the provider under test. This is a normal
{@link android.content.ContentProvider} object, but it takes all of its environment information
from the {@link android.test.IsolatedContext}, so it is restricted to
working in the isolated test environment. All of the tests done in the test case class run
against this isolated object.
</p>
<h3 id="MockObjects">Mock object classes</h3>
<p>
{@link android.test.ProviderTestCase2} uses {@link android.test.IsolatedContext} and
{@link android.test.mock.MockContentResolver}, which are standard mock object classes. To
learn more about them, please read
<a href="{@docRoot}guide/topics/testing/testing_android.html#MockObjectClasses">
Testing Fundamentals</a>.
</p>
<h2 id="WhatToTest">What To Test</h2>
<p>
The topic <a href="{@docRoot}guide/topics/testing/what_to_test.html">What To Test</a>
lists general considerations for testing Android components.
Here are some specific guidelines for testing content providers.
</p>
<ul>
<li>
Test with resolver methods: Even though you can instantiate a provider object in
{@link android.test.ProviderTestCase2}, you should always test with a resolver object
using the appropriate URI. This ensures that you are testing the provider using the same
interaction that a regular application would use.
</li>
<li>
Test a public provider as a contract: If you intent your provider to be public and
available to other applications, you should test it as a contract. This includes
the following ideas:
<ul>
<li>
Test with constants that your provider publicly exposes. For
example, look for constants that refer to column names in one of the provider's
data tables. These should always be constants publicly defined by the provider.
</li>
<li>
Test all the URIs offered by your provider. Your provider may offer several URIs,
each one referring to a different aspect of the data. The
<a href="{@docRoot}resources/samples/NotePad/index.html">Note Pad</a> sample,
for example, features a provider that offers one URI for retrieving a list of notes,
another for retrieving an individual note by it's database ID, and a third for
displaying notes in a live folder.
</li>
<li>
Test invalid URIs: Your unit tests should deliberately call the provider with an
invalid URI, and look for errors. Good provider design is to throw an
IllegalArgumentException for invalid URIs.
</li>
</ul>
</li>
<li>
Test the standard provider interactions: Most providers offer six access methods:
query, insert, delete, update, getType, and onCreate(). Your tests should verify that all
of these methods work. These are described in more detail in the topic
<a href="{@docRoot}guide/topics/providers/content-providers.html">Content Providers</a>.
</li>
<li>
Test business logic: Don't forget to test the business logic that your provider should
enforce. Business logic includes handling of invalid values, financial or arithmetic
calculations, elimination or combining of duplicates, and so forth. A content provider
does not have to have business logic, because it may be implemented by activities that
modify the data. If the provider does implement business logic, you should test it.
</li>
</ul>
<h2 id="NextSteps">Next Steps</h2>
<p>
To learn how to set up and run tests in Eclipse, please refer to <a
href="{@docRoot}guide/developing/testing/testing_eclipse.html">Testing in
Eclipse, with ADT</a>. If you're not working in Eclipse, refer to <a
href="{@docRoot}guide/developing/testing/testing_otheride.html">Testing in Other
IDEs</a>.
</p>
<p>
If you want a step-by-step introduction to testing activities, try one of the
testing tutorials:
</p>
<ul>
<li>
The <a
href="{@docRoot}resources/tutorials/testing/helloandroid_test.html">Hello,
Testing</a> tutorial introduces basic testing concepts and procedures in the
context of the Hello, World application.
</li>
<li>
The <a
href="{@docRoot}resources/tutorials/testing/activity_test.html">Activity
Testing</a> tutorial is an excellent follow-up to the Hello, Testing tutorial.
It guides you through a more complex testing scenario that you develop against a
more realistic activity-oriented application.
</li>
</ul>
@@ -0,0 +1,86 @@
page.title=Testing
@jd:body
<p>
The Android development environment includes an integrated testing framework that helps you
test all aspects of your application.
</p>
<h4>Fundamentals</h4>
<p>
To start learning how to use the framework to create tests for your applications, please
read the topic <a href="{@docRoot}guide/topics/testing/testing_android.html">
Testing Fundamentals</a>.
</p>
<h4>Concepts</h4>
<ul>
<li>
<a href="{@docRoot}guide/topics/testing/activity_testing.html">
Activity Testing</a> focuses on testing activities. It describes how instrumentation allows
you to control activities outside the normal application lifecycle. It also lists
activity-specific features you should test, and it provides tips for testing Android
user interfaces.
</li>
<li>
<a href="{@docRoot}guide/topics/testing/contentprovider_testing.html">
Content Provider Testing</a> focuses on testing content providers. It describes the
mock system objects you can use, provides tips for designing providers so that they
can be tested, and lists provider-specific features you should test.
</li>
<li>
<a href="{@docRoot}guide/topics/testing/service_testing.html">
Service Testing</a> focuses on testing services. It also lists service-specific features
you should test.
</li>
<li>
<a href="{@docRoot}guide/topics/testing/what_to_test.html">What to Test</a>
is an overview of the types of testing you should do. It focuses on testing
system-wide aspects of Android that can affect every component in your application.
</li>
</ul>
<h4>Procedures</h4>
<ul>
<li>
The topic <a href="{@docRoot}guide/developing/testing/testing_eclipse.html">
Testing in Eclipse, with ADT</a> describes how to create and run tests in Eclipse with ADT.
</li>
<li>
The topic <a href="{@docRoot}guide/developing/testing/testing_otheride.html">
Testing in other IDEs</a> describes how to create and run tests with command-line tools.
</li>
</ul>
<h4>Tutorials</h4>
<ul>
<li>
The <a href="{@docRoot}resources/tutorials/testing/helloandroid_test.html">
Hello, Testing</a> tutorial introduces basic testing concepts and procedures.
</li>
<li>
For a more advanced tutorial, try
<a href="{@docRoot}resources/tutorials/testing/activity_test.html">Activity Testing</a>,
which guides you through a more complex testing scenario.
</li>
</ul>
<h4>Tools</h4>
<ul>
<li>
The
<a href="{@docRoot}guide/developing/tools/monkey.html">UI/Application Exerciser Monkey</a>,
usually called Monkey, is a command-line tool that sends pseudo-random
streams of keystrokes, touches, and gestures to a device.
</li>
<li>
The <a href="{@docRoot}guide/developing/tools/monkeyrunner_concepts.html">monkeyrunner</a> tool
is an API and execution environment. You use monkeyrunner with Python programs
to test applications and devices.
</li>
</ul>
<!--
<h4>Samples</h4>
<ul>
<li>
The <a href="{@docRoot}resources/samples/AlarmServiceTest.html">Alarm Service Test</a>
is a test package for the <a href="{@docRoot}resources/samples/Alarm.html">Alarm</a>
sample application. It provides a simple example of unit
testing a {@link android.app.Service}.
</li>
</ul>
-->
@@ -0,0 +1,178 @@
page.title=Service Testing
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>In this document</h2>
<ol>
<li>
<a href="#DesignAndTest">Service Design and Testing</a>
</li>
<li>
<a href="#ServiceTestCase">ServiceTestCase</a>
</li>
<li>
<a href="#MockObjects">Mock object classes</a>
</li>
<li>
<a href="#TestAreas">What to Test</a>
</li>
</ol>
<h2>Key Classes</h2>
<ol>
<li>{@link android.test.InstrumentationTestRunner}</li>
<li>{@link android.test.ServiceTestCase}</li>
<li>{@link android.test.mock.MockApplication}</li>
<li>{@link android.test.RenamingDelegatingContext}</li>
</ol>
<h2>Related Tutorials</h2>
<ol>
<li>
<a href="{@docRoot}resources/tutorials/testing/helloandroid_test.html">
Hello, Testing</a>
</li>
<li>
<a href="{@docRoot}resources/tutorials/testing/activity_test.html">Activity Testing</a>
</li>
</ol>
<h2>See Also</h2>
<ol>
<li>
<a href="{@docRoot}guide/developing/testing/testing_eclipse.html">
Testing in Eclipse, with ADT</a>
</li>
<li>
<a href="{@docRoot}guide/developing/testing/testing_otheride.html">
Testing in Other IDEs</a>
</li>
</ol>
</div>
</div>
<p>
Android provides a testing framework for Service objects that can run them in
isolation and provides mock objects. The test case class for Service objects is
{@link android.test.ServiceTestCase}. Since the Service class assumes that it is separate
from its clients, you can test a Service object without using instrumentation.
</p>
<p>
This document describes techniques for testing Service objects. If you aren't familiar with the
Service class, please read <a href="{@docRoot}guide/topics/fundamentals.html">
Application Fundamentals</a>. If you aren't familiar with Android testing, please read
<a href="{@docRoot}guide/topics/testing/testing_android.html">Testing Fundamentals</a>,
the introduction to the Android testing and instrumentation framework.
</p>
<h2 id="DesignAndTest">Service Design and Testing</h2>
<p>
When you design a Service, you should consider how your tests can examine the various states
of the Service lifecycle. If the lifecycle methods that start up your Service, such as
{@link android.app.Service#onCreate() onCreate()} or
{@link android.app.Service#onStartCommand(Intent, int, int) onStartCommand()} do not normally
set a global variable to indicate that they were successful, you may want to provide such a
variable for testing purposes.
</p>
<p>
Most other testing is facilitated by the methods in the {@link android.test.ServiceTestCase}
test case class. For example, the {@link android.test.ServiceTestCase#getService()} method
returns a handle to the Service under test, which you can test to confirm that the Service is
running even at the end of your tests.
</p>
<h2 id="ServiceTestCase">ServiceTestCase</h2>
<p>
{@link android.test.ServiceTestCase} extends the JUnit {@link junit.framework.TestCase} class
with with methods for testing application permissions and for controlling the application and
Service under test. It also provides mock application and Context objects that isolate your
test from the rest of the system.
</p>
<p>
{@link android.test.ServiceTestCase} defers initialization of the test environment until you
call {@link android.test.ServiceTestCase#startService(Intent) ServiceTestCase.startService()} or
{@link android.test.ServiceTestCase#bindService(Intent) ServiceTestCase.bindService()}. This
allows you to set up your test environment, particularly your mock objects, before the Service
is started.
</p>
<p>
Notice that the parameters to <code>ServiceTestCase.bindService()</code>are different from
those for <code>Service.bindService()</code>. For the <code>ServiceTestCase</code> version,
you only provide an Intent. Instead of returning a boolean,
<code>ServiceTestCase.bindService()</code> returns an object that subclasses
{@link android.os.IBinder}.
</p>
<p>
The {@link android.test.ServiceTestCase#setUp()} method for {@link android.test.ServiceTestCase}
is called before each test. It sets up the test fixture by making a copy of the current system
Context before any test methods touch it. You can retrieve this Context by calling
{@link android.test.ServiceTestCase#getSystemContext()}. If you override this method, you must
call <code>super.setUp()</code> as the first statement in the override.
</p>
<p>
The methods {@link android.test.ServiceTestCase#setApplication(Application) setApplication()}
and {@link android.test.AndroidTestCase#setContext(Context)} setContext()} allow you to set
a mock Context or mock Application (or both) for the Service, before you start it. These mock
objects are described in <a href="#MockObjects">Mock object classes</a>.
</p>
<p>
By default, {@link android.test.ServiceTestCase} runs the test method
{@link android.test.AndroidTestCase#testAndroidTestCaseSetupProperly()}, which asserts that
the base test case class successfully set up a Context before running.
</p>
<h2 id="MockObjects">Mock object classes</h2>
<p>
<code>ServiceTestCase</code> assumes that you will use a mock Context or mock Application
(or both) for the test environment. These objects isolate the test environment from the
rest of the system. If you don't provide your own instances of these objects before you
start the Service, then {@link android.test.ServiceTestCase} will create its own internal
instances and inject them into the Service. You can override this behavior by creating and
injecting your own instances before starting the Service
</p>
<p>
To inject a mock Application object into the Service under test, first create a subclass of
{@link android.test.mock.MockApplication}. <code>MockApplication</code> is a subclass of
{@link android.app.Application} in which all the methods throw an Exception, so to use it
effectively you subclass it and override the methods you need. You then inject it into the
Service with the
{@link android.test.ServiceTestCase#setApplication(Application) setApplication()} method.
This mock object allows you to control the application values that the Service sees, and
isolates it from the real system. In addition, any hidden dependencies your Service has on
its application reveal themselves as exceptions when you run the test.
</p>
<p>
You inject a mock Context into the Service under test with the
{@link android.test.AndroidTestCase#setContext(Context) setContext()} method. The mock
Context classes you can use are described in more detail in
<a href="{@docRoot}guide/topics/testing/testing_android.html#MockObjectClasses">
Testing Fundamentals</a>.
</p>
<h2 id="TestAreas">What to Test</h2>
<p>
The topic <a href="{@docRoot}guide/topics/testing/what_to_test.html">What To Test</a>
lists general considerations for testing Android components.
Here are some specific guidelines for testing a Service:
</p>
<ul>
<li>
Ensure that the {@link android.app.Service#onCreate()} is called in response to
{@link android.content.Context#startService(Intent) Context.startService()} or
{@link android.content.Context#bindService(Intent,ServiceConnection,int) Context.bindService()}.
Similarly, you should ensure that {@link android.app.Service#onDestroy()} is called in
response to {@link android.content.Context#stopService(Intent) Context.stopService()},
{@link android.content.Context#unbindService(ServiceConnection) Context.unbindService()},
{@link android.app.Service#stopSelf()}, or
{@link android.app.Service#stopSelfResult(int) stopSelfResult()}.
</li>
<li>
Test that your Service correctly handles multiple calls from
<code>Context.startService()</code>. Only the first call triggers
<code>Service.onCreate()</code>, but all calls trigger a call to
<code>Service.onStartCommand()</code>.
<p>
In addition, remember that <code>startService()</code> calls don't
nest, so a single call to <code>Context.stopService()</code> or
<code>Service.stopSelf()</code> (but not <code>stopSelf(int)</code>)
will stop the Service. You should test that your Service stops at the correct point.
</p>
</li>
<li>
Test any business logic that your Service implements. Business logic includes checking for
invalid values, financial and arithmetic calculations, and so forth.
</li>
</ul>
+663
View File
@@ -0,0 +1,663 @@
page.title=Testing Fundamentals
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>In this document</h2>
<ol>
<li>
<a href="#TestStructure">Test Structure</a>
</li>
<li>
<a href="#TestProjects">Test Projects</a>
</li>
<li>
<a href="#TestAPI">The Testing API</a>
<ol>
<li>
<a href="#JUnit">JUnit</a>
</li>
<li>
<a href="#Instrumentation">Instrumentation</a>
</li>
<li>
<a href="#TestCaseClasses">Test case classes</a>
</li>
<li>
<a href="#AssertionClasses">Assertion classes</a>
</li>
<li>
<a href="#MockObjectClasses">Mock object classes</a>
</li>
</ol>
</li>
<li>
<a href="#InstrumentationTestRunner">Running Tests</a>
</li>
<li>
<a href="#TestResults">Seeing Test Results</a>
</li>
<li>
<a href="#Monkeys">monkey and monkeyrunner</a>
</li>
<li>
<a href="#PackageNames">Working With Package Names</a>
</li>
<li>
<a href="#WhatToTest">What To Test</a>
</li>
<li>
<a href="#NextSteps">Next Steps</a>
</li>
</ol>
<h2>Key classes</h2>
<ol>
<li>{@link android.test.InstrumentationTestRunner}</li>
<li>{@link android.test}</li>
<li>{@link android.test.mock}</li>
<li>{@link junit.framework}</li>
</ol>
<h2>Related tutorials</h2>
<ol>
<li>
<a href="{@docRoot}resources/tutorials/testing/helloandroid_test.html">
Hello, Testing</a>
</li>
<li>
<a href="{@docRoot}resources/tutorials/testing/activity_test.html">Activity Testing</a>
</li>
</ol>
<h2>See also</h2>
<ol>
<li>
<a href="{@docRoot}guide/developing/testing/testing_eclipse.html">
Testing in Eclipse, with ADT</a>
</li>
<li>
<a href="{@docRoot}guide/developing/testing/testing_otheride.html">
Testing in Other IDEs</a>
</li>
<li>
<a href="{@docRoot}guide/developing/tools/monkeyrunner_concepts.html">
monkeyrunner</a>
</li>
<li>
<a href="{@docRoot}guide/developing/tools/monkey.html">UI/Application Exerciser Monkey</a>
</li>
</ol>
</div>
</div>
<p>
The Android testing framework, an integral part of the development environment,
provides an architecture and powerful tools that help you test every aspect of your application
at every level from unit to framework.
</p>
<p>
The testing framework has these key features:
</p>
<ul>
<li>
Android test suites are based on JUnit. You can use plain JUnit to test a class that doesn't
call the Android API, or Android's JUnit extensions to test Android components. If you're
new to Android testing, you can start with general-purpose test case classes such as {@link
android.test.AndroidTestCase} and then go on to use more sophisticated classes.
</li>
<li>
The Android JUnit extensions provide component-specific test case classes. These classes
provide helper methods for creating mock objects and methods that help you control the
lifecycle of a component.
</li>
<li>
Test suites are contained in test packages that are similar to main application packages, so
you don't need to learn a new set of tools or techniques for designing and building tests.
</li>
<li>
The SDK tools for building and tests are available in Eclipse with ADT, and also in
command-line form for use with other IDES. These tools get information from the project of
the application under test and use this information to automatically create the build files,
manifest file, and directory structure for the test package.
</li>
<li>
The SDK also provides
<a href="{@docRoot}guide/developing/tools/monkeyrunner_concepts.html">monkeyrunner</a>, an API
testing devices with Python programs, and <a
href="{@docRoot}guide/developing/tools/monkey.html">UI/Application Exerciser Monkey</a>,
a command-line tool for stress-testing UIs by sending pseudo-random events to a device.
</li>
</ul>
<p>
This document describes the fundamentals of the Android testing framework, including the
structure of tests, the APIs that you use to develop tests, and the tools that you use to run
tests and view results. The document assumes you have a basic knowledge of Android application
programming and JUnit testing methodology.
</p>
<p>
The following diagram summarizes the testing framework:
</p>
<div style="width: 70%; margin-left:auto; margin-right:auto;">
<a href="{@docRoot}images/testing/test_framework.png">
<img src="{@docRoot}images/testing/test_framework.png"
alt="The Android testing framework"/>
</a>
</div>
<h2 id="TestStructure">Test Structure</h2>
<p>
Android's build and test tools assume that test projects are organized into a standard
structure of tests, test case classes, test packages, and test projects.
</p>
<p>
Android testing is based on JUnit. In general, a JUnit test is a method whose
statements test a part of the application under test. You organize test methods into classes
called test cases (or test suites). Each test is an isolated test of an individual module in
the application under test. Each class is a container for related test methods, although it
often provides helper methods as well.
</p>
<p>
In JUnit, you build one or more test source files into a class file. Similarly, in Android you
use the SDK's build tools to build one or more test source files into class files in an
Android test package. In JUnit, you use a test runner to execute test classes. In Android, you
use test tools to load the test package and the application under test, and the tools then
execute an Android-specific test runner.
</p>
<h2 id="TestProjects">Test Projects</h2>
<p>
Tests, like Android applications, are organized into projects.
</p>
<p>
A test project is a directory or Eclipse project in which you create the source code, manifest
file, and other files for a test package. The Android SDK contains tools for Eclipse with ADT
and for the command line that create and update test projects for you. The tools create the
directories you use for source code and resources and the manifest file for the test package.
The command-line tools also create the Ant build files you need.
</p>
<p>
You should always use Android tools to create a test project. Among other benefits,
the tools:
</p>
<ul>
<li>
Automatically set up your test package to use
{@link android.test.InstrumentationTestRunner} as the test case runner. You must use
<code>InstrumentationTestRunner</code> (or a subclass) to run JUnit tests.
</li>
<li>
Create an appropriate name for the test package. If the application
under test has a package name of <code>com.mydomain.myapp</code>, then the
Android tools set the test package name to <code>com.mydomain.myapp.test</code>. This
helps you identify their relationship, while preventing conflicts within the system.
</li>
<li>
Automatically create the proper build files, manifest file, and directory
structure for the test project. This helps you to build the test package without
having to modify build files and sets up the linkage between your test package and
the application under test.
The
</li>
</ul>
<p>
You can create a test project anywhere in your file system, but the best approach is to
add the test project so that its root directory <code>tests/</code> is at the same level
as the <code>src/</code> directory of the main application's project. This helps you find the
tests associated with an application. For example, if your application project's root directory
is <code>MyProject</code>, then you should use the following directory structure:
</p>
<pre class="classic no-pretty-print">
MyProject/
AndroidManifest.xml
res/
... (resources for main application)
src/
... (source code for main application) ...
tests/
AndroidManifest.xml
res/
... (resources for tests)
src/
... (source code for tests)
</pre>
<h2 id="TestAPI">The Testing API</h2>
<p>
The Android testing API is based on the JUnit API and extended with a instrumentation
framework and Android-specific testing classes.
</p>
<h3 id="JUnit">JUnit</h3>
<p>
You can use the JUnit {@link junit.framework.TestCase TestCase} class to do unit testing on
a plain Java object. <code>TestCase</code> is also the base class for
{@link android.test.AndroidTestCase}, which you can use to test Android-dependent objects.
Besides providing the JUnit framework, AndroidTestCase offers Android-specific setup,
teardown, and helper methods.
</p>
<p>
You use the JUnit {@link junit.framework.Assert} class to display test results.
The assert methods compare values you expect from a test to the actual results and
throw an exception if the comparison fails. Android also provides a class of assertions that
extend the possible types of comparisons, and another class of assertions for testing the UI.
These are described in more detail in the section <a href="#AssertionClasses">
Assertion classes</a>
</p>
<p>
To learn more about JUnit, you can read the documentation on the
<a href="http://www.junit.org">junit.org</a> home page.
Note that the Android testing API supports JUnit 3 code style, but not JUnit 4. Also, you must
use Android's instrumented test runner {@link android.test.InstrumentationTestRunner} to run
your test case classes. This test runner is described in the
section <a href="#InstrumentationTestRunner">Running Tests</a>.
</p>
<h3 id="Instrumentation">Instrumentation</h3>
<p>
Android instrumentation is a set of control methods or "hooks" in the Android system. These hooks
control an Android component independently of its normal lifecycle. They also control how
Android loads applications.
</p>
<p>
Normally, an Android component runs in a lifecycle determined by the system. For example, an
Activity object's lifecycle starts when the Activity is activated by an Intent. The object's
<code>onCreate()</code> method is called, followed by <code>onResume()</code>. When the user
starts another application, the <code>onPause()</code> method is called. If the Activity
code calls the <code>finish()</code> method, the <code>onDestroy()</code> method is called.
The Android framework API does not provide a way for your code to invoke these callback
methods directly, but you can do so using instrumentation.
</p>
<p>
Also, the system runs all the components of an application into the same
process. You can allow some components, such as content providers, to run in a separate process,
but you can't force an application to run in the same process as another application that is
already running.
</p>
<p>
With Android instrumentation, though, you can invoke callback methods in your test code.
This allows you to run through the lifecycle of a component step by step, as if you were
debugging the component. The following test code snippet demonstrates how to use this to
test that an Activity saves and restores its state:
</p>
<a name="ActivitySnippet"></a>
<pre>
// Start the main activity of the application under test
mActivity = getActivity();
// Get a handle to the Activity object's main UI widget, a Spinner
mSpinner = (Spinner)mActivity.findViewById(com.android.example.spinner.R.id.Spinner01);
// Set the Spinner to a known position
mActivity.setSpinnerPosition(TEST_STATE_DESTROY_POSITION);
// Stop the activity - The onDestroy() method should save the state of the Spinner
mActivity.finish();
// Re-start the Activity - the onResume() method should restore the state of the Spinner
mActivity = getActivity();
// Get the Spinner's current position
int currentPosition = mActivity.getSpinnerPosition();
// Assert that the current position is the same as the starting position
assertEquals(TEST_STATE_DESTROY_POSITION, currentPosition);
</pre>
<p>
The key method used here is
{@link android.test.ActivityInstrumentationTestCase2#getActivity()}, which is a
part of the instrumentation API. The Activity under test is not started until you call this
method. You can set up the test fixture in advance, and then call this method to start the
Activity.
</p>
<p>
Also, instrumentation can load both a test package and the application under test into the
same process. Since the application components and their tests are in the same process, the
tests can invoke methods in the components, and modify and examine fields in the components.
</p>
<h3 id="TestCaseClasses">Test case classes</h3>
<p>
Android provides several test case classes that extend {@link junit.framework.TestCase} and
{@link junit.framework.Assert} with Android-specific setup, teardown, and helper methods.
</p>
<h4 id="AndroidTestCase">AndroidTestCase</h4>
<p>
A useful general test case class, especially if you are
just starting out with Android testing, is {@link android.test.AndroidTestCase}. It extends
both {@link junit.framework.TestCase} and {@link junit.framework.Assert}. It provides the
JUnit-standard <code>setUp()</code> and <code>tearDown()</code> methods, as well as well as
all of JUnit's Assert methods. In addition, it provides methods for testing permissions, and a
method that guards against memory leaks by clearing out certain class references.
</p>
<h4 id="ComponentTestCase">Component-specific test cases</h4>
<p>
A key feature of the Android testing framework is its component-specific test case classes.
These address specific component testing needs with methods for fixture setup and
teardown and component lifecycle control. They also provide methods for setting up mock objects.
These classes are described in the component-specific testing topics:
</p>
<ul>
<li>
<a href="{@docRoot}guide/topics/testing/activity_testing.html">Activity Testing</a>
</li>
<li>
<a href="{@docRoot}guide/topics/testing/contentprovider_testing.html">
Content Provider Testing</a>
</li>
<li>
<a href="{@docRoot}guide/topics/testing/service_testing.html">Service Testing</a>
</li>
</ul>
<p>
Android does not provide a separate test case class for BroadcastReceiver. Instead, test a
BroadcastReceiver by testing the component that sends it Intent objects, to verify that the
BroadcastReceiver responds correctly.
</p>
<h4 id="ApplicationTestCase">ApplicationTestCase</h4>
<p>
You use the {@link android.test.ApplicationTestCase} test case class to test the setup and
teardown of {@link android.app.Application} objects. These objects maintain the global state of
information that applies to all the components in an application package. The test case can
be useful in verifying that the &lt;application&gt; element in the manifest file is correctly
set up. Note, however, that this test case does not allow you to control testing of the
components within your application package.
</p>
<h4 id="InstrumentationTestCase">InstrumentationTestCase</h4>
<p>
If you want to use instrumentation methods in a test case class, you must use
{@link android.test.InstrumentationTestCase} or one of its subclasses. The
{@link android.app.Activity} test cases extend this base class with other functionality that
assists in Activity testing.
</p>
<h3 id="AssertionClasses">Assertion classes</h3>
<p>
Because Android test case classes extend JUnit, you can use assertion methods to display the
results of tests. An assertion method compares an actual value returned by a test to an
expected value, and throws an AssertionException if the comparison test fails. Using assertions
is more convenient than doing logging, and provides better test performance.
</p>
<p>
Besides the JUnit {@link junit.framework.Assert} class methods, the testing API also provides
the {@link android.test.MoreAsserts} and {@link android.test.ViewAsserts} classes:
</p>
<ul>
<li>
{@link android.test.MoreAsserts} contains more powerful assertions such as
{@link android.test.MoreAsserts#assertContainsRegex}, which does regular expression
matching.
</li>
<li>
{@link android.test.ViewAsserts} contains useful assertions about Views. For example
it contains {@link android.test.ViewAsserts#assertHasScreenCoordinates} that tests if a View
has a particular X and Y position on the visible screen. These asserts simplify testing of
geometry and alignment in the UI.
</li>
</ul>
<h3 id="MockObjectClasses">Mock object classes</h3>
<p>
To facilitate dependency injection in testing, Android provides classes that create mock system
objects such as {@link android.content.Context} objects,
{@link android.content.ContentProvider} objects, {@link android.content.ContentResolver}
objects, and {@link android.app.Service} objects. Some test cases also provide mock
{@link android.content.Intent} objects. You use these mocks both to isolate tests
from the rest of the system and to facilitate dependency injection for testing. These classes
are found in the Java packages {@link android.test} and {@link android.test.mock}.
</p>
<p>
Mock objects isolate tests from a running system by stubbing out or overriding
normal operations. For example, a {@link android.test.mock.MockContentResolver}
replaces the normal resolver framework with its own local framework, which is isolated
from the rest of the system. MockContentResolver also also stubs out the
{@link android.content.ContentResolver#notifyChange(Uri, ContentObserver, boolean)} method
so that observer objects outside the test environment are not accidentally triggered.
</p>
<p>
Mock object classes also facilitate dependency injection by providing a subclass of the
normal object that is non-functional except for overrides you define. For example, the
{@link android.test.mock.MockResources} object provides a subclass of
{@link android.content.res.Resources} in which all the methods throw Exceptions when called.
To use it, you override only those methods that must provide information.
</p>
<p>
These are the mock object classes available in Android:
</p>
<h4 id="SimpleMocks">Simple mock object classes</h4>
<p>
{@link android.test.mock.MockApplication}, {@link android.test.mock.MockContext},
{@link android.test.mock.MockContentProvider}, {@link android.test.mock.MockCursor},
{@link android.test.mock.MockDialogInterface}, {@link android.test.mock.MockPackageManager}, and
{@link android.test.mock.MockResources} provide a simple and useful mock strategy. They are
stubbed-out versions of the corresponding system object class, and all of their methods throw an
{@link java.lang.UnsupportedOperationException} exception if called. To use them, you override
the methods you need in order to provide mock dependencies.
</p>
<p class="Note"><strong>Note:</strong>
{@link android.test.mock.MockContentProvider}
and {@link android.test.mock.MockCursor} are new as of API level 8.
</p>
<h4 id="ResolverMocks">Resolver mock objects</h4>
<p>
{@link android.test.mock.MockContentResolver} provides isolated testing of content providers by
masking out the normal system resolver framework. Instead of looking in the system to find a
content provider given an authority string, MockContentResolver uses its own internal table. You
must explicitly add providers to this table using
{@link android.test.mock.MockContentResolver#addProvider(String,ContentProvider)}.
</p>
<p>
With this feature, you can associate a mock content provider with an authority. You can create
an instance of a real provider but use test data in it. You can even set the provider for an
authority to <code>null</code>. In effect, a MockContentResolver object isolates your test
from providers that contain real data. You can control the
function of the provider, and you can prevent your test from affecting real data.
</p>
<h3 id="ContextMocks">Contexts for testing</h3>
<p>
Android provides two Context classes that are useful for testing:
</p>
<ul>
<li>
{@link android.test.IsolatedContext} provides an isolated {@link android.content.Context},
File, directory, and database operations that use this Context take place in a test area.
Though its functionality is limited, this Context has enough stub code to respond to
system calls.
<p>
This class allows you to test an application's data operations without affecting real
data that may be present on the device.
</p>
</li>
<li>
{@link android.test.RenamingDelegatingContext} provides a Context in which
most functions are handled by an existing {@link android.content.Context}, but
file and database operations are handled by a {@link android.test.IsolatedContext}.
The isolated part uses a test directory and creates special file and directory names.
You can control the naming yourself, or let the constructor determine it automatically.
<p>
This object provides a quick way to set up an isolated area for data operations,
while keeping normal functionality for all other Context operations.
</p>
</li>
</ul>
<h2 id="InstrumentationTestRunner">Running Tests</h2>
<p>
Test cases are run by a test runner class that loads the test case class, set ups,
runs, and tears down each test. An Android test runner must also be instrumented, so that
the system utility for starting applications can control how the test package
loads test cases and the application under test. You tell the Android platform
which instrumented test runner to use by setting a value in the test package's manifest file.
</p>
<p>
{@link android.test.InstrumentationTestRunner} is the primary Android test runner class. It
extends the JUnit test runner framework and is also instrumented. It can run any of the test
case classes provided by Android and supports all possible types of testing.
</p>
<p>
You specify <code>InstrumentationTestRunner</code> or a subclass in your test package's
manifest file, in the <a href="{@docRoot}guide/topics/manifest/instrumentation-element.html">
instrumentation</a> element. Also, <code>InstrumentationTestRunner</code> code resides
in the shared library <code>android.test.runner</code>, which is not normally linked to
Android code. To include it, you must specify it in a
<a href="{@docRoot}guide/topics/manifest/uses-library-element.html">uses-library</a> element.
You do not have to set up these elements yourself. Both Eclipse with ADT and the
<code>android</code> command-line tool construct them automatically and add them to your
test package's manifest file.
</p>
<p class="Note">
<strong>Note:</strong> If you use a test runner other than
<code>InstrumentationTestRunner</code>, you must change the &lt;instrumentation&gt;
element to point to the class you want to use.
</p>
<p>
To run {@link android.test.InstrumentationTestRunner}, you use internal system classes called by
Android tools. When you run a test in Eclipse with ADT, the classes are called automatically.
When you run a test from the command line, you run these classes with
<a href="{@docRoot}guide/developing/tools/adb.html">Android Debug Bridge (adb)</a>.
</p>
<p>
The system classes load and start the test package, kill any processes that
are running an instance of the application under test, and then load a new instance of the
application under test. They then pass control to
{@link android.test.InstrumentationTestRunner}, which runs
each test case class in the test package. You can also control which test cases and
methods are run using settings in Eclipse with ADT, or using flags with the command-line tools.
</p>
<p>
Neither the system classes nor {@link android.test.InstrumentationTestRunner} run
the application under test. Instead, the test case does this directly. It either calls methods
in the application under test, or it calls its own methods that trigger lifecycle events in
the application under test. The application is under the complete control of the test case,
which allows it to set up the test environment (the test fixture) before running a test. This
is demonstrated in the previous <a href="#ActivitySnippet">code snippet</a> that tests an
Activity that displays a Spinner widget.
</p>
<p>
To learn more about running tests, please read the topics
<a href="{@docRoot}guide/developing/testing/testing_eclipse.html"">
Testing in Eclipse, with ADT</a> or
<a href="{@docRoot}guide/developing/testing/testing_otheride.html">
Testing in Other IDes</a>.
</p>
<h2 id="TestResults">Seeing Test Results</h2>
<p>
The Android testing framework returns test results back to the tool that started the test.
If you run a test in Eclipse with ADT, the results are displayed in a new JUnit view pane. If
you run a test from the command line, the results are displayed in <code>STDOUT</code>. In
both cases, you see a test summary that displays the name of each test case and method that
was run. You also see all the assertion failures that occurred. These include pointers to the
line in the test code where the failure occurred. Assertion failures also list the expected
value and actual value.
</p>
<p>
The test results have a format that is specific to the IDE that you are using. The test
results format for Eclipse with ADT is described in
<a href="{@docRoot}guide/developing/testing/testing_eclipse.html#RunTestEclipse">
Testing in Eclipse, with ADT</a>. The test results format for tests run from the
command line is described in
<a href="{@docRoot}guide/developing/testing/testing_otheride.html#RunTestsCommand">
Testing in Other IDEs</a>.
</p>
<h2 id="Monkeys">monkey and monkeyrunner</h2>
<p>
The SDK provides two tools for functional-level application testing:
</p>
<ul>
<li>
The <a href="{@docRoot}guide/developing/tools/monkey.html">UI/Application Exerciser Monkey</a>,
usually called "monkey", is a command-line tool that sends pseudo-random streams of
keystrokes, touches, and gestures to a device. You run it with the
<a href="{@docRoot}guide/developing/tools/adb.html">Android Debug Bridge</a> (adb) tool.
You use it to stress-test your application and report back errors that are encountered.
You can repeat a stream of events by running the tool each time with the same random
number seed.
</li>
<li>
The <a href="{@docRoot}guide/developing/tools/monkeyrunner_concepts.html">monkeyrunner</a> tool
is an API and execution environment for test programs written in Python. The API
includes functions for connecting to a device, installing and uninstalling packages,
taking screenshots, comparing two images, and running a test package against an
application. Using the API, you can write a wide range of large, powerful, and complex
tests. You run programs that use the API with the <code>monkeyrunner</code> command-line
tool.
</li>
</ul>
<h2 id="PackageNames">Working With Package names</h2>
<p>
In the test environment, you work with both Android application package names and
Java package identifiers. Both use the same naming format, but they represent substantially
different entities. You need to know the difference to set up your tests correctly.
</p>
<p>
An Android package name is a unique system name for a <code>.apk</code> file, set by the
&quot;android:package&quot; attribute of the &lt;manifest&gt; element in the package's
manifest. The Android package name of your test package must be different from the
Android package name of the application under test. By default, Android tools create the
test package name by appending ".test" to the package name of the application under test.
</p>
<p>
The test package also uses an Android package name to target the application package it
tests. This is set in the &quot;android:targetPackage&quot; attribute of the
&lt;instrumentation&gt; element in the test package's manifest.
</p>
<p>
A Java package identifier applies to a source file. This package name reflects the directory
path of the source file. It also affects the visibility of classes and members to each other.
</p>
<p>
Android tools that create test projects set up an Android test package name for you.
From your input, the tools set up the test package name and the target package name for the
application under test. For these tools to work, the application project must already exist.
</p>
<p>
By default, these tools set the Java package identifier for the test class to be the same
as the Android package identifier. You may want to change this if you want to expose
members in the application under test by giving them package visibility. If you do this,
change only the Java package identifier, not the Android package names, and change only the
test case source files. Do not change the Java package name of the generated
<code>R.java</code> class in your test package, because it will then conflict with the
<code>R.java</code> class in the application under test. Do not change the Android package name
of your test package to be the same as the application it tests, because then their names
will no longer be unique in the system.
</p>
<h2 id="WhatToTest">What to Test</h2>
<p>
The topic <a href="{@docRoot}guide/topics/testing/what_to_test.html">What To Test</a>
describes the key functionality you should test in an Android application, and the key
situations that might affect that functionality.
</p>
<p>
Most unit testing is specific to the Android component you are testing.
The topics <a href="{@docRoot}guide/topics/testing/activity_testing.html">Activity Testing</a>,
<a href="{@docRoot}guide/topics/testing/contentprovider_testing.html">
Content Provider Testing</a>, and <a href="{@docRoot}guide/topics/testing/service_testing.html">
Service Testing</a> each have a section entitled "What To Test" that lists possible testing
areas.
</p>
<p>
When possible, you should run these tests on an actual device. If this is not possible, you can
use the <a href="{@docRoot}guide/developing/tools/emulator.html">Android Emulator</a> with
<a href="{@docRoot}guide/developing/tools/avd.html">Android Virtual Devices</a> configured for
the hardware, screens, and versions you want to test.
</p>
<h2 id="NextSteps">Next Steps</h2>
<p>
To learn how to set up and run tests in Eclipse, please refer to <a
href="{@docRoot}guide/developing/testing/testing_eclipse.html">Testing in
Eclipse, with ADT</a>. If you're not working in Eclipse, refer to <a
href="{@docRoot}guide/developing/testing/testing_otheride.html">Testing in Other
IDEs</a>.
</p>
<p>
If you want a step-by-step introduction to Android testing, try one of the
testing tutorials or sample test packages:
</p>
<ul>
<li>
The <a
href="{@docRoot}resources/tutorials/testing/helloandroid_test.html">Hello,
Testing</a> tutorial introduces basic testing concepts and procedures in the
context of the Hello, World application.
</li>
<li>
The <a href="{@docRoot}resources/tutorials/testing/activity_test.html">Activity
Testing</a> tutorial is an excellent follow-up to the Hello, Testing tutorial.
It guides you through a more complex testing scenario that you develop against a
more realistic application.
</li>
<li>
The sample test package <a href="{@docRoot}resources/samples/AlarmServiceTest"}>
Alarm Service Test</a> is an example of testing a {@link android.app.Service}. It contains
a set of unit tests for the Alarm Service sample application's {@link android.app.Service}.
</li>
</ul>
@@ -0,0 +1,84 @@
page.title=What To Test
@jd:body
<p>
As you develop Android applications, knowing what to test is as important as knowing how to
test. This document lists some most common Android-related situations that you should consider
when you test, even at the unit test level. This is not an exhaustive list, and you consult the
documentation for the features that you use for more ideas. The
<a href="http://groups.google.com/group/android-developers">android-developers</a> Google Groups
site is another resource for information about testing.
</p>
<h2 id="Tests">Ideas for Testing</h2>
<p>
The following sections are organized by behaviors or situations that you should test. Each
section contains a scenario that further illustrates the situation and the test or tests you
should do.
</p>
<h4>Change in orientation</h4>
<p>
For devices that support multiple orientations, Android detects a change in orientation when
the user turns the device so that the display is "landscape" (long edge is horizontal) instead
of "portrait" (long edge is vertical).
</p>
<p>
When Android detects a change in orientation, its default behavior is to destroy and then
re-start the foreground Activity. You should consider testing the following:
</p>
<ul>
<li>
Is the screen re-drawn correctly? Any custom UI code you have should handle changes in the
orientation.
</li>
<li>
Does the application maintain its state? The Activity should not lose anything that the
user has already entered into the UI. The application should not "forget" its place in the
current transaction.
</li>
</ul>
<h4>Change in configuration</h4>
<p>
A situation that is more general than a change in orientation is a change in the device's
configuration, such as a change in the availability of a keyboard or a change in system
language.
</p>
<p>
A change in configuration also triggers the default behavior of destroying and then restarting
the foreground Activity. Besides testing that the application maintains the UI and its
transaction state, you should also test that the application updates itself to respond
correctly to the new configuration.
</p>
<h4>Battery life</h4>
<p>
Mobile devices primarily run on battery power. A device has finite "battery budget", and when it
is gone, the device is useless until it is recharged. You need to write your application to
minimize battery usage, you need to test its battery performance, and you need to test the
methods that manage battery usage.
</p>
<p>
Techniques for minimizing battery usage were presented at the 2010 Google I/O conference in the
presentation
<a href="http://code.google.com/events/io/2009/sessions/CodingLifeBatteryLife.html">
Coding for Life -- Battery Life, That Is</a>. This presentation describes the impact on battery
life of various operations, and the ways you can design your application to minimize these
impacts. When you code your application to reduce battery usage, you also write the
appropriate unit tests.
</p>
<h4>Dependence on external resources</h4>
<p>
If your application depends on network access, SMS, Bluetooth, or GPS, then you should
test what happens when the resource or resources are not available.
</p>
<p>
For example, if your application uses the network,it can notify the user if access is
unavailable, or disable network-related features, or do both. For GPS, it can switch to
IP-based location awareness. It can also wait for WiFi access before doing large data transfers,
since WiFi transfers maximize battery usage compared to transfers over 3G or EDGE.
</p>
<p>
You can use the emulator to test network access and bandwidth. To learn more, please see
<a href="{@docRoot}guide/developing/tools/emulator.html#netspeed">Network Speed Emulation</a>.
To test GPS, you can use the emulator console and {@link android.location.LocationManager}. To
learn more about the emulator console, please see
<a href="{@docRoot}guide/developing/tools/emulator.html#console">
Using the Emulator Console</a>.
</p>
+113
View File
@@ -0,0 +1,113 @@
page.title=Binding to Data with AdapterView
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="#FillingTheLayout">Filling the Layout with Data</a></li>
<li><a href="#HandlingUserSelections">Handling User Selections</a></li>
</ol>
<h2>Related tutorials</h2>
<ol>
<li><a href="{@docRoot}resources/tutorials/views/hello-spinner.html">Spinner</a></li>
<li><a href="{@docRoot}resources/tutorials/views/hello-listview.html">List View</a></li>
<li><a href="{@docRoot}resources/tutorials/views/hello-gridview.html">Grid View</a></li>
</ol>
</div>
</div>
<p>The {@link android.widget.AdapterView} is a ViewGroup subclass whose child Views are determined by an {@link android.widget.Adapter Adapter} that
binds to data of some type. AdapterView is useful whenever you need to display stored data (as opposed to resource strings or drawables) in your layout.</p>
<p>{@link android.widget.Gallery Gallery}, {@link android.widget.ListView ListView}, and {@link android.widget.Spinner Spinner} are examples of AdapterView subclasses that you can use to bind to a specific type of data and display it in a certain way. </p>
<p>AdapterView objects have two main responsibilities: </p>
<ul>
<li>Filling the layout with data
</li>
<li>Handling user selections
</li>
</ul>
<h2 id="FillingTheLayout">Filling the Layout with Data</h2>
<p>Inserting data into the layout is typically done by binding the AdapterView class to an {@link
android.widget.Adapter}, which retrieves data from an external source (perhaps a list that
the code supplies or query results from the device's database). </p>
<p>The following code sample does the following:</p>
<ol>
<li>Creates a {@link android.widget.Spinner Spinner} with an existing View and binds it to a new ArrayAdapter
that reads an array of colors from the local resources.</li>
<li>Creates another Spinner object from a View and binds it to a new SimpleCursorAdapter that will read
people's names from the device contacts (see {@link android.provider.Contacts.People}).</li>
</ol>
<pre>
// Get a Spinner and bind it to an ArrayAdapter that
// references a String array.
Spinner s1 = (Spinner) findViewById(R.id.spinner1);
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(
this, R.array.colors, android.R.layout.simple_spinner_item);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
s1.setAdapter(adapter);
// Load a Spinner and bind it to a data query.
private static String[] PROJECTION = new String[] {
People._ID, People.NAME
};
Spinner s2 = (Spinner) findViewById(R.id.spinner2);
Cursor cur = managedQuery(People.CONTENT_URI, PROJECTION, null, null);
SimpleCursorAdapter adapter2 = new SimpleCursorAdapter(this,
android.R.layout.simple_spinner_item, // Use a template
// that displays a
// text view
cur, // Give the cursor to the list adapter
new String[] {People.NAME}, // Map the NAME column in the
// people database to...
new int[] {android.R.id.text1}); // The "text1" view defined in
// the XML template
adapter2.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
s2.setAdapter(adapter2);
</pre>
<p>Note that it is necessary to have the People._ID column in projection used with CursorAdapter
or else you will get an exception.</p>
<p>If, during the course of your application's life, you change the underlying data that is read by your Adapter,
you should call {@link android.widget.ArrayAdapter#notifyDataSetChanged()}. This will notify the attached View
that the data has been changed and it should refresh itself.</p>
<h2 id="HandlingUserSelections">Handling User Selections</h2>
<p>You handle the user's selection by setting the class's {@link
android.widget.AdapterView.OnItemClickListener} member to a listener and
catching the selection changes. </p>
<pre>
// Create a message handling object as an anonymous class.
private OnItemClickListener mMessageClickedHandler = new OnItemClickListener() {
public void onItemClick(AdapterView parent, View v, int position, long id)
{
// Display a messagebox.
Toast.makeText(mContext,"You've got an event",Toast.LENGTH_SHORT).show();
}
};
// Now hook into our object and set its onItemClickListener member
// to our class handler object.
mHistoryView = (ListView)findViewById(R.id.history);
mHistoryView.setOnItemClickListener(mMessageClickedHandler);
</pre>
<div class="special">
<p>For more discussion on how to create different AdapterViews, read the following tutorials:
<a href="{@docRoot}resources/tutorials/views/hello-spinner.html">Hello Spinner</a>,
<a href="{@docRoot}resources/tutorials/views/hello-listview.html">Hello ListView</a>, and
<a href="{@docRoot}resources/tutorials/views/hello-gridview.html">Hello GridView</a>.
</div>
@@ -0,0 +1,563 @@
page.title=Building Custom Components
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="#basic">The Basic Approach</a></li>
<li><a href="#custom">Fully Customized Components</a></li>
<li><a href="#compound">Compound Controls</a></li>
<li><a href="#modifying">Modifying an Existing View Type</a></li>
</ol>
</div>
</div>
<p>Android offers a sophisticated and powerful componentized model for building your UI,
based on the fundamental layout classes: {@link android.view.View} and
{@link android.view.ViewGroup}. To start with, the platform includes a variety of prebuilt
View and ViewGroup subclasses &mdash; called widgets and layouts, respectively &mdash;
that you can use to construct your UI.</p>
<p>A partial list of available widgets includes {@link android.widget.Button Button},
{@link android.widget.TextView TextView},
{@link android.widget.EditText EditText},
{@link android.widget.ListView ListView},
{@link android.widget.CheckBox CheckBox},
{@link android.widget.RadioButton RadioButton},
{@link android.widget.Gallery Gallery},
{@link android.widget.Spinner Spinner}, and the more special-purpose
{@link android.widget.AutoCompleteTextView AutoCompleteTextView},
{@link android.widget.ImageSwitcher ImageSwitcher}, and
{@link android.widget.TextSwitcher TextSwitcher}. </p>
<p>Among the layouts available are {@link android.widget.LinearLayout LinearLayout},
{@link android.widget.FrameLayout FrameLayout}, {@link android.widget.RelativeLayout RelativeLayout},
and others. For more examples, see <a href="layout-objects.html">Common Layout Objects</a>.</p>
<p>If none of the prebuilt widgets or layouts meets your needs, you can create your own View subclass.
If you only need to make small adjustments to an existing widget or layout, you can simply subclass
the widget or layout and override its methods.
</p>
<p>Creating your own View subclasses gives you precise control over the appearance and function
of a screen element. To give an idea of the control you get with custom views, here are some
examples of what you could do with them:</p>
<ul>
<li>
You could create a completely custom-rendered View type, for example a "volume
control" knob rendered using 2D graphics, and which resembles an
analog electronic control.
</li>
<li>
You could combine a group of View components into a new single component, perhaps
to make something like a ComboBox (a combination of popup list and free
entry text field), a dual-pane selector control (a left and right pane
with a list in each where you can re-assign which item is in which
list), and so on.
</li>
<li>
You could override the way that an EditText component is rendered on the screen
(the <a href="{@docRoot}resources/samples/NotePad/index.html">Notepad Tutorial</a> uses this to good effect,
to create a lined-notepad page).
</li>
<li>
You could capture other events like key presses and handle them in some custom
way (such as for a game).
</li>
</ul>
<p>
The sections below explain how to create custom Views and use them in your application.
For detailed reference information, see the {@link android.view.View} class. </p>
<h2 id="basic">The Basic Approach</h2>
<p>Here is a high level overview of what you need to know to get started in creating your own
View components:</p>
<ol>
<li>
Extend an existing {@link android.view.View View} class or subclass
with your own class.
</li>
<li>
Override some of the methods from the superclass. The superclass methods
to override start with '<code>on</code>', for
example, {@link android.view.View#onDraw onDraw()},
{@link android.view.View#onMeasure onMeasure()}, and
{@link android.view.View#onKeyDown onKeyDown()}.
This is similar to the <code>on...</code> events in {@link android.app.Activity Activity}
or {@link android.app.ListActivity ListActivity}
that you override for lifecycle and other functionality hooks.
<li>
Use your new extension class. Once completed, your new extension class
can be used in place of the view upon which it was based.
</li>
</ol>
<p class="note"><strong>Tip:</strong>
Extension classes can be defined as inner classes inside the activities
that use them. This is useful because it controls access to them but
isn't necessary (perhaps you want to create a new public View for
wider use in your application).
</p>
<h2 id="custom">Fully Customized Components</h2>
<p>
Fully customized components can be used to create graphical components that
appear however you wish. Perhaps a graphical VU
meter that looks like an old analog gauge, or a sing-a-long text view where
a bouncing ball moves along the words so you can sing along with a karaoke
machine. Either way, you want something that the built-in components just
won't do, no matter how you combine them.</p>
<p>Fortunately, you can easily create components that look and behave in any
way you like, limited perhaps only by your imagination, the size of the
screen, and the available processing power (remember that ultimately your
application might have to run on something with significantly less power
than your desktop workstation).</p>
<p>To create a fully customized component:</p>
<ol>
<li>
The most generic view you can extend is, unsurprisingly, {@link
android.view.View View}, so you will usually start by extending this to
create your new super component.
</li>
<li>
You can supply a constructor which can
take attributes and parameters from the XML, and you can also consume
your own such attributes and parameters (perhaps the color and range of
the VU meter, or the width and damping of the needle, etc.)
</li>
<li>
You will probably want to create your own event listeners,
property accessors and modifiers, and possibly more sophisticated
behavior in your component class as well.
</li>
<li>
You will almost certainly want to override <code>onMeasure()</code> and
are also likely to need to override <code>onDraw()</code> if you want
the component to show something. While both have default behavior,
the default <code>onDraw()</code> will do nothing, and the default
<code>onMeasure()</code> will always set a size of 100x100 &mdash; which is
probably not what you want.
</li>
<li>
Other <code>on...</code> methods may also be overridden as required.
</li>
</ol>
<h3>Extend <code>onDraw()</code> and <code>onMeasure()</code></h3>
<p>The <code>onDraw()</code> method delivers you a {@link android.graphics.Canvas Canvas}
upon which you can implement anything you want: 2D graphics, other standard or
custom components, styled text, or anything else you can think of.</p>
<p class="note"><strong>Note:</strong>
This does not apply to 3D graphics. If you want to
use 3D graphics, you must extend {@link android.view.SurfaceView SurfaceView}
instead of View, and draw from a separate thread. See the
GLSurfaceViewActivity sample
for details.</p>
<p><code>onMeasure()</code> is a little more involved. <code>onMeasure()</code>
is a critical piece of the rendering contract between your component and its
container. <code>onMeasure()</code> should be overridden to efficiently and
accurately report the measurements of its contained parts. This is made
slightly more complex by the requirements of limits from the parent
(which are passed in to the <code>onMeasure()</code> method) and by the
requirement to call the <code>setMeasuredDimension()</code> method with the
measured width and height once they have been calculated. If you fail to
call this method from an overridden <code>onMeasure()</code> method, the
result will be an exception at measurement time.</p>
<p>At a high level, implementing <code>onMeasure()</code> looks something
like this:</p>
<ol>
<li>
The overridden <code>onMeasure()</code> method is called with width and
height measure specifications (<code>widthMeasureSpec</code> and
<code>heightMeasureSpec</code> parameters, both are integer codes
representing dimensions) which should be treated as requirements for
the restrictions on the width and height measurements you should produce. A
full reference to the kind of restrictions these specifications can require
can be found in the reference documentation under {@link
android.view.View#onMeasure View.onMeasure(int, int)} (this reference
documentation does a pretty good job of explaining the whole measurement
operation as well).
</li>
<li>
Your component's <code>onMeasure()</code> method should calculate a
measurement width and height which will be required to render the
component. It should try to stay within the specifications passed in,
although it can choose to exceed them (in this case, the parent can
choose what to do, including clipping, scrolling, throwing an exception,
or asking the <code>onMeasure()</code> to try again, perhaps with
different measurement specifications).
</li>
<li>
Once the width and height are calculated, the <code>setMeasuredDimension(int
width, int height)</code> method must be called with the calculated
measurements. Failure to do this will result in an exception being
thrown.
</li>
</ol>
<p>
Here's a summary of some of the other standard methods that the framework calls on views:
</p>
<table border="2" width="85%" align="center" cellpadding="5">
<thead>
<tr><th>Category</th> <th>Methods</th> <th>Description</th></tr>
</thead>
<tbody>
<tr>
<td rowspan="2">Creation</td>
<td>Constructors</td>
<td>There is a form of the constructor that are called when the view
is created from code and a form that is called when the view is
inflated from a layout file. The second form should parse and apply
any attributes defined in the layout file.
</td>
</tr>
<tr>
<td><code>{@link android.view.View#onFinishInflate()}</code></td>
<td>Called after a view and all of its children has been inflated
from XML.</td>
</tr>
<tr>
<td rowspan="3">Layout</td>
<td><code>{@link android.view.View#onMeasure}</code></td>
<td>Called to determine the size requirements for this view and all
of its children.
</td>
</tr>
<tr>
<td><code>{@link android.view.View#onLayout}</code></td>
<td>Called when this view should assign a size and position to all
of its children.
</td>
</tr>
<tr>
<td><code>{@link android.view.View#onSizeChanged}</code></td>
<td>Called when the size of this view has changed.
</td>
</tr>
<tr>
<td>Drawing</td>
<td><code>{@link android.view.View#onDraw}</code></td>
<td>Called when the view should render its content.
</td>
</tr>
<tr>
<td rowspan="4">Event processing</td>
<td><code>{@link android.view.View#onKeyDown}</code></td>
<td>Called when a new key event occurs.
</td>
</tr>
<tr>
<td><code>{@link android.view.View#onKeyUp}</code></td>
<td>Called when a key up event occurs.
</td>
</tr>
<tr>
<td><code>{@link android.view.View#onTrackballEvent}</code></td>
<td>Called when a trackball motion event occurs.
</td>
</tr>
<tr>
<td><code>{@link android.view.View#onTouchEvent}</code></td>
<td>Called when a touch screen motion event occurs.
</td>
</tr>
<tr>
<td rowspan="2">Focus</td>
<td><code>{@link android.view.View#onFocusChanged}</code></td>
<td>Called when the view gains or loses focus.
</td>
</tr>
<tr>
<td><code>{@link android.view.View#onWindowFocusChanged}</code></td>
<td>Called when the window containing the view gains or loses focus.
</td>
</tr>
<tr>
<td rowspan="3">Attaching</td>
<td><code>{@link android.view.View#onAttachedToWindow()}</code></td>
<td>Called when the view is attached to a window.
</td>
</tr>
<tr>
<td><code>{@link android.view.View#onDetachedFromWindow}</code></td>
<td>Called when the view is detached from its window.
</td>
</tr>
<tr>
<td><code>{@link android.view.View#onWindowVisibilityChanged}</code></td>
<td>Called when the visibility of the window containing the view
has changed.
</td>
</tr>
</tbody>
</table>
<h3 id="customexample">A Custom View Example</h3>
<p>The CustomView sample in the
<a href="{@docRoot}resources/samples/ApiDemos/index.html">API Demos</a> provides an example
of a customized View. The custom View is defined in the
<a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/view/LabelView.html">LabelView</a>
class.</p>
<p>The LabelView sample demonstrates a number of different aspects of custom components:</p>
<ul>
<li>Extending the View class for a completely custom component.</li>
<li>Parameterized constructor that takes the view inflation parameters
(parameters defined in the XML). Some of these are passed through to the
View superclass, but more importantly, there are some custom attributes defined
and used for LabelView.</li>
<li>Standard public methods of the type you would expect to see for a label
component, for example <code>setText()</code>, <code>setTextSize()</code>,
<code>setTextColor()</code> and so on.</li>
<li>An overridden <code>onMeasure</code> method to determine and set the
rendering size of the component. (Note that in LabelView, the real work is done
by a private <code>measureWidth()</code> method.)</li>
<li>An overridden <code>onDraw()</code> method to draw the label onto the
provided canvas.</li>
</ul>
<p>You can see some sample usages of the LabelView custom View in
<a href="{@docRoot}resources/samples/ApiDemos/res/layout/custom_view_1.html">custom_view_1.xml</a>
from the samples. In particular, you can see a mix of both <code>android:</code>
namespace parameters and custom <code>app:</code> namespace parameters. These
<code>app:</code> parameters are the custom ones that the LabelView recognizes
and works with, and are defined in a styleable inner class inside of the
samples R resources definition class.</p>
<h2 id="compound">Compound Controls
</h2>
<p>If you don't want to create a completely customized component, but instead
are looking to put together a reusable component that consists of a group of
existing controls, then creating a Compound Component (or Compound Control) might
fit the bill. In a nutshell, this brings together a number of more atomic
controls (or views) into a logical group of items that can be treated as a
single thing. For example, a Combo Box can be thought of as a
combination of a single line EditText field and an adjacent button with an attached
PopupList. If you press the button and select
something from the list, it populates the EditText field, but the user can
also type something directly into the EditText if they prefer.</p>
<p>In Android, there are actually two other Views readily available to do
this: {@link android.widget.Spinner Spinner} and
{@link android.widget.AutoCompleteTextView AutoCompleteTextView}, but
regardless, the concept of a Combo Box makes an easy-to-understand
example.</p>
<p>To create a compound component:</p>
<ol>
<li>
The usual starting point is a Layout of some kind, so create a class
that extends a Layout. Perhaps in the case of a Combo box we might use
a LinearLayout with horizontal orientation. Remember that other layouts
can be nested inside, so the compound component can be arbitrarily
complex and structured. Note that just like with an Activity, you can
use either the declarative (XML-based) approach to creating the
contained components, or you can nest them programmatically from your
code.
</li>
<li>
In the constructor for the new class, take whatever parameters the
superclass expects, and pass them through to the superclass constructor
first. Then you can set up the other views to use within your new
component; this is where you would create the EditText field and the
PopupList. Note that you also might introduce your own attributes and
parameters into the XML that can be pulled out and used by your
constructor.
</li>
<li>
You can also create listeners for events that your contained views might
generate, for example, a listener method for the List Item Click Listener
to update the contents of the EditText if a list selection is made.
</li>
<li>
You might also create your own properties with accessors and modifiers,
for example, allow the EditText value to be set initially in the
component and query for its contents when needed.
</li>
<li>
In the case of extending a Layout, you don't need to override the
<code>onDraw()</code> and <code>onMeasure()</code> methods since the
layout will have default behavior that will likely work just fine. However,
you can still override them if you need to.
</li>
<li>
You might override other <code>on...</code> methods, like
<code>onKeyDown()</code>, to perhaps choose certain default values from
the popup list of a combo box when a certain key is pressed.
</li>
</ol>
<p>
To summarize, the use of a Layout as the basis for a Custom Control has a
number of advantages, including:</p>
<ul>
<li>
You can specify the layout using the declarative XML files just like
with an activity screen, or you can create views programmatically and
nest them into the layout from your code.
</li>
<li>
The <code>onDraw()</code> and <code>onMeasure()</code> methods (plus
most of the other <code>on...</code> methods) will likely have suitable behavior so
you don't have to override them.
</li>
<li>
In the end, you can very quickly construct arbitrarily complex compound
views and re-use them as if they were a single component.
</li>
</ul>
<h4>Examples of Compound Controls</h4>
<p>In the API Demos project
that comes with the SDK, there are two List
examples &mdash; Example 4 and Example 6 under Views/Lists demonstrate a
SpeechView which extends LinearLayout to make a component for displaying
Speech quotes. The corresponding classes in the sample code are
<code>List4.java</code> and <code>List6.java</code>.</p>
<h2 id="modifying">Modifying an Existing View Type</h2>
<p>There is an even easier option for creating a custom View which is
useful in certain circumstances. If there is a component that is already very
similar to what you want, you can simply extend that component and just
override the behavior that you want to change. You can do all of the things
you would do with a fully customized component, but by starting with a more
specialized class in the View hierarchy, you can also get a lot of behavior for
free that probably does exactly what you want.</p>
<p>For example, the SDK includes a <a
href="{@docRoot}resources/samples/NotePad/index.html">NotePad application</a> in the
samples. This demonstrates many aspects of using the Android platform, among
them is extending an EditText View to make a lined notepad. This is not a
perfect example, and the APIs for doing this might change from this early
preview, but it does demonstrate the principles.</p>
<p>If you haven't done so already, import the
NotePad sample into Eclipse (or
just look at the source using the link provided). In particular look at the definition of
<code>MyEditText</code> in the <a
href="{@docRoot}resources/samples/NotePad/src/com/example/android/notepad/NoteEditor.html">NoteEditor.java</a>
file.</p>
<p>Some points to note here</p>
<ol>
<li>
<strong>The Definition</strong>
<p>The class is defined with the following line:<br/>
<code>public static class MyEditText extends EditText</code></p>
<ul>
<li>
It is defined as an inner class within the <code>NoteEditor</code>
activity, but it is public so that it could be accessed as
<code>NoteEditor.MyEditText</code> from outside of the <code>NoteEditor</code>
class if desired.
</li>
<li>
It is <code>static</code>, meaning it does not generate the so-called
"synthetic methods" that allow it to access data from the parent
class, which in turn means that it really behaves as a separate
class rather than something strongly related to <code>NoteEditor</code>.
This is a cleaner way to create inner classes if they do not need
access to state from the outer class, keeps the generated class
small, and allows it to be used easily from other classes.
</li>
<li>
It extends <code>EditText</code>, which is the View we have chosen to
customize in this case. When we are finished, the new class will be
able to substitute for a normal <code>EditText</code> view.
</li>
</ul>
</li>
<li>
<strong>Class Initialization</strong>
<p>As always, the super is called first. Furthermore,
this is not a default constructor, but a parameterized one. The
EditText is created with these parameters when it is inflated from an
XML layout file, thus, our constructor needs to both take them and pass them
to the superclass constructor as well.</p>
</li>
<li>
<strong>Overridden Methods</strong>
<p>In this example, there is only one method to be overridden:
<code>onDraw()</code> &mdash; but there could easily be others needed when you
create your own custom components.</p>
<p>For the NotePad sample, overriding the <code>onDraw()</code> method allows
us to paint the blue lines on the <code>EditText</code> view canvas (the
canvas is passed into the overridden <code>onDraw()</code> method). The
super.onDraw() method is called before the method ends. The
superclass method should be invoked, but in this case, we do it at the
end after we have painted the lines we want to include.</p>
<li>
<strong>Use the Custom Component</strong>
<p>We now have our custom component, but how can we use it? In the
NotePad example, the custom component is used directly from the
declarative layout, so take a look at <code>note_editor.xml</code> in the
<code>res/layout</code> folder.</p>
<pre>
&lt;view
class=&quot;com.android.notepad.NoteEditor$MyEditText&quot;
id=&quot;&#64;+id/note&quot;
android:layout_width=&quot;fill_parent&quot;
android:layout_height=&quot;fill_parent&quot;
android:background=&quot;&#64;android:drawable/empty&quot;
android:padding=&quot;10dip&quot;
android:scrollbars=&quot;vertical&quot;
android:fadingEdge=&quot;vertical&quot; /&gt;
</pre>
<ul>
<li>
The custom component is created as a generic view in the XML, and
the class is specified using the full package. Note also that the
inner class we defined is referenced using the
<code>NoteEditor$MyEditText</code> notation which is a standard way to
refer to inner classes in the Java programming language.
<p>If your custom View component is not defined as an inner class, then you can,
alternatively, declare the View component
with the XML element name, and exclude the <code>class</code> attribute. For example:</p>
<pre>
&lt;com.android.notepad.MyEditText
id=&quot;&#64;+id/note&quot;
... />
</pre>
<p>Notice that the <code>MyEditText</code> class is now a separate class file. When the class
is nested in the <code>NoteEditor</code> class, this technique will not work.</p>
</li>
<li>
The other attributes and parameters in the definition are the ones
passed into the custom component constructor, and then passed
through to the EditText constructor, so they are the same
parameters that you would use for an EditText view. Note that it is
possible to add your own parameters as well, and we will touch on
this again below.
</li>
</ul>
</li>
</ol>
<p>And that's all there is to it. Admittedly this is a simple case, but
that's the point &mdash; creating custom components is only as complicated as you
need it to be.</p>
<p>A more sophisticated component may override even more <code>on...</code> methods and
introduce some of its own helper methods, substantially customizing its properties and
behavior. The only limit is your imagination and what you need the component to
do.</p>
@@ -0,0 +1,299 @@
page.title=Declaring Layout
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="#write">Write the XML</a></li>
<li><a href="#load">Load the XML Resource</a></li>
<li><a href="#attributes">Attributes</a>
<ol>
<li><a href="#id">ID</a></li>
<li><a href="#layout-params">Layout Parameters</a></li>
</ol>
</li>
<li><a href="#Position">Position</a></li>
<li><a href="#SizePaddingMargins">Size, Padding and Margins</a></li>
</ol>
<h2>Key classes</h2>
<ol>
<li>{@link android.view.View}</li>
<li>{@link android.view.ViewGroup}</li>
<li>{@link android.view.ViewGroup.LayoutParams}</li>
</ol>
</div>
</div>
<p>Your layout is the architecture for the user interface in an Activity.
It defines the layout structure and holds all the elements that appear to the user.
You can declare your layout in two ways:</p>
<ul>
<li><strong>Declare UI elements in XML</strong>. Android provides a straightforward XML
vocabulary that corresponds to the View classes and subclasses, such as those for widgets and layouts.</li>
<li><strong>Instantiate layout elements at runtime</strong>. Your
application can create View and ViewGroup objects (and manipulate their properties) programmatically. </li>
</ul>
<p>The Android framework gives you the flexibility to use either or both of these methods for declaring and managing your application's UI. For example, you could declare your application's default layouts in XML, including the screen elements that will appear in them and their properties. You could then add code in your application that would modify the state of the screen objects, including those declared in XML, at run time. </p>
<div class="sidebox-wrapper">
<div class="sidebox">
<ul>
<li>The <a href="{@docRoot}sdk/eclipse-adt.html">ADT
Plugin for Eclipse</a> offers a layout preview of your XML &mdash;
with the XML file opened, select the <strong>Layout</strong> tab.</li>
<li>You should also try the
<a href="{@docRoot}guide/developing/tools/hierarchy-viewer.html">Hierarchy Viewer</a> tool,
for debugging layouts &mdash; it reveals layout property values,
draws wireframes with padding/margin indicators, and full rendered views while
you debug on the emulator or device.</li>
<li>The <a href="{@docRoot}guide/developing/tools/layoutopt.html">layoutopt</a> tool lets
you quickly analyze your layouts and hierarchies for inefficiencies or other problems.</li>
</div>
</div>
<p>The advantage to declaring your UI in XML is that it enables you to better separate the presentation of your application from the code that controls its behavior. Your UI descriptions are external to your application code, which means that you can modify or adapt it without having to modify your source code and recompile. For example, you can create XML layouts for different screen orientations, different device screen sizes, and different languages. Additionally, declaring the layout in XML makes it easier to visualize the structure of your UI, so it's easier to debug problems. As such, this document focuses on teaching you how to declare your layout in XML. If you're
interested in instantiating View objects at runtime, refer to the {@link android.view.ViewGroup} and
{@link android.view.View} class references.</p>
<p>In general, the XML vocabulary for declaring UI elements closely follows the structure and naming of the classes and methods, where element names correspond to class names and attribute names correspond to methods. In fact, the correspondence is often so direct that you can guess what XML attribute corresponds to a class method, or guess what class corresponds to a given xml element. However, note that not all vocabulary is identical. In some cases, there are slight naming differences. For
example, the EditText element has a <code>text</code> attribute that corresponds to
<code>EditText.setText()</code>. </p>
<p class="note"><strong>Tip:</strong> Learn more about different layout types in <a href="{@docRoot}guide/topics/ui/layout-objects.html">Common
Layout Objects</a>. There are also a collection of tutorials on building various layouts in the
<a href="{@docRoot}resources/tutorials/views/index.html">Hello Views</a> tutorial guide.</p>
<h2 id="write">Write the XML</h2>
<div class="sidebox-wrapper">
<div class="sidebox">
<p>For your convenience, the API reference documentation for UI related classes
lists the available XML attributes that correspond to the class methods, including inherited
attributes.</p>
<p>To learn more about the available XML elements and attributes, as well as the format of the XML file, see <a
href="{@docRoot}guide/topics/resources/available-resources.html#layoutresources">Layout Resources</a>.</p>
</div>
</div>
<p>Using Android's XML vocabulary, you can quickly design UI layouts and the screen elements they contain, in the same way you create web pages in HTML &mdash; with a series of nested elements. </p>
<p>Each layout file must contain exactly one root element, which must be a View or ViewGroup object. Once you've defined the root element, you can add additional layout objects or widgets as child elements to gradually build a View hierarchy that defines your layout. For example, here's an XML layout that uses a vertical {@link android.widget.LinearLayout}
to hold a {@link android.widget.TextView} and a {@link android.widget.Button}:</p>
<pre>
&lt;?xml version="1.0" encoding="utf-8"?>
&lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
&lt;TextView android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello, I am a TextView" />
&lt;Button android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello, I am a Button" />
&lt;/LinearLayout>
</pre>
<p>After you've declared your layout in XML, save the file with the <code>.xml</code> extension,
in your Android project's <code>res/layout/</code> directory, so it will properly compile. </p>
<p>We'll discuss each of the attributes shown here a little later.</p>
<h2 id="load">Load the XML Resource</h2>
<p>When you compile your application, each XML layout file is compiled into a
{@link android.view.View} resource. You should load the layout resource from your application code, in your
{@link android.app.Activity#onCreate(android.os.Bundle) Activity.onCreate()} callback implementation.
Do so by calling <code>{@link android.app.Activity#setContentView(int) setContentView()}</code>,
passing it the reference to your layout resource in the form of:
<code>R.layout.<em>layout_file_name</em></code>
For example, if your XML layout is saved as <code>main_layout.xml</code>, you would load it
for your Activity like so:</p>
<pre>
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView.(R.layout.main_layout);
}
</pre>
<p>The <code>onCreate()</code> callback method in your Activity is called by the Android framework when
your Activity is launched (see the discussion on Lifecycles, in the
<a href="{@docRoot}guide/topics/fundamentals.html#lcycles">Application Fundamentals</a>, for more on this).</p>
<h2 id="attributes">Attributes</h2>
<p>Every View and ViewGroup object supports their own variety of XML attributes.
Some attributes are specific to a View object (for example, TextView supports the <code>textSize</code>
attribute), but these attributes are also inherited by any View objects that may extend this class.
Some are common to all View objects, because they are inherited from the root View class (like
the <code>id</code> attribute). And, other attributes are considered "layout parameters," which are
attributes that describe certain layout orientations of the View object, as defined by that object's
parent ViewGroup object.</p>
<h3 id="id">ID</h3>
<p>Any View object may have an integer ID associated with it, to uniquely identify the View within the tree.
When the application is compiled, this ID is referenced as an integer, but the ID is typically
assigned in the layout XML file as a string, in the <code>id</code> attribute.
This is an XML attribute common to all View objects
(defined by the {@link android.view.View} class) and you will use it very often.
The syntax for an ID, inside an XML tag is:</p>
<pre>android:id="&#64;+id/my_button"</pre>
<p>The at-symbol (&#64;) at the beginning of the string indicates that the XML parser should parse and expand the rest
of the ID string and identify it as an ID resource. The plus-symbol (+) means that this is a new resource name that must
be created and added to our resources (in the <code>R.java</code> file). There are a number of other ID resources that
are offered by the Android framework. When referencing an Android resource ID, you do not need the plus-symbol,
but must add the <code>android</code> package namespace, like so:</p>
<pre>android:id="&#64;android:id/empty"</pre>
<p>With the <code>android</code> package namespace in place, we're now referencing an ID from the <code>android.R</code>
resources class, rather than the local resources class.</p>
<p>In order to create views and reference them from the application, a common pattern is to:</p>
<ol>
<li>Define a view/widget in the layout file and assign it a unique ID:
<pre>
&lt;Button android:id="&#64;+id/my_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="&#64;string/my_button_text"/>
</pre>
</li>
<li>Then create an instance of the view object and capture it from the layout
(typically in the <code>{@link android.app.Activity#onCreate(Bundle) onCreate()}</code> method):
<pre>
Button myButton = (Button) findViewById(R.id.my_button);
</pre>
</li>
</ol>
<p>Defining IDs for view objects is important when creating a {@link android.widget.RelativeLayout}.
In a relative layout, sibling views can define their layout relative to another sibling view,
which is referenced by the unique ID.</p>
<p>An ID need not be unique throughout the entire tree, but it should be
unique within the part of the tree you are searching (which may often be the entire tree, so it's best
to be completely unique when possible).</p>
<h3 id="layout-params">Layout Parameters</h3>
<p>XML layout attributes named <code>layout_<em>something</em></code> define
layout parameters for the View that are appropriate for the ViewGroup in which it resides.</p>
<p>Every ViewGroup class implements a nested class that extends {@link
android.view.ViewGroup.LayoutParams}. This subclass
contains property types that define the size and position for each child view, as
appropriate for the view group. As you can see in the figure below, the parent
view group defines layout parameters for each child view (including the child view group).</p>
<img src="{@docRoot}images/layoutparams.png" alt="" height="300" align="center"/>
<p>Note that every LayoutParams subclass has its own syntax for setting
values. Each child element must define LayoutParams that are appropriate for its parent,
though it may also define different LayoutParams for its own children. </p>
<p>All view groups include a width and height (<code>layout_width</code> and
<code>layout_height</code>), and each view is required to define them. Many
LayoutParams also include optional margins and borders. <p>
<p>You can specify width and height with exact measurements, though you probably
won't want to do this often. More often, you will use one of these constants to
set the width or height: </p>
<ul>
<li><var>wrap_content</var> tells your view to size itself to the dimensions
required by its content</li>
<li><var>fill_parent</var> (renamed <var>match_parent</var> in API Level 8)
tells your view to become as big as its parent view group will allow.</li>
</ul>
<p>In general, specifying a layout width and height using absolute units such as
pixels is not recommended. Instead, using relative measurements such as
density-independent pixel units (<var>dp</var>), <var>wrap_content</var>, or
<var>fill_parent</var>, is a better approach, because it helps ensure that
your application will display properly across a variety of device screen sizes.
The accepted measurement types are defined in the
<a href="{@docRoot}guide/topics/resources/available-resources.html#dimension">
Available Resources</a> document.</p>
<h2 id="Position">Layout Position</h2>
<p>
The geometry of a view is that of a rectangle. A view has a location,
expressed as a pair of <em>left</em> and <em>top</em> coordinates, and
two dimensions, expressed as a width and a height. The unit for location
and dimensions is the pixel.
</p>
<p>
It is possible to retrieve the location of a view by invoking the methods
{@link android.view.View#getLeft()} and {@link android.view.View#getTop()}. The former returns the left, or X,
coordinate of the rectangle representing the view. The latter returns the
top, or Y, coordinate of the rectangle representing the view. These methods
both return the location of the view relative to its parent. For instance,
when getLeft() returns 20, that means the view is located 20 pixels to the
right of the left edge of its direct parent.
</p>
<p>
In addition, several convenience methods are offered to avoid unnecessary
computations, namely {@link android.view.View#getRight()} and {@link android.view.View#getBottom()}.
These methods return the coordinates of the right and bottom edges of the
rectangle representing the view. For instance, calling {@link android.view.View#getRight()}
is similar to the following computation: <code>getLeft() + getWidth()</code>.
</p>
<h2 id="SizePaddingMargins">Size, Padding and Margins</h2>
<p>
The size of a view is expressed with a width and a height. A view actually
possess two pairs of width and height values.
</p>
<p>
The first pair is known as <em>measured width</em> and
<em>measured height</em>. These dimensions define how big a view wants to be
within its parent. The
measured dimensions can be obtained by calling {@link android.view.View#getMeasuredWidth()}
and {@link android.view.View#getMeasuredHeight()}.
</p>
<p>
The second pair is simply known as <em>width</em> and <em>height</em>, or
sometimes <em>drawing width</em> and <em>drawing height</em>. These
dimensions define the actual size of the view on screen, at drawing time and
after layout. These values may, but do not have to, be different from the
measured width and height. The width and height can be obtained by calling
{@link android.view.View#getWidth()} and {@link android.view.View#getHeight()}.
</p>
<p>
To measure its dimensions, a view takes into account its padding. The padding
is expressed in pixels for the left, top, right and bottom parts of the view.
Padding can be used to offset the content of the view by a specific amount of
pixels. For instance, a left padding of 2 will push the view's content by
2 pixels to the right of the left edge. Padding can be set using the
{@link android.view.View#setPadding(int, int, int, int)} method and queried by calling
{@link android.view.View#getPaddingLeft()}, {@link android.view.View#getPaddingTop()},
{@link android.view.View#getPaddingRight()} and {@link android.view.View#getPaddingBottom()}.
</p>
<p>
Even though a view can define a padding, it does not provide any support for
margins. However, view groups provide such a support. Refer to
{@link android.view.ViewGroup} and
{@link android.view.ViewGroup.MarginLayoutParams} for further information.
</p>
<p>For more information about dimensions, see <a href="{@docRoot}guide/topics/resources/available-resources.html#dimension">Dimension Values</a>.</p>
+651
View File
@@ -0,0 +1,651 @@
page.title=Creating 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="#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>
</ol>
<h2>Key classes</h2>
<ol>
<li>{@link android.app.Dialog}</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 and short activities that directly relate to the application in progress.</p>
<p>The Android API supports the following types of {@link android.app.Dialog} objects:</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>
<h2 id="ShowingADialog">Showing a Dialog</h2>
<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>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;
}
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>
<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>
<h2 id="DismissingADialog">Dismissing a Dialog</h2>
<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>
<img src="{@docRoot}images/dialog_buttons.png" alt="" style="float:right" />
<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>
<pre>
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage("Are you sure you want to exit?")
.setCancelable(false)
.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
MyActivity.this.finish();
}
})
.setNegativeButton("No", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
}
});
AlertDialog alert = 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
{@link android.content.DialogInterface.OnClickListener} that defines the action to take
when the user selects 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>
<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>
<pre>
final CharSequence[] items = {"Red", "Green", "Blue"};
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>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>
<h4>Adding checkboxes and radio buttons</h4>
<img src="{@docRoot}images/dialog_singlechoicelist.png" alt="" style="float:right" />
<p>To create a list of multiple-choice items (checkboxes) or
single-choice items (radio buttons) inside the dialog, 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/topics/fundamentals.html#lcycles">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
{@link android.app.AlertDialog.Builder#setSingleChoiceItems(int,int,DialogInterface.OnClickListener)
setSingleChoiceItems()}:</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>
<h2 id="ProgressDialog">Creating a ProgressDialog</h2>
<img src="{@docRoot}images/dialog_progress_spinning.png" alt="" style="float:right" />
<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>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>
<pre>
ProgressDialog dialog = ProgressDialog.show(MyActivity.this, "",
"Loading. Please wait...", true);
</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>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>
<h3 id="ShowingAProgressBar">Showing a progress bar</h3>
<img src="/images/dialog_progress_bar.png" alt="" style="float:right" />
<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>
<pre>
ProgressDialog progressDialog;
progressDialog = new ProgressDialog(mContext);
progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
progressDialog.setMessage("Loading...");
progressDialog.setCancelable(false);
</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>
<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);
}
});
}
protected Dialog onCreateDialog(int id) {
switch(id) {
case PROGRESS_DIALOG:
progressDialog = new ProgressDialog(NotificationTest.this);
progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
progressDialog.setMessage("Loading...");
progressThread = new ProgressThread(handler);
progressThread.start();
return progressDialog;
default:
return null;
}
}
// Define the Handler that receives messages from the thread and update the progress
final Handler handler = new Handler() {
public void handleMessage(Message msg) {
int total = msg.getData().getInt("total");
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();
Bundle b = new Bundle();
b.putInt("total", total);
msg.setData(b);
mHandler.sendMessage(msg);
total++;
}
}
/* sets the current state for the thread,
* used to stop the thread */
public void setState(int state) {
mState = state;
}
}
}
</pre>
</div> <!-- end toggleme -->
</div> <!-- end toggleable -->
<h2 id="CustomDialog">Creating a Custom Dialog</h2>
<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>
<p>For example, to create the dialog shown to the right:</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>
</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>
<pre>
Context mContext = getApplicationContext();
Dialog dialog = new Dialog(mContext);
dialog.setContentView(R.layout.custom_dialog);
dialog.setTitle("Custom Dialog");
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);
</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>
<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();
</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, refer to the reference documentation for the
{@link android.app.Dialog} and {@link android.app.AlertDialog.Builder}
classes.</p>
@@ -0,0 +1,98 @@
page.title=How Android Draws Views
parent.title=User Interface
parent.link=index.html
@jd:body
<p>When an Activity receives focus, it will be requested to draw its layout.
The Android framework will handle the procedure for drawing, but the Activity must provide
the root node of its layout hierarchy.</p>
<p>Drawing begins with the root node of the layout. It is requested to measure and
draw the layout tree. Drawing is handled by walking the tree and rendering each View that
intersects the invalid region. In turn, each View group is responsible for requesting
each of its children to be drawn (with the <code>{@link android.view.View#draw(Canvas) draw()}</code> method)
and each View is responsible for drawing itself.
Because the tree is traversed in-order,
this means that parents will be drawn before (i.e., behind) their children, with
siblings drawn in the order they appear in the tree.
</p>
<div class="sidebox-wrapper">
<div class="sidebox">
<p>The framework will not draw Views that are not in the invalid region, and also
will take care of drawing the Views background for you.</p>
<p>You can force a View to draw, by calling <code>{@link android.view.View#invalidate()}</code>.
</p>
</div>
</div>
<p>
Drawing the layout is a two pass process: a measure pass and a layout pass. The measuring
pass is implemented in <code>{@link android.view.View#measure(int, int)}</code> and is a top-down traversal
of the View tree. Each View pushes dimension specifications down the tree
during the recursion. At the end of the measure pass, every View has stored
its measurements. The second pass happens in
<code>{@link android.view.View#layout(int,int,int,int)}</code> and is also top-down. During
this pass each parent is responsible for positioning all of its children
using the sizes computed in the measure pass.
</p>
<p>
When a View's <code>measure()</code> method returns, its <code>{@link android.view.View#getMeasuredWidth()}</code> and
<code>{@link android.view.View#getMeasuredHeight()}</code> values must be set, along with those for all of
that View's descendants. A View's measured width and measured height values
must respect the constraints imposed by the View's parents. This guarantees
that at the end of the measure pass, all parents accept all of their
children's measurements. A parent View may call <code>measure()</code> more than once on
its children. For example, the parent may measure each child once with
unspecified dimensions to find out how big they want to be, then call
<code>measure()</code> on them again with actual numbers if the sum of all the children's
unconstrained sizes is too big or too small (i.e., if the children don't agree among themselves
as to how much space they each get, the parent will intervene and set the rules on the second pass).
</p>
<div class="sidebox-wrapper">
<div class="sidebox"><p>
To initiate a layout, call <code>{@link android.view.View#requestLayout}</code>. This method is typically
called by a View on itself when it believes that is can no longer fit within
its current bounds.</p>
</div>
</div>
<p>
The measure pass uses two classes to communicate dimensions. The
{@link android.view.View.MeasureSpec} class is used by Views to tell their parents how they
want to be measured and positioned. The base LayoutParams class just
describes how big the View wants to be for both width and height. For each
dimension, it can specify one of:</p>
<ul>
<li> an exact number
<li><var>FILL_PARENT</var>, which means the View wants to be as big as its parent
(minus padding)</li>
<li><var>WRAP_CONTENT</var>, which means that the View wants to be just big enough to
enclose its content (plus padding).</li>
</ul>
<p>There are subclasses of LayoutParams for different subclasses of ViewGroup.
For example, RelativeLayout has its own subclass of LayoutParams, which includes
the ability to center child Views horizontally and vertically.
</p>
<p>
MeasureSpecs are used to push requirements down the tree from parent to
child. A MeasureSpec can be in one of three modes:</p>
<ul>
<li><var>UNSPECIFIED</var>: This is used by a parent to determine the desired dimension
of a child View. For example, a LinearLayout may call <code>measure()</code> on its child
with the height set to <var>UNSPECIFIED</var> and a width of <var>EXACTLY</var> 240 to find out how
tall the child View wants to be given a width of 240 pixels.</li>
<li><var>EXACTLY</var>: This is used by the parent to impose an exact size on the
child. The child must use this size, and guarantee that all of its
descendants will fit within this size.</li>
<li><var>AT_MOST</var>: This is used by the parent to impose a maximum size on the
child. The child must guarantee that it and all of its descendants will fit
within this size.</li>
</ul>
+235
View File
@@ -0,0 +1,235 @@
page.title=User Interface
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>In this document</h2>
<ol>
<li><a href="#ViewHierarchy">View Hierarchy</a></li>
<li><a href="#Layout">Layout</a></li>
<li><a href="#Widgets">Widgets</a></li>
<li><a href="#Events">UI Events</a></li>
<li><a href="#Menus">Menus</a></li>
<li><a href="#Advanced">Advanced Topics</a>
<ol>
<li><a href="#Adapters">Adapters</a></li>
<li><a href="#StylesAndThemes">Styles and Themes</a></li>
</ol>
</li>
</ol>
<h2>Key classes</h2>
<ol>
<li>{@link android.view.View}</li>
<li>{@link android.view.ViewGroup}</li>
<li>{@link android.widget Widget classes}</li>
</ol>
</div>
</div>
<p>In an Android application, the user interface is built using {@link android.view.View} and
{@link android.view.ViewGroup} objects. There are many types of views and view groups, each of which
is a descendant of the {@link android.view.View} class.</p>
<p>View objects are the basic units of user interface expression on the Android platform.
The View class serves as the base for subclasses called "widgets," which offer fully implemented
UI objects, like text fields and buttons. The ViewGroup class serves as the base for subclasses called "layouts,"
which offer different kinds of layout architecture, like linear, tabular and relative.</p>
<p>A View object is a data structure whose properties store the layout parameters and content for a specific
rectangular area of the screen. A View object handles its own measurement, layout, drawing, focus change,
scrolling, and key/gesture interactions for the rectangular area of the screen in which it resides. As an
object in the user interface, a View is also a point of interaction for the user and the receiver
of the interaction events.</p>
<h2 id="ViewHierarchy">View Hierarchy</h2>
<p>On the Android platform, you define an Activity's UI using a hierarchy of View and ViewGroup nodes,
as shown in the diagram below. This hierarchy tree can be as simple or complex as you need it to be, and you
can build it up using Android's set of predefined widgets and layouts, or with custom Views that you
create yourself.</p>
<img src="{@docRoot}images/viewgroup.png" alt="" width="312" height="211" align="center"/>
<p>
In order to attach the view hierarchy tree to the screen for rendering, your Activity must call the
<code>{@link android.app.Activity#setContentView(int) setContentView()}</code>
method and pass a reference to the root node object. The Android system
receives this reference and uses it to invalidate, measure, and draw the tree. The root node of the hierarchy requests
that its child nodes draw themselves &mdash; in turn, each view group node is responsible for calling
upon each of its own child views to draw themselves.
The children may request a size and location within the parent, but the parent object has the final
decision on where how big each child can be. Android parses
the elements of your layout in-order (from the top of the hierarchy tree), instantiating the Views and
adding them to their parent(s). Because these are drawn in-order, if there are elements that
overlap positions, the last one to be drawn will lie on top of others previously drawn to that space.</p>
<p>For a more detailed discussion on how view hierarchies are measured
and drawn, read <a href="how-android-draws.html">How Android Draws Views</a>.</p>
<h2 id="Layout">Layout</h2>
<p>The most common way to define your layout and express the view hierarchy is with an XML layout file.
XML offers a human-readable structure for the layout, much like HTML. Each element in XML is
either a View or ViewGroup object (or descendant thereof). View objects are leaves in the tree,
ViewGroup objects are branches in the tree (see the View Hierarchy figure above).</p>
<p>The name of an XML element
is respective to the Java class that it represents. So a <code>&lt;TextView></code> element creates
a {@link android.widget.TextView} in your UI, and a <code>&lt;LinearLayout></code> element creates
a {@link android.widget.LinearLayout} view group. When you load a layout resource,
the Android system initializes these run-time objects, corresponding to the elements in your layout.</p>
<p>For example, a simple vertical layout with a text view and a button looks like this:</p>
<pre>
&lt;?xml version="1.0" encoding="utf-8"?>
&lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
&lt;TextView android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello, I am a TextView" />
&lt;Button android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello, I am a Button" />
&lt;/LinearLayout>
</pre>
<p>Notice that the LinearLayout element contains both the TextView and the Button. You can nest
another LinearLayout (or other type of view group) inside here, to lengthen the view hierarchy and create a more
complex layout.</p>
<p>For more on building a UI layout, read <a href="declaring-layout.html">Declaring Layout</a>.
<div class="sidebox-wrapper">
<div class="sidebox">
<p><b>Tip:</b> You can also draw View and ViewGroups objects in Java code,
using the <code>{@link android.view.ViewGroup#addView(View)}</code> methods
to dynamically insert new View and ViewGroup objects.</p>
</div>
</div>
<p>There are a variety of ways in which you can layout your views. Using more and different kinds of view groups,
you can structure child views and view groups in an infinite number of ways.
Some pre-defined view groups offered by Android (called layouts) include LinearLayout, RelativeLayout,
TableLayout, GridLayout and others. Each offers a unique set of layout parameters that are used to define the
positions of child views and layout structure.</p>
<p>To learn about some of the different kinds of view groups used for a layout,
read <a href="layout-objects.html">Common Layout Objects</a>.</p>
<h2 id="Widgets">Widgets</h2>
<p>A widget is a View object that serves as an interface for interaction with the user.
Android provides a set of fully implemented
widgets, like buttons, checkboxes, and text-entry fields, so you can quickly build your UI.
Some widgets provided by Android are more complex, like a date picker, a clock, and zoom controls.
But you're not limited to the kinds of widgets provided by the Android platform. If you'd
like to do something more customized and create your own actionable elements, you can, by defining your own
View object or by extending and combining existing widgets.</p>
<p>Read more in <a href="custom-components.html">Building Custom Components</a>.</p>
<p>For a list of the widgets provided by Android, see the {@link android.widget} package.</p>
<h2 id="Events">UI Events</h2>
<p>Once you've added some Views/widgets to the UI, you probably want to know about the
user's interaction with them, so you can perform actions. To be informed of UI events, you need to
do one of two things:</p>
<ul>
<li><strong>Define an event listener and register it with the View.</strong> More often than not,
this is how you'll listen for events. The View class contains a collection of nested interfaces named
On<em>&lt;something></em>Listener, each with a callback method called <code>On<em>&lt;something></em>()</code>.
For example, {@link android.view.View.OnClickListener} (for handling "clicks" on a View),
{@link android.view.View.OnTouchListener} (for handling touch screen events in a View), and
{@link android.view.View.OnKeyListener} (for handling device key presses within a View). So if you want your View
to be notified when it is "clicked" (such as when a button is selected), implement OnClickListener and define
its <code>onClick()</code> callback method (where you perform the action upon click), and register it
to the View with <code>{@link android.view.View#setOnClickListener(View.OnClickListener) setOnClickListener()}</code>.
</li>
<li><strong>Override an existing callback method for the View.</strong> This is
what you should do when you've implemented your own View class and want to listen for specific events
that occur within it. Example events you can handle include when the
screen is touched (<code>{@link android.view.View#onTouchEvent(MotionEvent) onTouchEvent()}</code>), when
the trackball is moved (<code>{@link android.view.View#onTrackballEvent(MotionEvent) onTrackballEvent()}</code>),
or when a key on the device is pressed (<code>{@link android.view.View#onKeyDown(int, KeyEvent)
onKeyDown()}</code>). This allows you to define the default behavior for each event inside your custom View and determine
whether the event should be passed on to some other child View. Again, these are callbacks to the View class,
so your only chance to define them is when you
<a href="{@docRoot}guide/topics/ui/custom-components.html">build a custom component</a>.
</li>
</ul>
<p>Continue reading about handling user interaction with Views in the <a href="ui-events.html">Handling UI Events</a>
document.</p>
<h2 id="Menus">Menus</h2>
<p>Application menus are another important part of an application's UI. Menus offers a reliable interface that reveals
application functions and settings. The most common application menu is revealed by pressing
the MENU key on the device. However, you can also add Context Menus, which may be revealed when the user presses
and holds down on an item.</p>
<p>Menus are also structured using a View hierarchy, but you don't define this structure yourself. Instead,
you define the <code>{@link android.app.Activity#onCreateOptionsMenu(Menu) onCreateOptionsMenu()}</code> or
<code>{@link android.app.Activity#onCreateContextMenu(ContextMenu,View,ContextMenu.ContextMenuInfo) onCreateContextMenu()}</code>
callback methods for your Activity and declare the items that you want to include in your menu.
At the appropriate time, Android will automatically create the necessary View hierarchy for the menu and
draw each of your menu items in it.</p>
<p>Menus also handle their own events, so there's no need to register event listeners on the items in your menu.
When an item in your menu is selected, the <code>{@link android.app.Activity#onOptionsItemSelected(MenuItem)
onOptionsItemSelected()}</code> or
<code>{@link android.app.Activity#onContextItemSelected(MenuItem) onContextItemSelected()}</code>
method will be called by the framework.</p>
<p>And just like your application layout, you have the option to declare the items for you menu in an XML file.</p>
<p>Read <a href="{@docRoot}guide/topics/ui/menus.html">Creating Menus</a> to learn more.</p>
<h2 id="Advanced">Advanced Topics</h2>
<p>Once you've grappled the fundamentals of creating a user interface, you can explore
some advanced features for creating a more complex application interface.</p>
<h3 id="Adapters">Adapters</h3>
<p>Sometimes you'll want to populate a view group with some information that can't be hard-coded, instead,
you want to bind your view to an external source of data. To do this, you use an AdapterView as
your view group and each child View is initialized and populated with data from the Adapter.</p>
<p>The AdapterView object is an implementation of ViewGroup that determines its child views
based on a given Adapter object. The Adapter acts like a courier between your data source (perhaps an
array of external strings) and the AdapterView, which displays it. There are several implementations
of the Adapter class, for specific tasks, such as the CursorAdapter for reading database data from a Cursor,
or an ArrayAdapter for reading from an arbitrary array.</p>
<p>To learn more about using an Adapter to populate your views, read
<a href="binding.html">Binding to Data with AdapterView</a>.</p>
<h3 id="StylesAndThemes">Styles and Themes</h3>
<p>Perhaps you're not satisfied with the look of the standard widgets. To revise them, you can create some
of your own styles and themes.</p>
<ul>
<li>A style is a set of one or more formatting attributes that you can apply as a unit to individual elements
in your layout. For example, you could define a style that specifies a certain text size and color, then
apply it to only specific View elements.</li>
<li>A theme is a set of one or more formatting attributes that you can apply as a unit to all activities in
an application, or just a single activity. For example, you could define a theme that sets specific colors for
the window frame and the panel background, and sets text sizes and colors for menus. This theme can then be
applied to specific activities or the entire application.</li>
</ul>
<p>Styles and themes are resources. Android provides some default style and theme resources that you can use,
or you can declare your own custom style and theme resources.</p>
<p>Learn more about using styles and themes in the
<a href="themes.html">Applying Styles and Themes</a> document.</p>
@@ -0,0 +1,291 @@
page.title=Common Layout Objects
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="#framelayout">FrameLayout</a></li>
<li><a href="#linearlayout">LinearLayout</a></li>
<li><a href="#tablelayout">TableLayout</a></li>
<li><a href="#relativelayout">RelativeLayout</a></li>
<li><a href="#viewgroupsummary">Summary of Important View Groups</a></li>
</ol>
</div>
</div>
<p>This section describes some of the more common types of layout objects
to use in your applications. Like all layouts, they are subclasses of {@link android.view.ViewGroup ViewGroup}.</p>
<p>Also see the <a href="{@docRoot}resources/tutorials/views/index.html">Hello Views</a> tutorials for
some guidance on using more Android View layouts.</p>
<h2 id="framelayout">FrameLayout</h2>
<p>{@link android.widget.FrameLayout FrameLayout} is the simplest type of layout
object. It's basically a blank space on your screen that you can
later fill with a single object &mdash; for example, a picture that you'll swap in and out.
All child elements of the FrameLayout are pinned to the top left corner of the screen; you cannot
specify a different location for a child view. Subsequent child views will simply be drawn over previous ones,
partially or totally obscuring them (unless the newer object is transparent).
</p>
<h2 id="linearlayout">LinearLayout</h2>
<p>{@link android.widget.LinearLayout LinearLayout} aligns all children in a
single direction &mdash; vertically or horizontally, depending on how you
define the <code>orientation</code> attribute. All children are
stacked one after the other, so a vertical list will only have one child per
row, no matter how wide they are, and a horizontal list will only be one row
high (the height of the tallest child, plus padding). A {@link
android.widget.LinearLayout LinearLayout} respects <em>margin</em>s between children
and the <em>gravity</em> (right, center, or left alignment) of each child. </p>
<p>{@link android.widget.LinearLayout LinearLayout} also supports assigning a
<em>weight</em> to individual children. This attribute assigns an "importance" value to a view,
and allows it to expand to fill any remaining space in the parent view.
Child views can specify an integer weight value, and then any remaining space in the view group is
assigned to children in the proportion of their declared weight. Default
weight is zero. For example, if there are three text boxes and two of
them declare a weight of 1, while the other is given no weight (0), the third text box without weight
will not grow and will only occupy the area required by its content.
The other two will expand equally to fill the space remaining after all three boxes are measured.
If the third box is then given a weight of 2 (instead of 0), then it is now declared
"more important" than both the others, so it gets half the total remaining space, while the first two
share the rest equally.</p>
<div class="sidebox-wrapper">
<div class="sidebox">
<p><strong>Tip</strong>: To create a proportionate size
layout on the screen, create a container view group object with the
<code>layout_width</code> and <code>layout_height</code> attributes set to <var>fill_parent</var>; assign
the children <code>height</code> or <code>width</code> to <code>0</code> (zero); then assign relative
<code>weight</code> values
to each child, depending on what proportion of the screen each should
have.</p>
</div>
</div>
<p>The following two forms represent a {@link android.widget.LinearLayout LinearLayout} with a set of elements: a
button, some labels and text boxes. The text boxes have their width set to <var>fill_parent</var>; other
elements are set to <var>wrap_content</var>. The gravity, by default, is left.
The difference between the two versions of the form is that the form
on the left has weight values unset (0 by default), while the form on the right has
the comments text box weight set to 1. If the Name textbox had also been set
to 1, the Name and Comments text boxes would be the same height. </p>
<img src="{@docRoot}images/linearlayout.png" alt="" />
<p>Within a horizontal {@link android.widget.LinearLayout LinearLayout}, items are aligned by the position of
their text base line (the first line of the first list element &mdash; topmost or
leftmost &mdash; is considered the reference line). This is so that people scanning
elements in a form shouldn't have to jump up and down to read element text in
neighboring elements. This can be turned off by setting
<code>android:baselineAligned=&quot;false&quot;</code> in the layout XML. </p>
<p>To view other sample code, see the
<a href="{@docRoot}resources/tutorials/views/hello-linearlayout.html">Hello LinearLayout</a> tutorial.</p>
<h2 id="tablelayout">TableLayout</h2>
<p>{@link android.widget.TableLayout} positions its children into rows
and columns. TableLayout containers do not display border lines for their rows, columns,
or cells. The table will have as many columns as the row with the most cells. A table can leave
cells empty, but cells cannot span columns, as they can in HTML.</p>
<p>{@link android.widget.TableRow} objects are the child views of a TableLayout
(each TableRow defines a single row in the table).
Each row has zero or more cells, each of which is defined by any kind of other View. So, the cells of a row may be
composed of a variety of View objects, like ImageView or TextView objects.
A cell may also be a ViewGroup object (for example, you can nest another TableLayout as a cell).</p>
<p>The following sample layout has two rows and two cells in each. The accompanying screenshot shows the
result, with cell borders displayed as dotted lines (added for visual effect). </p>
<table class="columns">
<tr>
<td>
<pre>
&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:stretchColumns="1">
&lt;TableRow>
&lt;TextView
android:text="@string/table_layout_4_open"
android:padding="3dip" />
&lt;TextView
android:text="@string/table_layout_4_open_shortcut"
android:gravity="right"
android:padding="3dip" />
&lt;/TableRow>
&lt;TableRow>
&lt;TextView
android:text="@string/table_layout_4_save"
android:padding="3dip" />
&lt;TextView
android:text="@string/table_layout_4_save_shortcut"
android:gravity="right"
android:padding="3dip" />
&lt;/TableRow>
&lt;/TableLayout>
</pre></td>
<td><img src="{@docRoot}images/table_layout.png" alt="" style="margin:0" /></td>
</tr>
</table>
<p>Columns can be hidden, marked to stretch and fill the available screen space,
or can be marked as shrinkable to force the column to shrink until the table
fits the screen. See the {@link android.widget.TableLayout TableLayout reference}
documentation for more details. </p>
<p>To view sample code, see the <a href="{@docRoot}resources/tutorials/views/hello-tablelayout.html">Hello
TableLayout</a> tutorial.</p>
<h2 id="relativelayout">RelativeLayout</h2>
<p>{@link android.widget.RelativeLayout} lets child views specify their
position relative to the parent view or to each other (specified by ID). So you can
align two elements by right border, or make one below another, centered in
the screen, centered left, and so on. Elements are rendered in the order given, so if the first element
is centered in the screen, other elements aligning themselves to that element
will be aligned relative to screen center. Also, because of this ordering, if using XML to specify this layout,
the element that you will reference (in order to position other view objects) must be listed in the XML
file before you refer to it from the other views via its reference ID. </p>
<p>The example below shows an XML file and the resulting screen in the UI.
Note that the attributes that refer to relative elements (e.g., <var>layout_toLeft</var>)
refer to the ID using the syntax of a relative resource
(<var>@id/<em>id</em></var>). </p>
<table class="columns">
<tr>
<td>
<pre>
&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;RelativeLayout xmlns:android=&quot;http://schemas.android.com/apk/res/android
android:layout_width=&quot;fill_parent&quot;
android:layout_height=&quot;wrap_content&quot;
android:background=&quot;@drawable/blue&quot;
android:padding=&quot;10px&quot; &gt;
&lt;TextView android:id=&quot;@+id/label&quot;
android:layout_width=&quot;fill_parent&quot;
android:layout_height=&quot;wrap_content&quot;
android:text=&quot;Type here:&quot; /&gt;
&lt;EditText android:id=&quot;@+id/entry&quot;
android:layout_width=&quot;fill_parent&quot;
android:layout_height=&quot;wrap_content&quot;
android:background=&quot;@android:drawable/editbox_background&quot;
android:layout_below=&quot;@id/label&quot; /&gt;
&lt;Button android:id=&quot;@+id/ok&quot;
android:layout_width=&quot;wrap_content&quot;
android:layout_height=&quot;wrap_content&quot;
android:layout_below=&quot;@id/entry&quot;
android:layout_alignParentRight=&quot;true&quot;
android:layout_marginLeft=&quot;10px&quot;
android:text=&quot;OK&quot; /&gt;
&lt;Button android:layout_width=&quot;wrap_content&quot;
android:layout_height=&quot;wrap_content&quot;
android:layout_toLeftOf=&quot;@id/ok&quot;
android:layout_alignTop=&quot;@id/ok&quot;
android:text=&quot;Cancel&quot; /&gt;
&lt;/RelativeLayout&gt;
</pre></td>
<td><img src="{@docRoot}images/designing_ui_layout_example.png" alt="" style="margin:0" /></td>
</tr>
</table>
<p>Some of these properties are supported directly by
the element, and some are supported by its LayoutParams member (subclass RelativeLayout
for all the elements in this screen, because all elements are children of a RelativeLayout
parent object). The defined RelativeLayout parameters are: <code>width</code>, <code>height</code>,
<code>below</code>, <code>alignTop</code>, <code>toLeft</code>, <code>padding[Bottom|Left|Right|Top]</code>,
and <code>margin[Bottom|Left|Right|Top]</code>. Note that some of these parameters specifically support
relative layout positions &mdash; their values must be the ID of the element to which you'd like this view laid relative.
For example, assigning the parameter <code>toLeft="my_button"</code> to a TextView would place the TextView to
the left of the View with the ID <var>my_button</var> (which must be written in the XML <em>before</em> the TextView). </p>
<p>To view this sample code, see the <a href="{@docRoot}resources/tutorials/views/hello-relativelayout.html">Hello
RelativeLayout</a> tutorial.</p>
<h2 id="viewgroupsummary">Summary of Important View Groups</h2>
<p>These objects all hold child UI elements. Some provide their own form of a visible UI, while others
are invisible structures that only manage the layout of their child views. </p>
<table width="100%" border="1">
<tr>
<th scope="col">Class</th>
<th scope="col">Description</th>
</tr>
<tr>
<td>{@link android.widget.FrameLayout FrameLayout}</td>
<td>Layout that acts as a view frame to display
a single object. </td>
</tr>
<tr>
<td>{@link android.widget.Gallery Gallery} </td>
<td>A horizontal scrolling display of images, from a bound list. </td>
</tr>
<tr>
<td>{@link android.widget.GridView GridView} </td>
<td>Displays a scrolling grid of m columns and n rows.</td>
</tr>
<tr>
<td>{@link android.widget.LinearLayout LinearLayout} </td>
<td>A layout that organizes its children into a single horizontal or vertical
row. It creates a scrollbar if the length of the window exceeds the length
of the screen. </td>
</tr>
<tr>
<td>{@link android.widget.ListView ListView} </td>
<td>Displays a scrolling single column list. </td>
</tr>
<tr>
<td>{@link android.widget.RelativeLayout RelativeLayout} </td>
<td>Enables you to specify the location of child objects relative to each
other (child A to the left of child B) or to the parent (aligned to the
top of the parent). </td>
</tr>
<tr>
<td>{@link android.widget.ScrollView ScrollView} </td>
<td>A vertically scrolling column of elements. </td>
</tr>
<tr>
<td>{@link android.widget.Spinner Spinner} </td>
<td>Displays a single item at a time from a bound list, inside a one-row
textbox. Rather like a one-row listbox that can scroll either horizontally
or vertically. </td>
</tr>
<tr>
<td>{@link android.view.SurfaceView SurfaceView} </td>
<td>Provides direct access to a dedicated drawing surface. It can hold child
views layered on top of the surface, but is intended for applications
that need to draw pixels, rather than using widgets. </td>
</tr>
<tr>
<td>{@link android.widget.TabHost TabHost} </td>
<td>Provides a tab selection list that monitors clicks and enables the application
to change the screen whenever a tab is clicked. </td>
</tr>
<tr>
<td>{@link android.widget.TableLayout TableLayout} </td>
<td>A tabular layout with an arbitrary number of rows and columns, each cell
holding the widget of your choice. The rows resize to fit the largest
column. The cell borders are not
visible. </td>
</tr>
<tr>
<td>{@link android.widget.ViewFlipper ViewFlipper} </td>
<td>A list that displays one item at a time, inside a one-row textbox. It
can be set to swap items at timed intervals, like a slide show. </td>
</tr>
<tr>
<td>{@link android.widget.ViewSwitcher ViewSwitcher} </td>
<td>Same as ViewFlipper. </td>
</tr>
</table>
+650
View File
@@ -0,0 +1,650 @@
page.title=Creating Menus
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="#xml">Defining Menus</a></li>
<li><a href="#Inflating">Inflating a Menu Resource</a>
<li><a href="#options-menu">Creating an Options Menu</a>
<ol>
<li><a href="#ChangingTheMenu">Changing the menu when it opens</a></li>
</ol>
</li>
<li><a href="#context-menu">Creating a Context Menu</a></li>
<li><a href="#submenu">Creating a Submenu</a></li>
<li><a href="#features">Other Menu Features</a>
<ol>
<li><a href="#groups">Menu groups</a></li>
<li><a href="#checkable">Checkable menu items</a></li>
<li><a href="#shortcuts">Shortcut keys</a></li>
<li><a href="#intents">Intents for menu items</a></li>
</ol>
</li>
</ol>
<h2>Key classes</h2>
<ol>
<li>{@link android.view.Menu}</li>
<li>{@link android.view.MenuItem}</li>
<li>{@link android.view.ContextMenu}</li>
<li>{@link android.view.SubMenu}</li>
</ol>
<h2>See also</h2>
<ol>
<li><a href="{@docRoot}guide/topics/resources/menu-resource.html">Menu Resource</a></li>
</ol>
</div>
</div>
<p>Menus are an important part of an application that provide a familiar interface for the user
to access application functions and settings. Android offers an easy programming interface
for you to provide application menus in your application.</p>
<p>Android provides three types of application menus:</p>
<dl>
<dt><strong>Options Menu</strong></dt>
<dd>The primary menu for an Activity, which appears when the user presses
the device MENU key. Within the Options Menu are two groups:
<dl style="margin-top:1em">
<dt><em>Icon Menu</em></dt>
<dd>The menu items visible at the bottom of the screen
at the press of the MENU key. It supports a maximum of six menu items.
These are the only menu items that support icons and the only menu items that <em>do not</em> support
checkboxes or radio buttons.</dd>
<dt><em>Expanded Menu</em></dt>
<dd>The vertical list of menu items exposed by the "More" menu item in the Icon Menu.
When the Icon Menu is full, the expanded menu is comprised of the sixth
menu item and the rest.</dd>
</dl>
</dd>
<dt><strong>Context Menu</strong></dt>
<dd>A floating list of menu items that appears when the user performs a long-press on a View.
</dd>
<dt><strong>Submenu</strong></dt>
<dd>A floating list of menu items that the user opens by pressing a menu item in the Options
Menu or a context menu. A submenu item cannot support a nested submenu. </dd>
</dl>
<h2 id="xml">Defining Menus</h2>
<p>Instead of instantiating {@link android.view.Menu} objects in your application code, you should
define a menu and all its items in an XML <a
href="{@docRoot}guide/topics/resources/menu-resource.html">menu resource</a>, then inflate the menu
resource (load it as a programmable object) in your application code. Defining your menus in XML is
a good practice because it separates your interface design from your application code (the same as
when you <a href="{@docRoot}guide/topics/ui/declaring-layout.html">define your Activity
layout</a>).</p>
<p>To define a menu, create an XML file inside your project's <code>res/menu/</code>
directory and build the menu with the following elements:</p>
<dl>
<dt><code>&lt;menu></code></dt>
<dd>Creates a {@link android.view.Menu}, which is a container for menu items. It must be
the root node and holds one or more of the following elements. You can also nest this element
in an {@code &lt;item&gt;} to create a submenu.</dd>
<dt><code>&lt;item></code></dt>
<dd>Creates a {@link android.view.MenuItem}, which represents a single item in a menu.</dd>
<dt><code>&lt;group></code></dt>
<dd>An optional, invisible container for {@code &lt;item&gt;} elements. It allows you to
categorize menu items so they share properties such as active state and visibility. See <a
href="#groups">Menu groups</a>.</dd>
</dl>
<p>For example, here is a file in <code>res/menu/</code> named <code>game_menu.xml</code>:</p>
<pre>
&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;menu xmlns:android="http://schemas.android.com/apk/res/android"&gt;
&lt;item android:id="@+id/new_game"
android:icon="@drawable/ic_new_game"
android:title="@string/new_game" /&gt;
&lt;item android:id="@+id/quit"
android:icon="@drawable/ic_quit"
android:title="@string/quit" /&gt;
&lt;/menu&gt;
</pre>
<p>This example defines a menu with two menu items. Each item includes the attributes:</p>
<dl>
<dt>{@code android:id}</dt>
<dd>A resource ID that's unique to the item so that the application can recognize the item when
the user selects it.</dd>
<dt>{@code android:icon}</dt>
<dd>A drawable resource that is the icon visible to the user.</dd>
<dt>{@code android:title}</dt>
<dd>A string resource that is the title visible to the user.</dd>
</dl>
<p>For more about the XML syntax and attributes for a menu resource, see the <a
href="{@docRoot}guide/topics/resources/menu-resource.html">Menu Resource</a> reference.</p>
<h2 id="Inflating">Inflating a Menu Resource</h2>
<p>You can inflate your menu resource (convert the XML resource into a programmable object) using
{@link android.view.MenuInflater#inflate(int,Menu) MenuInflater.inflate()}. For
example, the following code inflates the <code>game_menu.xml</code> file defined above during the
{@link android.app.Activity#onCreateOptionsMenu(Menu) onCreateOptionsMenu()} callback method, to be
used for the Options Menu:</p>
<pre>
&#64;Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.game_menu, menu);
return true;
}
</pre>
<p>The {@link android.app.Activity#getMenuInflater()} method returns a {@link
android.view.MenuInflater} for the Activity. With this object, you can call {@link
android.view.MenuInflater#inflate(int,Menu) inflate()}, which inflates a menu resource into a
{@link android.view.Menu} object. In this example, the menu resource defined by
<code>game_menu.xml</code>
is inflated into the {@link android.view.Menu} that was passed into {@link
android.app.Activity#onCreateOptionsMenu(Menu) onCreateOptionsMenu()}. (This callback method for
creating an option menu is discussed more in the next section.)</p>
<h2 id="options-menu">Creating an Options Menu</h2>
<div class="figure" style="width:200px">
<img src="{@docRoot}images/options_menu.png" height="300" alt="" />
<p class="img-caption"><strong>Figure 1.</strong> Screenshot of an Options Menu.</p>
</div>
<p>The Options Menu is where you should include basic application functions
and necessary navigation items (for example, a button
to open application settings). The user
can open the Options Menu with the device MENU key.
Figure 1 shows a screenshot of an Options Menu.</p>
<p>When opened, the first visible portion of the Options Menu is called the Icon Menu. It
holds the first six menu items.
If you add more than six items to the Options Menu, Android places the sixth item and those after it
into the Expanded Menu, which the user can open with the "More" menu item.</p>
<p>When the user opens the Options Menu for the first time, Android calls your Activity's
{@link android.app.Activity#onCreateOptionsMenu(Menu)
onCreateOptionsMenu()} method. Override this method in your Activity
and populate the {@link android.view.Menu} that is passed into the method. Populate the
{@link android.view.Menu} by inflating a menu resource as described in <a
href="#Inflating">Inflating a Menu Resource</a>. (You can
also populate the menu in code, using {@link android.view.Menu#add(int,int,int,int)
add()} to add menu items.)</p>
<p>When the user selects a menu item from the Options Menu, the system calls your Activity's
{@link android.app.Activity#onOptionsItemSelected(MenuItem) onOptionsItemSelected()}
method. This method passes the
{@link android.view.MenuItem} that the user selected. You can identify the menu item by calling
{@link android.view.MenuItem#getItemId()}, which returns the unique ID for the menu
item (defined by the {@code android:id} attribute in the menu resource or with an integer passed
to the {@link android.view.Menu#add(int,int,int,int) add()} method). You can match this ID
against known menu items and perform the appropriate action.</p>
<p>For example:</p>
<pre>
&#64;Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle item selection
switch (item.getItemId()) {
case R.id.new_game:
newGame();
return true;
case R.id.quit:
quit();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
</pre>
<p>In this example, {@link android.view.MenuItem#getItemId()} queries the ID for the selected menu
item and the switch statement compares the ID against the resource IDs that were assigned to menu
items in the XML resource. When a switch case successfully handles the item, it
returns "true" to indicate that the item selection was handled. Otherwise, the default statement
passes the menu item to the super class in
case it can handle the item selected. (If you've directly extended the {@link android.app.Activity}
class, then the super class returns "false", but it's a good practice to
pass unhandled menu items to the super class instead of directly returning "false".)</p>
<p class="note"><strong>Tip:</strong> If your application contains multiple activities and
some of them provide the same Options Menu, consider creating
an Activity that implements nothing except the {@link android.app.Activity#onCreateOptionsMenu(Menu)
onCreateOptionsMenu()} and {@link android.app.Activity#onOptionsItemSelected(MenuItem)
onOptionsItemSelected()} methods. Then extend this class for each Activity that should share the
same Options Menu. This way, you have to manage only one set of code for handling menu
actions and each decendent class inherits the menu behaviors.<br/><br/>
If you want to add menu items to one of your decendent activities,
override {@link android.app.Activity#onCreateOptionsMenu(Menu)
onCreateOptionsMenu()} in that Activity. Call {@code super.onCreateOptionsMenu(menu)} so the
original menu items are created, then add new menu items with {@link
android.view.Menu#add(int,int,int,int) menu.add()}. You can also override the super class's
behavior for individual menu items.</p>
<h3 id="ChangingTheMenu">Changing the menu when it opens</h3>
<p>The {@link android.app.Activity#onCreateOptionsMenu(Menu) onCreateOptionsMenu()} method is
called only the first time the Options Menu is opened. The system keeps and re-uses the {@link
android.view.Menu} you define in this method until your Activity is destroyed. If you want to change
the Options Menu each time it opens, you must override the
{@link android.app.Activity#onPrepareOptionsMenu(Menu) onPrepareOptionsMenu()} method. This passes
you the {@link android.view.Menu} object as it currently exists. This is useful if you'd like to
remove, add, disable, or enable menu items depending on the current state of your application.</p>
<p class="note"><strong>Note:</strong>
You should never change items in the Options Menu based on the {@link android.view.View} currently
in focus. When in touch mode (when the user is not using a trackball or d-pad), Views
cannot take focus, so you should never use focus as the basis for modifying
items in the Options Menu. If you want to provide menu items that are context-sensitive to a {@link
android.view.View}, use a <a href="#context-menu">Context Menu</a>.</p>
<h2 id="context-menu">Creating a Context Menu</h2>
<p>A context menu is conceptually similar to the menu displayed when the user performs a
"right-click" on a PC. You should use a context menu to provide the user access to
actions that pertain to a specific item in the user interface. On Android, a context menu is
displayed when the user performs a "long press" (press and hold) on an item.</p>
<p>You can create a context menu for any View, though context menus are most often used for items in
a {@link android.widget.ListView}. When the user performs a long-press on an item in a ListView and
the list is registered to provide a context menu, the list item signals to the user that a context
menu is available by animating its background color&mdash;it transitions from
orange to white before opening the context menu. (The Contacts application demonstrates this
feature.)</p>
<div class="sidebox-wrapper">
<div class="sidebox">
<h3>Register a ListView</h3>
<p>If your Activity uses a {@link android.widget.ListView} and
you want all list items to provide a context menu, register all items for a context
menu by passing the {@link android.widget.ListView} to {@link
android.app.Activity#registerForContextMenu(View) registerForContextMenu()}. For
example, if you're using a {@link android.app.ListActivity}, register all list items like this:</p>
<p><code>registerForContextMenu({@link android.app.ListActivity#getListView()});</code></p>
</div>
</div>
<p>In order for a View to provide a context menu, you must "register" the view for a context
menu. Call {@link android.app.Activity#registerForContextMenu(View) registerForContextMenu()} and
pass it the {@link android.view.View} you want to give a context menu. When this View then
receives a long-press, it displays a context menu.</p>
<p>To define the context menu's appearance and behavior, override your Activity's context menu
callback methods, {@link android.app.Activity#onCreateContextMenu(ContextMenu,View,ContextMenuInfo)
onCreateContextMenu()} and
{@link android.app.Activity#onContextItemSelected(MenuItem) onContextItemSelected()}.</p>
<p>For example, here's an {@link
android.app.Activity#onCreateContextMenu(ContextMenu,View,ContextMenuInfo)
onCreateContextMenu()} that uses the {@code context_menu.xml} menu resource:</p>
<pre>
&#64;Override
public void onCreateContextMenu(ContextMenu menu, View v,
ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo);
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.context_menu, menu);
}
</pre>
<p>{@link android.view.MenuInflater} is used to inflate the context menu from a <a
href="{@docRoot}guide/topics/resources/menu-resource.html">menu resource</a>. (You can also use
{@link android.view.Menu#add(int,int,int,int) add()} to add menu items.) The callback method
parameters include the {@link android.view.View}
that the user selected and a {@link android.view.ContextMenu.ContextMenuInfo} object that provides
additional information about the item selected. You might use these parameters to determine
which context menu should be created, but in this example, all context menus for the Activity are
the same.</p>
<p>Then when the user selects an item from the context menu, the system calls {@link
android.app.Activity#onContextItemSelected(MenuItem) onContextItemSelected()}. Here is an example
of how you can handle selected items:</p>
<pre>
&#64;Override
public boolean onContextItemSelected(MenuItem item) {
AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
switch (item.getItemId()) {
case R.id.edit:
editNote(info.id);
return true;
case R.id.delete:
deleteNote(info.id);
return true;
default:
return super.onContextItemSelected(item);
}
}
</pre>
<p>The structure of this code is similar to the example for <a href="#options-menu">Creating an
Options Menu</a>, in which {@link android.view.MenuItem#getItemId()} queries the ID for the selected
menu item and a switch statement matches the item to the IDs that are defined in the menu resource.
And like the options menu example, the default statement calls the super class in case it
can handle menu items not handled here, if necessary.</p>
<p>In this example, the selected item is an item from a {@link android.widget.ListView}. To
perform an action on the selected item, the application needs to know the list
ID for the selected item (it's position in the ListView). To get the ID, the application calls
{@link android.view.MenuItem#getMenuInfo()}, which returns a {@link
android.widget.AdapterView.AdapterContextMenuInfo} object that includes the list ID for the
selected item in the {@link android.widget.AdapterView.AdapterContextMenuInfo#id id} field. The
local methods <code>editNote()</code> and <code>deleteNote()</code> methods accept this list ID to
perform an action on the data specified by the list ID.</p>
<p class="note"><strong>Note:</strong> Items in a context menu do not support icons or shortcut
keys.</p>
<h2 id="submenu">Creating Submenus</h2>
<p>A submenu is a menu that the user can open by selecting an item in another menu. You can add a
submenu to any menu (except a submenu). Submenus are useful when your application has a lot of
functions that can be organized into topics, like items in a PC application's menu bar (File, Edit,
View, etc.).</p>
<p>When creating your <a href="{@docRoot}guide/topics/resources/menu-resource.html">menu
resource</a>, you can create a submenu by adding a {@code &lt;menu&gt;} element as the child of an
{@code &lt;item&gt;}. For example:</p>
<pre>
&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;menu xmlns:android="http://schemas.android.com/apk/res/android"&gt;
&lt;item android:id="@+id/file"
android:icon="@drawable/file"
android:title="@string/file" &gt;
&lt;!-- "file" submenu --&gt;
&lt;menu"&gt;
&lt;item android:id="@+id/new"
android:title="@string/new" /&gt;
&lt;item android:id="@+id/open"
android:title="@string/open" /&gt;
&lt;/menu&gt;
&lt;/item&gt;
&lt;/menu&gt;
</pre>
<p>When the user selects an item from a submenu, the parent menu's respective on-item-selected
callback method receives the event. For instance, if the above menu is applied as an Options Menu,
then the {@link android.app.Activity#onOptionsItemSelected(MenuItem) onOptionsItemSelected()} method
is called when a submenu item is selected.</p>
<p>You can also use {@link android.view.Menu#addSubMenu(int,int,int,int) addSubMenu()} to
dynamically add a {@link android.view.SubMenu} to an existing {@link android.view.Menu}. This
returns the new {@link android.view.SubMenu} object, to which you can add
submenu items, using {@link android.view.Menu#add(int,int,int,int) add()}</p>
<h2 id="features">Other Menu Features</h2>
<p>Here are some other features that you can apply to most menu items.</p>
<h3 id="groups">Menu groups</h3>
<p>A menu group is a collection of menu items that share certain traits. With a group, you
can:</p>
<ul>
<li>Show or hide all items with {@link android.view.Menu#setGroupVisible(int,boolean)
setGroupVisible()}</li>
<li>Enable or disable all items with {@link android.view.Menu#setGroupEnabled(int,boolean)
setGroupEnabled()}</li>
<li>Specify whether all items are checkable with {@link
android.view.Menu#setGroupCheckable(int,boolean,boolean) setGroupCheckable()}</li>
</ul>
<p>You can create a group by nesting {@code &lt;item&gt;} elements inside a {@code &lt;group&gt;}
element in your menu resource or by specifying a group ID with the the {@link
android.view.Menu#add(int,int,int,int) add()} method.</p>
<p>Here's an example menu resource that includes a group:</p>
<pre>
&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;menu xmlns:android="http://schemas.android.com/apk/res/android"&gt;
&lt;item android:id="@+id/item1"
android:icon="@drawable/item1"
android:title="@string/item1" /&gt;
&lt;!-- menu group --&gt;
&lt;group android:id="@+id/group1"&gt;
&lt;item android:id="@+id/groupItem1"
android:title="@string/groupItem1" /&gt;
&lt;item android:id="@+id/groupItem2"
android:title="@string/groupItem2" /&gt;
&lt;/group&gt;
&lt;/menu&gt;
</pre>
<p>The items that are in the group appear the same as the first item that is not in a
group&mdash;all three items in the menu are siblings. However, you can modify the traits of the two
items in the group by referencing the group ID and using the methods listed above.</p>
<h3 id="checkable">Checkable menu items</h3>
<div class="figure" style="width:200px">
<img src="{@docRoot}images/radio_buttons.png" height="300" alt="" />
<p class="img-caption"><strong>Figure 2.</strong> Screenshot of checkable menu items</p>
</div>
<p>A menu can be useful as an interface for turning options on and off, using a checkbox for
stand-alone options, or radio buttons for groups of
mutually exclusive options. Figure 2 shows a submenu with items that are checkable with radio
buttons.</p>
<p class="note"><strong>Note:</strong> Menu items in the Icon Menu (from the Options Menu) cannot
display a checkbox or radio button. If you choose to make items in the Icon Menu checkable,
you must manually indicate the checked state by swapping the icon and/or text
each time the state changes.</p>
<p>You can define the checkable behavior for individual menu items using the {@code
android:checkable} attribute in the {@code &lt;item&gt;} element, or for an entire group with
the {@code android:checkableBehavior} attribute in the {@code &lt;group&gt;} element. For
example, all items in this menu group are checkable with a radio button:</p>
<pre>
&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;menu xmlns:android="http://schemas.android.com/apk/res/android"&gt;
&lt;group android:checkableBehavior="single"&gt;
&lt;item android:id="@+id/red"
android:title="@string/red" /&gt;
&lt;item android:id="@+id/blue"
android:title="@string/blue" /&gt;
&lt;/group&gt;
&lt;/menu&gt;
</pre>
<p>The {@code android:checkableBehavior} attribute accepts either:
<dl>
<dt>{@code single}</dt>
<dd>Only one item from the group can be checked (radio buttons)</dd>
<dt>{@code all}</dt>
<dd>All items can be checked (checkboxes)</dd>
<dt>{@code none}</dt>
<dd>No items are checkable</dd>
</dl>
<p>You can apply a default checked state to an item using the {@code android:checked} attribute in
the {@code &lt;item&gt;} element and change it in code with the {@link
android.view.MenuItem#setChecked(boolean) setChecked()} method.</p>
<p>When a checkable item is selected, the system calls your respective item-selected callback method
(such as {@link android.app.Activity#onOptionsItemSelected(MenuItem) onOptionsItemSelected()}). It
is here that you must set the state of the checkbox, because a checkbox or radio button does not
change its state automatically. You can query the current state of the item (as it was before the
user selected it) with {@link android.view.MenuItem#isChecked()} and then set the checked state with
{@link android.view.MenuItem#setChecked(boolean) setChecked()}. For example:</p>
<pre>
&#64;Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.vibrate:
case R.id.dont_vibrate:
if (item.isChecked()) item.setChecked(false);
else item.setChecked(true);
return true;
default:
return super.onOptionsItemSelected(item);
}
}
</pre>
<p>If you don't set the checked state this way, then the visible state of the item (the checkbox or
radio button) will not
change when the user selects it. When you do set the state, the Activity preserves the checked state
of the item so that when the user opens the menu later, the checked state that you
set is visible.</p>
<p class="note"><strong>Note:</strong>
Checkable menu items are intended to be used only on a per-session basis and not saved after the
application is destroyed. If you have application settings that you would like to save for the user,
you should store the data using <a
href="{@docRoot}guide/topics/data/data-storage.html#pref">Shared Preferences</a>.</p>
<h3 id="shortcuts">Shortcut keys</h3>
<p>You can add quick-access shortcut keys using letters and/or numbers to menu items with the
{@code android:alphabeticShortcut} and {@code android:numericShortcut} attributes in the {@code
&lt;item&gt;} element. You can also use the methods {@link
android.view.MenuItem#setAlphabeticShortcut(char)} and {@link
android.view.MenuItem#setNumericShortcut(char)}. Shortcut keys are <em>not</em>
case sensitive.</p>
<p>For example, if you apply the "s" character as an alphabetic shortcut to a "save" menu item, then
when the menu is open (or while the user holds the MENU key) and the user presses the "s" key,
the "save" menu item is selected.</p>
<p>This shortcut key is displayed as a tip in the menu item, below the menu item name
(except for items in the Icon Menu, which are displayed only if the user holds the MENU
key).</p>
<p class="note"><strong>Note:</strong> Shortcut keys for menu items only work on devices with a
hardware keyboard. Shortcuts cannot be added to items in a Context Menu.</p>
<h3 id="intents">Intents for menu items</h3>
<p>Sometimes you'll want a menu item to launch an Activity using an Intent (whether it's an
Actvitity in your application or another application). When you know the Intent you want to use and
have a specific menu item that should initiate the Intent, you can execute the Intent with {@link
android.app.Activity#startActivity(Intent) startActivity()} during the appropriate on-item-selected
callback method (such as the {@link android.app.Activity#onOptionsItemSelected(MenuItem)
onOptionsItemSelected()} callback).</p>
<p>However, if you are not certain that the user's device
contains an application that handles the Intent, then adding a menu item that executes the
Intent can result in a non-functioning menu item, because the Intent might not resolve to an
Activity that accepts it. To solve this, Android lets you dynamically add menu items to your menu
when Android finds activities on the device that handle your Intent.</p>
<p>If you're not familiar with creating Intents, read the <a
href="/guide/topics/intents/intents-filters.html">Intents and Intent Filters</a>.</p>
<h4>Dynamically adding Intents</h4>
<p>When you don't know if the user's device has an application that handles a specific Intent,
you can define the Intent and let Android search the device for activities that accept the Intent.
When it finds activies that handle the Intent, it adds a menu item for
each one to your menu and attaches the appropriate Intent to open the Activity when the user
selects it.</p>
<p>To add menu items based on available activities that accept an Intent:</p>
<ol>
<li>Define an
Intent with the category {@link android.content.Intent#CATEGORY_ALTERNATIVE} and/or
{@link android.content.Intent#CATEGORY_SELECTED_ALTERNATIVE}, plus any other requirements.</li>
<li>Call {@link
android.view.Menu#addIntentOptions(int,int,int,ComponentName,Intent[],Intent,int,MenuItem[])
Menu.addIntentOptions()}. Android then searches for any applications that can perform the Intent
and adds them to your menu.</li>
</ol>
<p>If there are no applications installed
that satisfy the Intent, then no menu items are added.</p>
<p class="note"><strong>Note:</strong>
{@link android.content.Intent#CATEGORY_SELECTED_ALTERNATIVE} is used to handle the currently
selected element on the screen. So, it should only be used when creating a Menu in {@link
android.app.Activity#onCreateContextMenu(ContextMenu,View,ContextMenuInfo)
onCreateContextMenu()}.</p>
<p>For example:</p>
<pre>
&#64;Override
public boolean onCreateOptionsMenu(Menu menu){
super.onCreateOptionsMenu(menu);
// Create an Intent that describes the requirements to fulfill, to be included
// in our menu. The offering app must include a category value of Intent.CATEGORY_ALTERNATIVE.
Intent intent = new Intent(null, dataUri);
intent.addCategory(Intent.CATEGORY_ALTERNATIVE);
// Search and populate the menu with acceptable offering applications.
menu.addIntentOptions(
R.id.intent_group, // Menu group to which new items will be added
0, // Unique item ID (none)
0, // Order for the items (none)
this.getComponentName(), // The current Activity name
null, // Specific items to place first (none)
intent, // Intent created above that describes our requirements
0, // Additional flags to control items (none)
null); // Array of MenuItems that correlate to specific items (none)
return true;
}</pre>
<p>For each Activity found that provides an Intent filter matching the Intent defined, a menu
item is added, using the value in the Intent filter's <code>android:label</code> as the
menu item title and the application icon as the menu item icon. The
{@link android.view.Menu#addIntentOptions(int,int,int,ComponentName,Intent[],Intent,int,MenuItem[])
addIntentOptions()} method returns the number of menu items added.</p>
<p class="note"><strong>Note:</strong> When you call {@link
android.view.Menu#addIntentOptions(int,int,int,ComponentName,Intent[],Intent,int,MenuItem[])
addIntentOptions()}, it overrides any and all menu items by the menu group specified in the first
argument.</p>
<h4>Allowing your Activity to be added to menus</h4>
<p>You can also offer the services of your Activity to other applications, so your
application can be included in the menu of others (reverse the roles described above).</p>
<p>To be included in other application menus, you need to define an Intent
filter as usual, but be sure to include the {@link android.content.Intent#CATEGORY_ALTERNATIVE}
and/or {@link android.content.Intent#CATEGORY_SELECTED_ALTERNATIVE} values for the Intent filter
category. For example:</p>
<pre>
&lt;intent-filter label="Resize Image">
...
&lt;category android:name="android.intent.category.ALTERNATIVE" />
&lt;category android:name="android.intent.category.SELECTED_ALTERNATIVE" />
...
&lt;/intent-filter>
</pre>
<p>Read more about writing Intent filters in the
<a href="/guide/topics/intents/intents-filters.html">Intents and Intent Filters</a> document.</p>
<p>For a sample application using this technique, see the
<a href="{@docRoot}resources/samples/NotePad/src/com/example/android/notepad/NoteEditor.html">Note
Pad</a> sample code.</p>
@@ -0,0 +1,101 @@
page.title=Notifying the User
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>Topics</h2>
<ol>
<li><a href="toasts.html">Creating Toast Notifications</a></li>
<li><a href="notifications.html">Creating Status Bar Notifications</a></li>
<li><a href="{@docRoot}guide/topics/ui/dialogs.html">Creating Dialogs</a></li>
</ol>
</div>
</div>
<p>Several types of situations may arise that require you to notify the user
about an event that occurs in your application. Some events require the user to respond
and others do not. For example:</p>
<ul>
<li>When an event such as saving a file is complete, a small message
should appear to confirm that the save was successful.</li>
<li>If the application is running in the background and needs the user's attention,
the application should create a notification that allows the user to respond at
his or her convenience.</li>
<li>If the application is
performing work that the user must wait for (such as loading a file),
the application should show a hovering progress wheel or bar.</li>
</ul>
<p>Each of these notification tasks can be achieved using a different technique:</p>
<ul>
<li>A <a href="#Toast">Toast Notification</a>, for brief messages that come
from the background.</li>
<li>A <a href="#StatusBar">Status Bar Notification</a>, for persistent reminders
that come from the background and request the user's response.</li>
<li>A <a href="#Dialog">Dialog Notification</a>, for Activity-related notifications.</li>
</ul>
<p>This document summarizes each of these techniques for notifying the user and includes
links to full documentation.</p>
<h2 id="Toast">Toast Notification</h2>
<img src="{@docRoot}images/toast.png" alt="" style="float:right" />
<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. Because a toast can be created from a background
{@link android.app.Service}, it appears even if the application isn't visible.</p>
<p>A toast is best for short text messages, such as "File saved,"
when you're fairly certain the user is paying attention
to the screen. A toast can not accept user interaction events; if you'd like
the user to respond and take action, consider using a
<a href="#StatusBar">Status Bar Notification</a> instead.</p>
<p>For more information, refer to <a href="toasts.html">Creating Toast Notifications</a>.</p>
<h2 id="StatusBar">Status Bar Notification</h2>
<img src="{@docRoot}images/notifications_window.png" alt="" style="float:right; clear:right;" />
<p>A status bar notification adds an icon to the system's status bar
(with an optional ticker-text message) and an expanded message in the "Notifications" window.
When the user selects the expanded message, Android fires an
{@link android.content.Intent} that is defined by the 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>This kind of notification is ideal when your application is working in
a background {@link android.app.Service} and needs to
notify the user about an event. If you need to alert the user about an event that occurs
while your Activity is still in focus, consider using a
<a href="#Dialog">Dialog Notification</a> instead.</p>
<p>For more information, refer to
<a href="notifications.html">Creating Status Bar Notifications</a>.</p>
<h2 id="Dialog">Dialog Notification</h2>
<img src="{@docRoot}images/dialog_progress_spinning.png" alt="" style="float:right" />
<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 and short activities that directly relate to the application in progress.</p>
<p>You should use a dialog when you need to show a progress bar or a short
message that requires confirmation from the user (such as an alert with "OK" and "Cancel" buttons).
You can use also use dialogs as integral components
in your application's UI and for other purposes besides notifications.
For a complete discussion on all the available types of dialogs,
including its uses for notifications, refer to
<a href="{@docRoot}guide/topics/ui/dialogs.html">Creating Dialogs</a>.</p>
@@ -0,0 +1,440 @@
page.title=Creating Status Bar Notifications
parent.title=Notifying the User
parent.link=index.html
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>Quickview</h2>
<ul>
<li>A status bar 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>
<ol>
<li><a href="#Basics">The Basics</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 Expanded View</a></li>
</ol>
<h2>Key classes</h2>
<ol>
<li>{@link android.app.Notification}</li>
<li>{@link android.app.NotificationManager}</li>
</ol>
</div>
</div>
<p>A status bar notification adds an icon to the system's status bar
(with an optional ticker-text message) and an expanded message in the "Notifications" window.
When the user selects the expanded message, Android fires an
{@link android.content.Intent} that is defined by the 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 bar 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 bar notification that will launch the Activity
when selected by the user.</p>
<p>The screenshot below shows the status bar with a notification icon on the left side.</p>
<img src="{@docRoot}images/status_bar.png" alt="" />
<p>The next screenshot shows the notification's expanded message in the "Notifications" window.
The user can reveal the Notifications window by pulling down the status bar
(or selecting <em>Notifications</em> from the Home options menu).</p>
<img src="{@docRoot}images/notifications_window.png" alt="" />
<h2 id="Basics">The Basics</h2>
<p>An {@link android.app.Activity} or {@link android.app.Service} can initiate a status bar
notification. Because an Activity can perform actions only while it is
active and in focus, you should create your status bar 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 bar notification, such as the status bar icon, the expanded 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 Notifications. You do not instantiate the NotificationManager. In order
to give it your Notification, you must retrieve a reference to the NotificationManager with
{@link android.app.Activity#getSystemService(String) getSystemService()} and
then, when you want to notify the user, pass it your Notification object with
{@link android.app.NotificationManager#notify(int,Notification) notify()}. </p>
<p>To create a status bar notification:</p>
<ol>
<li>Get a reference to the NotificationManager:
<pre>
String ns = Context.NOTIFICATION_SERVICE;
NotificationManager mNotificationManager = (NotificationManager) getSystemService(ns);
</pre>
</li>
<li>Instantiate the 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 expanded message and Intent:
<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>
<li>Pass the Notification to the 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>
</ol>
<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 send your status bar notification, pass the Notification object
to the NotificationManager with {@link android.app.NotificationManager#notify(int,Notification)}.
The first parameter is the unique ID for the Notification and the second is the Notification object.
The ID uniquely identifies the Notification from within your
application. This 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 bar notification when the user selects it from the Notifications
window, add the "FLAG_AUTO_CANCEL" flag to your Notification object. 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 bar notification <em>requires</em> all of the following:</p>
<ul>
<li>An icon for the status bar</li>
<li>A title and expanded message for the expanded view (unless you define a
<a href="#CustomExpandedView">custom expanded view</a>)</li>
<li>A {@link android.app.PendingIntent}, to be fired when the notification is selected</li>
</ul>
<p>Optional settings for the status bar notification include:</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>
</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"; // expanded message title
CharSequence contentText = "Hello World!"; // expanded 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 bar 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
to the NotificationManager because it avoids clutter in the Notifications window.</p>
<p>Because each notification is uniquely identified
by the 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 Context and the expanded message 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 expanded
view</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>
<pre>
notification.sound = Uri.withAppendedPath(Audio.Media.INTERNAL_CONTENT_URI, "6");
</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 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 "FLAG_INSISTENT" to the <var>flags</var> field.</p>
<p class="note"><strong>Note:</strong> If the <var>defaults</var> field includes
"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 "DEFAULT_VIBRATE" to the <var>defaults</var> field:</p>
<pre>
notification.defaults |= Notification.DEFAULT_VIBRATE;
</pre>
<p>To define your own vibration pattern, pass an array of <em>long</em> values to the
<var>vibrate</var> field:</p>
<pre>
long[] vibrate = {0,100,200,300};
notification.vibrate = vibrate;
</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>
<p class="note"><strong>Note:</strong> If the <var>defaults</var> field includes
"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 "DEFAULT_LIGHTS" to the <var>defaults</var> field:</p>
<pre>
notification.defaults |= Notification.DEFAULT_LIGHTS;
</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 "FLAG_SHOW_LIGHTS" to the <var>flags</var> field:</p>
<pre>
notification.ledARGB = 0xff00ff00;
notification.ledOnMS = 300;
notification.ledOffMS = 1000;
notification.flags |= Notification.FLAG_SHOW_LIGHTS;
</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 Notification fields and flags. Some useful features include the following:</p>
<dl>
<dt>"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>"FLAG_INSISTENT" flag</dt>
<dd>Add this to the <var>flags</var> field to repeat the audio until the
user responds.</dd>
<dt>"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 is still running in the background, even when the application is not
visible (such as with music or a phone call).</dd>
<dt>"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><var>number</var> 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 bar 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><var>iconLevel</var> 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 Expanded View</h2>
<img src="{@docRoot}images/custom_message.png" alt="" style="float:right;" />
<p>By default, the expanded view used in the "Notifications" window includes a basic title and text
message. 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 expanded view using
{@link android.widget.RemoteViews}. The screenshot to the right shows an example of a
custom expanded view that uses an ImageView and TextView in a LinearLayout.</p>
<p>To define your own layout for the expanded message,
instantiate a {@link android.widget.RemoteViews} object and
pass it to the <var>contentView</var> field of your Notification. Pass the
{@link android.app.PendingIntent} to the <var>contentIntent</var> field.</p>
<p>Creating a custom expanded view is best understood with an example:</p>
<ol>
<li>Create the XML layout for the expanded view.
For example, create a layout file called <code>custom_notification_layout.xml</code> and
build it like so:
<pre>
&lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:padding="3dp"
>
&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="#000"
/>
&lt;/LinearLayout>
</pre>
<p>This layout is used for the expanded view,
but the content of the ImageView and TextView still needs to be defined by the application.
RemoteViews offers some convenient methods that allow you to define this content...</p>
</li>
<li>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:
<pre>
RemoteViews contentView = new RemoteViews(getPackageName(), R.layout.custom_notification_layout);
contentView.setImageViewResource(R.id.image, R.drawable.notification_image);
contentView.setTextViewText(R.id.text, "Hello, this message is in a custom expanded view");
notification.contentView = contentView;
</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:
<pre>
Intent notificationIntent = new Intent(this, MyClass.class);
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
notification.contentIntent = contentIntent;
</pre>
</li>
<li>The notification can now be sent as usual:
<pre>mNotificationManager.notify(CUSTOM_VIEW_ID, notification);</pre>
</li>
</ol>
<p>The 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 expanded view. For more information about creating custom layouts with
RemoteViews, refer to the {@link android.widget.RemoteViews} class reference.</p>
<p class="warning"><strong>Note:</strong>
When creating a custom expanded view, 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>
@@ -0,0 +1,162 @@
page.title=Creating Toast Notifications
parent.title=Notifying the User
parent.link=index.html
@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>
<h2>In this document</h2>
<ol>
<li><a href="#Basics">The Basics</a></li>
<li><a href="#Positioning">Positioning your Toast</a></li>
<li><a href="#CustomToastView">Creating a Custom Toast View</a></li>
</ol>
<h2>Key classes</h2>
<ol>
<li>{@link android.widget.Toast}</li>
</ol>
</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>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>
<h2 id="Basics">The Basics</h2>
<p>First, instantiate a {@link android.widget.Toast}
object with one of the {@link android.widget.Toast#makeText(Context,int,int) makeText()} methods.
This method takes three parameters: the application {@link android.content.Context},
the text message, and the duration for the toast. It returns a properly initialized Toast
object. You can display the toast notification with {@link android.widget.Toast#show()},
as shown in the following example:</p>
<pre>
Context context = getApplicationContext();
CharSequence text = "Hello toast!";
int duration = Toast.LENGTH_SHORT;
Toast toast = Toast.makeText(context, text, duration);
toast.show();
</pre>
<p>This example demonstrates everything you need for most toast notifications.
You should rarely need anything else. You may, however, want to position the
toast differently or even use your own layout instead of a simple text message.
The following sections describe how you can do these things.</p>
<p>You can also chain your methods and avoid holding on to the Toast object, like this:</p>
<pre>Toast.makeText(context, text, duration).show();</pre>
<h2 id="Positioning">Positioning your Toast</h2>
<p>A standard toast notification appears near the bottom of the screen, centered horizontally.
You can change this position with the {@link android.widget.Toast#setGravity(int,int,int)}
method. This accepts three parameters: a {@link android.view.Gravity} constant,
an x-position offset, and a y-position offset.</p>
<p>For example, if you decide that the toast should appear in the top-left corner, you can set the
gravity like this:</p>
<pre>
toast.setGravity(Gravity.TOP|Gravity.LEFT, 0, 0);
</pre>
<p>If you want to nudge the position to the right, increase the value of the second parameter.
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
to the {@link android.widget.Toast#setView(View)} method.</p>
<p>For example, you can create the layout for the toast visible in the screenshot to the right
with the following XML (saved as <em>toast_layout.xml</em>):</p>
<pre>
&lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/toast_layout_root"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:padding="10dp"
android:background="#DAAA"
>
&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>
</pre>
<p>Notice that the ID of the LinearLayout element is "toast_layout". You must use this
ID to inflate the layout from the XML, as shown here:</p>
<pre>
LayoutInflater inflater = getLayoutInflater();
View layout = inflater.inflate(R.layout.toast_layout,
(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!");
Toast toast = new Toast(getApplicationContext());
toast.setGravity(Gravity.CENTER_VERTICAL, 0, 0);
toast.setDuration(Toast.LENGTH_LONG);
toast.setView(layout);
toast.show();
</pre>
<p>First, retrieve the {@link android.view.LayoutInflater} with
{@link android.app.Activity#getLayoutInflater()}
(or {@link android.content.Context#getSystemService(String) getSystemService()}),
and then inflate the layout from XML using
{@link android.view.LayoutInflater#inflate(int, ViewGroup)}. The first parameter
is the layout resource ID and the second is the root View. You can use
this inflated layout to find more View objects in the layout, so now capture and
define the content for the ImageView and TextView elements. Finally, create
a new Toast with {@link android.widget.Toast#Toast(Context)} and set some properties
of the toast, such as the gravity and duration. Then call
{@link android.widget.Toast#setView(View)} and pass it the inflated layout.
You can now display the toast with your custom layout by calling
{@link android.widget.Toast#show()}.</p>
<p class="note"><strong>Note:</strong> Do not use the public constructor for a Toast
unless you are going to define the layout with {@link android.widget.Toast#setView(View)}.
If you do not have a custom layout to use, you must use
{@link android.widget.Toast#makeText(Context,int,int)} to create the Toast.</p>
+390
View File
@@ -0,0 +1,390 @@
page.title=Applying Styles and Themes
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="#DefiningStyles">Defining Styles</a>
<ol>
<li><a href="#Inheritance">Inheritance</a></li>
<li><a href="#Properties">Style Properties</a></li>
</ol>
</li>
<li><a href="#ApplyingStyles">Applying Styles and Themes to the UI</a>
<ol>
<li><a href="#ApplyAStyle">Apply a style to a View</a></li>
<li><a href="#ApplyATheme">Apply a theme to an Activity or application</a></li>
</ol>
</li>
<li><a href="#PlatformStyles">Using Platform Styles and Themes</a></li>
</ol>
<h2>See also</h2>
<ol>
<li><a href="{@docRoot}guide/topics/resources/available-resources.html#stylesandthemes">Style
and Theme Resources</a></li>
<li>{@link android.R.style} for Android styles and themes</li>
<li>{@link android.R.attr} for all style attributes</li>
</ol>
</div>
</div>
<p>A <strong>style</strong> is a collection of properties that
specify the look and format for a {@link android.view.View} or window.
A style can specify properties such as height, padding, font color, font size,
background color, and much more. A style is defined in an XML resource that is
separate from the XML that specifies the layout.</p>
<p>Styles in Android share a similar philosophy to cascading stylesheets in web
design&mdash;they allow you to separate the design from the
content.</p>
<p>For example, by using a style, you can take this layout XML:</p>
<pre>
&lt;TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textColor="#00FF00"
android:typeface="monospace"
android:text="@string/hello" />
</pre>
<p>And turn it into this:</p>
<pre>
&lt;TextView
style="@style/CodeFont"
android:text="@string/hello" />
</pre>
<p>All of the attributes related to style have been removed from the layout XML and put into a
style definition called {@code CodeFont}, which is then applied with the <code>style</code>
attribute. You'll see the definition for this style in the following section.</p>
<p>A <strong>theme</strong> is a style applied to an entire {@link android.app.Activity} or
application, rather than an individual {@link android.view.View} (as in the example above). When a
style is applied as a theme, every View in the Activity or application will apply each style
property that it supports. For example, you can apply the same {@code CodeFont} style
as a theme for an Activity and then all text inside that Activity will have green monospace
font.</p>
<h2 id="DefiningStyles">Defining Styles</h2>
<p>To create a set of styles, save an XML file in the {@code res/values/}
directory of your project. The name of the XML file is arbitrary, but it must use the
{@code .xml} extension and be saved in the {@code res/values/} folder.</p>
<p>The root node of the XML file must be {@code &lt;resources&gt;}.</p>
<p>For each style you want to create, add a {@code &lt;style>} element to the file
with a {@code name} that uniquely identifies the style (this attribute is required).
Then add an {@code &lt;item>} element for each property of that style, with a
{@code name} that declares the style property and a value to go with it (this attribute
is required). The value for the {@code &lt;item>} can
be a keyword string, a hex color, a reference to another resource type, or other value
depending on the style property.
Here's an example file with a single style:</p>
<pre>
&lt;?xml version="1.0" encoding="utf-8"?>
&lt;resources&gt;
&lt;style name="CodeFont" parent="@android:style/TextAppearance.Medium"&gt;
&lt;item name="android:layout_width"&gt;fill_parent&lt;/item&gt;
&lt;item name="android:layout_height"&gt;wrap_content&lt;/item&gt;
&lt;item name="android:textColor"&gt;#00FF00&lt;/item&gt;
&lt;item name="android:typeface"&gt;monospace&lt;/item&gt;
&lt;/style&gt;
&lt;/resources&gt;
</pre>
<p>Each child of the {@code &lt;resources>} element is converted into an application resource
object at compile-time, which can be referenced by the value in the {@code &lt;style>} element's
{@code name} attribute. This example style can be referenced from an XML layout as
{@code @style/CodeFont} (as demonstrated in the introduction above).</p>
<p>The <code>parent</code> attribute in the {@code &lt;style>} element is optional and
specifies the resource ID of another style from which this style should inherit
properties. You can then override the inherited style properties if you want to.</p>
<p>Remember, a style that you want to use as an Activity or application theme is defined in XML
exactly the same as a style for a View. A style such as the one defined above can be applied as a
style for a single View or as a theme for an entire Activity or application. How to apply a style
for a single View or as an application theme is discussed later.</p>
<h3 id="Inheritance">Inheritance</h3>
<p>The {@code parent} attribute in the {@code &lt;style>} element lets you specify a style
from which your style should inherit properties.
You can use this to inherit properties from an existing style and
then define only the properties that you want to change or add. You can
inherit from styles that you've created yourself or from styles that are built into the
platform. (See <a href="#PlatformStyles">Using Platform Styles and Themes</a>, below, for
information about inheriting from styles defined by the Android platform.) For example, you can
inherit the Android platform's default text appearance and then modify it:</p>
<pre>
&lt;style name="GreenText" parent="@android:style/TextAppearance"&gt;
&lt;item name="android:textColor"&gt;#00FF00&lt;/item&gt;
&lt;/style&gt;
</pre>
<p>If you want to inherit from styles that you've defined yourself, you <em>do not</em> have to use
the <code>parent</code> attribute. Instead, just prefix the name of the style you want to
inherit to the name of your new style, separated by a period. For example, to create a new style
that inherits the <code>CodeFont</code> style defined above, but make the color red,
you can author the new style like this:</p>
<pre>
&lt;style name="CodeFont.Red"&gt;
&lt;item name="android:textColor"&gt;#FF0000&lt;/item&gt;
&lt;/style&gt;
</pre>
<p>Notice that there is no {@code parent} attribute in the {@code &lt;style&gt;} tag, but because
the {@code name} attribute begins with the {@code CodeFont} style name (which
is a style that you have created), this style inherits all style properties from that style. This
style then overrides the {@code android:textColor} property to make the text red. You can
reference this new style as {@code @style/CodeFont.Red}.</p>
<p>You can continue inheriting like
this as many times as you'd like, by chaining names with periods. For example, you can
extend {@code CodeFont.Red} to be bigger, with:</p>
<pre>
&lt;style name="CodeFont.Red.Big"&gt;
&lt;item name="android:textSize"&gt;30sp&lt;/item&gt;
&lt;/style&gt;
</pre>
<p>This inherits from both {@code CodeFont} and {@code CodeFont.Red} styles, then adds the
{@code android:textSize} property.</p>
<p class="note"><strong>Note:</strong> This technique for inheritance by chaining together
names only works for styles defined by your own resources. You can't inherit Android built-in styles
this way. To reference a built-in style, such as {@link android.R.style#TextAppearance}, you must
use the {@code parent} attribute.</p>
<h3 id="Properties">Style Properties</h3>
<p>Now that you understand how a style is defined, you need to learn what kind
of style properties&mdash;defined by the {@code &lt;item>} element&mdash;are available.
You're probably familiar with some already, such as {@link android.R.attr#layout_width} and
{@link android.R.attr#textColor}. Of course, there are many more style properties you can use.</p>
<p>The best place to find properties that apply to a specific {@link android.view.View} is the
corresponding class reference, which lists all of the supported XML attributes. For example, all of the
attributes listed in the table of
<a href="{@docRoot}reference/android/widget/TextView.html#lattrs">TextView XML
attributes</a> can be used in a style definition for a {@link android.widget.TextView} element (or one of
its subclasses). One of the attributes listed in the reference is <a
href="{@docRoot}reference/android/widget/TextView.html#attr_android:inputType">{@code
android:inputType}</a>, so where you might normally place the <a
href="{@docRoot}reference/android/widget/TextView.html#attr_android:inputType">{@code
android:inputType}</a>
attribute in an {@code &lt;EditText>} element, like this:</p>
<pre>
&lt;EditText
android:inputType="number"
... />
</pre>
<p>You can instead create a style for the {@link android.widget.EditText} element that includes this property:</p>
<pre>
&lt;style name="Numbers">
&lt;item name="android:inputType">number&lt;/item>
...
&lt;/style>
</pre>
<p>So your XML for the layout can now implement this style:</p>
<pre>
&lt;EditText
style="@style/Numbers"
... />
</pre>
<p>This simple example may look like more work, but when you add more style properties and
factor-in the ability to re-use the style in various places, the pay-off can be huge.</p>
<p>For a reference of all available style properties, see the {@link android.R.attr}
reference. Keep in mind that all View objects don't accept all the same style attributes, so you
should normally refer to the specific {@link android.view.View} class for supported style
properties. However, if you
apply a style to a View that does not support all of the style properties, the View will
apply only those properties that are supported and simply ignore the others.</p>
<p>Some style properties, however, are not supported by any View element and can only be applied
as a theme. These style properties apply to the entire window and not to any type of View.
For example, style properties for a theme can hide the application title, hide the status bar,
or change the window's background. These kind of style properties do not belong to any View object.
To discover these theme-only style properties, look at the {@link android.R.attr} reference for
attributes that begin with {@code window}. For instance, {@code windowNoTitle} and {@code
windowBackground} are style properties that are effective only when the style is applied as
a theme to an Activity or application. See the next section for information about applying a
style as a theme.</p>
<p class="note"><strong>Note:</strong> Don't forget to prefix the property names in each
{@code &lt;item&gt;} element with the <code>android:</code> namespace. For example:
{@code &lt;item name="android:inputType">}.</p>
<h2 id="ApplyingStyles">Applying Styles and Themes to the UI</h2>
<p>There are two ways to set a style:</p>
<ul>
<li>To an individual View, by adding the <code>style</code> attribute to a View
element in the XML for your layout.</li>
<li>Or, to an entire Activity or application, by adding the <code>android:theme</code>
attribute to the <code>&lt;activity></code> or <code>&lt;application></code> element
in the Android manifest.</li>
</ul>
<p>When you apply a style to a single {@link android.view.View} in the layout, the properties
defined by the style are applied only to that {@link android.view.View}. If a style is applied to a
{@link android.view.ViewGroup}, the child {@link android.view.View} elements will
<strong>not</strong> inherit the style properties&mdash;only the element to which you directly apply
the style will apply its properties. However, you <em>can</em> apply a style so that it
applies to all {@link android.view.View} elements&mdash;by applying the style as a theme.</p>
<p>To apply a style definition as a theme, you must apply the style to an
{@link android.app.Activity} or application in the Android manifest. When you do so,
every {@link android.view.View} within the Activity or
application will apply each property that it supports. For example, if you apply the {@code
CodeFont} style from the previous examples to an Activity, then all View elements
that support the text style properties will apply them. Any View that does not support
the properties will ignore them. If a View supports only some of the properties, then
it will apply only those properties.</p>
<h3 id="ApplyAStyle">Apply a style to a View</h3>
<p>Here's how to set a style for a View in the XML layout:</p>
<pre>
&lt;TextView
style="@style/CodeFont"
android:text="@string/hello" />
</pre>
<p>Now this TextView will be styled as defined by the style named {@code CodeFont}.
(See the sample above, in <a href="#DefiningStyles">Defining Styles</a>.)</p>
<p class="note"><strong>Note:</strong> The <code>style</code> attribute
does <em>not</em> use the <code>android:</code> namespace prefix.</p>
<h3 id="ApplyATheme">Apply a theme to an Activity or application</h3>
<p>To set a theme for all the activities of your application, open the {@code AndroidManifest.xml} file and
edit the <code>&lt;application></code> tag to include the <code>android:theme</code> attribute with the
style name. For example:</p>
<pre>
&lt;application android:theme="@style/CustomTheme">
</pre>
<p>If you want a theme applied to just one Activity in your application, then add the
<code>android:theme</code> attribute to the <code>&lt;activity></code> tag instead.</p>
<p>Just as Android provides other built-in resources, there are many pre-defined themes that you can use, to avoid
writing them yourself. For example, you can use the {@code Dialog} theme and make your Activity
appear like a dialog box:</p>
<pre>
&lt;activity android:theme="@android:style/Theme.Dialog">
</pre>
<p>Or if you want the background to be transparent, use the Translucent theme:</p>
<pre>
&lt;activity android:theme="@android:style/Theme.Translucent">
</pre>
<p>If you like a theme, but want to tweak it, just add the theme as the <code>parent</code>
of your custom theme. For example, you can modify the traditional dialog theme to use your own
background image like this:</p>
<pre>
&lt;style name="CustomDialogTheme" parent="@android:style/Theme.Dialog">
&lt;item name="android:windowBackground">@drawable/custom_dialog_background&lt;/item>
&lt;/style>
</pre>
<p>Now use {@code CustomDialogTheme} instead of {@code Theme.Dialog} inside the Android
Manifest:</p>
<pre>
&lt;activity android:theme="@style/CustomDialogTheme">
</pre>
<!-- This currently has some bugs
<h3 id="setThemeFromTheApp">Set the theme from the application</h3>
<p>We recommend that you set your themes in you Android manifest, as described above, because it's simple and
keeps your program code focused on application functionality, rather than style. But if it's necessary
for you to change your theme programatically (perhaps based on a user preference), you can.</p>
<p>To set the theme in your program code, use the {@link android.content.ContextWrapper#setTheme(int)}
method and pass it the theme resource ID. Note that, when doing so, you must be sure to set the theme <em>before</em>
instantiating any Views in the context, for example, before calling
<code>setContentView(View)</code> or <code>inflate(int, ViewGroup)</code>. This ensures that
the system applies the same theme for all of your UI screens. Here's an example:</p>
<pre>
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
setTheme(android.R.style.Theme_Light);
setContentView(R.layout.linear_layout_3);
}
</pre>
<p>If you are considering loading a theme programmatically for the main
screen of your application, note that the theme would not be applied
in any animations the system would use to start the activity, which
would take place before your application opens. In most cases, if
you want to apply a theme to your main screen, doing so in XML
is a better approach. </p>
-->
<h2 id="PlatformStyles">Using Platform Styles and Themes</h2>
<p>The Android platform provides a large collection of styles and themes that you can
use in your applications. You can find a reference of all available styles in the
{@link android.R.style} class. To use the styles listed here, replace all underscores in
the style name with a period. For example, you can apply the
{@link android.R.style#Theme_NoTitleBar} theme with
{@code "@android:style/Theme.NoTitleBar"}.</p>
<p>The {@link android.R.style} reference, however, is not well documented and does not
thoroughly describe the styles, so viewing the actual source code for these styles and
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>
</ul>
<p>These files will help you learn through example. For instance, in the Android themes source code,
you'll find a declaration for <code>&lt;style name="Theme.Dialog"&gt;</code>. In this definition,
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 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
View class for which you are creating a style.</p>
+283
View File
@@ -0,0 +1,283 @@
page.title=Handling UI Events
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="#EventListeners">Event Listeners</a></li>
<li><a href="#EventHandlers">Event Handlers</a></li>
<li><a href="#TouchMode">Touch Mode</a></li>
<li><a href="#HandlingFocus">Handling Focus</a></li>
</ol>
<h2>Related tutorials</h2>
<ol>
<li><a href="{@docRoot}resources/tutorials/views/hello-formstuff.html">Form Stuff</a></li>
</ol>
</div>
</div>
<p>On Android, there's more than one way to intercept the events from a user's interaction with your application.
When considering events within your user interface, the approach is to capture the events from
the specific View object that the user interacts with. The View class provides the means to do so.</p>
<p>Within the various View classes that you'll use to compose your layout, you may notice several public callback
methods that look useful for UI events. These methods are called by the Android framework when the
respective action occurs on that object. For instance, when a View (such as a Button) is touched,
the <code>onTouchEvent()</code> method is called on that object. However, in order to intercept this, you must extend
the class and override the method. However, extending every View object
in order to handle such an event would not be practical. This is why the View class also contains
a collection of nested interfaces with callbacks that you can much more easily define. These interfaces,
called <a href="#EventListeners">event listeners</a>, are your ticket to capturing the user interaction with your UI.</p>
<p>While you will more commonly use the event listeners to listen for user interaction, there may
come a time when you do want to extend a View class, in order to build a custom component.
Perhaps you want to extend the {@link android.widget.Button}
class to make something more fancy. In this case, you'll be able to define the default event behaviors for your
class using the class <a href="#EventHandlers">event handlers</a>.</p>
<h2 id="EventListeners">Event Listeners</h2>
<p>An event listener is an interface in the {@link android.view.View} class that contains a single
callback method. These methods will be called by the Android framework when the View to which the listener has
been registered is triggered by user interaction with the item in the UI.</p>
<p>Included in the event listener interfaces are the following callback methods:</p>
<dl>
<dt><code>onClick()</code></dt>
<dd>From {@link android.view.View.OnClickListener}.
This is called when the user either touches the item
(when in touch mode), or focuses upon the item with the navigation-keys or trackball and
presses the suitable "enter" key or presses down on the trackball.</dd>
<dt><code>onLongClick()</code></dt>
<dd>From {@link android.view.View.OnLongClickListener}.
This is called when the user either touches and holds the item (when in touch mode), or
focuses upon the item with the navigation-keys or trackball and
presses and holds the suitable "enter" key or presses and holds down on the trackball (for one second).</dd>
<dt><code>onFocusChange()</code></dt>
<dd>From {@link android.view.View.OnFocusChangeListener}.
This is called when the user navigates onto or away from the item, using the navigation-keys or trackball.</dd>
<dt><code>onKey()</code></dt>
<dd>From {@link android.view.View.OnKeyListener}.
This is called when the user is focused on the item and presses or releases a key on the device.</dd>
<dt><code>onTouch()</code></dt>
<dd>From {@link android.view.View.OnTouchListener}.
This is called when the user performs an action qualified as a touch event, including a press, a release,
or any movement gesture on the screen (within the bounds of the item).</dd>
<dt><code>onCreateContextMenu()</code></dt>
<dd>From {@link android.view.View.OnCreateContextMenuListener}.
This is called when a Context Menu is being built (as the result of a sustained "long click"). See the discussion
on context menus in <a href="{@docRoot}guide/topics/ui/menus.html#context-menu">Creating Menus</a> for more information.</dd>
</dl>
<p>These methods are the sole inhabitants of their respective interface. To define one of these methods
and handle your events, implement the nested interface in your Activity or define it as an anonymous class.
Then, pass an instance of your implementation
to the respective <code>View.set...Listener()</code> method. (E.g., call
<code>{@link android.view.View#setOnClickListener(View.OnClickListener) setOnClickListener()}</code>
and pass it your implementation of the {@link android.view.View.OnClickListener OnClickListener}.)</p>
<p>The example below shows how to register an on-click listener for a Button. </p>
<pre>
// Create an anonymous implementation of OnClickListener
private OnClickListener mCorkyListener = new OnClickListener() {
public void onClick(View v) {
// do something when the button is clicked
}
};
protected void onCreate(Bundle savedValues) {
...
// Capture our button from layout
Button button = (Button)findViewById(R.id.corky);
// Register the onClick listener with the implementation above
button.setOnClickListener(mCorkyListener);
...
}
</pre>
<p>You may also find it more convenient to implement OnClickListener as a part of your Activity.
This will avoid the extra class load and object allocation. For example:</p>
<pre>
public class ExampleActivity extends Activity implements OnClickListener {
protected void onCreate(Bundle savedValues) {
...
Button button = (Button)findViewById(R.id.corky);
button.setOnClickListener(this);
}
// Implement the OnClickListener callback
public void onClick(View v) {
// do something when the button is clicked
}
...
}
</pre>
<p>Notice that the <code>onClick()</code> callback in the above example has
no return value, but some other event listener methods must return a boolean. The reason
depends on the event. For the few that do, here's why:</p>
<ul>
<li><code>{@link android.view.View.OnLongClickListener#onLongClick(View) onLongClick()}</code> -
This returns a boolean to indicate whether you have consumed the event and it should not be carried further.
That is, return <em>true</em> to indicate that you have handled the event and it should stop here;
return <em>false</em> if you have not handled it and/or the event should continue to any other
on-click listeners.</li>
<li><code>{@link android.view.View.OnKeyListener#onKey(View,int,KeyEvent) onKey()}</code> -
This returns a boolean to indicate whether you have consumed the event and it should not be carried further.
That is, return <em>true</em> to indicate that you have handled the event and it should stop here;
return <em>false</em> if you have not handled it and/or the event should continue to any other
on-key listeners.</li>
<li><code>{@link android.view.View.OnTouchListener#onTouch(View,MotionEvent) onTouch()}</code> -
This returns a boolean to indicate whether your listener consumes this event. The important thing is that
this event can have multiple actions that follow each other. So, if you return <em>false</em> when the
down action event is received, you indicate that you have not consumed the event and are also
not interested in subsequent actions from this event. Thus, you will not be called for any other actions
within the event, such as a finger gesture, or the eventual up action event.</li>
</ul>
<p>Remember that key events are always delivered to the View currently in focus. They are dispatched starting from the top
of the View hierarchy, and then down, until they reach the appropriate destination. If your View (or a child of your View)
currently has focus, then you can see the event travel through the <code>{@link android.view.View#dispatchKeyEvent(KeyEvent)
dispatchKeyEvent()}</code> method. As an alternative to capturing key events through your View, you can also receive
all of the events inside your Activity with <code>{@link android.app.Activity#onKeyDown(int,KeyEvent) onKeyDown()}</code>
and <code>{@link android.app.Activity#onKeyUp(int,KeyEvent) onKeyUp()}</code>.</p>
<p class="note"><strong>Note:</strong> Android will call event handlers first and then the appropriate default
handlers from the class definition second. As such, returning <em>true</em> from these event listeners will stop
the propagation of the event to other event listeners and will also block the callback to the
default event handler in the View. So be certain that you want to terminate the event when you return <em>true</em>.</p>
<h2 id="EventHandlers">Event Handlers</h2>
<p>If you're building a custom component from View, then you'll be able to define several callback methods
used as default event handlers.
In the document on <a href="{@docRoot}guide/topics/ui/custom-components.html">Building Custom Components</a>,
you'll learn see some of the common callbacks used for event handling, including:</p>
<ul>
<li><code>{@link android.view.View#onKeyDown}</code> - Called when a new key event occurs.</li>
<li><code>{@link android.view.View#onKeyUp}</code> - Called when a key up event occurs.</li>
<li><code>{@link android.view.View#onTrackballEvent}</code> - Called when a trackball motion event occurs.</li>
<li><code>{@link android.view.View#onTouchEvent}</code> - Called when a touch screen motion event occurs.</li>
<li><code>{@link android.view.View#onFocusChanged}</code> - Called when the view gains or loses focus.</li>
</ul>
<p>There are some other methods that you should be aware of, which are not part of the View class,
but can directly impact the way you're able to handle events. So, when managing more complex events inside
a layout, consider these other methods:</p>
<ul>
<li><code>{@link android.app.Activity#dispatchTouchEvent(MotionEvent)
Activity.dispatchTouchEvent(MotionEvent)}</code> - This allows your {@link
android.app.Activity} to intercept all touch events before they are dispatched to the window.</li>
<li><code>{@link android.view.ViewGroup#onInterceptTouchEvent(MotionEvent)
ViewGroup.onInterceptTouchEvent(MotionEvent)}</code> - This allows a {@link
android.view.ViewGroup} to watch events as they are dispatched to child Views.</li>
<li><code>{@link android.view.ViewParent#requestDisallowInterceptTouchEvent(boolean)
ViewParent.requestDisallowInterceptTouchEvent(boolean)}</code> - Call this
upon a parent View to indicate that it should not intercept touch events with <code>{@link
android.view.ViewGroup#onInterceptTouchEvent(MotionEvent)}</code>.</li>
</ul>
<h2 id="TouchMode">Touch Mode</h2>
<p>
When a user is navigating a user interface with directional keys or a trackball, it is
necessary to give focus to actionable items (like buttons) so the user can see
what will accept input. If the device has touch capabilities, however, and the user
begins interacting with the interface by touching it, then it is no longer necessary to
highlight items, or give focus to a particular View. Thus, there is a mode
for interaction named "touch mode."
</p>
<p>
For a touch-capable device, once the user touches the screen, the device
will enter touch mode. From this point onward, only Views for which
{@link android.view.View#isFocusableInTouchMode} is true will be focusable, such as text editing widgets.
Other Views that are touchable, like buttons, will not take focus when touched; they will
simply fire their on-click listeners when pressed.
</p>
<p>
Any time a user hits a directional key or scrolls with a trackball, the device will
exit touch mode, and find a view to take focus. Now, the user may resume interacting
with the user interface without touching the screen.
</p>
<p>
The touch mode state is maintained throughout the entire system (all windows and activities).
To query the current state, you can call
{@link android.view.View#isInTouchMode} to see whether the device is currently in touch mode.
</p>
<h2 id="HandlingFocus">Handling Focus</h2>
<p>The framework will handle routine focus movement in response to user input.
This includes changing the focus as Views are removed or hidden, or as new
Views become available. Views indicate their willingness to take focus
through the <code>{@link android.view.View#isFocusable()}</code> method. To change whether a View can take
focus, call <code>{@link android.view.View#setFocusable(boolean) setFocusable()}</code>. When in touch mode,
you may query whether a View allows focus with <code>{@link android.view.View#isFocusableInTouchMode()}</code>.
You can change this with <code>{@link android.view.View#setFocusableInTouchMode(boolean) setFocusableInTouchMode()}</code>.
</p>
<p>Focus movement is based on an algorithm which finds the nearest neighbor in a
given direction. In rare cases, the default algorithm may not match the
intended behavior of the developer. In these situations, you can provide
explicit overrides with the following XML attributes in the layout file:
<var>nextFocusDown</var>, <var>nextFocusLeft</var>, <var>nextFocusRight</var>, and
<var>nextFocusUp</var>. Add one of these attributes to the View <em>from</em> which
the focus is leaving. Define the value of the attribute to be the id of the View
<em>to</em> which focus should be given. For example:</p>
<pre>
&lt;LinearLayout
android:orientation="vertical"
... >
&lt;Button android:id="@+id/top"
android:nextFocusUp="@+id/bottom"
... />
&lt;Button android:id="@+id/bottom"
android:nextFocusDown="@+id/top"
... />
&lt;/LinearLayout>
</pre>
<p>Ordinarily, in this vertical layout, navigating up from the first Button would not go
anywhere, nor would navigating down from the second Button. Now that the top Button has
defined the bottom one as the <var>nextFocusUp</var> (and vice versa), the navigation focus will
cycle from top-to-bottom and bottom-to-top.</p>
<p>If you'd like to declare a View as focusable in your UI (when it is traditionally not),
add the <code>android:focusable</code> XML attribute to the View, in your layout declaration.
Set the value <var>true</var>. You can also declare a View
as focusable while in Touch Mode with <code>android:focusableInTouchMode</code>.</p>
<p>To request a particular View to take focus, call <code>{@link android.view.View#requestFocus()}</code>.</p>
<p>To listen for focus events (be notified when a View receives or looses focus), use
<code>{@link android.view.View.OnFocusChangeListener#onFocusChange(View,boolean) onFocusChange()}</code>,
as discussed in the <a href="#EventListeners">Event Listeners</a> section, above.</p>
<!--
<h2 is="EventCycle">Event Cycle</h2>
<p>The basic cycle of a View is as follows:</p>
<ol>
<li>An event comes in and is dispatched to the appropriate View. The View
handles the event and notifies any listeners.</li>
<li>If, in the course of processing the event, the View's bounds may need
to be changed, the View will call {@link android.view.View#requestLayout()}.</li>
<li>Similarly, if in the course of processing the event the View's appearance
may need to be changed, the View will call {@link android.view.View#invalidate()}.</li>
<li>If either {@link android.view.View#requestLayout()} or {@link android.view.View#invalidate()} were called,
the framework will take care of measuring, laying out, and drawing the tree
as appropriate.</li>
</ol>
<p class="note"><strong>Note:</strong> The entire View tree is single threaded. You must always be on
the UI thread when calling any method on any View.
If you are doing work on other threads and want to update the state of a View
from that thread, you should use a {@link android.os.Handler}.
</p>
-->
@@ -0,0 +1,544 @@
page.title=Building Custom Views
parent.title=Views and Layout
parent.link=index.html
@jd:body
<p>Android offers a sophisticated and powerful componentized model for building your UI, based on the fundamental building block classes {@link android.view.View} and {@link android.view.ViewGroup}. To start with, the platform includes a variety of prebuilt View and ViewGroup subclasses &mdash; called widgets and layouts, respectively &mdash; that you can use to construct your UI. The widgets and layouts are fully implemented and handle all of their own measuring and drawing, so you can use them right away. You can make new types of UI elements simply by nesting and grouping the widgets and layouts. Using widgets and layouts is the recommended approach to building a UI for your applications.</p>
<p>A partial list of available widgets includes {@link android.widget.Button Button},
{@link android.widget.TextView TextView},
{@link android.widget.EditText EditText},
{@link android.widget.ListView ListView},
{@link android.widget.CheckBox CheckBox},
{@link android.widget.RadioButton RadioButton},
{@link android.widget.Gallery Gallery},
{@link android.widget.Spinner Spinner}, and the more special-purpose
{@link android.widget.AutoCompleteTextView AutoCompleteTextView},
{@link android.widget.ImageSwitcher ImageSwitcher}, and
{@link android.widget.TextSwitcher TextSwitcher}. </p>
<p>Among the layouts available are {@link android.widget.LinearLayout LinearLayout},
{@link android.widget.FrameLayout FrameLayout}, {@link android.widget.AbsoluteLayout AbsoluteLayout}, and others. For more examples, see <a href="layout">Common Layout Objects</a>.</p>
<p>If none of the prebuilt widgets or layouts meets your needs, you can also create your own View subclass, such as a layout group or compound control. If you only need to make small adjustments to an existing widget or layout, you can simply subclass the widget or layout and override its methods.
</p>
<p>Creating your own View subclasses gives you precise control over the appearance and function of a screen element. To give an idea of the control you get with custom views, here are some examples of what you could do with them:</p>
<ul>
<li>
You could create a completely custom-rendered View type, for example a "volume
control" knob rendered using 2D graphics, and which resembles an
analog electronic control.
</li>
<li>
You could combine a group of View components into a new single component, perhaps
to make something like a ComboBox (a combination of popup list and free
entry text field), a dual-pane selector control (a left and right pane
with a list in each where you can re-assign which item is in which
list), and so on.
</li>
<li>
You could override the way that an EditText component is rendered on the screen
(the <a href="{@docRoot}resources/samples/NotePad/">Notepad sample</a> uses this to good effect,
to create a lined-notepad page).
</li>
<li>
You could capture other events like key presses and handle them in some custom
way (such as for a game).
</li>
</ul>
<p>
The sections below explain how to create custom Views and use them in your application.
For detailed reference information, see the {@link android.view.View} class. </p>
<p>This document covers the following:</p>
<ol class="toc">
<li><a href="#basic">The Basic Approach</a></li>
<li><a href="#custom">Fully Customized Views</a></li>
<li><a href="#customexample">Customized View Example</a></li>
<li><a href="#compound">Compound Controls</a></li>
<li><a href="#tweaking">Modifying an Existing Component Type</a></li>
</ol>
<a name="basic"></a>
<h2>The Basic Approach
</h2>
<p>
These steps provide a high level overview of
what you need to know to get started in creating your own
View components:</p>
<ol>
<li>
Extend an existing {@link android.view.View View} class or subclass
with your own class.
</li>
<li>
Override some of the methods from the superclass: the superclass methods
to override start with '<code>on</code>', for
example, {@link android.view.View#onDraw onDraw()},
{@link android.view.View#onMeasure onMeasure()}, and
{@link android.view.View#onKeyDown onKeyDown()}.
<ul>
<li>
This is similar to the <code>on...</code> events in {@link android.app.Activity
Activity} or {@link android.app.ListActivity ListActivity}
that you override for life cycle and other functionality hooks.
</li>
</ul>
<li>
Use your new extension class: once completed, your new extension class
can be used in place of the view upon which it was based, but now with the new
functionality.
</li>
</ol>
<p class="note"><strong>Tip:</strong>
Extension classes can be defined as inner classes inside the activities
that use them. This is useful because it controls access to them but
isn't necessary (perhaps you want to create a new public View for
wider use in your application).
</p>
<a name="custom"></a>
<h2>Fully Customized Components</h2>
<p>
Fully customized components can be used to create graphical components that
appear however you wish. Perhaps a graphical VU
meter that looks like an old analog gauge, or a sing-a-long text view where
a bouncing ball moves along the words so you can sing along with a karaoke
machine. Either way, you want something that the built-in components just
won't do, no matter how you combine them.</p>
<p>Fortunately, you can easily create components that look and behave in any
way you like, limited perhaps only by your imagination, the size of the
screen, and the available processing power (remember that ultimately your
application might have to run on something with significantly less power
than your desktop workstation).</p>
<p>To create a fully customized component:</p>
<ol>
<li>
The most generic view you can extend is, unsurprisingly, {@link
android.view.View View}, so you will usually start by extending this to
create your new super component.
</li>
<li>
You can supply a constructor which can
take attributes and parameters from the XML, and you can also consume
your own such attributes and parameters (perhaps the color and range of
the VU meter, or the width and damping of the needle, etc.)
</li>
<li>
You will probably want to create your own event listeners,
property accessors and modifiers, and possibly more sophisticated
behavior in your component class as well.
</li>
<li>
You will almost certainly want to override <code>onMeasure()</code> and
are also likely to need to override <code>onDraw()</code> if you want
the component to show something. While both have default behavior,
the default <code>onDraw()</code> will do nothing, and the default
<code>onMeasure()</code> will always set a size of 100x100 &mdash; which is
probably not what you want.
</li>
<li>
Other <code>on...</code> methods may also be overridden as required.
</li>
</ol>
<h4><code>onDraw()</code> and <code>onMeasure()</code></h4>
<p><code>onDraw()</code> delivers you a {@link android.graphics.Canvas Canvas}
upon which you can implement anything you want: 2D graphics, other standard or
custom components, styled text, or anything else you can think of.</p>
<p><em>Note:</em>
Except for 3D graphics. If you want to
use 3D graphics, you must extend {@link android.view.SurfaceView SurfaceView}
instead of View, and draw from a separate thread. See the
GLSurfaceViewActivity sample
for details.</p>
<p><code>onMeasure()</code> is a little more involved. <code>onMeasure()</code>
is a critical piece of the rendering contract between your component and its
container. <code>onMeasure()</code> should be overridden to efficiently and
accurately report the measurements of its contained parts. This is made
slightly more complex by the requirements of limits from the parent
(which are passed in to the <code>onMeasure()</code> method) and by the
requirement to call the <code>setMeasuredDimension()</code> method with the
measured width and height once they have been calculated. If you fail to
call this method from an overridden <code>onMeasure()</code> method, the
result will be an exception at measurement time.</p>
<p>At a high level, implementing <code>onMeasure()</code> looks something
like this:</p>
<ol>
<li>
The overridden <code>onMeasure()</code> method is called with width and
height measure specifications (<code>widthMeasureSpec</code> and
<code>heightMeasureSpec</code> parameters, both are integer codes
representing dimensions) which should be treated as requirements for
the restrictions on the width and height measurements you should produce. A
full reference to the kind of restrictions these specifications can require
can be found in the reference documentation under {@link
android.view.View#onMeasure View.onMeasure(int, int)} (this reference
documentation does a pretty good job of explaining the whole measurement
operation as well).
</li>
<li>
Your component's <code>onMeasure()</code> method should calculate a
measurement width and height which will be required to render the
component. It should try to stay within the specifications passed in,
although it can choose to exceed them (in this case, the parent can
choose what to do, including clipping, scrolling, throwing an exception,
or asking the <code>onMeasure()</code> to try again, perhaps with
different measurement specifications).
</li>
<li>
Once the width and height are calculated, the <code>setMeasuredDimension(int
width, int height)</code> method must be called with the calculated
measurements. Failure to do this will result in an exception being
thrown.
</li>
</ol>
<p>
Here's a summary of some of the other standard methods that the framework calls on views:
</p>
<table border="2" width="85%" align="center" cellpadding="5">
<thead>
<tr><th>Category</th> <th>Methods</th> <th>Description</th></tr>
</thead>
<tbody>
<tr>
<td rowspan="2">Creation</td>
<td>Constructors</td>
<td>There is a form of the constructor that are called when the view
is created from code and a form that is called when the view is
inflated from a layout file. The second form should parse and apply
any attributes defined in the layout file.
</td>
</tr>
<tr>
<td><code>{@link android.view.View#onFinishInflate()}</code></td>
<td>Called after a view and all of its children has been inflated
from XML.</td>
</tr>
<tr>
<td rowspan="3">Layout</td>
<td><code>{@link android.view.View#onMeasure}</code></td>
<td>Called to determine the size requirements for this view and all
of its children.
</td>
</tr>
<tr>
<td><code>{@link android.view.View#onLayout}</code></td>
<td>Called when this view should assign a size and position to all
of its children.
</td>
</tr>
<tr>
<td><code>{@link android.view.View#onSizeChanged}</code></td>
<td>Called when the size of this view has changed.
</td>
</tr>
<tr>
<td>Drawing</td>
<td><code>{@link android.view.View#onDraw}</code></td>
<td>Called when the view should render its content.
</td>
</tr>
<tr>
<td rowspan="4">Event processing</td>
<td><code>{@link android.view.View#onKeyDown}</code></td>
<td>Called when a new key event occurs.
</td>
</tr>
<tr>
<td><code>{@link android.view.View#onKeyUp}</code></td>
<td>Called when a key up event occurs.
</td>
</tr>
<tr>
<td><code>{@link android.view.View#onTrackballEvent}</code></td>
<td>Called when a trackball motion event occurs.
</td>
</tr>
<tr>
<td><code>{@link android.view.View#onTouchEvent}</code></td>
<td>Called when a touch screen motion event occurs.
</td>
</tr>
<tr>
<td rowspan="2">Focus</td>
<td><code>{@link android.view.View#onFocusChanged}</code></td>
<td>Called when the view gains or loses focus.
</td>
</tr>
<tr>
<td><code>{@link android.view.View#onWindowFocusChanged}</code></td>
<td>Called when the window containing the view gains or loses focus.
</td>
</tr>
<tr>
<td rowspan="3">Attaching</td>
<td><code>{@link android.view.View#onAttachedToWindow()}</code></td>
<td>Called when the view is attached to a window.
</td>
</tr>
<tr>
<td><code>{@link android.view.View#onDetachedFromWindow}</code></td>
<td>Called when the view is detached from its window.
</td>
</tr>
<tr>
<td><code>{@link android.view.View#onWindowVisibilityChanged}</code></td>
<td>Called when the visibility of the window containing the view
has changed.
</td>
</tr>
</tbody>
</table>
<a name="customexample"></a>
<h3>A Custom View Example</h3>
<p>The CustomView sample in the
<a href="{@docRoot}samples/ApiDemos/index.html">API Demos</a> provides an example
of a customized View. The custom View is defined in the
<a href="{@docRoot}samples/ApiDemos/src/com/example/android/apis/view/LabelView.html">LabelView</a>
class.</p>
<p>The LabelView sample demonstrates a number of different aspects of custom components:</p>
<ul>
<li>Extending the View class for a completely custom component.</li>
<li>Parameterized constructor that takes the view inflation parameters
(parameters defined in the XML). Some of these are passed through to the
View superclass, but more importantly, there are some custom attributes defined
and used for LabelView.</li>
<li>Standard public methods of the type you would expect to see for a label
component, for example <code>setText()</code>, <code>setTextSize()</code>,
<code>setTextColor()</code> and so on.</li>
<li>An overridden <code>onMeasure</code> method to determine and set the
rendering size of the component. (Note that in LabelView, the real work is done
by a private <code>measureWidth()</code> method.)</li>
<li>An overridden <code>onDraw()</code> method to draw the label onto the
provided canvas.</li>
</ul>
<p>You can see some sample usages of the LabelView custom View in
<a href="{@docRoot}samples/ApiDemos/res/layout/custom_view_1.html">custom_view_1.xml</a>
from the samples. In particular, you can see a mix of both <code>android:</code>
namespace parameters and custom <code>app:</code> namespace parameters. These
<code>app:</code> parameters are the custom ones that the LabelView recognizes
and works with, and are defined in a styleable inner class inside of the
samples R resources definition class.</p>
<a name="compound"></a>
<h2>Compound Controls
</h2>
<p>If you don't want to create a completely customized component, but instead
are looking to put together a reusable component that consists of a group of
existing controls, then creating a Compound Component (or Compound Control) might
fit the bill. In a nutshell, this brings together a number of more atomic
controls (or views) into a logical group of items that can be treated as a
single thing. For example, a Combo Box can be thought of as a
combination of a single line EditText field and an adjacent button with an attached
PopupList. If you press the button and select
something from the list, it populates the EditText field, but the user can
also type something directly into the EditText if they prefer.</p>
<p>In Android, there are actually two other Views readily available to do
this: {@link android.widget.Spinner Spinner} and
{@link android.widget.AutoCompleteTextView AutoCompleteTextView}, but
regardless, the concept of a Combo Box makes an easy-to-understand
example.</p>
<p>To create a compound component:</p>
<ol>
<li>
The usual starting point is a Layout of some kind, so create a class
that extends a Layout. Perhaps in the case of a Combo box we might use
a LinearLayout with horizontal orientation. Remember that other layouts
can be nested inside, so the compound component can be arbitrarily
complex and structured. Note that just like with an Activity, you can
use either the declarative (XML-based) approach to creating the
contained components, or you can nest them programmatically from your
code.
</li>
<li>
In the constructor for the new class, take whatever parameters the
superclass expects, and pass them through to the superclass constructor
first. Then you can set up the other views to use within your new
component; this is where you would create the EditText field and the
PopupList. Note that you also might introduce your own attributes and
parameters into the XML that can be pulled out and used by your
constructor.
</li>
<li>
You can also create listeners for events that your contained views might
generate, for example, a listener method for the List Item Click Listener
to update the contents of the EditText if a list selection is made.
</li>
<li>
You might also create your own properties with accessors and modifiers,
for example, allow the EditText value to be set initially in the
component and query for its contents when needed.
</li>
<li>
In the case of extending a Layout, you don't need to override the
<code>onDraw()</code> and <code>onMeasure()</code> methods since the
layout will have default behavior that will likely work just fine. However,
you can still override them if you need to.
</li>
<li>
You might override other <code>on...</code> methods, like
<code>onKeyDown()</code>, to perhaps choose certain default values from
the popup list of a combo box when a certain key is pressed.
</li>
</ol>
<p>
To summarize, the use of a Layout as the basis for a Custom Control has a
number of advantages, including:</p>
<ul>
<li>
You can specify the layout using the declarative XML files just like
with an activity screen, or you can create views programmatically and
nest them into the layout from your code.
</li>
<li>
The <code>onDraw()</code> and <code>onMeasure()</code> methods (plus
most of the other <code>on...</code> methods) will likely have suitable behavior so
you don't have to override them.
</li>
<li>
In the end, you can very quickly construct arbitrarily complex compound
views and re-use them as if they were a single component.
</li>
</ul>
<h4>Examples of Compound Controls</h4>
<p>In the API Demos project
that comes with the SDK, there are two List
examples &mdash; Example 4 and Example 6 under Views/Lists demonstrate a
SpeechView which extends LinearLayout to make a component for displaying
Speech quotes. The corresponding classes in the sample code are
<code>List4.java</code> and <code>List6.java</code>.</p>
<a name="tweaking"></a>
<h2>Modifying an Existing View Type
</h2>
<p>There is an even easier option for creating a custom View which is
useful in certain circumstances. If there is a component that is already very
similar to what you want, you can simply extend that component and just
override the behavior that you want to change. You can do all of the things
you would do with a fully customized component, but by starting with a more
specialized class in the View hierarchy, you can also get a lot of behavior for
free that probably does exactly what you want.</p>
<p>For example, the SDK includes a <a
href="{@docRoot}samples/NotePad/index.html">NotePad application</a> in the
samples. This demonstrates many aspects of using the Android platform, among
them is extending an EditText View to make a lined notepad. This is not a
perfect example, and the APIs for doing this might change from this early
preview, but it does demonstrate the principles.</p>
<p>If you haven't done so already, import the
NotePad sample into Eclipse (or
just look at the source using the link provided). In particular look at the definition of
<code>MyEditText</code> in the <a
href="{@docRoot}samples/NotePad/src/com/example/android/notepad/NoteEditor.html">NoteEditor.java</a>
file.</p>
<p>Some points to note here</p>
<ol>
<li>
<strong>The Definition</strong>
<p>The class is defined with the following line:</p>
<code>public static class MyEditText extends EditText</code><br><br>
<ul>
<li>
It is defined as an inner class within the <code>NoteEditor</code>
activity, but it is public so that it could be accessed as
<code>NoteEditor.MyEditText</code> from outside of the <code>NoteEditor</code>
class if desired.
</li>
<li>
It is <code>static</code>, meaning it does not generate the so-called
"synthetic methods" that allow it to access data from the parent
class, which in turn means that it really behaves as a separate
class rather than something strongly related to <code>NoteEditor</code>.
This is a cleaner way to create inner classes if they do not need
access to state from the outer class, keeps the generated class
small, and allows it to be used easily from other classes.
</li>
<li>
It extends <code>EditText</code>, which is the View we have chosen to
customize in this case. When we are finished, the new class will be
able to substitute for a normal <code>EditText</code> view.<br>
<br>
</li>
</ul>
</li>
<li>
<strong>Class Initialization</strong>
<p>As always, the super is called first. Furthermore,
this is not a default constructor, but a parameterized one. The
EditText is created with these parameters when it is inflated from an
XML layout file, thus, our constructor needs to both take them and pass them
to the superclass constructor as well.</p>
</li>
<li>
<strong>Overridden Methods</strong>
<p>In this example, there is only one method to be overridden:
<code>onDraw()</code> &mdash; but there could easily be others needed when you
create your own custom components.</p>
<p>For the NotePad sample, overriding the <code>onDraw()</code> method allows
us to paint the blue lines on the <code>EditText</code> view canvas (the
canvas is passed into the overridden <code>onDraw()</code> method). The
super.onDraw() method is called before the method ends. The
superclass method should be invoked, but in this case, we do it at the
end after we have painted the lines we want to include.</p>
<li>
<strong>Use the Custom Component</strong>
<p>We now have our custom component, but how can we use it? In the
NotePad example, the custom component is used directly from the
declarative layout, so take a look at <code>note_editor.xml</code> in the
<code>res/layout</code> folder.</p>
<pre>
&lt;view xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
class=&quot;com.android.notepad.NoteEditor$MyEditText&quot;
id=&quot;&#64;+id/note&quot;
android:layout_width=&quot;fill_parent&quot;
android:layout_height=&quot;fill_parent&quot;
android:background=&quot;&#64;android:drawable/empty&quot;
android:padding=&quot;10dip&quot;
android:scrollbars=&quot;vertical&quot;
android:fadingEdge=&quot;vertical&quot; /&gt; </pre>
<ul>
<li>
The custom component is created as a generic view in the XML, and
the class is specified using the full package. Note also that the
inner class we defined is referenced using the
<code>NoteEditor$MyEditText</code> notation which is a standard way to
refer to inner classes in the Java programming language.
</li>
<li>
The other attributes and parameters in the definition are the ones
passed into the custom component constructor, and then passed
through to the EditText constructor, so they are the same
parameters that you would use for an EditText view. Note that it is
possible to add your own parameters as well, and we will touch on
this again below.
</li>
</ul>
</li>
</ol>
<p>And that's all there is to it. Admittedly this is a simple case, but
that's the point &mdash; creating custom components is only as complicated as you
need it to be.</p>
<p>A more sophisticated component may override even more <code>on...</code> methods and
introduce some of its own helper methods, substantially customizing its properties and
behavior. The only limit is your imagination and what you need the component to
do.</p>
@@ -0,0 +1,49 @@
page.title=Introduction to Views
parent.title=Views and Layout
parent.link=index.html
@jd:body
<p>The basic functional unit of an Android application is the <em>activity</em> &mdash; an object of the class {@link android.app.Activity android.app.Activity}. An activity can do many things, but by itself it does not have a presence on the screen. To give your activity a screen presence and design its UI, you work with <em>views</em> and <em>viewgroups</em> -- basic units of user interface expression on the Android platform.</p>
<h2>Views</h2>
<p>A view is an object of base class {@link android.view.View android.view.View}. It's a data structure whose properties store the layout and content for a specific rectangular area of the screen. A View object handles measuring and layout, drawing, focus change, scrolling, and key/gestures for the screen area it represents. </p>
<p>The View class serves as a base class for <em>widgets </em> &mdash; a set of fully implemented subclasses that draw interactive screen elements. Widgets handle their own measuring and drawing, so you can use them to build your UI more quickly. The list of widgets available includes Text, EditText, InputMethod, MovementMethod, Button, RadioButton, Checkbox, and ScrollView.</p>
<h2>Viewgroups </h2>
<p>A viewgroup is an object of class {@link android.view.ViewGroup android.view.Viewgroup}. As its name indicates, a viewgroup is a special type of view object whose function is to contain and manage a subordinate set of views and other viewgroups, Viewgroups let you add structure to your UI and build up complex screen elements that can be addressed as a single entity. </p>
<p>The Viewgroup class serves as a base class for <em>layouts</em> &mdash; a set of fully implemented subclasses that provide common types of screen layout. The layouts give you a way to build a structure for a set of views. </p>
<h2>A Tree-Structured UI</h2>
<p>On the Android platform, you define an Activity's UI using a tree of view and viewgroup nodes, as shown in the diagram below. The tree can be as simple or complex as you need to make it, and you can build it up using Android's set of predefined widgets and layouts or custom view types that you create yourself. </p>
<img src={@docRoot}images/viewgroup.png alt="An example of a tree of views and viewgroups" width="312" height="211" align="center"/>
<p>To attach the tree to the screen for rendering, your Activity calls its setContentView() method and passes a reference to the root node object. Once the Android system has the reference to the root node object, it can work directly with the node to invalidate, measure, and draw the tree. When your Activity becomes active and receives focus, the system notifies your activity and requests the root node to measure and draw the tree. The root node then requests that its child nodes draw themselves &mdash; in turn, each viewgroup node in the tree is responsible for drawing its direct children. </p>
<p>As mentioned previously, each view group has the responsibility of
measuring its available space, laying out its children, and calling Draw() on
each child to let it render itself. The children may request a size and location
in the parent, but the parent object has the final decision on where how big
each child can be.</p>
<h2>LayoutParams: How a Child Specifies Its Position and Size</h2>
<p>Every viewgroup class uses a nested class that extends {@link
android.view.ViewGroup.LayoutParams ViewGroup.LayoutParams}. This subclass
contains property types that define a child's size and position, in properties
appropriate for that view group class. </p>
<img src={@docRoot}images/layoutparams.png alt="An example of layoutparams" width="632" height="369" align="center"/>
<p>Note that every LayoutParams subclass has its own syntax for setting
values. Each child element must define LayoutParams that are appropriate for its parent, although it may define different LayoutParams for its children. </p>
<p>All viewgroups include width and height. Many also include margins and
borders. You can specify width and height exactly, though you probably won't want
to do this often. More often you will tell your view to size itself either to
the dimensions of its content, or to become as big as its containing object
will allow.</p>
+138
View File
@@ -0,0 +1,138 @@
page.title=Declaring a UI in XML
parent.title=Views and Layout
parent.link=index.html
@jd:body
<p>You can create your application's user interface in two ways:
<ul>
<li>You can declare UI elements statically, in XML. Android provides a straightforward XML vocabulary that corresponds to the View classes and subclasses, such as those for widgets and layouts. </li>
<li>You can instantiate screen elements dynamically, at runtime, through code in your application. Your application can refer to or create View or other class objects and manipulate their properties programmatically. </li>
</ul>
<p>One advantage of declaring your UI in XML is that it enables you to better separate the presentation of your application from the code that controls it's behavior. Your UI description is external to your application code, which means that you can modify or adapt it without having to modify your source code and recompile. For example, you can create XML layouts for different screen orientations and for a variety of device screen sizes or languages. Additionally, declaring in XML makes it easier to see the elements and structure of your UI, so it's easier to debug problems. </p>
<p>The Android framework gives you the flexibility to use either or both of these ways of declaring and managing your application's UI. For example, you could declare your application's default layouts in XML, including the screen elements that will appear in them and their properties. You could then add code in your application that would modify the state of the screen objects, including those declared in XML, at run time. </p>
<p>You build your application's UI in approximately the same way, whether you are declaring it in XML or programmatically. In both cases, your UI will be a tree structure that may include multiple View or Viewgroup subclasses. <p>
<p>In general, the XML vocabulary for declaring UI elements closely follows the structure and naming of the framework's UI-related classes and methods, where element names correspond to class names and attribute names correspond to methods. In fact, the correspondence is often so direct that you can guess what XML attribute corresponds to a class method, or guess what class corresponds to a given xml element. </p>
<p>However, note that the XML vocabulary for defining UI is not entirely identical to the framework's classes and methods. In some cases, there are slight naming differences. For
example, the EditText element has a <code>text</code> attribute that corresponds to
EditText.setText. </p>
<div class="sidebox-wrapper">
<div class="sidebox">
<p>For your convenience, the API reference documentation for UI related classes
lists the available XML attributes that correspond to the class methods, including inherited
attributes.</p>
<p>To learn more about the available XML elements and attributes, as well as the format of the XML file, see <a
href="{@docRoot}reference/available-resources.html#layoutresources">Layout Resources</a>.</p>
</div>
</div>
<p>Using Android's XML vocabulary, you can quickly design UI layouts and the screen elements they contain, in the same way you create HTML files &mdash; as a series of nested tags. </p>
<p>Each layout file must contain exactly one root element, and the root element must be a View or ViewGroup object. Once you've defined the root element, you can add additional layout objects or controls as child elements of the root element, if needed. In the example below, the tree of XML elements evaluates to the outermost LinearLayout object.
<p>After you've declared your layout in XML, you must save the file, with the <code>.xml</code> extension, in the proper location, so that it will be compiled correctly. The proper location for storing layout files is in your application's <code>res/layout/</code> directory. </p>
<p>When you compile your application, each XML layout file is compiled into an
android.view.View resource. You can then load the layout resource from your application code, by calling <code>setContentView(R.layout.<em>layout_file_name</em>)</code> in your {@link android.app.Activity#onCreate(android.os.Bundle) Activity.onCreate()}
implementation.</p>
<p>When you load a layout resource, the Android system initializes run-time objects corresponding to the elements in your layout. It parses the elements of your layout in-order (depth-first), instantiating the Views and adding them to their parent(s). </p>
<p>Attributes named <code>layout_<em>something</em></code> apply to that
object's LayoutParams member. <a href="{@docRoot}reference/available-resources.html#layoutresources">Layout
Resources</a> also describes how to learn the syntax for specifying
LayoutParams properties. </p>
<p>Also note that Android draws elements in the order in which they
appear in the XML. Therefore, if elements overlap, the last one in the XML
file will probably be drawn on top of any previously listed elements in that
same space.</p>
<p>The following values are supported for dimensions (described in {@link
android.util.TypedValue TypedValue}):</p>
<ul>
<li>px (pixels) </li>
<li>dip (device independent pixels) </li>
<li>sp (scaled pixels &mdash; best for text size) </li>
<li>pt (points) </li>
<li>in (inches) </li>
<li>mm (millimeters) </li>
</ul>
<p>Example: <code>android:layout_width=&quot;25px&quot;</code> </p>
<p>For more information about these dimensions, see <a href="{@docRoot}reference/available-resources.html#dimension">Dimension Values</a>.</p>
<p>The example below shows an XML file and the resulting screen in the UI. Note that the text on the
top of the screen was set by calling {@link
android.app.Activity#setTitle(java.lang.CharSequence) Activity.setTitle}. Note
that the attributes that refer to relative elements (i.e., layout_toLeft)
refer to the ID using the syntax of a relative resource
(@id/<em>id_number</em>). </p>
<table border="1">
<tr>
<td>
<pre>&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;!-- Demonstrates using a relative layout to create a form --&gt;
&lt;RelativeLayout xmlns:android=&quot;http://schemas.android.com/apk/res/android
android:layout_width=&quot;fill_parent&quot;
android:layout_height=&quot;wrap_content&quot;
android:background=&quot;@drawable/blue&quot;
android:padding=&quot;10px&quot;&gt;
&lt;TextView id=&quot;@+id/label&quot;
android:layout_width=&quot;fill_parent&quot;
android:layout_height=&quot;wrap_content&quot;
android:text=&quot;Type here:&quot;/&gt;
&lt;EditText id=&quot;@+id/entry&quot;
android:layout_width=&quot;fill_parent&quot;
android:layout_height=&quot;wrap_content&quot;
android:background=&quot;@android:drawable/editbox_background&quot;
android:layout_below=&quot;@id/label&quot;/&gt;
&lt;Button id=&quot;@+id/ok&quot;
android:layout_width=&quot;wrap_content&quot;
android:layout_height=&quot;wrap_content&quot;
android:layout_below=&quot;@id/entry&quot;
android:layout_alignParentRight=&quot;true&quot;
android:layout_marginLeft=&quot;10px&quot;
android:text=&quot;OK&quot; /&gt;
&lt;Button android:layout_width=&quot;wrap_content&quot;
android:layout_height=&quot;wrap_content&quot;
android:layout_toLeftOf=&quot;@id/ok&quot;
android:layout_alignTop=&quot;@id/ok&quot;
android:text=&quot;Cancel&quot; /&gt;
&lt;/RelativeLayout&gt;</pre></td>
<td><img src="{@docRoot}images/designing_ui_layout_example.png" alt="Screen shot showing how this layout XML file is rendered." /></td>
</tr>
</table>
<h3>Loading the XML Resource </h3>
<p>Loading the compiled layout resource is very easy, and done with a single
call in the activity's onCreate() method, as shown here:</p>
<pre>
protected void onCreate(Bundle savedValues)
{
// Be sure to call the super class.
super.onCreate(savedValues);
// Load the compiled layout resource into the window's
// default ViewGroup.
// The source file is res/layout/hello_activity.xml
setContentView(R.layout.hello_activity);
// Retrieve any important stored values.
restoreValues(savedValues);
} </pre>
@@ -0,0 +1,846 @@
page.title=Bluetooth
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>Quickview</h2>
<ul>
<li>Android's bluetooth APIs allow your application to perform wireless data transactions with
other devices</li>
</ul>
<h2>In this document</h2>
<ol>
<li><a href="#TheBasics">The Basics</a></li>
<li><a href="#Permissions">Bluetooth Permissions</a></li>
<li><a href="#SettingUp">Setting Up Bluetooth</a></li>
<li><a href="#FindingDevices">Finding Devices</a>
<ol>
<li><a href="#QueryingPairedDevices">Querying paired devices</a></li>
<li><a href="#DiscoveringDevices">Discovering devices</a>
<ol><li><a href="#EnablingDiscoverability">Enabling
discoverability</a></li></ol>
</li>
</ol>
</li>
<li><a href="#ConnectingDevices">Connecting Devices</a>
<ol>
<li><a href="#ConnectingAsAServer">Connecting as a server</a></li>
<li><a href="#ConnectingAsAClient">Connecting as a client</a></li>
</ol>
</li>
<li><a href="#ManagingAConnection">Managing a Connection</a></li>
</ol>
<h2>Key classes</h2>
<ol>
<li>{@link android.bluetooth.BluetoothAdapter}</li>
<li>{@link android.bluetooth.BluetoothDevice}</li>
<li>{@link android.bluetooth.BluetoothSocket}</li>
<li>{@link android.bluetooth.BluetoothServerSocket}</li>
</ol>
<h2>Related samples</h2>
<ol>
<li><a href="{@docRoot}resources/samples/BluetoothChat/index.html">Bluetooth Chat</a></li>
</ol>
</div>
</div>
<p>The Android platform includes support for the Bluetooth network stack,
which allows a device to wirelessly exchange data with other Bluetooth devices.
The application framework provides access to the Bluetooth functionality through
the Android Bluetooth APIs. These APIs let applications wirelessly
connect to other Bluetooth devices, enabling point-to-point and multipoint
wireless features.</p>
<p>Using the Bluetooth APIs, an Android application can perform the
following:</p>
<ul>
<li>Scan for other Bluetooth devices</li>
<li>Query the local Bluetooth adapter for paired Bluetooth devices</li>
<li>Establish RFCOMM channels</li>
<li>Connect to other devices through service discovery</li>
<li>Transfer data to and from other devices</li>
<li>Manage multiple connections</li>
</ul>
<h2 id="TheBasics">The Basics</h2>
<p>This document describes how to us the Android Bluetooth APIs to accomplish
the four major tasks necessary to communicate using Bluetooth: setting up
Bluetooth, finding devices that are either paired or available in the local
area, connecting devices, and transferring data between devices.</p>
<p>All of the Bluetooth APIs are available in the {@link android.bluetooth}
package. Here's a summary of the classes you will need to create Bluetooth
connections:</p>
<dl>
<dt>{@link android.bluetooth.BluetoothAdapter}</dt>
<dd>Represents the local Bluetooth adapter (Bluetooth radio). The
{@link android.bluetooth.BluetoothAdapter} is the entry-point for all Bluetooth
interaction. Using this,
you can discover other Bluetooth devices, query a list of bonded (paired)
devices, instantiate a {@link android.bluetooth.BluetoothDevice} using a known
MAC address, and create a {@link android.bluetooth.BluetoothServerSocket} to
listen for communications
from other devices.</dd>
<dt>{@link android.bluetooth.BluetoothDevice}</dt>
<dd>Represents a remote Bluetooth device. Use this to request a connection
with a remote device through a {@link android.bluetooth.BluetoothSocket} or
query information about the
device such as its name, address, class, and bonding state.</dd>
<dt>{@link android.bluetooth.BluetoothSocket}</dt>
<dd>Represents the interface for a Bluetooth socket (similar to a TCP
{@link java.net.Socket}). This is the connection point that allows
an application to exchange data with another Bluetooth device via InputStream
and OutputStream.</dd>
<dt>{@link android.bluetooth.BluetoothServerSocket}</dt>
<dd>Represents an open server socket that listens for incoming requests
(similar to a TCP {@link java.net.ServerSocket}). In order to connect two
Android devices, one device must open a server socket with this class. When a
remote Bluetooth device makes a connection request to the this device, the
{@link android.bluetooth.BluetoothServerSocket} will return a connected {@link
android.bluetooth.BluetoothSocket} when the
connection is accepted.</dd>
<dt>{@link android.bluetooth.BluetoothClass}</dt>
<dd>Describes the general characteristics and capabilities of a Bluetooth
device. This is a read-only set of properties that define the device's major and
minor device classes and its services. However, this does not reliably describe
all Bluetooth profiles and services supported by the device, but is useful as a
hint to the device type.</dd>
</dl>
<h2 id="Permissions">Bluetooth Permissions</h2>
<p>In order to use Bluetooth features in your application, you need to declare
at least one of two Bluetooth permissions: {@link
android.Manifest.permission#BLUETOOTH} and {@link
android.Manifest.permission#BLUETOOTH_ADMIN}.</p>
<p>You must request the {@link android.Manifest.permission#BLUETOOTH} permission
in order to perform any Bluetooth communication, such as requesting a
connection, accepting a connection, and transferring data.</p>
<p>You must request the {@link android.Manifest.permission#BLUETOOTH_ADMIN}
permission in order to initiate device discovery or manipulate Bluetooth
settings. Most applications need this permission solely for the
ability to discover local Bluetooth devices. The other abilities granted by this
permission should not be used, unless the application is a "power manager" that
will modify Bluetooth settings upon user request. <strong>Note:</strong> If you
use {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission, then must
also have the {@link android.Manifest.permission#BLUETOOTH} permission.</p>
<p>Declare the Bluetooth permission(s) in your application manifest file. For
example:</p>
<pre>
&lt;manifest ... >
&lt;uses-permission android:name="android.permission.BLUETOOTH" />
...
&lt;/manifest>
</pre>
<p>See the <a
href="{@docRoot}guide/topics/manifest/uses-permission-element.html">&lt;uses-permission></a>
reference for more information about declaring application permissions.</p>
<h2 id="SettingUp">Setting Up Bluetooth</h2>
<div class="figure" style="width:200px">
<img src="{@docRoot}images/bt_enable_request.png" />
<strong>Figure 1:</strong> The enabling Bluetooth dialog.
</div>
<p>Before your application can communicate over Bluetooth, you need to verify
that Bluetooth is supported on the device, and if so, ensure that it is enabled.</p>
<p>If Bluetooth is not supported, then you should gracefully disable any
Bluetooth features. If Bluetooth is supported, but disabled, then you can request that the
user enable Bluetooth without leaving your application. This setup is
accomplished in two steps, using the {@link android.bluetooth.BluetoothAdapter}.</p>
<ol>
<li>Get the {@link android.bluetooth.BluetoothAdapter}
<p>The {@link android.bluetooth.BluetoothAdapter} is required for any and all Bluetooth
activity. To get the {@link android.bluetooth.BluetoothAdapter}, call the static {@link
android.bluetooth.BluetoothAdapter#getDefaultAdapter()} method. This returns a
{@link android.bluetooth.BluetoothAdapter} that represents the device's own
Bluetooth adapter (the Bluetooth radio). There's one Bluetooth adapter for the
entire system, and your application can interact with it using this object. If
{@link android.bluetooth.BluetoothAdapter#getDefaultAdapter()} returns null,
then the device does not support Bluetooth and your story ends here. For example:</p>
<pre>
BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (mBluetoothAdapter == null) {
// Device does not support Bluetooth
}
</pre>
</li>
<li>Enable Bluetooth
<p>Next, you need to ensure that Bluetooth is enabled. Call {@link
android.bluetooth.BluetoothAdapter#isEnabled()} to check whether Bluetooth is
currently enable. If this method returns false, then Bluetooth is disabled. To
request that Bluetooth be enabled, call {@link
android.app.Activity#startActivityForResult(Intent,int) startActivityForResult()}
with the {@link android.bluetooth.BluetoothAdapter#ACTION_REQUEST_ENABLE} action Intent.
This will issue a request to enable Bluetooth through the system settings (without
stopping your application). For example:</p>
<pre>
if (!mBluetoothAdapter.isEnabled()) {
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
}
</pre>
<p>A dialog will appear requesting user permission to enable Bluetooth, as shown
in Figure 1. If the user responds "Yes," the system will begin to enable Bluetooth
and focus will return to your application once the process completes (or fails).</p>
<p>If enabling Bluetooth succeeds, your Activity will receive the {@link
android.app.Activity#RESULT_OK} result code in the {@link
android.app.Activity#onActivityResult(int,int,Intent) onActivityResult()}
callback. If Bluetooth was not enabled
due to an error (or the user responded "No") then the result code will be {@link
android.app.Activity#RESULT_CANCELED}.</p>
</li>
</ol>
<p>Optionally, your application can also listen for the
{@link android.bluetooth.BluetoothAdapter#ACTION_STATE_CHANGED} broadcast Intent, which
the system will broadcast whenever the Bluetooth state has changed. This broadcast contains
the extra fields {@link android.bluetooth.BluetoothAdapter#EXTRA_STATE} and {@link
android.bluetooth.BluetoothAdapter#EXTRA_PREVIOUS_STATE}, containing the new and old
Bluetooth states, respectively. Possible values for these extra fields are
{@link android.bluetooth.BluetoothAdapter#STATE_TURNING_ON}, {@link
android.bluetooth.BluetoothAdapter#STATE_ON}, {@link
android.bluetooth.BluetoothAdapter#STATE_TURNING_OFF}, and {@link
android.bluetooth.BluetoothAdapter#STATE_OFF}. Listening for this
broadcast can be useful to detect changes made to the Bluetooth state while your
app is running.</p>
<p class="note"><strong>Tip:</strong> Enabling discoverability will automatically
enable Bluetooth. If you plan to consistently enable device discoverability before
performing Bluetooth activity, you can skip
step 2 above. Read about <a href="#EnablingDiscoverability">enabling discoverability</a>,
below.</p>
<h2 id="FindingDevices">Finding Devices</h2>
<p>Using the {@link android.bluetooth.BluetoothAdapter}, you can find remote Bluetooth
devices either through device discovery or by querying the list of paired (bonded)
devices.</p>
<p>Device discovery is a scanning procedure that searches the local area for
Bluetooth enabled devices and then requesting some information about each one
(this is sometimes referred to as "discovering," "inquiring" or "scanning").
However, a Bluetooth device within the local area will respond to a discovery
request only if it is currently enabled to be discoverable. If a device is
discoverable, it will respond to the discovery request by sharing some
information, such as the device name, class, and its unique MAC address. Using
this information, the device performing discovery can then choose to initiate a
connection to the discovered device.</p>
<p>Once a connection is made with a remote device for the first time, a pairing
request is automatically presented to the user. When a device is
paired, the basic information about that device (such as the device name, class,
and MAC address) is saved and can be read using the Bluetooth APIs. Using the
known MAC address for a remote device, a connection can be initiated with it at
any time without performing discovery (assuming the device is within range).</p>
<p>Remember there is a difference between being paired and being connected. To
be paired means that two devices are aware of each other's existence, have a
shared link-key that can be used for authentication, and are capable of
establishing an encrypted connection with each other. To be connected means that
the devices currently share an RFCOMM channel and are able to transmit data with
each other. The current Android Bluetooth API's require devices to be paired
before an RFCOMM connection can be established. (Pairing is automatically performed
when you initiate an encrypted connection with the Bluetooth APIs.)</p>
<p>The following sections describe how to find devices that have been paired, or
discover new devices using device discovery.</p>
<p class="note"><strong>Note:</strong> Android-powered devices are not
discoverable by default. A user can make
the device discoverable for a limited time through the system settings, or an
application can request that the user enable discoverability without leaving the
application. How to <a href="#EnablingDiscoverability">enable discoverability</a>
is discussed below.</p>
<h3 id="QueryingPairedDevices">Querying paired devices</h3>
<p>Before performing device discovery, its worth querying the set
of paired devices to see if the desired device is already known. To do so,
call {@link android.bluetooth.BluetoothAdapter#getBondedDevices()}. This
will return a Set of {@link android.bluetooth.BluetoothDevice}s representing
paired devices. For example, you can query all paired devices and then
show the name of each device to the user, using an ArrayAdapter:</p>
<pre>
Set&lt;BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices();
// If there are paired devices
if (pairedDevices.size() > 0) {
// Loop through paired devices
for (BluetoothDevice device : pairedDevices) {
// Add the name and address to an array adapter to show in a ListView
mArrayAdapter.add(device.getName() + "\n" + device.getAddress());
}
}
</pre>
<p>All that's needed from the {@link android.bluetooth.BluetoothDevice} object
in order to initiate a connection is the MAC address. In this example, it's saved
as a part of an ArrayAdapter that's shown to the user. The MAC address can later
be extracted in order to initiate the connection. You can learn more about creating
a connection in the section about <a href="#ConnectingDevices">Connecting Devices</a>.</p>
<h3 id="DiscoveringDevices">Discovering devices</h3>
<p>To start discovering devices, simply call {@link
android.bluetooth.BluetoothAdapter#startDiscovery()}. The
process is asynchronous and the method will immediately return with a boolean
indicating whether discovery has successfully started. The discovery process
usually involves an inquiry scan of about 12 seconds, followed by a page scan of
each found device to retrieve its Bluetooth name.</p>
<p>Your application must register a BroadcastReceiver for the
{@link android.bluetooth.BluetoothDevice#ACTION_FOUND} Intent in
order to receive information about each
device discovered. For each device, the system will broadcast the
{@link android.bluetooth.BluetoothDevice#ACTION_FOUND} Intent. This
Intent carries the extra fields
{@link android.bluetooth.BluetoothDevice#EXTRA_DEVICE} and
{@link android.bluetooth.BluetoothDevice#EXTRA_CLASS}, containing a
{@link android.bluetooth.BluetoothDevice} and a {@link
android.bluetooth.BluetoothClass}, respectively. For example, here's how you can
register to handle the broadcast when devices are discovered:</p>
<pre>
// Create a BroadcastReceiver for ACTION_FOUND
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
// When discovery finds a device
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
// Get the BluetoothDevice object from the Intent
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
// Add the name and address to an array adapter to show in a ListView
mArrayAdapter.add(device.getName() + "\n" + device.getAddress());
}
}
};
// Register the BroadcastReceiver
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
registerReceiver(mReceiver, filter); // Don't forget to unregister during onDestroy
</pre>
<p>All that's needed from the {@link android.bluetooth.BluetoothDevice} object
in order to initiate a
connection is the MAC address. In this example, it's saved as a part of an
ArrayAdapter that's shown to the user. The MAC address can later be extracted in
order to initiate the connection. You can learn more about creating a connection
in the section about <a href="#ConnectingDevices">Connecting Devices</a>.</p>
<p class="caution"><strong>Caution:</strong> Performing device discovery is
a heavy procedure for the Bluetooth
adapter and will consume a lot of its resources. Once you have found a device to
connect, be certain that you always stop discovery with
{@link android.bluetooth.BluetoothAdapter#cancelDiscovery()} before
attempting a connection. Also, if you
already hold a connection with a device, then performing discovery can
significantly reduce the bandwidth available for the connection, so you should
not perform discovery while connected.</p>
<h4 id="EnablingDiscoverability">Enabling discoverability</h4>
<p>If you would like to make the local device discoverable to other devices,
call {@link android.app.Activity#startActivityForResult(Intent,int)} with the
{@link android.bluetooth.BluetoothAdapter#ACTION_REQUEST_DISCOVERABLE} action Intent.
This will issue a request to enable discoverable mode through the system settings (without
stopping your application). By default, the device will become discoverable for
120 seconds. You can define a different duration by adding the
{@link android.bluetooth.BluetoothAdapter#EXTRA_DISCOVERABLE_DURATION} Intent extra
(maximum duration is 300 seconds). For example:</p>
<pre>
Intent discoverableIntent = new
Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);
startActivity(discoverableIntent);
</pre>
<div class="figure" style="width:200px">
<img src="{@docRoot}images/bt_enable_discoverable.png" />
<strong>Figure 2:</strong> The enabling discoverability dialog.
</div>
<p>A dialog will be displayed, requesting user permission to make the device
discoverable, as shown in Figure 2. If the user responds "Yes," then the device
will become discoverable for the specified amount of time. Your Activity will
then receive a call to the {@link android.app.Activity#onActivityResult(int,int,Intent)
onActivityResult())} callback, with the result code equal to the duration that the device
is discoverable. If the user responded "No" or if an error occurred, the result code will
be Activity.RESULT_CANCELLED.</p>
<p class="note"><strong>Note:</strong> If Bluetooth has not been enabled on the device,
then enabling device discoverability will automatically enable Bluetooth.</p>
<p>The device will silently remain in discoverable mode for the allotted time.
If you would like to be notified when the discoverable mode has changed, you can
register a BroadcastReceiver for the {@link
android.bluetooth.BluetoothAdapter#ACTION_SCAN_MODE_CHANGED}
Intent. This will contain the extra fields {@link
android.bluetooth.BluetoothAdapter#EXTRA_SCAN_MODE} and
{@link android.bluetooth.BluetoothAdapter#EXTRA_PREVIOUS_SCAN_MODE}, which tell you the
new and old scan mode, respectively. Possible values for each are
{@link android.bluetooth.BluetoothAdapter#SCAN_MODE_CONNECTABLE_DISCOVERABLE},
{@link android.bluetooth.BluetoothAdapter#SCAN_MODE_CONNECTABLE}, or {@link
android.bluetooth.BluetoothAdapter#SCAN_MODE_NONE},
which indicate that the device is either in discoverable mode, not in
discoverable mode but still able to receive connections, or not in discoverable
mode and unable to receive connections, respectively.</p>
<p>You do not need to enable device discoverability if you will be initiating
the connection to a remote device. Enabling discoverability is only necessary when
you want your application to host a server socket that will accept incoming
connections, because the remote devices must be able to discover the device
before it can initiate the connection.</p>
<h2 id="ConnectingDevices">Connecting Devices</h2>
<p>In order to create a connection between your application on two devices, you
must implement both the server-side and client-side mechanisms, because one
device must open a server socket and the other one must initiate the connection
(using the server device's MAC address to initiate a connection). The server and
client are considered connected to each other when they each have a connected
{@link android.bluetooth.BluetoothSocket} on the same RFCOMM channel. At this
point, each device can obtain input and output streams and data transfer can
begin, which is discussed in the section about <a
href="#ManagingAConnection">Managing a Connection</a>. This section describes how
to initiate the connection between two devices.</p>
<p>The server device and the client device each obtain the required {@link
android.bluetooth.BluetoothSocket} in different ways. The server will receive it
when an incoming connection is accepted. The client will receive it when it
opens an RFCOMM channel to the server.</p>
<div class="figure" style="width:200px">
<img src="{@docRoot}images/bt_pairing_request.png" />
<strong>Figure 3:</strong> The Bluetooth pairing dialog.
</div>
<p>One implementation technique is to automatically prepare each device as a
server, so that each one has a server socket open and listening for connections.
Then either device can initiate a connection with the other and become the
client. Alternatively, one device can explicitly "host" the connection and open
a server socket on demand and the other device can simply initiate the
connection.</p>
<p class="note"><strong>Note:</strong> If the two devices have not been previously paired,
then the Android framework will automatically show a pairing request notification or
dialog to the user during the connection procedure, as shown in Figure 3. So
when attempting to connect devices,
your application does not need to be concerned about whether or not the devices are
paired. Your RFCOMM connection attempt will block until the user has successfully paired,
or will fail if the user rejects pairing, or if pairing fails or times out. </p>
<h3 id="ConnectingAsAServer">Connecting as a server</h3>
<p>When you want to connect two devices, one must act as a server by holding an
open {@link android.bluetooth.BluetoothServerSocket}. The purpose of the server
socket is to listen for incoming connection requests and when one is accepted,
provide a connected {@link android.bluetooth.BluetoothSocket}. When the {@link
android.bluetooth.BluetoothSocket} is acquired from the {@link
android.bluetooth.BluetoothServerSocket},
the {@link android.bluetooth.BluetoothServerSocket} can (and should) be
discarded, unless you want to accept more connections.</p>
<div class="sidebox-wrapper">
<div class="sidebox">
<h2>About UUID</h2>
<p>A Universally Unique Identifier (UUID) is a standardized 128-bit format for a string
ID used to uniquely identify information. The point of a UUID is that it's big
enough that you can select any random and it won't clash. In this case, it's
used to uniquely identify your application's Bluetooth service. To get a UUID to
use with your application, you can use one of the many random UUID generators on
the web, then initialize a {@link java.util.UUID} with {@link
java.util.UUID#fromString(String)}.</p>
</div>
</div>
<p>Here's the basic procedure to set up a server socket and accept a
connection:</p>
<ol>
<li>Get a {@link android.bluetooth.BluetoothServerSocket} by calling the
{@link
android.bluetooth.BluetoothAdapter#listenUsingRfcommWithServiceRecord(String,
UUID)}.
<p>The string is an identifiable name of your service, which the system will
automatically write to a new Service Discovery Protocol (SDP) database entry on
the device (the name is arbitrary and can simply be your application name). The
UUID is also included in the SDP entry and will be the basis for the connection
agreement with the client device. That is, when the client attempts to connect
with this device, it will carry a UUID that uniquely identifies the service with
which it wants to connect. These UUIDs must match in order for the connection to
be accepted (in the next step).</p>
</li>
<li>Start listening for connection requests by calling
{@link android.bluetooth.BluetoothServerSocket#accept()}.
<p>This is a blocking call. It will return when either a connection has been
accepted or an exception has occurred. A connection is accepted only when a
remote device has sent a connection request with a UUID matching the one
registered with this listening server socket. When successful, {@link
android.bluetooth.BluetoothServerSocket#accept()} will
return a connected {@link android.bluetooth.BluetoothSocket}.</p>
</li>
<li>Unless you want to accept additional connections, call
{@link android.bluetooth.BluetoothServerSocket#close()}.
<p>This releases the server socket and all its resources, but does <em>not</em> close the
connected {@link android.bluetooth.BluetoothSocket} that's been returned by {@link
android.bluetooth.BluetoothServerSocket#accept()}. Unlike TCP/IP, RFCOMM only allows one
connected client per channel at a time, so in most cases it makes sense to call {@link
android.bluetooth.BluetoothServerSocket#close()} on the {@link
android.bluetooth.BluetoothServerSocket} immediately after accepting a connected
socket.</p>
</li>
</ol>
<p>The {@link android.bluetooth.BluetoothServerSocket#accept()} call should not
be executed in the main Activity UI thread because it is a blocking call and
will prevent any other interaction with the application. It usually makes
sense to do all work with a {@link android.bluetooth.BluetoothServerSocket} or {@link
android.bluetooth.BluetoothSocket} in a new
thread managed by your application. To abort a blocked call such as {@link
android.bluetooth.BluetoothServerSocket#accept()}, call {@link
android.bluetooth.BluetoothServerSocket#close()} on the {@link
android.bluetooth.BluetoothServerSocket} (or {@link
android.bluetooth.BluetoothSocket}) from another thread and the blocked call will
immediately return. Note that all methods on a {@link
android.bluetooth.BluetoothServerSocket} or {@link android.bluetooth.BluetoothSocket}
are thread-safe.</p>
<h4>Example</h4>
<p>Here's a simplified thread for the server component that accepts incoming
connections:</p>
<pre>
private class AcceptThread extends Thread {
private final BluetoothServerSocket mmServerSocket;
public AcceptThread() {
// Use a temporary object that is later assigned to mmServerSocket,
// because mmServerSocket is final
BluetoothServerSocket tmp = null;
try {
// MY_UUID is the app's UUID string, also used by the client code
tmp = mAdapter.listenUsingRfcommWithServiceRecord(NAME, MY_UUID);
} catch (IOException e) { }
mmServerSocket = tmp;
}
public void run() {
BluetoothSocket socket = null;
// Keep listening until exception occurs or a socket is returned
while (true) {
try {
socket = mmServerSocket.accept();
} catch (IOException e) {
break;
}
// If a connection was accepted
if (socket != null) {
// Do work to manage the connection (in a separate thread)
manageConnectedSocket(socket);
mmServerSocket.close();
break;
}
}
}
/** Will cancel the listening socket, and cause the thread to finish */
public void cancel() {
try {
mmServerSocket.close();
} catch (IOException e) { }
}
}
</pre>
<p>In this example, only one incoming connection is desired, so as soon as a
connection is accepted and the {@link android.bluetooth.BluetoothSocket} is
acquired, the application
sends the acquired {@link android.bluetooth.BluetoothSocket} to a separate
thread, closes the
{@link android.bluetooth.BluetoothServerSocket} and breaks the loop.</p>
<p>Note that when {@link android.bluetooth.BluetoothServerSocket#accept()}
returns the {@link android.bluetooth.BluetoothSocket}, the socket is already
connected, so you should <em>not</em> call {@link
android.bluetooth.BluetoothSocket#connect()} (as you do from the
client-side).</p>
<p><code>manageConnectedSocket()</code> is a fictional method in the application
that will
initiate the thread for transferring data, which is discussed in the section
about <a href="#ManagingAConnection">Managing a Connection</a>.</p>
<p>You should usually close your {@link android.bluetooth.BluetoothServerSocket}
as soon as you are done listening for incoming connections. In this example, {@link
android.bluetooth.BluetoothServerSocket#close()} is called as soon
as the {@link android.bluetooth.BluetoothSocket} is acquired. You may also want
to provide a public method in your thread that can close the private {@link
android.bluetooth.BluetoothSocket} in the event that you need to stop listening on the
server socket.</p>
<h3 id="ConnectingAsAClient">Connecting as a client</h3>
<p>In order to initiate a connection with a remote device (a device holding an
open
server socket), you must first obtain a {@link
android.bluetooth.BluetoothDevice} object that represents the remote device.
(Getting a {@link android.bluetooth.BluetoothDevice} is covered in the above
section about <a
href="#FindingDevices">Finding Devices</a>.) You must then use the
{@link android.bluetooth.BluetoothDevice} to acquire a {@link
android.bluetooth.BluetoothSocket} and initiate the connection.</p>
<p>Here's the basic procedure:</p>
<ol>
<li>Using the {@link android.bluetooth.BluetoothDevice}, get a {@link
android.bluetooth.BluetoothSocket} by calling {@link
android.bluetooth.BluetoothDevice#createRfcommSocketToServiceRecord(UUID)}.
<p>This initializes a {@link android.bluetooth.BluetoothSocket} that will
connect to the {@link android.bluetooth.BluetoothDevice}. The UUID passed here
must match the UUID used by the server device when it opened its
{@link android.bluetooth.BluetoothServerSocket} (with {@link
android.bluetooth.BluetoothAdapter#listenUsingRfcommWithServiceRecord(String,
UUID)}). Using the same UUID is simply a matter of hard-coding the UUID string
into your application and then referencing it from both the server and client
code.</p>
</li>
<li>Initiate the connection by calling {@link
android.bluetooth.BluetoothSocket#connect()}.
<p>Upon this call, the system will perform an SDP lookup on the remote device in
order to match the UUID. If the lookup is successful and the remote device
accepts the connection, it will share the RFCOMM channel to use during the
connection and {@link
android.bluetooth.BluetoothSocket#connect()} will return. This method is a
blocking call. If, for
any reason, the connection fails or the {@link
android.bluetooth.BluetoothSocket#connect()} method times out (after about
12 seconds), then it will throw an exception.</p>
<p>Because {@link
android.bluetooth.BluetoothSocket#connect()} is a blocking call, this connection
procedure should always be performed in a thread separate from the main Activity
thread.</p>
<p class="note">Note: You should always ensure that the device is not performing
device discovery when you call {@link
android.bluetooth.BluetoothSocket#connect()}. If discovery is in progress, then
the
connection attempt will be significantly slowed and is more likely to fail.</p>
</li>
</ol>
<h4>Example</h4>
<p>Here is a basic example of a thread that initiates a Bluetooth
connection:</p>
<pre>
private class ConnectThread extends Thread {
private final BluetoothSocket mmSocket;
private final BluetoothDevice mmDevice;
public ConnectThread(BluetoothDevice device) {
// Use a temporary object that is later assigned to mmSocket,
// because mmSocket is final
BluetoothSocket tmp = null;
mmDevice = device;
// Get a BluetoothSocket to connect with the given BluetoothDevice
try {
// MY_UUID is the app's UUID string, also used by the server code
tmp = device.createRfcommSocketToServiceRecord(MY_UUID);
} catch (IOException e) { }
mmSocket = tmp;
}
public void run() {
// Cancel discovery because it will slow down the connection
mAdapter.cancelDiscovery();
try {
// Connect the device through the socket. This will block
// until it succeeds or throws an exception
mmSocket.connect();
} catch (IOException connectException) {
// Unable to connect; close the socket and get out
try {
mmSocket.close();
} catch (IOException closeException) { }
return;
}
// Do work to manage the connection (in a separate thread)
manageConnectedSocket(mmSocket);
}
/** Will cancel an in-progress connection, and close the socket */
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) { }
}
}
</pre>
<p>Notice that {@link android.bluetooth.BluetoothAdapter#cancelDiscovery()} is called
before the connection is made. You should always do this before connecting and it is safe
to call without actually checking whether it is running or not (but if you do want to
check, call {@link android.bluetooth.BluetoothAdapter#isDiscovering()}).</p>
<p><code>manageConnectedSocket()</code> is a fictional method in the application
that will initiate the thread for transferring data, which is discussed in the section
about <a href="#ManagingAConnection">Managing a Connection</a>.</p>
<p>When you're done with your {@link android.bluetooth.BluetoothSocket}, always
call {@link android.bluetooth.BluetoothSocket#close()} to clean up.
Doing so will immediately close the connected socket and clean up all internal
resources.</p>
<h2 id="ManagingAConnection">Managing a Connection</h2>
<p>When you have successfully connected two (or more) devices, each one will
have a connected {@link android.bluetooth.BluetoothSocket}. This is where the fun
begins because you can share data between devices. Using the {@link
android.bluetooth.BluetoothSocket}, the general procedure to transfer arbitrary data is
simple:</p>
<ol>
<li>Get the {@link java.io.InputStream} and {@link java.io.OutputStream} that
handle transmissions through the socket, via {@link
android.bluetooth.BluetoothSocket#getInputStream()} and
{@link android.bluetooth.BluetoothSocket#getOutputStream}, respectively.</li>
<li>Read and write data to the streams with {@link
java.io.InputStream#read(byte[])} and {@link java.io.OutputStream#write(byte[])}.</li>
</ol>
<p>That's it.</p>
<p>There are, of course, implementation details to consider. First and foremost,
you should use a dedicated thread for all stream reading and writing. This is
important because both {@link java.io.InputStream#read(byte[])} and {@link
java.io.OutputStream#write(byte[])} methods are blocking calls. {@link
java.io.InputStream#read(byte[])} will block until there is something to read
from the stream. {@link java.io.OutputStream#write(byte[])} does not usually
block, but can block for flow control if the remote device is not calling {@link
java.io.InputStream#read(byte[])} quickly enough and the intermediate buffers are full.
So, your main loop in the thread should be dedicated to reading from the {@link
java.io.InputStream}. A separate public method in the thread can be used to initiate
writes to the {@link java.io.OutputStream}.</p>
<h4>Example</h4>
<p>Here's an example of how this might look:</p>
<pre>
private class ConnectedThread extends Thread {
private final BluetoothSocket mmSocket;
private final InputStream mmInStream;
private final OutputStream mmOutStream;
public ConnectedThread(BluetoothSocket socket) {
mmSocket = socket;
InputStream tmpIn = null;
OutputStream tmpOut = null;
// Get the input and output streams, using temp objects because
// member streams are final
try {
tmpIn = socket.getInputStream();
tmpOut = socket.getOutputStream();
} catch (IOException e) { }
mmInStream = tmpIn;
mmOutStream = tmpOut;
}
public void run() {
byte[] buffer = new byte[1024]; // buffer store for the stream
int bytes; // bytes returned from read()
// Keep listening to the InputStream until an exception occurs
while (true) {
try {
// Read from the InputStream
bytes = mmInStream.read(buffer);
// Send the obtained bytes to the UI Activity
mHandler.obtainMessage(MESSAGE_READ, bytes, -1, buffer)
.sendToTarget();
} catch (IOException e) {
break;
}
}
}
/* Call this from the main Activity to send data to the remote device */
public void write(byte[] bytes) {
try {
mmOutStream.write(bytes);
} catch (IOException e) { }
}
/* Call this from the main Activity to shutdown the connection */
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) { }
}
}
</pre>
<p>The constructor acquires the necessary streams and once executed, the thread
will wait for data to come through the InputStream. When {@link
java.io.InputStream#read(byte[])} returns with
bytes from the stream, the data is sent to the main Activity using a member
Handler from the parent class. Then it goes back and waits for more bytes from
the stream.</p>
<p>Sending outgoing data is as simple as calling the thread's
<code>write()</code> method from the main Activity and passing in the bytes to
be sent. This method then simply calls {@link
java.io.OutputStream#write(byte[])} to send the data to the remote device.</p>
<p>The thread's <code>cancel()</code> method is important so that the connection
can be
terminated at any time by closing the {@link android.bluetooth.BluetoothSocket}.
This should always be called when you're done using the Bluetooth
connection.</p>
<div class="special">
<p>For a complete demonstration using the Bluetooth APIs, see the <a
href="{@docRoot}resources/samples/BluetoothChat/index.html">Bluetooth Chat sample app</a>.</p>
</div>
@@ -0,0 +1,23 @@
page.title=Wireless Controls
@jd:body
Go away.
<!--
<h2>Wi-Fi</h2>
<p>The Wi-Fi APIs provide a means by which application can communicate with the lower-level
wireless stack that provides Wi-Fi network access. Almost all information from the device supplicant
is available, including the connected network's link speed, IP address, negotiation state, and more.
It also provides information about all non-connected available networks. Some of the available network
interactions include the ability to scan, add, dave, terminate and initiate connections.</p>
<h2>Bluetooth</h2>
<p>The Android platform includes support for the Bluetooth network stack, which allows a device to
wirelessly exchange data with other Bluetooth devices. The application framework provides access to
the Bluetooth functionality through the Android Bluetooth APIs. These APIs let applications
wirelessly connect to other Bluetooth devices, enabling point-to-point and multipoint wireless
features.</p>
-->
@@ -0,0 +1,18 @@
page.title=Wi-Fi
parent.title=Wireless Controls
parent.link=index.html
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>In this document</h2>
<ol>
</ol>
</div>
</div>
Go away.