docs: Update startService() & bindService() documentation (Proj13) am: 9748d76be9 am: e8e196d007 am: d544dc785b
am: 5d1af7d918
Change-Id: I7ee574ff28491470cea4f1071c82d473fc07ad85
This commit is contained in:
@@ -9,18 +9,18 @@ page.tags="inapp, billing, iap"
|
|||||||
<h2>In this document</h2>
|
<h2>In this document</h2>
|
||||||
<ol>
|
<ol>
|
||||||
<li><a href="#billing-add-aidl">Adding the AIDL file</a></li>
|
<li><a href="#billing-add-aidl">Adding the AIDL file</a></li>
|
||||||
<li><a href="#billing-permission">Updating Your Manifest</a></li>
|
<li><a href="#billing-permission">Updating your manifest</a></li>
|
||||||
<li><a href="#billing-service">Creating a ServiceConnection</a></li>
|
<li><a href="#billing-service">Creating a ServiceConnection</a></li>
|
||||||
<li><a href="#billing-requests">Making In-app Billing Requests</a>
|
<li><a href="#billing-requests">Making In-app Billing requests</a>
|
||||||
<ol>
|
<ol>
|
||||||
<li><a href="#QueryDetails">Querying Items Available for Purchase</a><li>
|
<li><a href="#QueryDetails">Querying items available for purchase</a><li>
|
||||||
<li><a href="#Purchase">Purchasing an Item</a></li>
|
<li><a href="#Purchase">Purchasing an item</a></li>
|
||||||
<li><a href="#QueryPurchases">Querying Purchased Items</a></li>
|
<li><a href="#QueryPurchases">Querying purchased items</a></li>
|
||||||
<li><a href="#Consume">Consuming a Purchase</a></li>
|
<li><a href="#Consume">Consuming a purchase</a></li>
|
||||||
<li><a href="#Subs">Implementing Subscriptions</a></li>
|
<li><a href="#Subs">Implementing subscriptions</a></li>
|
||||||
</ol>
|
</ol>
|
||||||
</li>
|
</li>
|
||||||
<li><a href="#billing-security">Securing Your App</a>
|
<li><a href="#billing-security">Securing your app</a>
|
||||||
</ol>
|
</ol>
|
||||||
<h2>Reference</h2>
|
<h2>Reference</h2>
|
||||||
<ol>
|
<ol>
|
||||||
@@ -42,7 +42,7 @@ page.tags="inapp, billing, iap"
|
|||||||
In-app Billing on Google Play provides a straightforward, simple interface
|
In-app Billing on Google Play provides a straightforward, simple interface
|
||||||
for sending In-app Billing requests and managing In-app Billing transactions
|
for sending In-app Billing requests and managing In-app Billing transactions
|
||||||
using Google Play. The information below covers the basics of how to make
|
using Google Play. The information below covers the basics of how to make
|
||||||
calls from your application to the In-app Billing service using the Version 3
|
calls from your application to the In-app Billing service using the In-app Billing Version 3
|
||||||
API.
|
API.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
@@ -51,26 +51,25 @@ page.tags="inapp, billing, iap"
|
|||||||
your application, see the <a href=
|
your application, see the <a href=
|
||||||
"{@docRoot}training/in-app-billing/index.html">Selling In-app Products</a>
|
"{@docRoot}training/in-app-billing/index.html">Selling In-app Products</a>
|
||||||
training class. The training class provides a complete sample In-app Billing
|
training class. The training class provides a complete sample In-app Billing
|
||||||
application, including convenience classes to handle key tasks related to
|
application, including convenience classes to handle key tasks that are related to
|
||||||
setting up your connection, sending billing requests and processing responses
|
setting up your connection, sending billing requests, processing responses
|
||||||
from Google Play, and managing background threading so that you can make
|
from Google Play, and managing background threading so that you can make
|
||||||
In-app Billing calls from your main activity.
|
In-app Billing calls from your main activity.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
Before you start, be sure that you read the <a href=
|
Before you start, read the <a href=
|
||||||
"{@docRoot}google/play/billing/billing_overview.html">In-app Billing
|
"{@docRoot}google/play/billing/billing_overview.html">In-app Billing
|
||||||
Overview</a> to familiarize yourself with concepts that will make it easier
|
Overview</a> to familiarize yourself with concepts that make it easier
|
||||||
for you to implement In-app Billing.
|
for you to implement In-app Billing.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>To implement In-app Billing in your application, you need to do the
|
<p>Complete these steps to implement In-app Billing in your application:</p>
|
||||||
following:</p>
|
|
||||||
|
|
||||||
<ol>
|
<ol>
|
||||||
<li>Add the In-app Billing library to your project.</li>
|
<li>Add the In-app Billing library to your project.</li>
|
||||||
<li>Update your {@code AndroidManifest.xml} file.</li>
|
<li>Update your {@code AndroidManifest.xml} file.</li>
|
||||||
<li>Create a {@code ServiceConnection} and bind it to
|
<li>Create a {@code ServiceConnection} and bind it to the
|
||||||
{@code IInAppBillingService}.</li>
|
{@code IInAppBillingService}.</li>
|
||||||
<li>Send In-app Billing requests from your application to
|
<li>Send In-app Billing requests from your application to
|
||||||
{@code IInAppBillingService}.</li>
|
{@code IInAppBillingService}.</li>
|
||||||
@@ -79,55 +78,56 @@ following:</p>
|
|||||||
|
|
||||||
<h2 id="billing-add-aidl">Adding the AIDL file to your project</h2>
|
<h2 id="billing-add-aidl">Adding the AIDL file to your project</h2>
|
||||||
|
|
||||||
<p>{@code IInAppBillingService.aidl} is an Android Interface Definition
|
<p>The {@code IInAppBillingService.aidl} is an Android Interface Definition
|
||||||
Language (AIDL) file that defines the interface to the In-app Billing Version
|
Language (AIDL) file that defines the interface to the In-app Billing Version
|
||||||
3 service. You will use this interface to make billing requests by invoking IPC
|
3 service. You can use this interface to make billing requests by invoking IPC
|
||||||
method calls.</p>
|
method calls.</p>
|
||||||
<p>To get the AIDL file:</p>
|
|
||||||
|
<p>Complete these steps to get the AIDL file:</p>
|
||||||
<ol>
|
<ol>
|
||||||
<li>Open the <a href="{@docRoot}tools/help/sdk-manager.html">Android SDK Manager</a>.</li>
|
<li>Open the <a href="{@docRoot}tools/help/sdk-manager.html">Android SDK Manager</a>.</li>
|
||||||
<li>In the SDK Manager, expand the {@code Extras} section.</li>
|
<li>In the SDK Manager, expand the {@code Extras} section.</li>
|
||||||
<li>Select <strong>Google Play Billing Library</strong>.</li>
|
<li>Select <strong>Google Play Billing Library</strong>.</li>
|
||||||
<li>Click <strong>Install packages</strong> to complete the download.</li>
|
<li>Click <strong>Install packages</strong> to complete the download.</li>
|
||||||
</ol>
|
</ol>
|
||||||
<p>The {@code IInAppBillingService.aidl} file will be installed to {@code <sdk>/extras/google/play_billing/}.</p>
|
<p>The {@code IInAppBillingService.aidl} file will be installed to {@code <sdk>/extras/google/play_billing/}.</p>
|
||||||
|
|
||||||
<p>To add the AIDL to your project:</p>
|
<p>Complete these steps to add the AIDL to your project:</p>
|
||||||
|
|
||||||
<ol>
|
<ol>
|
||||||
<li>First, download the Google Play Billing Library to your Android project:
|
<li>Download the Google Play Billing Library to your Android project:
|
||||||
<ol type="a">
|
<ol type="a">
|
||||||
<li>Select <strong>Tools > Android > SDK Manager</strong>.</li>
|
<li>Select <strong>Tools > Android > SDK Manager</strong>.</li>
|
||||||
<li>Under <strong>Appearance & Behavior > System Settings > Android SDK</strong>,
|
<li>Under <strong>Appearance & Behavior > System Settings > Android SDK</strong>,
|
||||||
select the <em>SDK Tools</em> tab to select and download <em>Google Play Billing
|
select the <em>SDK Tools</em> tab to select and download <em>Google Play Billing
|
||||||
Library</em>.</li></ol>
|
Library</em>.</li></ol>
|
||||||
|
|
||||||
<li>Next, copy the {@code IInAppBillingService.aidl} file to your project.
|
<li>Copy the {@code IInAppBillingService.aidl} file to your project.
|
||||||
<ul>
|
<ul>
|
||||||
<li>If you are using Android Studio:
|
<li>If you are using Android Studio, complete these steps to copy the file:
|
||||||
<ol type="a">
|
<ol type="a">
|
||||||
<li>Navigate to {@code src/main} in the Project tool window.</li>
|
<li>Navigate to {@code src/main} in the Project tool window.</li>
|
||||||
|
|
||||||
<li>Select <strong>File > New > Directory</strong> and enter {@code aidl} in the
|
<li>Select <strong>File > New > Directory</strong>, enter {@code aidl} in the
|
||||||
<em>New Directory</em> window, then select <strong>OK</strong>.
|
<em>New Directory</em> window, and select <strong>OK</strong>.
|
||||||
|
|
||||||
<li>Select <strong>File > New > Package</strong> and enter
|
<li>Select <strong>File > New > Package</strong>, enter
|
||||||
{@code com.android.vending.billing} in the <em>New Package</em> window, then select
|
{@code com.android.vending.billing} in the <em>New Package</em> window, and select
|
||||||
<strong>OK</strong>.</li>
|
<strong>OK</strong>.</li>
|
||||||
|
|
||||||
<li>Using your operating system file explorer, navigate to
|
<li>Using your operating system file explorer, navigate to
|
||||||
{@code <sdk>/extras/google/play_billing/}, copy the
|
{@code <sdk>/extras/google/play_billing/}, copy the
|
||||||
{@code IInAppBillingService.aidl} file, and paste it into the
|
{@code IInAppBillingService.aidl} file, and paste it into the
|
||||||
{@code com.android.vending.billing} package in your project.
|
{@code com.android.vending.billing} package in your project.
|
||||||
</li>
|
</li>
|
||||||
</ol>
|
</ol>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li>If you are developing in a non-Android Studio environment: Create the
|
<li>If you are developing in a non-Android Studio environment, create the
|
||||||
following directory {@code /src/com/android/vending/billing} and copy the
|
following directory: {@code /src/com/android/vending/billing}. Copy the
|
||||||
{@code IInAppBillingService.aidl} file into this directory. Put the AIDL
|
{@code IInAppBillingService.aidl} file into this directory. Place the AIDL
|
||||||
file into your project and use the Gradle tool to build your project so that
|
file in your project and use the Gradle tool to build your project so that
|
||||||
the <code>IInAppBillingService.java</code> file gets generated.
|
the <code>IInAppBillingService.java</code> file is generated.
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
@@ -137,16 +137,16 @@ method calls.</p>
|
|||||||
</li>
|
</li>
|
||||||
</ol>
|
</ol>
|
||||||
|
|
||||||
<h2 id="billing-permission">Updating Your App's Manifest</h2>
|
<h2 id="billing-permission">Updating your app's manifest</h2>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
In-app billing relies on the Google Play application, which handles all
|
In-app billing relies on the Google Play application, which handles all
|
||||||
communication between your application and the Google Play server. To use the
|
of the communication between your application and the Google Play server. To use the
|
||||||
Google Play application, your application must request the proper permission.
|
Google Play application, your application must request the proper permission.
|
||||||
You can do this by adding the {@code com.android.vending.BILLING} permission
|
You can do this by adding the {@code com.android.vending.BILLING} permission
|
||||||
to your AndroidManifest.xml file. If your application does not declare the
|
to your AndroidManifest.xml file. If your application does not declare the
|
||||||
In-app Billing permission, but attempts to send billing requests, Google Play
|
In-app Billing permission, but attempts to send billing requests, Google Play
|
||||||
will refuse the requests and respond with an error.
|
refuses the requests and responds with an error.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
@@ -182,7 +182,7 @@ method calls.</p>
|
|||||||
onServiceDisconnected} and {@link
|
onServiceDisconnected} and {@link
|
||||||
android.content.ServiceConnection#onServiceConnected onServiceConnected}
|
android.content.ServiceConnection#onServiceConnected onServiceConnected}
|
||||||
methods to get a reference to the {@code IInAppBillingService} instance after
|
methods to get a reference to the {@code IInAppBillingService} instance after
|
||||||
a connection has been established.
|
a connection is established.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
@@ -208,20 +208,25 @@ ServiceConnection mServiceConn = new ServiceConnection() {
|
|||||||
bindService} method. Pass the method an {@link android.content.Intent} that
|
bindService} method. Pass the method an {@link android.content.Intent} that
|
||||||
references the In-app Billing service and an instance of the {@link
|
references the In-app Billing service and an instance of the {@link
|
||||||
android.content.ServiceConnection} that you created, and explicitly set the
|
android.content.ServiceConnection} that you created, and explicitly set the
|
||||||
Intent's target package name to <code>com.android.vending</code> — the
|
Intent's target package name to <code>com.android.vending</code>—the
|
||||||
package name of Google Play app.
|
package name of Google Play app.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p class="caution">
|
<p class="caution">
|
||||||
<strong>Caution:</strong> To protect the security of billing transactions,
|
<strong>Caution:</strong> To protect the security of billing transactions,
|
||||||
always make sure to explicitly set the intent's target package name to
|
always explicitly set the intent's target package name to
|
||||||
<code>com.android.vending</code>, using {@link
|
<code>com.android.vending</code>, using {@link
|
||||||
android.content.Intent#setPackage(java.lang.String) setPackage()} as shown in
|
android.content.Intent#setPackage(java.lang.String) setPackage()}.
|
||||||
the example below. Setting the package name explicitly ensures that
|
Setting the package name explicitly ensures that
|
||||||
<em>only</em> the Google Play app can handle billing requests from your app,
|
<em>only</em> the Google Play app can handle billing requests from your app,
|
||||||
preventing other apps from intercepting those requests.
|
preventing other apps from intercepting those requests.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
The following code sample demonstrates how to set the intent's target package
|
||||||
|
to protect the security of transactions:
|
||||||
|
</p>
|
||||||
|
|
||||||
<pre>@Override
|
<pre>@Override
|
||||||
public void onCreate(Bundle savedInstanceState) {
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
@@ -233,6 +238,13 @@ public void onCreate(Bundle savedInstanceState) {
|
|||||||
}
|
}
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
|
<p class="caution"><strong>Caution</strong>: To ensure that your app is secure, always use an
|
||||||
|
explicit intent when starting a {@link android.app.Service} and do not declare intent filters for
|
||||||
|
your services. Using an implicit intent to start a service is a security hazard because you cannot
|
||||||
|
be certain of the service that will respond to the intent, and the user cannot see which service
|
||||||
|
starts. Beginning with Android 5.0 (API level 21), the system throws an exception if you call
|
||||||
|
{@link android.content.Context#bindService bindService()} with an implicit intent.</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
You can now use the mService reference to communicate with the Google Play
|
You can now use the mService reference to communicate with the Google Play
|
||||||
service.
|
service.
|
||||||
@@ -242,10 +254,14 @@ public void onCreate(Bundle savedInstanceState) {
|
|||||||
<strong>Important:</strong> Remember to unbind from the In-app Billing
|
<strong>Important:</strong> Remember to unbind from the In-app Billing
|
||||||
service when you are done with your {@link android.app.Activity}. If you
|
service when you are done with your {@link android.app.Activity}. If you
|
||||||
don’t unbind, the open service connection could cause your device’s
|
don’t unbind, the open service connection could cause your device’s
|
||||||
performance to degrade. This example shows how to perform the unbind
|
performance to degrade.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
This example shows how to perform the unbind
|
||||||
operation on a service connection to In-app Billing called {@code
|
operation on a service connection to In-app Billing called {@code
|
||||||
mServiceConn} by overriding the activity’s {@link
|
mServiceConn} by overriding the activity’s {@link
|
||||||
android.app.Activity#onDestroy onDestroy} method.
|
android.app.Activity#onDestroy onDestroy} method:
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
@@ -264,29 +280,29 @@ public void onDestroy() {
|
|||||||
"{@docRoot}training/in-app-billing/preparing-iab-app.html">Selling In-app
|
"{@docRoot}training/in-app-billing/preparing-iab-app.html">Selling In-app
|
||||||
Products</a> training class and associated sample.
|
Products</a> training class and associated sample.
|
||||||
</p>
|
</p>
|
||||||
<h2 id="billing-requests">Making In-app Billing Requests</h2>
|
<h2 id="billing-requests">Making In-app Billing requests</h2>
|
||||||
<p>
|
<p>
|
||||||
Once your application is connected to Google Play, you can initiate purchase
|
After your application is connected to Google Play, you can initiate purchase
|
||||||
requests for in-app products. Google Play provides a checkout interface for
|
requests for in-app products. Google Play provides a checkout interface for
|
||||||
users to enter their payment method, so your application does not need to
|
users to enter their payment method, so your application doesn't need to
|
||||||
handle payment transactions directly. When an item is purchased, Google Play
|
handle payment transactions directly. When an item is purchased, Google Play
|
||||||
recognizes that the user has ownership of that item and prevents the user
|
recognizes that the user has ownership of that item and prevents the user
|
||||||
from purchasing another item with the same product ID until it is consumed.
|
from purchasing another item with the same product ID until it is consumed.
|
||||||
You can control how the item is consumed in your application, and notify
|
You can control how the item is consumed in your application and notify
|
||||||
Google Play to make the item available for purchase again. You can also query
|
Google Play to make the item available for purchase again. You can also query
|
||||||
Google Play to quickly retrieve the list of purchases that were made by the
|
Google Play to quickly retrieve the list of purchases that the
|
||||||
user. This is useful, for example, when you want to restore the user's
|
user made. This is useful, for example, when you want to restore the user's
|
||||||
purchases when your user launches your app.
|
purchases when your user launches your app.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<h3 id="QueryDetails">Querying for Items Available for Purchase</h3>
|
<h3 id="QueryDetails">Querying for items available for purchase</h3>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
In your application, you can query the item details from Google Play using
|
In your application, you can query the item details from Google Play using
|
||||||
the In-app Billing Version 3 API. To pass a request to the In-app Billing
|
the In-app Billing Version 3 API. To pass a request to the In-app Billing
|
||||||
service, first create a {@link android.os.Bundle} that contains a String
|
service, create a {@link android.os.Bundle} that contains a String
|
||||||
{@link java.util.ArrayList} of product IDs with key "ITEM_ID_LIST", where
|
{@link java.util.ArrayList} of product IDs with key "ITEM_ID_LIST", where
|
||||||
each string is a product ID for an purchasable item.
|
each string is a product ID for an purchasable item. Here is an example:
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
@@ -299,9 +315,9 @@ querySkus.putStringArrayList(“ITEM_ID_LIST”, skuList);
|
|||||||
|
|
||||||
<p>
|
<p>
|
||||||
To retrieve this information from Google Play, call the {@code getSkuDetails}
|
To retrieve this information from Google Play, call the {@code getSkuDetails}
|
||||||
method on the In-app Billing Version 3 API, and pass the method the In-app
|
method on the In-app Billing Version 3 API and pass the In-app
|
||||||
Billing API version (“3”), the package name of your calling app, the purchase
|
Billing API version (“3”), the package name of your calling app, the purchase
|
||||||
type (“inapp”), and the {@link android.os.Bundle} that you created.
|
type (“inapp”), and the {@link android.os.Bundle} that you created, into the method:
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
@@ -310,35 +326,35 @@ Bundle skuDetails = mService.getSkuDetails(3,
|
|||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
If the request is successful, the returned {@link android.os.Bundle}has a
|
If the request is successful, the returned {@link android.os.Bundle} has a
|
||||||
response code of {@code BILLING_RESPONSE_RESULT_OK} (0).
|
response code of {@code BILLING_RESPONSE_RESULT_OK} (0).
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p class="note">
|
<p class="note">
|
||||||
<strong>Warning:</strong> Do not call the {@code getSkuDetails} method on the
|
<strong>Warning:</strong> Don't call the {@code getSkuDetails} method on the
|
||||||
main thread. Calling this method triggers a network request which could block
|
main thread. Calling this method triggers a network request that could block
|
||||||
your main thread. Instead, create a separate thread and call the {@code
|
your main thread. Instead, create a separate thread and call the {@code
|
||||||
getSkuDetails} method from inside that thread.
|
getSkuDetails} method from inside of that thread.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
To see all the possible response codes from Google Play, see <a href=
|
To view all of the possible response codes from Google Play, see <a href=
|
||||||
"{@docRoot}google/play/billing/billing_reference.html#billing-codes">In-app
|
"{@docRoot}google/play/billing/billing_reference.html#billing-codes">In-app
|
||||||
Billing Reference</a>.
|
Billing Reference</a>.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
The query results are stored in a String ArrayList with key {@code
|
The query results are stored in a String ArrayList with key {@code
|
||||||
DETAILS_LIST}. The purchase information is stored in the String in JSON
|
DETAILS_LIST}. The purchase information is stored within the String in JSON
|
||||||
format. To see the types of product detail information that are returned, see
|
format. To view the types of product detail information that are returned, see
|
||||||
<a href=
|
<a href=
|
||||||
"{@docRoot}google/play/billing/billing_reference.html#getSkuDetails">In-app
|
"{@docRoot}google/play/billing/billing_reference.html#getSkuDetails">In-app
|
||||||
Billing Reference</a>.
|
Billing Reference</a>.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
In this example, you are retrieving the prices for your in-app items from the
|
In this example shows how to retrieve the prices for your in-app items from the
|
||||||
skuDetails {@link android.os.Bundle} returned from the previous code snippet.
|
skuDetails {@link android.os.Bundle} that is returned from the previous code snippet:
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
@@ -357,15 +373,15 @@ if (response == 0) {
|
|||||||
}
|
}
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
<h3 id="Purchase">Purchasing an Item</h3>
|
<h3 id="Purchase">Purchasing an item</h3>
|
||||||
<p>
|
<p>
|
||||||
To start a purchase request from your app, call the {@code getBuyIntent}
|
To start a purchase request from your app, call the {@code getBuyIntent}
|
||||||
method on the In-app Billing service. Pass in to the method the In-app
|
method on the In-app Billing service. Pass the In-app
|
||||||
Billing API version (“3”), the package name of your calling app, the product
|
Billing API version (“3”), the package name of your calling app, the product
|
||||||
ID for the item to purchase, the purchase type (“inapp” or "subs"), and a
|
ID for the item to purchase, the purchase type (“inapp” or "subs"), and a
|
||||||
{@code developerPayload} String. The {@code developerPayload} String is used
|
{@code developerPayload} String into the method. The {@code developerPayload} String is used
|
||||||
to specify any additional arguments that you want Google Play to send back
|
to specify any additional arguments that you want Google Play to send back
|
||||||
along with the purchase information.
|
along with the purchase information. Here is an example:
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
@@ -377,10 +393,13 @@ Bundle buyIntentBundle = mService.getBuyIntent(3, getPackageName(),
|
|||||||
If the request is successful, the returned {@link android.os.Bundle} has a
|
If the request is successful, the returned {@link android.os.Bundle} has a
|
||||||
response code of {@code BILLING_RESPONSE_RESULT_OK} (0) and a {@link
|
response code of {@code BILLING_RESPONSE_RESULT_OK} (0) and a {@link
|
||||||
android.app.PendingIntent} that you can use to start the purchase flow. To
|
android.app.PendingIntent} that you can use to start the purchase flow. To
|
||||||
see all the possible response codes from Google Play, see <a href=
|
view all of the possible response codes from Google Play, see <a href=
|
||||||
"{@docRoot}google/play/billing/billing_reference.html#billing-codes">In-app
|
"{@docRoot}google/play/billing/billing_reference.html#billing-codes">In-app
|
||||||
Billing Reference</a>. Next, extract a {@link android.app.PendingIntent} from
|
Billing Reference</a>.
|
||||||
the response {@link android.os.Bundle} with key {@code BUY_INTENT}.
|
|
||||||
|
<p>
|
||||||
|
The next step is to extract a {@link android.app.PendingIntent} from
|
||||||
|
the response {@link android.os.Bundle} with key {@code BUY_INTENT}, as shown here:
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
@@ -390,8 +409,8 @@ PendingIntent pendingIntent = buyIntentBundle.getParcelable("BUY_INTENT");
|
|||||||
<p>
|
<p>
|
||||||
To complete the purchase transaction, call the {@link
|
To complete the purchase transaction, call the {@link
|
||||||
android.app.Activity#startIntentSenderForResult startIntentSenderForResult}
|
android.app.Activity#startIntentSenderForResult startIntentSenderForResult}
|
||||||
method and use the {@link android.app.PendingIntent} that you created. In
|
method and use the {@link android.app.PendingIntent} that you created. This
|
||||||
this example, you are using an arbitrary value of 1001 for the request code.
|
example uses an arbitrary value of 1001 for the request code:
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
@@ -404,9 +423,9 @@ startIntentSenderForResult(pendingIntent.getIntentSender(),
|
|||||||
Google Play sends a response to your {@link android.app.PendingIntent} to the
|
Google Play sends a response to your {@link android.app.PendingIntent} to the
|
||||||
{@link android.app.Activity#onActivityResult onActivityResult} method of your
|
{@link android.app.Activity#onActivityResult onActivityResult} method of your
|
||||||
application. The {@link android.app.Activity#onActivityResult
|
application. The {@link android.app.Activity#onActivityResult
|
||||||
onActivityResult} method will have a result code of {@code
|
onActivityResult} method has a result code of {@code
|
||||||
Activity.RESULT_OK} (1) or {@code Activity.RESULT_CANCELED} (0). To see the
|
Activity.RESULT_OK} (1) or {@code Activity.RESULT_CANCELED} (0). To view the
|
||||||
types of order information that is returned in the response {@link
|
types of order information that are returned in the response {@link
|
||||||
android.content.Intent}, see <a href=
|
android.content.Intent}, see <a href=
|
||||||
"{@docRoot}google/play/billing/billing_reference.html#getBuyIntent">In-app
|
"{@docRoot}google/play/billing/billing_reference.html#getBuyIntent">In-app
|
||||||
Billing Reference</a>.
|
Billing Reference</a>.
|
||||||
@@ -415,7 +434,7 @@ startIntentSenderForResult(pendingIntent.getIntentSender(),
|
|||||||
<p>
|
<p>
|
||||||
The purchase data for the order is a String in JSON format that is mapped to
|
The purchase data for the order is a String in JSON format that is mapped to
|
||||||
the {@code INAPP_PURCHASE_DATA} key in the response {@link
|
the {@code INAPP_PURCHASE_DATA} key in the response {@link
|
||||||
android.content.Intent}, for example:
|
android.content.Intent}. Here is an example:
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
@@ -436,13 +455,13 @@ startIntentSenderForResult(pendingIntent.getIntentSender(),
|
|||||||
long. Pass this entire token to other methods, such as when you consume the
|
long. Pass this entire token to other methods, such as when you consume the
|
||||||
purchase, as described in <a href=
|
purchase, as described in <a href=
|
||||||
"{@docRoot}training/in-app-billing/purchase-iab-products.html#Consume">Consume
|
"{@docRoot}training/in-app-billing/purchase-iab-products.html#Consume">Consume
|
||||||
a Purchase</a>. Do not abbreviate or truncate this token; you must save and
|
a Purchase</a>. Don't abbreviate or truncate this token; you must save and
|
||||||
return the entire token.
|
return the entire token.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
Continuing from the previous example, you get the response code, purchase
|
Continuing from the previous example, you receive the response code, purchase
|
||||||
data, and signature from the response {@link android.content.Intent}.
|
data, and signature from the response {@link android.content.Intent}:
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
@@ -472,23 +491,23 @@ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
|||||||
<p class="note">
|
<p class="note">
|
||||||
<strong>Security Recommendation:</strong> When you send a purchase request,
|
<strong>Security Recommendation:</strong> When you send a purchase request,
|
||||||
create a String token that uniquely identifies this purchase request and
|
create a String token that uniquely identifies this purchase request and
|
||||||
include this token in the {@code developerPayload}.You can use a randomly
|
include this token in the {@code developerPayload}. You can use a randomly-generated
|
||||||
generated string as the token. When you receive the purchase response from
|
string as the token. When you receive the purchase response from
|
||||||
Google Play, make sure to check the returned data signature, the {@code
|
Google Play, ensure that you check the returned data signature, the {@code
|
||||||
orderId}, and the {@code developerPayload} String. For added security, you
|
orderId}, and the {@code developerPayload} String. For added security, you
|
||||||
should perform the checking on your own secure server. Make sure to verify
|
should perform the checking on your own secure server. Verify
|
||||||
that the {@code orderId} is a unique value that you have not previously
|
that the {@code orderId} is a unique value that you have not previously
|
||||||
processed, and the {@code developerPayload} String matches the token that you
|
processed and that the {@code developerPayload} String matches the token that you
|
||||||
sent previously with the purchase request.
|
sent previously with the purchase request.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<h3 id="QueryPurchases">Querying for Purchased Items</h3>
|
<h3 id="QueryPurchases">Querying for purchased items</h3>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
To retrieve information about purchases made by a user from your app, call
|
To retrieve information about purchases that are made by a user from your app, call
|
||||||
the {@code getPurchases} method on the In-app Billing Version 3 service. Pass
|
the {@code getPurchases} method on the In-app Billing Version 3 service. Pass
|
||||||
in to the method the In-app Billing API version (“3”), the package name of
|
the In-app Billing API version (“3”), the package name of
|
||||||
your calling app, and the purchase type (“inapp” or "subs").
|
your calling app, and the purchase type (“inapp” or "subs") into the method. Here is an example:
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
@@ -507,18 +526,18 @@ Bundle ownedItems = mService.getPurchases(3, getPackageName(), "inapp", null);
|
|||||||
To improve performance, the In-app Billing service returns only up to 700
|
To improve performance, the In-app Billing service returns only up to 700
|
||||||
products that are owned by the user when {@code getPurchase} is first called.
|
products that are owned by the user when {@code getPurchase} is first called.
|
||||||
If the user owns a large number of products, Google Play includes a String
|
If the user owns a large number of products, Google Play includes a String
|
||||||
token mapped to the key {@code INAPP_CONTINUATION_TOKEN} in the response
|
token that is mapped to the key {@code INAPP_CONTINUATION_TOKEN} in the response
|
||||||
{@link android.os.Bundle} to indicate that more products can be retrieved.
|
{@link android.os.Bundle} to indicate that more products can be retrieved.
|
||||||
Your application can then make a subsequent {@code getPurchases} call, and
|
Your application can then make a subsequent {@code getPurchases} call and
|
||||||
pass in this token as an argument. Google Play continues to return a
|
pass in this token as an argument. Google Play continues to return a
|
||||||
continuation token in the response {@link android.os.Bundle} until all
|
continuation token in the response {@link android.os.Bundle} until all
|
||||||
products that are owned by the user has been sent to your app.
|
of the products that are owned by the user are sent to your app.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>For more information about the data returned by {@code getPurchases}, see
|
<p>For more information about the data that is returned by {@code getPurchases}, see
|
||||||
<a href="{@docRoot}google/play/billing/billing_reference.html#getPurchases">
|
<a href="{@docRoot}google/play/billing/billing_reference.html#getPurchases">
|
||||||
In-app Billing Reference</a>. The following example shows how you can
|
In-app Billing Reference</a>. The following example shows how you can
|
||||||
retrieve this data from the response.
|
retrieve this data from the response:
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
@@ -548,26 +567,26 @@ if (response == 0) {
|
|||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
|
|
||||||
<h3 id="Consume">Consuming a Purchase</h3>
|
<h3 id="Consume">Consuming a purchase</h3>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
You can use the In-app Billing Version 3 API to track the ownership of
|
You can use the In-app Billing Version 3 API to track the ownership of
|
||||||
purchased in-app products in Google Play. Once an in-app product is
|
purchased in-app products in Google Play. Once an in-app product is
|
||||||
purchased, it is considered to be "owned" and cannot be purchased from Google
|
purchased, it is considered to be <em>owned</em> and cannot be purchased from Google
|
||||||
Play. You must send a consumption request for the in-app product before
|
Play. You must send a consumption request for the in-app product before
|
||||||
Google Play makes it available for purchase again.
|
Google Play makes it available for purchase again.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p class="caution">
|
<p class="note">
|
||||||
<strong>Important</strong>: Managed in-app products are consumable, but
|
<strong>Important</strong>: Managed in-app products are consumable, but
|
||||||
subscriptions are not.
|
subscriptions are not.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
How you use the consumption mechanism in your app is up to you. Typically,
|
The way that you use the consumption mechanism in your app is up to you. Typically,
|
||||||
you would implement consumption for in-app products with temporary benefits
|
you implement consumption for in-app products with temporary benefits
|
||||||
that users may want to purchase multiple times (for example, in-game currency
|
that users may want to purchase multiple times (for example, in-game currency
|
||||||
or equipment). You would typically not want to implement consumption for
|
or equipment). You typically don't want to implement consumption for
|
||||||
in-app products that are purchased once and provide a permanent effect (for
|
in-app products that are purchased once and provide a permanent effect (for
|
||||||
example, a premium upgrade).
|
example, a premium upgrade).
|
||||||
</p>
|
</p>
|
||||||
@@ -576,21 +595,21 @@ if (response == 0) {
|
|||||||
To record a purchase consumption, send the {@code consumePurchase} method to
|
To record a purchase consumption, send the {@code consumePurchase} method to
|
||||||
the In-app Billing service and pass in the {@code purchaseToken} String value
|
the In-app Billing service and pass in the {@code purchaseToken} String value
|
||||||
that identifies the purchase to be removed. The {@code purchaseToken} is part
|
that identifies the purchase to be removed. The {@code purchaseToken} is part
|
||||||
of the data returned in the {@code INAPP_PURCHASE_DATA} String by the Google
|
of the data that is returned in the {@code INAPP_PURCHASE_DATA} String by the Google
|
||||||
Play service following a successful purchase request. In this example, you
|
Play service following a successful purchase request. This example
|
||||||
are recording the consumption of a product that is identified with the {@code
|
records the consumption of a product that is identified with the {@code
|
||||||
purchaseToken} in the {@code token} variable.
|
purchaseToken} in the {@code token} variable:
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
int response = mService.consumePurchase(3, getPackageName(), token);
|
int response = mService.consumePurchase(3, getPackageName(), token);
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
<p class="note">
|
<p class="caution">
|
||||||
<strong>Warning:</strong> Do not call the {@code consumePurchase} method on
|
<strong>Warning:</strong> Don't call the {@code consumePurchase} method on
|
||||||
the main thread. Calling this method triggers a network request which could
|
the main thread. Calling this method triggers a network request that could
|
||||||
block your main thread. Instead, create a separate thread and call the {@code
|
block your main thread. Instead, create a separate thread and call the {@code
|
||||||
consumePurchase} method from inside that thread.
|
consumePurchase} method from inside of that thread.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
@@ -600,20 +619,20 @@ int response = mService.consumePurchase(3, getPackageName(), token);
|
|||||||
purchased.
|
purchased.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p class="note">
|
<p class="caution">
|
||||||
<strong>Security Recommendation:</strong> You must send a consumption request
|
<strong>Security Recommendation:</strong> Send a consumption request
|
||||||
before provisioning the benefit of the consumable in-app purchase to the
|
before provisioning the benefit of the consumable in-app purchase to the
|
||||||
user. Make sure that you have received a successful consumption response from
|
user. Ensure that you receive a successful consumption response from
|
||||||
Google Play before you provision the item.
|
Google Play before you provision the item.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<h3 id="Subs">Implementing Subscriptions</h3>
|
<h3 id="Subs">Implementing subscriptions</h3>
|
||||||
|
|
||||||
<p>Launching a purchase flow for a subscription is similar to launching the
|
<p>Launching a purchase flow for a subscription is similar to launching the
|
||||||
purchase flow for a product, with the exception that the product type must be set
|
purchase flow for a product, with the exception that the product type must be set
|
||||||
to "subs". The purchase result is delivered to your Activity's
|
to "subs". The purchase result is delivered to your Activity's
|
||||||
{@link android.app.Activity#onActivityResult onActivityResult} method, exactly
|
{@link android.app.Activity#onActivityResult onActivityResult} method, exactly
|
||||||
as in the case of in-app products.</p>
|
as in the case of in-app products. Here is an example:</p>
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
Bundle bundle = mService.getBuyIntent(3, "com.example.myapp",
|
Bundle bundle = mService.getBuyIntent(3, "com.example.myapp",
|
||||||
@@ -629,18 +648,18 @@ if (bundle.getInt(RESPONSE_CODE) == BILLING_RESPONSE_RESULT_OK) {
|
|||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
<p>To query for active subscriptions, use the {@code getPurchases} method, again
|
<p>To query for active subscriptions, use the {@code getPurchases} method, again
|
||||||
with the product type parameter set to "subs".</p>
|
with the product type parameter set to "subs":</p>
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
Bundle activeSubs = mService.getPurchases(3, "com.example.myapp",
|
Bundle activeSubs = mService.getPurchases(3, "com.example.myapp",
|
||||||
"subs", continueToken);
|
"subs", continueToken);
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
<p>The call returns a {@code Bundle} with all the active subscriptions owned by
|
<p>The call returns a {@code Bundle} with all of the active subscriptions that are owned by
|
||||||
the user. Once a subscription expires without renewal, it will no longer appear
|
the user. When a subscription expires without renewal, it no longer appears
|
||||||
in the returned {@code Bundle}.</p>
|
in the returned {@code Bundle}.</p>
|
||||||
|
|
||||||
<h2 id="billing-security">Securing Your Application</h2>
|
<h2 id="billing-security">Securing your application</h2>
|
||||||
|
|
||||||
<p>To help ensure the integrity of the transaction information that is sent to
|
<p>To help ensure the integrity of the transaction information that is sent to
|
||||||
your application, Google Play signs the JSON string that contains the response
|
your application, Google Play signs the JSON string that contains the response
|
||||||
@@ -648,21 +667,21 @@ data for a purchase order. Google Play uses the private key that is associated
|
|||||||
with your application in the Developer Console to create this signature. The
|
with your application in the Developer Console to create this signature. The
|
||||||
Developer Console generates an RSA key pair for each application.<p>
|
Developer Console generates an RSA key pair for each application.<p>
|
||||||
|
|
||||||
<p class="note"><strong>Note:</strong>To find the public key portion of this key
|
<p class="note"><strong>Note:</strong> To find the public key portion of this key
|
||||||
pair, open your application's details in the Developer Console, then click on
|
pair, open your application's details in the Developer Console, click
|
||||||
<strong>Services & APIs</strong>, and look at the field titled
|
<strong>Services & APIs</strong>, and review the field titled
|
||||||
<strong>Your License Key for This Application</strong>.</p>
|
<strong>Your License Key for This Application</strong>.</p>
|
||||||
|
|
||||||
<p>The Base64-encoded RSA public key generated by Google Play is in binary
|
<p>The Base64-encoded RSA public key that is generated by Google Play is in binary
|
||||||
encoded, X.509 subjectPublicKeyInfo DER SEQUENCE format. It is the same public
|
encoded, X.509 subjectPublicKeyInfo DER SEQUENCE format. It is the same public
|
||||||
key that is used with Google Play licensing.</p>
|
key that is used with Google Play licensing.</p>
|
||||||
|
|
||||||
<p>When your application receives this signed response you can
|
<p>When your application receives this signed response, you can
|
||||||
use the public key portion of your RSA key pair to verify the signature.
|
use the public key portion of your RSA key pair to verify the signature.
|
||||||
By performing signature verification you can detect responses that have
|
By performing signature verification, you can detect any responses that have
|
||||||
been tampered with or that have been spoofed. You can perform this signature
|
been tampered with or that have been spoofed. You can perform this signature
|
||||||
verification step in your application; however, if your application connects
|
verification step in your application; however, if your application connects
|
||||||
to a secure remote server then we recommend that you perform the signature
|
to a secure remote server, Google recommends that you perform the signature
|
||||||
verification on that server.</p>
|
verification on that server.</p>
|
||||||
|
|
||||||
<p>For more information about best practices for security and design, see <a
|
<p>For more information about best practices for security and design, see <a
|
||||||
|
|||||||
@@ -8,19 +8,19 @@ parent.link=services.html
|
|||||||
<ol id="qv">
|
<ol id="qv">
|
||||||
<h2>In this document</h2>
|
<h2>In this document</h2>
|
||||||
<ol>
|
<ol>
|
||||||
<li><a href="#Basics">The Basics</a></li>
|
<li><a href="#Basics">The basics</a></li>
|
||||||
<li><a href="#Creating">Creating a Bound Service</a>
|
<li><a href="#Creating">Creating a bound service</a>
|
||||||
<ol>
|
<ol>
|
||||||
<li><a href="#Binder">Extending the Binder class</a></li>
|
<li><a href="#Binder">Extending the Binder class</a></li>
|
||||||
<li><a href="#Messenger">Using a Messenger</a></li>
|
<li><a href="#Messenger">Using a Messenger</a></li>
|
||||||
</ol>
|
</ol>
|
||||||
</li>
|
</li>
|
||||||
<li><a href="#Binding">Binding to a Service</a>
|
<li><a href="#Binding">Binding to a service</a>
|
||||||
<ol>
|
<ol>
|
||||||
<li><a href="#Additional_Notes">Additional notes</a></li>
|
<li><a href="#Additional_Notes">Additional notes</a></li>
|
||||||
</ol>
|
</ol>
|
||||||
</li>
|
</li>
|
||||||
<li><a href="#Lifecycle">Managing the Lifecycle of a Bound Service</a></li>
|
<li><a href="#Lifecycle">Managing the lifecycle of a bound service</a></li>
|
||||||
</ol>
|
</ol>
|
||||||
|
|
||||||
<h2>Key classes</h2>
|
<h2>Key classes</h2>
|
||||||
@@ -32,9 +32,13 @@ parent.link=services.html
|
|||||||
|
|
||||||
<h2>Samples</h2>
|
<h2>Samples</h2>
|
||||||
<ol>
|
<ol>
|
||||||
<li><a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/RemoteService.html">{@code
|
<li><a
|
||||||
|
href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/RemoteService.html">
|
||||||
|
{@code
|
||||||
RemoteService}</a></li>
|
RemoteService}</a></li>
|
||||||
<li><a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/LocalService.html">{@code
|
<li><a
|
||||||
|
href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/LocalService.html">
|
||||||
|
{@code
|
||||||
LocalService}</a></li>
|
LocalService}</a></li>
|
||||||
</ol>
|
</ol>
|
||||||
|
|
||||||
@@ -45,19 +49,23 @@ parent.link=services.html
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<p>A bound service is the server in a client-server interface. A bound service allows components
|
<p>A bound service is the server in a client-server interface. It allows components
|
||||||
(such as activities) to bind to the service, send requests, receive responses, and even perform
|
(such as activities) to bind to the service, send requests, receive responses, and perform
|
||||||
interprocess communication (IPC). A bound service typically lives only while it serves another
|
interprocess communication (IPC). A bound service typically lives only while it serves another
|
||||||
application component and does not run in the background indefinitely.</p>
|
application component and does not run in the background indefinitely.</p>
|
||||||
|
|
||||||
<p>This document shows you how to create a bound service, including how to bind
|
<p class="note"><strong>Note:</strong> If your app targets Android 5.0 (API level 21) or later,
|
||||||
to the service from other application components. However, you should also refer to the <a
|
it's recommended that you use the {@link android.app.job.JobScheduler} to execute background
|
||||||
href="{@docRoot}guide/components/services.html">Services</a> document for additional
|
services. For more information about {@link android.app.job.JobScheduler}, see its
|
||||||
information about services in general, such as how to deliver notifications from a service, set
|
{@link android.app.job.JobScheduler API-reference documentation}.</p>
|
||||||
the service to run in the foreground, and more.</p>
|
|
||||||
|
|
||||||
|
<p>This document describes how to create a bound service, including how to bind
|
||||||
|
to the service from other application components. For additional information about services in
|
||||||
|
general, such as how to deliver notifications from a service and set the service to run
|
||||||
|
in the foreground, refer to the <a href="{@docRoot}guide/components/services.html">
|
||||||
|
Services</a> document.</p>
|
||||||
|
|
||||||
<h2 id="Basics">The Basics</h2>
|
<h2 id="Basics">The basics</h2>
|
||||||
|
|
||||||
<p>A bound service is an implementation of the {@link android.app.Service} class that allows
|
<p>A bound service is an implementation of the {@link android.app.Service} class that allows
|
||||||
other applications to bind to it and interact with it. To provide binding for a
|
other applications to bind to it and interact with it. To provide binding for a
|
||||||
@@ -67,57 +75,61 @@ clients can use to interact with the service.</p>
|
|||||||
|
|
||||||
<div class="sidebox-wrapper">
|
<div class="sidebox-wrapper">
|
||||||
<div class="sidebox">
|
<div class="sidebox">
|
||||||
<h3>Binding to a Started Service</h3>
|
<h3>Binding to a started service</h3>
|
||||||
|
|
||||||
<p>As discussed in the <a href="{@docRoot}guide/components/services.html">Services</a>
|
<p>As discussed in the <a href="{@docRoot}guide/components/services.html">Services</a>
|
||||||
document, you can create a service that is both started and bound. That is, the service can be
|
document, you can create a service that is both started and bound. That is, you can start a
|
||||||
started by calling {@link android.content.Context#startService startService()}, which allows the
|
service by calling {@link android.content.Context#startService startService()}, which allows the
|
||||||
service to run indefinitely, and also allow a client to bind to the service by calling {@link
|
service to run indefinitely, and you can also allow a client to bind to the service by
|
||||||
|
calling {@link
|
||||||
android.content.Context#bindService bindService()}.
|
android.content.Context#bindService bindService()}.
|
||||||
<p>If you do allow your service to be started and bound, then when the service has been
|
<p>If you do allow your service to be started and bound, then when the service has been
|
||||||
started, the system does <em>not</em> destroy the service when all clients unbind. Instead, you must
|
started, the system does <em>not</em> destroy the service when all clients unbind.
|
||||||
explicitly stop the service, by calling {@link android.app.Service#stopSelf stopSelf()} or {@link
|
Instead, you must
|
||||||
|
explicitly stop the service by calling {@link android.app.Service#stopSelf stopSelf()} or {@link
|
||||||
android.content.Context#stopService stopService()}.</p>
|
android.content.Context#stopService stopService()}.</p>
|
||||||
|
|
||||||
<p>Although you should usually implement either {@link android.app.Service#onBind onBind()}
|
<p>Although you usually implement either {@link android.app.Service#onBind onBind()}
|
||||||
<em>or</em> {@link android.app.Service#onStartCommand onStartCommand()}, it's sometimes necessary to
|
<em>or</em> {@link android.app.Service#onStartCommand onStartCommand()}, it's sometimes
|
||||||
|
necessary to
|
||||||
implement both. For example, a music player might find it useful to allow its service to run
|
implement both. For example, a music player might find it useful to allow its service to run
|
||||||
indefinitely and also provide binding. This way, an activity can start the service to play some
|
indefinitely and also provide binding. This way, an activity can start the service to play some
|
||||||
music and the music continues to play even if the user leaves the application. Then, when the user
|
music and the music continues to play even if the user leaves the application. Then, when the user
|
||||||
returns to the application, the activity can bind to the service to regain control of playback.</p>
|
returns to the application, the activity can bind to the service to regain control of
|
||||||
|
playback.</p>
|
||||||
|
|
||||||
<p>Be sure to read the section about <a href="#Lifecycle">Managing the Lifecycle of a Bound
|
<p>For more information about the service lifecycle when adding binding to a started service,
|
||||||
Service</a>, for more information about the service lifecycle when adding binding to a
|
see <a href="#Lifecycle">Managing the lifecycle of a bound Service</a>.</p>
|
||||||
started service.</p>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p>A client can bind to the service by calling {@link android.content.Context#bindService
|
<p>A client can bind to a service by calling {@link android.content.Context#bindService
|
||||||
bindService()}. When it does, it must provide an implementation of {@link
|
bindService()}. When it does, it must provide an implementation of {@link
|
||||||
android.content.ServiceConnection}, which monitors the connection with the service. The {@link
|
android.content.ServiceConnection}, which monitors the connection with the service. The {@link
|
||||||
android.content.Context#bindService bindService()} method returns immediately without a value, but
|
android.content.Context#bindService bindService()} method returns immediately without a
|
||||||
|
value, but
|
||||||
when the Android system creates the connection between the
|
when the Android system creates the connection between the
|
||||||
client and service, it calls {@link
|
client and service, it calls {@link
|
||||||
android.content.ServiceConnection#onServiceConnected onServiceConnected()} on the {@link
|
android.content.ServiceConnection#onServiceConnected onServiceConnected()} on the {@link
|
||||||
android.content.ServiceConnection}, to deliver the {@link android.os.IBinder} that
|
android.content.ServiceConnection}, to deliver the {@link android.os.IBinder} that
|
||||||
the client can use to communicate with the service.</p>
|
the client can use to communicate with the service.</p>
|
||||||
|
|
||||||
<p>Multiple clients can connect to the service at once. However, the system calls your service's
|
<p>Multiple clients can connect to a service simultaneously. However, the system calls your service's
|
||||||
{@link android.app.Service#onBind onBind()} method to retrieve the {@link android.os.IBinder} only
|
{@link android.app.Service#onBind onBind()} method to retrieve the
|
||||||
|
{@link android.os.IBinder} only
|
||||||
when the first client binds. The system then delivers the same {@link android.os.IBinder} to any
|
when the first client binds. The system then delivers the same {@link android.os.IBinder} to any
|
||||||
additional clients that bind, without calling {@link android.app.Service#onBind onBind()} again.</p>
|
additional clients that bind, without calling {@link android.app.Service#onBind onBind()}
|
||||||
|
again.</p>
|
||||||
|
|
||||||
<p>When the last client unbinds from the service, the system destroys the service (unless the
|
<p>When the last client unbinds from the service, the system destroys the service, unless the
|
||||||
service was also started by {@link android.content.Context#startService startService()}).</p>
|
service was also started by {@link android.content.Context#startService startService()}.</p>
|
||||||
|
|
||||||
<p>When you implement your bound service, the most important part is defining the interface
|
<p>The most important part of your bound service implementation is defining the interface
|
||||||
that your {@link android.app.Service#onBind onBind()} callback method returns. There are a few
|
that your {@link android.app.Service#onBind onBind()} callback method returns. The following
|
||||||
different ways you can define your service's {@link android.os.IBinder} interface and the following
|
section discusses several different ways that you can define your service's
|
||||||
section discusses each technique.</p>
|
{@link android.os.IBinder} interface.</p>
|
||||||
|
|
||||||
|
<h2 id="Creating">Creating a bound service</h2>
|
||||||
|
|
||||||
<h2 id="Creating">Creating a Bound Service</h2>
|
|
||||||
|
|
||||||
<p>When creating a service that provides binding, you must provide an {@link android.os.IBinder}
|
<p>When creating a service that provides binding, you must provide an {@link android.os.IBinder}
|
||||||
that provides the programming interface that clients can use to interact with the service. There
|
that provides the programming interface that clients can use to interact with the service. There
|
||||||
@@ -125,12 +137,14 @@ are three ways you can define the interface:</p>
|
|||||||
|
|
||||||
<dl>
|
<dl>
|
||||||
<dt><a href="#Binder">Extending the Binder class</a></dt>
|
<dt><a href="#Binder">Extending the Binder class</a></dt>
|
||||||
<dd>If your service is private to your own application and runs in the same process as the client
|
<dd>If your service is private to your own application and runs in the same process
|
||||||
(which is common), you should create your interface by extending the {@link android.os.Binder} class
|
as the client
|
||||||
|
(which is common), you should create your interface by extending the {@link android.os.Binder}
|
||||||
|
class
|
||||||
and returning an instance of it from
|
and returning an instance of it from
|
||||||
{@link android.app.Service#onBind onBind()}. The client receives the {@link android.os.Binder} and
|
{@link android.app.Service#onBind onBind()}. The client receives the {@link android.os.Binder} and
|
||||||
can use it to directly access public methods available in either the {@link android.os.Binder}
|
can use it to directly access public methods available in either the {@link android.os.Binder}
|
||||||
implementation or even the {@link android.app.Service}.
|
implementation or the {@link android.app.Service}.
|
||||||
<p>This is the preferred technique when your service is merely a background worker for your own
|
<p>This is the preferred technique when your service is merely a background worker for your own
|
||||||
application. The only reason you would not create your interface this way is because
|
application. The only reason you would not create your interface this way is because
|
||||||
your service is used by other applications or across separate processes.</dd>
|
your service is used by other applications or across separate processes.</dd>
|
||||||
@@ -143,20 +157,20 @@ android.os.Message} objects. This {@link android.os.Handler}
|
|||||||
is the basis for a {@link android.os.Messenger} that can then share an {@link android.os.IBinder}
|
is the basis for a {@link android.os.Messenger} that can then share an {@link android.os.IBinder}
|
||||||
with the client, allowing the client to send commands to the service using {@link
|
with the client, allowing the client to send commands to the service using {@link
|
||||||
android.os.Message} objects. Additionally, the client can define a {@link android.os.Messenger} of
|
android.os.Message} objects. Additionally, the client can define a {@link android.os.Messenger} of
|
||||||
its own so the service can send messages back.
|
its own, so the service can send messages back.
|
||||||
<p>This is the simplest way to perform interprocess communication (IPC), because the {@link
|
<p>This is the simplest way to perform interprocess communication (IPC), because the {@link
|
||||||
android.os.Messenger} queues all requests into a single thread so that you don't have to design
|
android.os.Messenger} queues all requests into a single thread so that you don't have to design
|
||||||
your service to be thread-safe.</p>
|
your service to be thread-safe.</p>
|
||||||
</dd>
|
</dd>
|
||||||
|
|
||||||
<dt>Using AIDL</dt>
|
<dt><a href="{@docRoot}guide/components/aidl.html">Using AIDL</a></dt>
|
||||||
<dd>AIDL (Android Interface Definition Language) performs all the work to decompose objects into
|
<dd>Android Interface Definition Language (AIDL) decomposes objects into
|
||||||
primitives that the operating system can understand and marshall them across processes to perform
|
primitives that the operating system can understand and marshals them across processes to perform
|
||||||
IPC. The previous technique, using a {@link android.os.Messenger}, is actually based on AIDL as
|
IPC. The previous technique, using a {@link android.os.Messenger}, is actually based on AIDL as
|
||||||
its underlying structure. As mentioned above, the {@link android.os.Messenger} creates a queue of
|
its underlying structure. As mentioned above, the {@link android.os.Messenger} creates a queue of
|
||||||
all the client requests in a single thread, so the service receives requests one at a time. If,
|
all the client requests in a single thread, so the service receives requests one at a time. If,
|
||||||
however, you want your service to handle multiple requests simultaneously, then you can use AIDL
|
however, you want your service to handle multiple requests simultaneously, then you can use AIDL
|
||||||
directly. In this case, your service must be capable of multi-threading and be built thread-safe.
|
directly. In this case, your service must be thread-safe and capable of multi-threading.
|
||||||
<p>To use AIDL directly, you must
|
<p>To use AIDL directly, you must
|
||||||
create an {@code .aidl} file that defines the programming interface. The Android SDK tools use
|
create an {@code .aidl} file that defines the programming interface. The Android SDK tools use
|
||||||
this file to generate an abstract class that implements the interface and handles IPC, which you
|
this file to generate an abstract class that implements the interface and handles IPC, which you
|
||||||
@@ -164,19 +178,18 @@ can then extend within your service.</p>
|
|||||||
</dd>
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
|
|
||||||
<p class="note"><strong>Note:</strong> Most applications <strong>should not</strong> use AIDL to
|
<p class="note"><strong>Note:</strong> Most applications <em>shouldn't</em> use AIDL to
|
||||||
create a bound service, because it may require multithreading capabilities and
|
create a bound service, because it may require multithreading capabilities and
|
||||||
can result in a more complicated implementation. As such, AIDL is not suitable for most applications
|
can result in a more complicated implementation. As such, AIDL is not suitable for
|
||||||
|
most applications
|
||||||
and this document does not discuss how to use it for your service. If you're certain that you need
|
and this document does not discuss how to use it for your service. If you're certain that you need
|
||||||
to use AIDL directly, see the <a href="{@docRoot}guide/components/aidl.html">AIDL</a>
|
to use AIDL directly, see the <a href="{@docRoot}guide/components/aidl.html">AIDL</a>
|
||||||
document.</p>
|
document.</p>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h3 id="Binder">Extending the Binder class</h3>
|
<h3 id="Binder">Extending the Binder class</h3>
|
||||||
|
|
||||||
<p>If your service is used only by the local application and does not need to work across processes,
|
<p>If your service is used only by the local application and does not need to
|
||||||
|
work across processes,
|
||||||
then you can implement your own {@link android.os.Binder} class that provides your client direct
|
then you can implement your own {@link android.os.Binder} class that provides your client direct
|
||||||
access to public methods in the service.</p>
|
access to public methods in the service.</p>
|
||||||
|
|
||||||
@@ -187,13 +200,14 @@ background.</p>
|
|||||||
|
|
||||||
<p>Here's how to set it up:</p>
|
<p>Here's how to set it up:</p>
|
||||||
<ol>
|
<ol>
|
||||||
<li>In your service, create an instance of {@link android.os.Binder} that either:
|
<li>In your service, create an instance of {@link android.os.Binder} that does
|
||||||
|
one of the following:
|
||||||
<ul>
|
<ul>
|
||||||
<li>contains public methods that the client can call</li>
|
<li>Contains public methods that the client can call.</li>
|
||||||
<li>returns the current {@link android.app.Service} instance, which has public methods the
|
<li>Returns the current {@link android.app.Service} instance, which has public methods the
|
||||||
client can call</li>
|
client can call.</li>
|
||||||
<li>or, returns an instance of another class hosted by the service with public methods the
|
<li>Returns an instance of another class hosted by the service with public methods the
|
||||||
client can call</li>
|
client can call.</li>
|
||||||
</ul>
|
</ul>
|
||||||
<li>Return this instance of {@link android.os.Binder} from the {@link
|
<li>Return this instance of {@link android.os.Binder} from the {@link
|
||||||
android.app.Service#onBind onBind()} callback method.</li>
|
android.app.Service#onBind onBind()} callback method.</li>
|
||||||
@@ -202,12 +216,13 @@ android.content.ServiceConnection#onServiceConnected onServiceConnected()} callb
|
|||||||
make calls to the bound service using the methods provided.</li>
|
make calls to the bound service using the methods provided.</li>
|
||||||
</ol>
|
</ol>
|
||||||
|
|
||||||
<p class="note"><strong>Note:</strong> The reason the service and client must be in the same
|
<p class="note"><strong>Note:</strong> The service and client must be in the same
|
||||||
application is so the client can cast the returned object and properly call its APIs. The service
|
application so that the client can cast the returned object and properly call its APIs.
|
||||||
|
The service
|
||||||
and client must also be in the same process, because this technique does not perform any
|
and client must also be in the same process, because this technique does not perform any
|
||||||
marshalling across processes.</p>
|
marshaling across processes.</p>
|
||||||
|
|
||||||
<p>For example, here's a service that provides clients access to methods in the service through
|
<p>For example, here's a service that provides clients with access to methods in the service through
|
||||||
a {@link android.os.Binder} implementation:</p>
|
a {@link android.os.Binder} implementation:</p>
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
@@ -316,32 +331,30 @@ section provides more information about this process of binding to the service.<
|
|||||||
<p class="note"><strong>Note:</strong> In the example above, the
|
<p class="note"><strong>Note:</strong> In the example above, the
|
||||||
{@link android.app.Activity#onStop onStop()} method unbinds the client from the service. Clients
|
{@link android.app.Activity#onStop onStop()} method unbinds the client from the service. Clients
|
||||||
should unbind from services at appropriate times, as discussed in
|
should unbind from services at appropriate times, as discussed in
|
||||||
<a href="#Additional_Notes">Additional Notes</a>.
|
<a href="#Additional_Notes">Additional notes</a>.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>For more sample code, see the <a
|
<p>For more sample code, see the <a
|
||||||
href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/LocalService.html">{@code
|
href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/LocalService.html">
|
||||||
|
{@code
|
||||||
LocalService.java}</a> class and the <a
|
LocalService.java}</a> class and the <a
|
||||||
href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/LocalServiceActivities.html">{@code
|
href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/LocalServiceActivities.html">
|
||||||
|
{@code
|
||||||
LocalServiceActivities.java}</a> class in <a
|
LocalServiceActivities.java}</a> class in <a
|
||||||
href="{@docRoot}resources/samples/ApiDemos/index.html">ApiDemos</a>.</p>
|
href="{@docRoot}resources/samples/ApiDemos/index.html">ApiDemos</a>.</p>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h3 id="Messenger">Using a Messenger</h3>
|
<h3 id="Messenger">Using a Messenger</h3>
|
||||||
|
|
||||||
<div class="sidebox-wrapper">
|
<div class="sidebox-wrapper">
|
||||||
<div class="sidebox">
|
<div class="sidebox">
|
||||||
<h4>Compared to AIDL</h4>
|
<h4>Compared to AIDL</h4>
|
||||||
<p>When you need to perform IPC, using a {@link android.os.Messenger} for your interface is
|
<p>When you need to perform IPC, using a {@link android.os.Messenger} for your interface is
|
||||||
simpler than implementing it with AIDL, because {@link android.os.Messenger} queues
|
simpler than using AIDL, because {@link android.os.Messenger} queues
|
||||||
all calls to the service, whereas, a pure AIDL interface sends simultaneous requests to the
|
all calls to the service. A pure AIDL interface sends simultaneous requests to the
|
||||||
service, which must then handle multi-threading.</p>
|
service, which must then handle multi-threading.</p>
|
||||||
<p>For most applications, the service doesn't need to perform multi-threading, so using a {@link
|
<p>For most applications, the service doesn't need to perform multi-threading, so using a {@link
|
||||||
android.os.Messenger} allows the service to handle one call at a time. If it's important
|
android.os.Messenger} allows the service to handle one call at a time. If it's important
|
||||||
that your service be multi-threaded, then you should use <a
|
that your service be multi-threaded, use <a
|
||||||
href="{@docRoot}guide/components/aidl.html">AIDL</a> to define your interface.</p>
|
href="{@docRoot}guide/components/aidl.html">AIDL</a> to define your interface.</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -352,10 +365,11 @@ you to perform interprocess communication (IPC) without the need to use AIDL.</p
|
|||||||
|
|
||||||
<p>Here's a summary of how to use a {@link android.os.Messenger}:</p>
|
<p>Here's a summary of how to use a {@link android.os.Messenger}:</p>
|
||||||
|
|
||||||
<ul>
|
<ol>
|
||||||
<li>The service implements a {@link android.os.Handler} that receives a callback for each
|
<li>The service implements a {@link android.os.Handler} that receives a callback for each
|
||||||
call from a client.</li>
|
call from a client.</li>
|
||||||
<li>The {@link android.os.Handler} is used to create a {@link android.os.Messenger} object
|
<li>The service uses the {@link android.os.Handler} to create a {@link android.os.Messenger}
|
||||||
|
object
|
||||||
(which is a reference to the {@link android.os.Handler}).</li>
|
(which is a reference to the {@link android.os.Handler}).</li>
|
||||||
<li>The {@link android.os.Messenger} creates an {@link android.os.IBinder} that the service
|
<li>The {@link android.os.Messenger} creates an {@link android.os.IBinder} that the service
|
||||||
returns to clients from {@link android.app.Service#onBind onBind()}.</li>
|
returns to clients from {@link android.app.Service#onBind onBind()}.</li>
|
||||||
@@ -365,11 +379,12 @@ returns to clients from {@link android.app.Service#onBind onBind()}.</li>
|
|||||||
<li>The service receives each {@link android.os.Message} in its {@link
|
<li>The service receives each {@link android.os.Message} in its {@link
|
||||||
android.os.Handler}—specifically, in the {@link android.os.Handler#handleMessage
|
android.os.Handler}—specifically, in the {@link android.os.Handler#handleMessage
|
||||||
handleMessage()} method.</li>
|
handleMessage()} method.</li>
|
||||||
</ul>
|
</ol>
|
||||||
|
|
||||||
|
|
||||||
<p>In this way, there are no "methods" for the client to call on the service. Instead, the
|
<p>In this way, there are no <em>methods</em> for the client to call on the service. Instead, the
|
||||||
client delivers "messages" ({@link android.os.Message} objects) that the service receives in
|
client delivers <em>messages</em> ({@link android.os.Message} objects) that the service
|
||||||
|
receives in
|
||||||
its {@link android.os.Handler}.</p>
|
its {@link android.os.Handler}.</p>
|
||||||
|
|
||||||
<p>Here's a simple example service that uses a {@link android.os.Messenger} interface:</p>
|
<p>Here's a simple example service that uses a {@link android.os.Messenger} interface:</p>
|
||||||
@@ -488,41 +503,42 @@ public class ActivityMessenger extends Activity {
|
|||||||
}
|
}
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
<p>Notice that this example does not show how the service can respond to the client. If you want the
|
<p>Notice that this example does not show how the service can respond to the client.
|
||||||
service to respond, then you need to also create a {@link android.os.Messenger} in the client. Then
|
If you want the
|
||||||
when the client receives the {@link android.content.ServiceConnection#onServiceConnected
|
service to respond, you need to also create a {@link android.os.Messenger} in the client.
|
||||||
|
When the client receives the {@link android.content.ServiceConnection#onServiceConnected
|
||||||
onServiceConnected()} callback, it sends a {@link android.os.Message} to the service that includes
|
onServiceConnected()} callback, it sends a {@link android.os.Message} to the service that includes
|
||||||
the client's {@link android.os.Messenger} in the {@link android.os.Message#replyTo} parameter
|
the client's {@link android.os.Messenger} in the {@link android.os.Message#replyTo} parameter
|
||||||
of the {@link android.os.Messenger#send send()} method.</p>
|
of the {@link android.os.Messenger#send send()} method.</p>
|
||||||
|
|
||||||
<p>You can see an example of how to provide two-way messaging in the <a
|
<p>You can see an example of how to provide two-way messaging in the <a
|
||||||
href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/MessengerService.html">{@code
|
href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/MessengerService.html">
|
||||||
|
{@code
|
||||||
MessengerService.java}</a> (service) and <a
|
MessengerService.java}</a> (service) and <a
|
||||||
href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/MessengerServiceActivities.html">{@code
|
href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/MessengerServiceActivities.html">
|
||||||
|
{@code
|
||||||
MessengerServiceActivities.java}</a> (client) samples.</p>
|
MessengerServiceActivities.java}</a> (client) samples.</p>
|
||||||
|
|
||||||
|
<h2 id="Binding">Binding to a service</h2>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h2 id="Binding">Binding to a Service</h2>
|
|
||||||
|
|
||||||
<p>Application components (clients) can bind to a service by calling
|
<p>Application components (clients) can bind to a service by calling
|
||||||
{@link android.content.Context#bindService bindService()}. The Android
|
{@link android.content.Context#bindService bindService()}. The Android
|
||||||
system then calls the service's {@link android.app.Service#onBind
|
system then calls the service's {@link android.app.Service#onBind
|
||||||
onBind()} method, which returns an {@link android.os.IBinder} for interacting with the service.</p>
|
onBind()} method, which returns an {@link android.os.IBinder} for interacting with
|
||||||
|
the service.</p>
|
||||||
|
|
||||||
<p>The binding is asynchronous. {@link android.content.Context#bindService
|
<p>The binding is asynchronous, and {@link android.content.Context#bindService
|
||||||
bindService()} returns immediately and does <em>not</em> return the {@link android.os.IBinder} to
|
bindService()} returns immediately without <em>not</em> returning the {@link android.os.IBinder} to
|
||||||
the client. To receive the {@link android.os.IBinder}, the client must create an instance of {@link
|
the client. To receive the {@link android.os.IBinder}, the client must create an
|
||||||
|
instance of {@link
|
||||||
android.content.ServiceConnection} and pass it to {@link android.content.Context#bindService
|
android.content.ServiceConnection} and pass it to {@link android.content.Context#bindService
|
||||||
bindService()}. The {@link android.content.ServiceConnection} includes a callback method that the
|
bindService()}. The {@link android.content.ServiceConnection} includes a callback method that the
|
||||||
system calls to deliver the {@link android.os.IBinder}.</p>
|
system calls to deliver the {@link android.os.IBinder}.</p>
|
||||||
|
|
||||||
<p class="note"><strong>Note:</strong> Only activities, services, and content providers can bind
|
<p class="note"><strong>Note:</strong> Only activities, services, and content providers can bind
|
||||||
to a service—you <strong>cannot</strong> bind to a service from a broadcast receiver.</p>
|
to a service—you <strong>can't</strong> bind to a service from a broadcast receiver.</p>
|
||||||
|
|
||||||
<p>So, to bind to a service from your client, you must: </p>
|
<p>To bind to a service from your client, follow these steps: </p>
|
||||||
<ol>
|
<ol>
|
||||||
<li>Implement {@link android.content.ServiceConnection}.
|
<li>Implement {@link android.content.ServiceConnection}.
|
||||||
<p>Your implementation must override two callback methods:</p>
|
<p>Your implementation must override two callback methods:</p>
|
||||||
@@ -533,7 +549,8 @@ the service's {@link android.app.Service#onBind onBind()} method.</dd>
|
|||||||
<dt>{@link android.content.ServiceConnection#onServiceDisconnected
|
<dt>{@link android.content.ServiceConnection#onServiceDisconnected
|
||||||
onServiceDisconnected()}</dt>
|
onServiceDisconnected()}</dt>
|
||||||
<dd>The Android system calls this when the connection to the service is unexpectedly
|
<dd>The Android system calls this when the connection to the service is unexpectedly
|
||||||
lost, such as when the service has crashed or has been killed. This is <em>not</em> called when the
|
lost, such as when the service has crashed or has been killed. This is <em>not</em>
|
||||||
|
called when the
|
||||||
client unbinds.</dd>
|
client unbinds.</dd>
|
||||||
</dl>
|
</dl>
|
||||||
</li>
|
</li>
|
||||||
@@ -548,12 +565,12 @@ android.content.Context#unbindService unbindService()}.
|
|||||||
<p>If your client is still bound to a service when your app destroys the client, destruction
|
<p>If your client is still bound to a service when your app destroys the client, destruction
|
||||||
causes the client to unbind. It is better practice to unbind the client as soon as it is done
|
causes the client to unbind. It is better practice to unbind the client as soon as it is done
|
||||||
interacting with the service. Doing so allows the idle service to shut down. For more information
|
interacting with the service. Doing so allows the idle service to shut down. For more information
|
||||||
about appropriate times to bind and unbind, see <a href="#Additional_Notes">Additional Notes</a>.
|
about appropriate times to bind and unbind, see <a href="#Additional_Notes">Additional notes</a>.
|
||||||
</p>
|
</p>
|
||||||
</li>
|
</li>
|
||||||
</ol>
|
</ol>
|
||||||
|
|
||||||
<p>For example, the following snippet connects the client to the service created above by
|
<p>The following example connects the client to the service created above by
|
||||||
<a href="#Binder">extending the Binder class</a>, so all it must do is cast the returned
|
<a href="#Binder">extending the Binder class</a>, so all it must do is cast the returned
|
||||||
{@link android.os.IBinder} to the {@code LocalService} class and request the {@code
|
{@link android.os.IBinder} to the {@code LocalService} class and request the {@code
|
||||||
LocalService} instance:</p>
|
LocalService} instance:</p>
|
||||||
@@ -579,8 +596,9 @@ private ServiceConnection mConnection = new ServiceConnection() {
|
|||||||
};
|
};
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
<p>With this {@link android.content.ServiceConnection}, the client can bind to a service by passing
|
<p>With this {@link android.content.ServiceConnection}, the client can bind to a service
|
||||||
it to {@link android.content.Context#bindService bindService()}. For example:</p>
|
by passing
|
||||||
|
it to {@link android.content.Context#bindService bindService()}, as shown in the following example:</p>
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
Intent intent = new Intent(this, LocalService.class);
|
Intent intent = new Intent(this, LocalService.class);
|
||||||
@@ -589,11 +607,21 @@ bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
|
|||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<li>The first parameter of {@link android.content.Context#bindService bindService()} is an
|
<li>The first parameter of {@link android.content.Context#bindService bindService()} is an
|
||||||
{@link android.content.Intent} that explicitly names the service to bind (thought the intent
|
{@link android.content.Intent} that explicitly names the service to bind.
|
||||||
could be implicit).</li>
|
<p class="caution"><strong>Caution:</strong> If you use an intent to bind to a
|
||||||
|
{@link android.app.Service}, ensure that your app is secure by using an <a href="{@docRoot}guide/components/intents-filters.html#Types">explicit</a>
|
||||||
|
intent. Using an implicit intent to start a service is a
|
||||||
|
security hazard because you can't be certain what service will respond to the intent,
|
||||||
|
and the user can't see which service starts. Beginning with Android 5.0 (API level 21),
|
||||||
|
the system
|
||||||
|
throws an exception if you call {@link android.content.Context#bindService bindService()}
|
||||||
|
with an implicit intent.</p>
|
||||||
|
</li>
|
||||||
|
|
||||||
<li>The second parameter is the {@link android.content.ServiceConnection} object.</li>
|
<li>The second parameter is the {@link android.content.ServiceConnection} object.</li>
|
||||||
<li>The third parameter is a flag indicating options for the binding. It should usually be {@link
|
<li>The third parameter is a flag indicating options for the binding. It should usually be {@link
|
||||||
android.content.Context#BIND_AUTO_CREATE} in order to create the service if its not already alive.
|
android.content.Context#BIND_AUTO_CREATE} in order to create the service if it's not already
|
||||||
|
alive.
|
||||||
Other possible values are {@link android.content.Context#BIND_DEBUG_UNBIND}
|
Other possible values are {@link android.content.Context#BIND_DEBUG_UNBIND}
|
||||||
and {@link android.content.Context#BIND_NOT_FOREGROUND}, or {@code 0} for none.</li>
|
and {@link android.content.Context#BIND_NOT_FOREGROUND}, or {@code 0} for none.</li>
|
||||||
</ul>
|
</ul>
|
||||||
@@ -606,10 +634,11 @@ and {@link android.content.Context#BIND_NOT_FOREGROUND}, or {@code 0} for none.<
|
|||||||
<li>You should always trap {@link android.os.DeadObjectException} exceptions, which are thrown
|
<li>You should always trap {@link android.os.DeadObjectException} exceptions, which are thrown
|
||||||
when the connection has broken. This is the only exception thrown by remote methods.</li>
|
when the connection has broken. This is the only exception thrown by remote methods.</li>
|
||||||
<li>Objects are reference counted across processes. </li>
|
<li>Objects are reference counted across processes. </li>
|
||||||
<li>You should usually pair the binding and unbinding during
|
<li>You usually pair the binding and unbinding during
|
||||||
matching bring-up and tear-down moments of the client's lifecycle. For example:
|
matching bring-up and tear-down moments of the client's lifecycle, as described in the
|
||||||
|
following examples:
|
||||||
<ul>
|
<ul>
|
||||||
<li>If you only need to interact with the service while your activity is visible, you
|
<li>If you need to interact with the service only while your activity is visible, you
|
||||||
should bind during {@link android.app.Activity#onStart onStart()} and unbind during {@link
|
should bind during {@link android.app.Activity#onStart onStart()} and unbind during {@link
|
||||||
android.app.Activity#onStop onStop()}.</li>
|
android.app.Activity#onStop onStop()}.</li>
|
||||||
<li>If you want your activity to receive responses even while it is stopped in the
|
<li>If you want your activity to receive responses even while it is stopped in the
|
||||||
@@ -619,33 +648,34 @@ activity needs to use the service the entire time it's running (even in the back
|
|||||||
the service is in another process, then you increase the weight of the process and it becomes
|
the service is in another process, then you increase the weight of the process and it becomes
|
||||||
more likely that the system will kill it.</li>
|
more likely that the system will kill it.</li>
|
||||||
</ul>
|
</ul>
|
||||||
<p class="note"><strong>Note:</strong> You should usually <strong>not</strong> bind and unbind
|
<p class="note"><strong>Note:</strong> You <em>don't</em> usually bind and unbind
|
||||||
during your activity's {@link android.app.Activity#onResume onResume()} and {@link
|
during your activity's {@link android.app.Activity#onResume onResume()} and {@link
|
||||||
android.app.Activity#onPause onPause()}, because these callbacks occur at every lifecycle transition
|
android.app.Activity#onPause onPause()}, because these callbacks occur at every
|
||||||
|
lifecycle transition
|
||||||
and you should keep the processing that occurs at these transitions to a minimum. Also, if
|
and you should keep the processing that occurs at these transitions to a minimum. Also, if
|
||||||
multiple activities in your application bind to the same service and there is a transition between
|
multiple activities in your application bind to the same service and there is a
|
||||||
two of those activities, the service may be destroyed and recreated as the current activity unbinds
|
transition between
|
||||||
(during pause) before the next one binds (during resume). (This activity transition for how
|
two of those activities, the service may be destroyed and recreated as the current
|
||||||
|
activity unbinds
|
||||||
|
(during pause) before the next one binds (during resume). This activity transition for how
|
||||||
activities coordinate their lifecycles is described in the <a
|
activities coordinate their lifecycles is described in the <a
|
||||||
href="{@docRoot}guide/components/activities.html#CoordinatingActivities">Activities</a>
|
href="{@docRoot}guide/components/activities.html#CoordinatingActivities">Activities</a>
|
||||||
document.)</p>
|
document.</p>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<p>For more sample code, showing how to bind to a service, see the <a
|
<p>For more sample code, showing how to bind to a service, see the <a
|
||||||
href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/RemoteService.html">{@code
|
href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/RemoteService.html">
|
||||||
|
{@code
|
||||||
RemoteService.java}</a> class in <a
|
RemoteService.java}</a> class in <a
|
||||||
href="{@docRoot}resources/samples/ApiDemos/index.html">ApiDemos</a>.</p>
|
href="{@docRoot}resources/samples/ApiDemos/index.html">ApiDemos</a>.</p>
|
||||||
|
|
||||||
|
<h2 id="Lifecycle">Managing the lifecycle of a bound service</h2>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h2 id="Lifecycle">Managing the Lifecycle of a Bound Service</h2>
|
|
||||||
|
|
||||||
<p>When a service is unbound from all clients, the Android system destroys it (unless it was also
|
<p>When a service is unbound from all clients, the Android system destroys it (unless it was also
|
||||||
started with {@link android.app.Service#onStartCommand onStartCommand()}). As such, you don't have
|
started with {@link android.app.Service#onStartCommand onStartCommand()}). As such, you don't have
|
||||||
to manage the lifecycle of your service if it's purely a bound
|
to manage the lifecycle of your service if it's purely a bound
|
||||||
service—the Android system manages it for you based on whether it is bound to any clients.</p>
|
service—the Android system manages it for you based on whether it is bound to
|
||||||
|
any clients.</p>
|
||||||
|
|
||||||
<p>However, if you choose to implement the {@link android.app.Service#onStartCommand
|
<p>However, if you choose to implement the {@link android.app.Service#onStartCommand
|
||||||
onStartCommand()} callback method, then you must explicitly stop the service, because the
|
onStartCommand()} callback method, then you must explicitly stop the service, because the
|
||||||
@@ -660,17 +690,11 @@ your {@link android.app.Service#onUnbind onUnbind()} method, you can optionally
|
|||||||
onRebind()} the next time a client binds to the service. {@link android.app.Service#onRebind
|
onRebind()} the next time a client binds to the service. {@link android.app.Service#onRebind
|
||||||
onRebind()} returns void, but the client still receives the {@link android.os.IBinder} in its
|
onRebind()} returns void, but the client still receives the {@link android.os.IBinder} in its
|
||||||
{@link android.content.ServiceConnection#onServiceConnected onServiceConnected()} callback.
|
{@link android.content.ServiceConnection#onServiceConnected onServiceConnected()} callback.
|
||||||
Below, figure 1 illustrates the logic for this kind of lifecycle.</p>
|
The following figure illustrates the logic for this kind of lifecycle.</p>
|
||||||
|
|
||||||
|
|
||||||
<img src="{@docRoot}images/fundamentals/service_binding_tree_lifecycle.png" alt="" />
|
<img src="{@docRoot}images/fundamentals/service_binding_tree_lifecycle.png" alt="" />
|
||||||
<p class="img-caption"><strong>Figure 1.</strong> The lifecycle for a service that is started
|
<p class="img-caption"><strong>Figure 1.</strong> The lifecycle for a service that is started
|
||||||
and also allows binding.</p>
|
and also allows binding.</p>
|
||||||
|
|
||||||
|
|
||||||
<p>For more information about the lifecycle of a started service, see the <a
|
<p>For more information about the lifecycle of a started service, see the <a
|
||||||
href="{@docRoot}guide/components/services.html#Lifecycle">Services</a> document.</p>
|
href="{@docRoot}guide/components/services.html#Lifecycle">Services</a> document.</p>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -6,28 +6,29 @@ page.title=Application Fundamentals
|
|||||||
|
|
||||||
<h2>In this document</h2>
|
<h2>In this document</h2>
|
||||||
<ol>
|
<ol>
|
||||||
<li><a href="#Components">App Components</a>
|
<li><a href="#Components">App components</a>
|
||||||
<ol>
|
<ol>
|
||||||
<li><a href="#ActivatingComponents">Activating components</a></li>
|
<li><a href="#ActivatingComponents">Activating components</a></li>
|
||||||
</ol>
|
</ol>
|
||||||
</li>
|
</li>
|
||||||
<li><a href="#Manifest">The Manifest File</a>
|
<li><a href="#Manifest">The manifest file</a>
|
||||||
<ol>
|
<ol>
|
||||||
<li><a href="#DeclaringComponents">Declaring components</a></li>
|
<li><a href="#DeclaringComponents">Declaring components</a></li>
|
||||||
<li><a href="#DeclaringRequirements">Declaring app requirements</a></li>
|
<li><a href="#DeclaringRequirements">Declaring app requirements</a></li>
|
||||||
</ol>
|
</ol>
|
||||||
</li>
|
</li>
|
||||||
<li><a href="#Resources">App Resources</a></li>
|
<li><a href="#Resources">App resources</a></li>
|
||||||
</ol>
|
</ol>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p>Android apps are written in the Java programming language. The Android SDK tools compile
|
<p>Android apps are written in the Java programming language. The Android SDK tools compile
|
||||||
your code—along with any data and resource files—into an APK: an <i>Android package</i>,
|
your code along with any data and resource files into an APK, an <i>Android package</i>,
|
||||||
which is an archive file with an {@code .apk} suffix. One APK file contains all the contents
|
which is an archive file with an {@code .apk} suffix. One APK file contains all the contents
|
||||||
of an Android app and is the file that Android-powered devices use to install the app.</p>
|
of an Android app and is the file that Android-powered devices use to install the app.</p>
|
||||||
|
|
||||||
<p>Once installed on a device, each Android app lives in its own security sandbox: </p>
|
<p>Each Android app lives in its own security sandbox, protected by
|
||||||
|
the following Android security features: </p>
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<li>The Android operating system is a multi-user Linux system in which each app is a
|
<li>The Android operating system is a multi-user Linux system in which each app is a
|
||||||
@@ -40,54 +41,61 @@ app so that only the user ID assigned to that app can access them. </li>
|
|||||||
<li>Each process has its own virtual machine (VM), so an app's code runs in isolation from
|
<li>Each process has its own virtual machine (VM), so an app's code runs in isolation from
|
||||||
other apps.</li>
|
other apps.</li>
|
||||||
|
|
||||||
<li>By default, every app runs in its own Linux process. Android starts the process when any
|
<li>By default, every app runs in its own Linux process. The Android system starts
|
||||||
of the app's components need to be executed, then shuts down the process when it's no longer
|
the process when any
|
||||||
|
of the app's components need to be executed, and then shuts down the process
|
||||||
|
when it's no longer
|
||||||
needed or when the system must recover memory for other apps.</li>
|
needed or when the system must recover memory for other apps.</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<p>In this way, the Android system implements the <em>principle of least privilege</em>. That is,
|
<p>The Android system implements the <em>principle of least privilege</em>. That is,
|
||||||
each app, by default, has access only to the components that it requires to do its work and
|
each app, by default, has access only to the components that it requires to do its work and
|
||||||
no more. This creates a very secure environment in which an app cannot access parts of
|
no more. This creates a very secure environment in which an app cannot access parts of
|
||||||
the system for which it is not given permission.</p>
|
the system for which it is not given permission. However, there are ways for an app to share
|
||||||
|
data with other apps and for an
|
||||||
<p>However, there are ways for an app to share data with other apps and for an
|
|
||||||
app to access system services:</p>
|
app to access system services:</p>
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<li>It's possible to arrange for two apps to share the same Linux user ID, in which case
|
<li>It's possible to arrange for two apps to share the same Linux user ID, in which case
|
||||||
they are able to access each other's files. To conserve system resources, apps with the
|
they are able to access each other's files. To conserve system resources, apps with the
|
||||||
same user ID can also arrange to run in the same Linux process and share the same VM (the
|
same user ID can also arrange to run in the same Linux process and share the same VM. The
|
||||||
apps must also be signed with the same certificate).</li>
|
apps must also be signed with the same certificate.</li>
|
||||||
<li>An app can request permission to access device data such as the user's
|
<li>An app can request permission to access device data such as the user's
|
||||||
contacts, SMS messages, the mountable storage (SD card), camera, Bluetooth, and more. The user has
|
contacts, SMS messages, the mountable storage (SD card), camera, and Bluetooth. The user has
|
||||||
to explicitly grant these permissions. For more information, see
|
to explicitly grant these permissions. For more information, see
|
||||||
<a href="{@docRoot}training/permissions/index.html">Working with System Permissions</a>.</li>
|
<a href="{@docRoot}training/permissions/index.html">Working with System Permissions</a>.</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<p>That covers the basics regarding how an Android app exists within the system. The rest of
|
<p>The rest of this document introduces the following concepts:</p>
|
||||||
this document introduces you to:</p>
|
|
||||||
<ul>
|
<ul>
|
||||||
<li>The core framework components that define your app.</li>
|
<li>The core framework components that define your app.</li>
|
||||||
<li>The manifest file in which you declare components and required device features for your
|
<li>The manifest file in which you declare the components and the required device
|
||||||
|
features for your
|
||||||
app.</li>
|
app.</li>
|
||||||
<li>Resources that are separate from the app code and allow your app to
|
<li>Resources that are separate from the app code and that allow your app to
|
||||||
gracefully optimize its behavior for a variety of device configurations.</li>
|
gracefully optimize its behavior for a variety of device configurations.</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h2 id="Components">App Components</h2>
|
<h2 id="Components">App components</h2>
|
||||||
|
|
||||||
<p>App components are the essential building blocks of an Android app. Each
|
<p>App components are the essential building blocks of an Android app. Each
|
||||||
component is a different point through which the system can enter your app. Not all
|
component is a different point through which the system can enter your app. Not all
|
||||||
components are actual entry points for the user and some depend on each other, but each one exists
|
components are actual entry points for the user and some depend on each other,
|
||||||
as its own entity and plays a specific role—each one is a unique building block that
|
but each one exists
|
||||||
helps define your app's overall behavior.</p>
|
as its own entity and plays a specific role.</p>
|
||||||
|
|
||||||
<p>There are four different types of app components. Each type serves a distinct purpose
|
<p>There are four different types of app components:
|
||||||
and has a distinct lifecycle that defines how the component is created and destroyed.</p>
|
<ul>
|
||||||
|
<li>Activities.</li>
|
||||||
<p>Here are the four types of app components:</p>
|
<li>Services.</li>
|
||||||
|
<li>Content providers.</li>
|
||||||
|
<li>Broadcast receivers.</li>
|
||||||
|
</ul></p>
|
||||||
|
Each type serves a distinct purpose
|
||||||
|
and has a distinct lifecycle that defines how the component is created and destroyed.
|
||||||
|
The following sections describe the four types of app components.</p>
|
||||||
|
|
||||||
<dl>
|
<dl>
|
||||||
|
|
||||||
@@ -98,11 +106,12 @@ an email app might have one activity that shows a list of new
|
|||||||
emails, another activity to compose an email, and another activity for reading emails. Although
|
emails, another activity to compose an email, and another activity for reading emails. Although
|
||||||
the activities work together to form a cohesive user experience in the email app, each one
|
the activities work together to form a cohesive user experience in the email app, each one
|
||||||
is independent of the others. As such, a different app can start any one of these
|
is independent of the others. As such, a different app can start any one of these
|
||||||
activities (if the email app allows it). For example, a camera app can start the
|
activities if the email app allows it. For example, a camera app can start the
|
||||||
activity in the email app that composes new mail, in order for the user to share a picture.
|
activity in the email app that composes new mail to allow the user to share a picture.
|
||||||
|
|
||||||
<p>An activity is implemented as a subclass of {@link android.app.Activity} and you can learn more
|
<p>An activity is implemented as a subclass of {@link android.app.Activity}. You can learn more
|
||||||
about it in the <a href="{@docRoot}guide/components/activities.html">Activities</a>
|
about {@link android.app.Activity} in the
|
||||||
|
<a href="{@docRoot}guide/components/activities.html">Activities</a>
|
||||||
developer guide.</p>
|
developer guide.</p>
|
||||||
</dd>
|
</dd>
|
||||||
|
|
||||||
@@ -111,13 +120,16 @@ developer guide.</p>
|
|||||||
|
|
||||||
<dd>A <i>service</i> is a component that runs in the background to perform long-running
|
<dd>A <i>service</i> is a component that runs in the background to perform long-running
|
||||||
operations or to perform work for remote processes. A service
|
operations or to perform work for remote processes. A service
|
||||||
does not provide a user interface. For example, a service might play music in the background while
|
does not provide a user interface. For example, a service might play music in the
|
||||||
|
background while
|
||||||
the user is in a different app, or it might fetch data over the network without
|
the user is in a different app, or it might fetch data over the network without
|
||||||
blocking user interaction with an activity. Another component, such as an activity, can start the
|
blocking user interaction with an activity. Another component, such as an activity,
|
||||||
|
can start the
|
||||||
service and let it run or bind to it in order to interact with it.
|
service and let it run or bind to it in order to interact with it.
|
||||||
|
|
||||||
<p>A service is implemented as a subclass of {@link android.app.Service} and you can learn more
|
<p>A service is implemented as a subclass of {@link android.app.Service}. You can learn more
|
||||||
about it in the <a href="{@docRoot}guide/components/services.html">Services</a> developer
|
about {@link android.app.Service} in the <a href="{@docRoot}guide/components/services.html">
|
||||||
|
Services</a> developer
|
||||||
guide.</p>
|
guide.</p>
|
||||||
</dd>
|
</dd>
|
||||||
|
|
||||||
@@ -125,12 +137,14 @@ guide.</p>
|
|||||||
<dt><b>Content providers</b></dt>
|
<dt><b>Content providers</b></dt>
|
||||||
|
|
||||||
<dd>A <i>content provider</i> manages a shared set of app data. You can store the data in
|
<dd>A <i>content provider</i> manages a shared set of app data. You can store the data in
|
||||||
the file system, an SQLite database, on the web, or any other persistent storage location your
|
the file system, in a SQLite database, on the web, or on any other persistent storage
|
||||||
app can access. Through the content provider, other apps can query or even modify
|
location that your
|
||||||
the data (if the content provider allows it). For example, the Android system provides a content
|
app can access. Through the content provider, other apps can query or modify
|
||||||
|
the data if the content provider allows it. For example, the Android system provides a content
|
||||||
provider that manages the user's contact information. As such, any app with the proper
|
provider that manages the user's contact information. As such, any app with the proper
|
||||||
permissions can query part of the content provider (such as {@link
|
permissions can query part of the content provider, such as {@link
|
||||||
android.provider.ContactsContract.Data}) to read and write information about a particular person.
|
android.provider.ContactsContract.Data}, to read and write information about
|
||||||
|
a particular person.
|
||||||
|
|
||||||
<p>Content providers are also useful for reading and writing data that is private to your
|
<p>Content providers are also useful for reading and writing data that is private to your
|
||||||
app and not shared. For example, the <a
|
app and not shared. For example, the <a
|
||||||
@@ -148,15 +162,17 @@ guide.</p>
|
|||||||
<dt><b>Broadcast receivers</b></dt>
|
<dt><b>Broadcast receivers</b></dt>
|
||||||
|
|
||||||
<dd>A <i>broadcast receiver</i> is a component that responds to system-wide broadcast
|
<dd>A <i>broadcast receiver</i> is a component that responds to system-wide broadcast
|
||||||
announcements. Many broadcasts originate from the system—for example, a broadcast announcing
|
announcements. Many broadcasts originate from the system—for example,
|
||||||
|
a broadcast announcing
|
||||||
that the screen has turned off, the battery is low, or a picture was captured.
|
that the screen has turned off, the battery is low, or a picture was captured.
|
||||||
Apps can also initiate broadcasts—for example, to let other apps know that
|
Apps can also initiate broadcasts—for example, to let other apps know that
|
||||||
some data has been downloaded to the device and is available for them to use. Although broadcast
|
some data has been downloaded to the device and is available for them to use.
|
||||||
|
Although broadcast
|
||||||
receivers don't display a user interface, they may <a
|
receivers don't display a user interface, they may <a
|
||||||
href="{@docRoot}guide/topics/ui/notifiers/notifications.html">create a status bar notification</a>
|
href="{@docRoot}guide/topics/ui/notifiers/notifications.html">create a status bar notification</a>
|
||||||
to alert the user when a broadcast event occurs. More commonly, though, a broadcast receiver is
|
to alert the user when a broadcast event occurs. More commonly, though, a broadcast receiver is
|
||||||
just a "gateway" to other components and is intended to do a very minimal amount of work. For
|
just a <em>gateway</em> to other components and is intended to do a very minimal amount of work.
|
||||||
instance, it might initiate a service to perform some work based on the event.
|
For instance, it might initiate a service to perform some work based on the event.
|
||||||
|
|
||||||
<p>A broadcast receiver is implemented as a subclass of {@link android.content.BroadcastReceiver}
|
<p>A broadcast receiver is implemented as a subclass of {@link android.content.BroadcastReceiver}
|
||||||
and each broadcast is delivered as an {@link android.content.Intent} object. For more information,
|
and each broadcast is delivered as an {@link android.content.Intent} object. For more information,
|
||||||
@@ -170,52 +186,59 @@ see the {@link android.content.BroadcastReceiver} class.</p>
|
|||||||
<p>A unique aspect of the Android system design is that any app can start another
|
<p>A unique aspect of the Android system design is that any app can start another
|
||||||
app’s component. For example, if you want the user to capture a
|
app’s component. For example, if you want the user to capture a
|
||||||
photo with the device camera, there's probably another app that does that and your
|
photo with the device camera, there's probably another app that does that and your
|
||||||
app can use it, instead of developing an activity to capture a photo yourself. You don't
|
app can use it instead of developing an activity to capture a photo yourself. You don't
|
||||||
need to incorporate or even link to the code from the camera app.
|
need to incorporate or even link to the code from the camera app.
|
||||||
Instead, you can simply start the activity in the camera app that captures a
|
Instead, you can simply start the activity in the camera app that captures a
|
||||||
photo. When complete, the photo is even returned to your app so you can use it. To the user,
|
photo. When complete, the photo is even returned to your app so you can use it. To the user,
|
||||||
it seems as if the camera is actually a part of your app.</p>
|
it seems as if the camera is actually a part of your app.</p>
|
||||||
|
|
||||||
<p>When the system starts a component, it starts the process for that app (if it's not
|
<p>When the system starts a component, it starts the process for that app if it's not
|
||||||
already running) and instantiates the classes needed for the component. For example, if your
|
already running and instantiates the classes needed for the component. For example, if your
|
||||||
app starts the activity in the camera app that captures a photo, that activity
|
app starts the activity in the camera app that captures a photo, that activity
|
||||||
runs in the process that belongs to the camera app, not in your app's process.
|
runs in the process that belongs to the camera app, not in your app's process.
|
||||||
Therefore, unlike apps on most other systems, Android apps don't have a single entry
|
Therefore, unlike apps on most other systems, Android apps don't have a single entry
|
||||||
point (there's no {@code main()} function, for example).</p>
|
point (there's no {@code main()} function).</p>
|
||||||
|
|
||||||
<p>Because the system runs each app in a separate process with file permissions that
|
<p>Because the system runs each app in a separate process with file permissions that
|
||||||
restrict access to other apps, your app cannot directly activate a component from
|
restrict access to other apps, your app cannot directly activate a component from
|
||||||
another app. The Android system, however, can. So, to activate a component in
|
another app. However, the Android system can. To activate a component in
|
||||||
another app, you must deliver a message to the system that specifies your <em>intent</em> to
|
another app, deliver a message to the system that specifies your <em>intent</em> to
|
||||||
start a particular component. The system then activates the component for you.</p>
|
start a particular component. The system then activates the component for you.</p>
|
||||||
|
|
||||||
|
|
||||||
<h3 id="ActivatingComponents">Activating Components</h3>
|
<h3 id="ActivatingComponents">Activating components</h3>
|
||||||
|
|
||||||
<p>Three of the four component types—activities, services, and
|
<p>Three of the four component types—activities, services, and
|
||||||
broadcast receivers—are activated by an asynchronous message called an <em>intent</em>.
|
broadcast receivers—are activated by an asynchronous message called an <em>intent</em>.
|
||||||
Intents bind individual components to each other at runtime (you can think of them
|
Intents bind individual components to each other at runtime. You can think of them
|
||||||
as the messengers that request an action from other components), whether the component belongs
|
as the messengers that request an action from other components, whether the component belongs
|
||||||
to your app or another.</p>
|
to your app or another.</p>
|
||||||
|
|
||||||
<p>An intent is created with an {@link android.content.Intent} object, which defines a message to
|
<p class="note"><strong>Note:</strong> If your app targets Android 5.0 (API level 21) or later,
|
||||||
activate either a specific component or a specific <em>type</em> of component—an intent
|
use the {@link android.app.job.JobScheduler} to execute background
|
||||||
can be either explicit or implicit, respectively.</p>
|
services. For more information about using this class, see the
|
||||||
|
{@link android.app.job.JobScheduler} reference documentation.</p>
|
||||||
|
|
||||||
<p>For activities and services, an intent defines the action to perform (for example, to "view" or
|
<p>An intent is created with an {@link android.content.Intent} object, which defines a message to
|
||||||
"send" something) and may specify the URI of the data to act on (among other things that the
|
activate either a specific component (explicit intent) or a specific <em>type</em> of component
|
||||||
component being started might need to know). For example, an intent might convey a request for an
|
(implicit intent).</p>
|
||||||
|
|
||||||
|
<p>For activities and services, an intent defines the action to perform (for example, to
|
||||||
|
<em>view</em> or
|
||||||
|
<em>send</em> something) and may specify the URI of the data to act on, among other things that the
|
||||||
|
component being started might need to know. For example, an intent might convey a request for an
|
||||||
activity to show an image or to open a web page. In some cases, you can start an
|
activity to show an image or to open a web page. In some cases, you can start an
|
||||||
activity to receive a result, in which case, the activity also returns
|
activity to receive a result, in which case the activity also returns
|
||||||
the result in an {@link android.content.Intent} (for example, you can issue an intent to let
|
the result in an {@link android.content.Intent}. For example, you can issue an intent to let
|
||||||
the user pick a personal contact and have it returned to you—the return intent includes a
|
the user pick a personal contact and have it returned to you. The return intent includes a
|
||||||
URI pointing to the chosen contact).</p>
|
URI pointing to the chosen contact.</p>
|
||||||
|
|
||||||
<p>For broadcast receivers, the intent simply defines the
|
<p>For broadcast receivers, the intent simply defines the
|
||||||
announcement being broadcast (for example, a broadcast to indicate the device battery is low
|
announcement being broadcast. For example, a broadcast to indicate the device battery is low
|
||||||
includes only a known action string that indicates "battery is low").</p>
|
includes only a known action string that indicates <em>battery is low</em>.</p>
|
||||||
|
|
||||||
<p>The other component type, content provider, is not activated by intents. Rather, it is
|
<p>Unlike activities, services, and broadcast receivers, content providers are not activated
|
||||||
|
by intents. Rather, they are
|
||||||
activated when targeted by a request from a {@link android.content.ContentResolver}. The content
|
activated when targeted by a request from a {@link android.content.ContentResolver}. The content
|
||||||
resolver handles all direct transactions with the content provider so that the component that's
|
resolver handles all direct transactions with the content provider so that the component that's
|
||||||
performing transactions with the provider doesn't need to and instead calls methods on the {@link
|
performing transactions with the provider doesn't need to and instead calls methods on the {@link
|
||||||
@@ -224,15 +247,19 @@ provider and the component requesting information (for security).</p>
|
|||||||
|
|
||||||
<p>There are separate methods for activating each type of component:</p>
|
<p>There are separate methods for activating each type of component:</p>
|
||||||
<ul>
|
<ul>
|
||||||
<li>You can start an activity (or give it something new to do) by
|
<li>You can start an activity or give it something new to do by
|
||||||
passing an {@link android.content.Intent} to {@link android.content.Context#startActivity
|
passing an {@link android.content.Intent} to {@link android.content.Context#startActivity
|
||||||
startActivity()} or {@link android.app.Activity#startActivityForResult startActivityForResult()}
|
startActivity()} or {@link android.app.Activity#startActivityForResult startActivityForResult()}
|
||||||
(when you want the activity to return a result).</li>
|
(when you want the activity to return a result).</li>
|
||||||
<li>You can start a service (or give new instructions to an ongoing service) by
|
|
||||||
|
|
||||||
|
<li>With Android 5.0 (API level 21) and later, you can start a service with
|
||||||
|
{@link android.app.job.JobScheduler}. For earlier Android versions, you can start
|
||||||
|
a service (or give new instructions to an ongoing service) by
|
||||||
passing an {@link android.content.Intent} to {@link android.content.Context#startService
|
passing an {@link android.content.Intent} to {@link android.content.Context#startService
|
||||||
startService()}. Or you can bind to the service by passing an {@link android.content.Intent} to
|
startService()}. You can bind to the service by passing an {@link android.content.Intent} to
|
||||||
{@link android.content.Context#bindService bindService()}.</li>
|
{@link android.content.Context#bindService bindService()}. </li>
|
||||||
<li>You can initiate a broadcast by passing an {@link android.content.Intent} to methods like
|
<li>You can initiate a broadcast by passing an {@link android.content.Intent} to methods such as
|
||||||
{@link android.content.Context#sendBroadcast(Intent) sendBroadcast()}, {@link
|
{@link android.content.Context#sendBroadcast(Intent) sendBroadcast()}, {@link
|
||||||
android.content.Context#sendOrderedBroadcast(Intent, String) sendOrderedBroadcast()}, or {@link
|
android.content.Context#sendOrderedBroadcast(Intent, String) sendOrderedBroadcast()}, or {@link
|
||||||
android.content.Context#sendStickyBroadcast sendStickyBroadcast()}.</li>
|
android.content.Context#sendStickyBroadcast sendStickyBroadcast()}.</li>
|
||||||
@@ -242,35 +269,35 @@ android.content.ContentProvider#query query()} on a {@link android.content.Conte
|
|||||||
|
|
||||||
<p>For more information about using intents, see the <a
|
<p>For more information about using intents, see the <a
|
||||||
href="{@docRoot}guide/components/intents-filters.html">Intents and
|
href="{@docRoot}guide/components/intents-filters.html">Intents and
|
||||||
Intent Filters</a> document. More information about activating specific components is also provided
|
Intent Filters</a> document.
|
||||||
in the following documents: <a
|
The following documents provide more information about activating specifc components:
|
||||||
href="{@docRoot}guide/components/activities.html">Activities</a>, <a
|
<a href="{@docRoot}guide/components/activities.html">Activities</a>,
|
||||||
href="{@docRoot}guide/components/services.html">Services</a>, {@link
|
<a href="{@docRoot}guide/components/services.html">Services
|
||||||
android.content.BroadcastReceiver} and <a
|
{@link android.content.BroadcastReceiver}, and
|
||||||
href="{@docRoot}guide/topics/providers/content-providers.html">Content Providers</a>.</p>
|
<a ref="{@docRoot}guide/topics/providers/content-providers.html">Content Providers</a>.</p>
|
||||||
|
|
||||||
|
<h2 id="Manifest">The manifest file</h2>
|
||||||
<h2 id="Manifest">The Manifest File</h2>
|
|
||||||
|
|
||||||
<p>Before the Android system can start an app component, the system must know that the
|
<p>Before the Android system can start an app component, the system must know that the
|
||||||
component exists by reading the app's {@code AndroidManifest.xml} file (the "manifest"
|
component exists by reading the app's <em>manifest file</em>, {@code AndroidManifest.xml}.
|
||||||
file). Your app must declare all its components in this file, which must be at the root of
|
Your app must declare all its components in this file, which must be at the root of the
|
||||||
the app project directory.</p>
|
app project directory.</p>
|
||||||
|
|
||||||
<p>The manifest does a number of things in addition to declaring the app's components,
|
<p>The manifest does a number of things in addition to declaring the app's components,
|
||||||
such as:</p>
|
such as the following:</p>
|
||||||
<ul>
|
<ul>
|
||||||
<li>Identify any user permissions the app requires, such as Internet access or
|
<li>Identifies any user permissions the app requires, such as Internet access or
|
||||||
read-access to the user's contacts.</li>
|
read-access to the user's contacts.</li>
|
||||||
<li>Declare the minimum <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#ApiLevels">API Level</a>
|
<li>Declares the minimum
|
||||||
|
<a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#ApiLevels">API Level</a>
|
||||||
required by the app, based on which APIs the app uses.</li>
|
required by the app, based on which APIs the app uses.</li>
|
||||||
<li>Declare hardware and software features used or required by the app, such as a camera,
|
<li>Declares hardware and software features used or required by the app, such as a camera,
|
||||||
bluetooth services, or a multitouch screen.</li>
|
bluetooth services, or a multitouch screen.</li>
|
||||||
<li>API libraries the app needs to be linked against (other than the Android framework
|
<li>Declares API libraries the app needs to be linked against (other than the Android framework
|
||||||
APIs), such as the <a
|
APIs), such as the <a
|
||||||
href="http://code.google.com/android/add-ons/google-apis/maps-overview.html">Google Maps
|
href="http://code.google.com/android/add-ons/google-apis/maps-overview.html">
|
||||||
library</a>.</li>
|
Google Maps library</a>.</li>
|
||||||
<li>And more</li>
|
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
|
||||||
@@ -301,47 +328,59 @@ the {@code android:name} attribute specifies the fully qualified class name of t
|
|||||||
android.app.Activity} subclass and the {@code android:label} attribute specifies a string
|
android.app.Activity} subclass and the {@code android:label} attribute specifies a string
|
||||||
to use as the user-visible label for the activity.</p>
|
to use as the user-visible label for the activity.</p>
|
||||||
|
|
||||||
<p>You must declare all app components this way:</p>
|
<p>You must declare all app components using the following elements:</p>
|
||||||
<ul>
|
<ul>
|
||||||
<li><code><a
|
<li><code><a
|
||||||
href="{@docRoot}guide/topics/manifest/activity-element.html"><activity></a></code> elements
|
href="{@docRoot}guide/topics/manifest/activity-element.html"><activity></a></code> elements
|
||||||
for activities</li>
|
for activities.</li>
|
||||||
<li><code><a
|
<li><code><a
|
||||||
href="{@docRoot}guide/topics/manifest/service-element.html"><service></a></code> elements for
|
href="{@docRoot}guide/topics/manifest/service-element.html"><service></a></code> elements for
|
||||||
services</li>
|
services.</li>
|
||||||
<li><code><a
|
<li><code><a
|
||||||
href="{@docRoot}guide/topics/manifest/receiver-element.html"><receiver></a></code> elements
|
href="{@docRoot}guide/topics/manifest/receiver-element.html"><receiver></a></code> elements
|
||||||
for broadcast receivers</li>
|
for broadcast receivers.</li>
|
||||||
<li><code><a
|
<li><code><a
|
||||||
href="{@docRoot}guide/topics/manifest/provider-element.html"><provider></a></code> elements
|
href="{@docRoot}guide/topics/manifest/provider-element.html"><provider></a></code> elements
|
||||||
for content providers</li>
|
for content providers.</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<p>Activities, services, and content providers that you include in your source but do not declare
|
<p>Activities, services, and content providers that you include in your source but do not declare
|
||||||
in the manifest are not visible to the system and, consequently, can never run. However,
|
in the manifest are not visible to the system and, consequently, can never run. However,
|
||||||
broadcast
|
broadcast
|
||||||
receivers can be either declared in the manifest or created dynamically in code (as
|
receivers can be either declared in the manifest or created dynamically in code as
|
||||||
{@link android.content.BroadcastReceiver} objects) and registered with the system by calling
|
{@link android.content.BroadcastReceiver} objects and registered with the system by calling
|
||||||
{@link android.content.Context#registerReceiver registerReceiver()}.</p>
|
{@link android.content.Context#registerReceiver registerReceiver()}.</p>
|
||||||
|
|
||||||
<p>For more about how to structure the manifest file for your app, see <a
|
<p>For more about how to structure the manifest file for your app, see <a
|
||||||
href="{@docRoot}guide/topics/manifest/manifest-intro.html">The AndroidManifest.xml File</a>
|
href="{@docRoot}guide/topics/manifest/manifest-intro.html">The AndroidManifest.xml File</a>
|
||||||
documentation. </p>
|
documentation. </p>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h3 id="DeclaringComponentCapabilities">Declaring component capabilities</h3>
|
<h3 id="DeclaringComponentCapabilities">Declaring component capabilities</h3>
|
||||||
|
|
||||||
<p>As discussed above, in <a href="#ActivatingComponents">Activating Components</a>, you can use an
|
<p>As discussed above, in <a href="#ActivatingComponents">Activating components</a>, you can use an
|
||||||
{@link android.content.Intent} to start activities, services, and broadcast receivers. You can do so
|
{@link android.content.Intent} to start activities, services, and broadcast receivers.
|
||||||
by explicitly naming the target component (using the component class name) in the intent. However,
|
|
||||||
the real power of intents lies in the concept of <em>implicit intents</em>. An implicit intent
|
|
||||||
simply describes the type of action to perform (and, optionally, the data upon which you’d like to
|
|
||||||
perform the action) and allows the system to find a component on the device that can perform the
|
|
||||||
action and start it. If there are multiple components that can perform the action described by the
|
|
||||||
intent, then the user selects which one to use.</p>
|
|
||||||
|
|
||||||
<p>The way the system identifies the components that can respond to an intent is by comparing the
|
|
||||||
|
|
||||||
|
You can use an {@link android.content.Intent}
|
||||||
|
by explicitly naming the target component (using the component class name) in the intent.
|
||||||
|
You can also use an implicit intent, which
|
||||||
|
describes the type of action to perform and, optionally, the data upon which you’d like to
|
||||||
|
perform the action. The implicit intent allows the system to find a component on the device
|
||||||
|
that can perform the
|
||||||
|
action and start it. If there are multiple components that can perform the action described by the
|
||||||
|
intent, the user selects which one to use.</p>
|
||||||
|
|
||||||
|
<p class="caution"><strong>Caution:</strong> If you use an intent to start a
|
||||||
|
{@link android.app.Service}, ensure that your app is secure by using an
|
||||||
|
<a href="{@docRoot}guide/components/intents-filters.html#Types">explicit</a>
|
||||||
|
intent. Using an implicit intent to start a service is a
|
||||||
|
security hazard because you cannot be certain what service will respond to the intent,
|
||||||
|
and the user cannot see which service starts. Beginning with Android 5.0 (API level 21), the system
|
||||||
|
throws an exception if you call {@link android.content.Context#bindService bindService()}
|
||||||
|
with an implicit intent. Do not declare intent filters for your services. </p>
|
||||||
|
|
||||||
|
<p>The system identifies the components that can respond to an intent by comparing the
|
||||||
intent received to the <i>intent filters</i> provided in the manifest file of other apps on
|
intent received to the <i>intent filters</i> provided in the manifest file of other apps on
|
||||||
the device.</p>
|
the device.</p>
|
||||||
|
|
||||||
@@ -351,8 +390,9 @@ from other apps. You can declare an intent filter for your component by
|
|||||||
adding an <a href="{@docRoot}guide/topics/manifest/intent-filter-element.html">{@code
|
adding an <a href="{@docRoot}guide/topics/manifest/intent-filter-element.html">{@code
|
||||||
<intent-filter>}</a> element as a child of the component's declaration element.</p>
|
<intent-filter>}</a> element as a child of the component's declaration element.</p>
|
||||||
|
|
||||||
<p>For example, if you've built an email app with an activity for composing a new email, you can
|
<p>For example, if you build an email app with an activity for composing a new email, you can
|
||||||
declare an intent filter to respond to "send" intents (in order to send a new email) like this:</p>
|
declare an intent filter to respond to "send" intents (in order to send a new email),
|
||||||
|
as shown in the following example:</p>
|
||||||
<pre>
|
<pre>
|
||||||
<manifest ... >
|
<manifest ... >
|
||||||
...
|
...
|
||||||
@@ -368,8 +408,9 @@ declare an intent filter to respond to "send" intents (in order to send a new em
|
|||||||
</manifest>
|
</manifest>
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
<p>Then, if another app creates an intent with the {@link
|
<p>If another app creates an intent with the {@link
|
||||||
android.content.Intent#ACTION_SEND} action and passes it to {@link android.app.Activity#startActivity
|
android.content.Intent#ACTION_SEND} action and passes it to
|
||||||
|
{@link android.app.Activity#startActivity
|
||||||
startActivity()}, the system may start your activity so the user can draft and send an
|
startActivity()}, the system may start your activity so the user can draft and send an
|
||||||
email.</p>
|
email.</p>
|
||||||
|
|
||||||
@@ -382,7 +423,7 @@ href="{@docRoot}guide/components/intents-filters.html">Intents and Intent Filter
|
|||||||
<h3 id="DeclaringRequirements">Declaring app requirements</h3>
|
<h3 id="DeclaringRequirements">Declaring app requirements</h3>
|
||||||
|
|
||||||
<p>There are a variety of devices powered by Android and not all of them provide the
|
<p>There are a variety of devices powered by Android and not all of them provide the
|
||||||
same features and capabilities. In order to prevent your app from being installed on devices
|
same features and capabilities. To prevent your app from being installed on devices
|
||||||
that lack features needed by your app, it's important that you clearly define a profile for
|
that lack features needed by your app, it's important that you clearly define a profile for
|
||||||
the types of devices your app supports by declaring device and software requirements in your
|
the types of devices your app supports by declaring device and software requirements in your
|
||||||
manifest file. Most of these declarations are informational only and the system does not read
|
manifest file. Most of these declarations are informational only and the system does not read
|
||||||
@@ -391,7 +432,7 @@ for users when they search for apps from their device.</p>
|
|||||||
|
|
||||||
<p>For example, if your app requires a camera and uses APIs introduced in Android 2.1 (<a
|
<p>For example, if your app requires a camera and uses APIs introduced in Android 2.1 (<a
|
||||||
href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#ApiLevels">API Level</a> 7),
|
href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#ApiLevels">API Level</a> 7),
|
||||||
you should declare these as requirements in your manifest file like this:</p>
|
you must declare these as requirements in your manifest file as shown in the following example:</p>
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
<manifest ... >
|
<manifest ... >
|
||||||
@@ -402,10 +443,10 @@ you should declare these as requirements in your manifest file like this:</p>
|
|||||||
</manifest>
|
</manifest>
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
<p>Now, devices that do <em>not</em> have a camera and have an
|
<p>With the declarations shown in the example, devices that do <em>not</em> have a
|
||||||
Android version <em>lower</em> than 2.1 cannot install your app from Google Play.</p>
|
camera and have an
|
||||||
|
Android version <em>lower</em> than 2.1 cannot install your app from Google Play.
|
||||||
<p>However, you can also declare that your app uses the camera, but does not
|
However, you can declare that your app uses the camera, but does not
|
||||||
<em>require</em> it. In that case, your app must set the <a href=
|
<em>require</em> it. In that case, your app must set the <a href=
|
||||||
"{@docRoot}guide/topics/manifest/uses-feature-element.html#required">{@code required}</a>
|
"{@docRoot}guide/topics/manifest/uses-feature-element.html#required">{@code required}</a>
|
||||||
attribute to {@code "false"} and check at runtime whether
|
attribute to {@code "false"} and check at runtime whether
|
||||||
@@ -417,15 +458,15 @@ document.</p>
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h2 id="Resources">App Resources</h2>
|
<h2 id="Resources">App resources</h2>
|
||||||
|
|
||||||
<p>An Android app is composed of more than just code—it requires resources that are
|
<p>An Android app is composed of more than just code—it requires resources that are
|
||||||
separate from the source code, such as images, audio files, and anything relating to the visual
|
separate from the source code, such as images, audio files, and anything relating to the visual
|
||||||
presentation of the app. For example, you should define animations, menus, styles, colors,
|
presentation of the app. For example, you can define animations, menus, styles, colors,
|
||||||
and the layout of activity user interfaces with XML files. Using app resources makes it easy
|
and the layout of activity user interfaces with XML files. Using app resources makes it easy
|
||||||
to update various characteristics of your app without modifying code and—by providing
|
to update various characteristics of your app without modifying code. Providing
|
||||||
sets of alternative resources—enables you to optimize your app for a variety of
|
sets of alternative resources enables you to optimize your app for a variety of
|
||||||
device configurations (such as different languages and screen sizes).</p>
|
device configurations, such as different languages and screen sizes.</p>
|
||||||
|
|
||||||
<p>For every resource that you include in your Android project, the SDK build tools define a unique
|
<p>For every resource that you include in your Android project, the SDK build tools define a unique
|
||||||
integer ID, which you can use to reference the resource from your app code or from
|
integer ID, which you can use to reference the resource from your app code or from
|
||||||
@@ -435,20 +476,22 @@ named {@code R.drawable.logo}, which you can use to reference the image and inse
|
|||||||
user interface.</p>
|
user interface.</p>
|
||||||
|
|
||||||
<p>One of the most important aspects of providing resources separate from your source code
|
<p>One of the most important aspects of providing resources separate from your source code
|
||||||
is the ability for you to provide alternative resources for different device
|
is the ability to provide alternative resources for different device
|
||||||
configurations. For example, by defining UI strings in XML, you can translate the strings into other
|
configurations. For example, by defining UI strings in XML, you can translate
|
||||||
languages and save those strings in separate files. Then, based on a language <em>qualifier</em>
|
the strings into other
|
||||||
|
languages and save those strings in separate files. Then Android applies the
|
||||||
|
appropriate language strings
|
||||||
|
to your UI based on a language <em>qualifier</em>
|
||||||
that you append to the resource directory's name (such as {@code res/values-fr/} for French string
|
that you append to the resource directory's name (such as {@code res/values-fr/} for French string
|
||||||
values) and the user's language setting, the Android system applies the appropriate language strings
|
values) and the user's language setting.</p>
|
||||||
to your UI.</p>
|
|
||||||
|
|
||||||
<p>Android supports many different <em>qualifiers</em> for your alternative resources. The
|
<p>Android supports many different <em>qualifiers</em> for your alternative resources. The
|
||||||
qualifier is a short string that you include in the name of your resource directories in order to
|
qualifier is a short string that you include in the name of your resource directories in order to
|
||||||
define the device configuration for which those resources should be used. As another
|
define the device configuration for which those resources should be used. For
|
||||||
example, you should often create different layouts for your activities, depending on the
|
example, you should create different layouts for your activities, depending on the
|
||||||
device's screen orientation and size. For example, when the device screen is in portrait
|
device's screen orientation and size. When the device screen is in portrait
|
||||||
orientation (tall), you might want a layout with buttons to be vertical, but when the screen is in
|
orientation (tall), you might want a layout with buttons to be vertical, but when the screen is in
|
||||||
landscape orientation (wide), the buttons should be aligned horizontally. To change the layout
|
landscape orientation (wide), the buttons could be aligned horizontally. To change the layout
|
||||||
depending on the orientation, you can define two different layouts and apply the appropriate
|
depending on the orientation, you can define two different layouts and apply the appropriate
|
||||||
qualifier to each layout's directory name. Then, the system automatically applies the appropriate
|
qualifier to each layout's directory name. Then, the system automatically applies the appropriate
|
||||||
layout depending on the current device orientation.</p>
|
layout depending on the current device orientation.</p>
|
||||||
@@ -465,15 +508,15 @@ create alternative resources for different device configurations, read <a href=
|
|||||||
<dl>
|
<dl>
|
||||||
<dt><a href="{@docRoot}guide/components/intents-filters.html">Intents and Intent Filters</a>
|
<dt><a href="{@docRoot}guide/components/intents-filters.html">Intents and Intent Filters</a>
|
||||||
</dt>
|
</dt>
|
||||||
<dd>Information about how to use the {@link android.content.Intent} APIs to
|
<dd>How to use the {@link android.content.Intent} APIs to
|
||||||
activate app components, such as activities and services, and how to make your app components
|
activate app components, such as activities and services, and how to make your app components
|
||||||
available for use by other apps.</dd>
|
available for use by other apps.</dd>
|
||||||
<dt><a href="{@docRoot}guide/components/activities.html">Activities</a></dt>
|
<dt><a href="{@docRoot}guide/components/activities.html">Activities</a></dt>
|
||||||
<dd>Information about how to create an instance of the {@link android.app.Activity} class,
|
<dd>How to create an instance of the {@link android.app.Activity} class,
|
||||||
which provides a distinct screen in your application with a user interface.</dd>
|
which provides a distinct screen in your application with a user interface.</dd>
|
||||||
<dt><a
|
<dt><a
|
||||||
href="{@docRoot}guide/topics/resources/providing-resources.html">Providing Resources</a></dt>
|
href="{@docRoot}guide/topics/resources/providing-resources.html">Providing Resources</a></dt>
|
||||||
<dd>Information about how Android apps are structured to separate app resources from the
|
<dd>How Android apps are structured to separate app resources from the
|
||||||
app code, including how you can provide alternative resources for specific device
|
app code, including how you can provide alternative resources for specific device
|
||||||
configurations.
|
configurations.
|
||||||
</dd>
|
</dd>
|
||||||
@@ -484,14 +527,13 @@ href="{@docRoot}guide/topics/resources/providing-resources.html">Providing Resou
|
|||||||
<dl>
|
<dl>
|
||||||
<dt><a href="{@docRoot}guide/practices/compatibility.html"
|
<dt><a href="{@docRoot}guide/practices/compatibility.html"
|
||||||
>Device Compatibility</a></dt>
|
>Device Compatibility</a></dt>
|
||||||
<dd>Information about Android works on different types of devices and an introduction
|
<dd>How Android works on different types of devices and an introduction
|
||||||
to how you can optimize your app for each device or restrict your app's availability
|
to how you can optimize your app for each device or restrict your app's availability
|
||||||
to different devices.</dd>
|
to different devices.</dd>
|
||||||
<dt><a href="{@docRoot}guide/topics/security/permissions.html"
|
<dt><a href="{@docRoot}guide/topics/security/permissions.html"
|
||||||
>System Permissions</a></dt>
|
>System Permissions</a></dt>
|
||||||
<dd>Information about how Android restricts app access to certain APIs with a permission
|
<dd>How Android restricts app access to certain APIs with a permission
|
||||||
system that requires the user's consent for your app to use those APIs.</dd>
|
system that requires the user's consent for your app to use those APIs.</dd>
|
||||||
</dl>
|
</dl>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -7,21 +7,21 @@ page.tags="IntentFilter"
|
|||||||
|
|
||||||
<h2>In this document</h2>
|
<h2>In this document</h2>
|
||||||
<ol>
|
<ol>
|
||||||
<li><a href="#Types">Intent Types</a></li>
|
<li><a href="#Types">Intent types</a></li>
|
||||||
<li><a href="#Building">Building an Intent</a>
|
<li><a href="#Building">Building an intent</a>
|
||||||
<ol>
|
<ol>
|
||||||
<li><a href="#ExampleExplicit">Example explicit intent</a></li>
|
<li><a href="#ExampleExplicit">Example explicit intent</a></li>
|
||||||
<li><a href="#ExampleSend">Example implicit intent</a></li>
|
<li><a href="#ExampleSend">Example implicit intent</a></li>
|
||||||
<li><a href="#ForceChooser">Forcing an app chooser</a></li>
|
<li><a href="#ForceChooser">Forcing an app chooser</a></li>
|
||||||
</ol>
|
</ol>
|
||||||
</li>
|
</li>
|
||||||
<li><a href="#Receiving">Receiving an Implicit Intent</a>
|
<li><a href="#Receiving">Receiving an implicit intent</a>
|
||||||
<ol>
|
<ol>
|
||||||
<li><a href="#ExampleFilters">Example filters</a></li>
|
<li><a href="#ExampleFilters">Example filters</a></li>
|
||||||
</ol>
|
</ol>
|
||||||
</li>
|
</li>
|
||||||
<li><a href="#PendingIntent">Using a Pending Intent</a></li>
|
<li><a href="#PendingIntent">Using a pending intent</a></li>
|
||||||
<li><a href="#Resolution">Intent Resolution</a>
|
<li><a href="#Resolution">Intent resolution</a>
|
||||||
<ol>
|
<ol>
|
||||||
<li><a href="#ActionTest">Action test</a></li>
|
<li><a href="#ActionTest">Action test</a></li>
|
||||||
<li><a href="#CategoryTest">Category test</a></li>
|
<li><a href="#CategoryTest">Category test</a></li>
|
||||||
@@ -46,13 +46,14 @@ page.tags="IntentFilter"
|
|||||||
<p>An {@link android.content.Intent} is a messaging object you can use to request an action
|
<p>An {@link android.content.Intent} is a messaging object you can use to request an action
|
||||||
from another <a href="{@docRoot}guide/components/fundamentals.html#Components">app component</a>.
|
from another <a href="{@docRoot}guide/components/fundamentals.html#Components">app component</a>.
|
||||||
Although intents facilitate communication between components in several ways, there are three
|
Although intents facilitate communication between components in several ways, there are three
|
||||||
fundamental use-cases:</p>
|
fundamental use cases:</p>
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<li><b>To start an activity:</b>
|
<li><b>Starting an activity</b>
|
||||||
<p>An {@link android.app.Activity} represents a single screen in an app. You can start a new
|
<p>An {@link android.app.Activity} represents a single screen in an app. You can start a new
|
||||||
instance of an {@link android.app.Activity} by passing an {@link android.content.Intent}
|
instance of an {@link android.app.Activity} by passing an {@link android.content.Intent}
|
||||||
to {@link android.content.Context#startActivity startActivity()}. The {@link android.content.Intent}
|
to {@link android.content.Context#startActivity startActivity()}.
|
||||||
|
The {@link android.content.Intent}
|
||||||
describes the activity to start and carries any necessary data.</p>
|
describes the activity to start and carries any necessary data.</p>
|
||||||
|
|
||||||
<p>If you want to receive a result from the activity when it finishes,
|
<p>If you want to receive a result from the activity when it finishes,
|
||||||
@@ -63,10 +64,16 @@ android.app.Activity#onActivityResult onActivityResult()} callback.
|
|||||||
For more information, see the <a
|
For more information, see the <a
|
||||||
href="{@docRoot}guide/components/activities.html">Activities</a> guide.</p></li>
|
href="{@docRoot}guide/components/activities.html">Activities</a> guide.</p></li>
|
||||||
|
|
||||||
<li><b>To start a service:</b>
|
<li><b>Starting a service</b>
|
||||||
<p>A {@link android.app.Service} is a component that performs operations in the background
|
<p>A {@link android.app.Service} is a component that performs operations in the background
|
||||||
without a user interface. You can start a service to perform a one-time operation
|
without a user interface. With Android 5.0 (API level 21) and later, you can start a service
|
||||||
(such as download a file) by passing an {@link android.content.Intent}
|
with {@link android.app.job.JobScheduler}. For more information
|
||||||
|
about {@link android.app.job.JobScheduler}, see its
|
||||||
|
{@link android.app.job.JobScheduler API-reference documentation}.</p>
|
||||||
|
<p>For versions earlier than Android 5.0 (API level 21), you can start a service by using
|
||||||
|
methods of the {@link android.app.Service} class. You can start a service
|
||||||
|
to perform a one-time operation
|
||||||
|
(such as downloading a file) by passing an {@link android.content.Intent}
|
||||||
to {@link android.content.Context#startService startService()}. The {@link android.content.Intent}
|
to {@link android.content.Context#startService startService()}. The {@link android.content.Intent}
|
||||||
describes the service to start and carries any necessary data.</p>
|
describes the service to start and carries any necessary data.</p>
|
||||||
|
|
||||||
@@ -75,7 +82,7 @@ from another component by passing an {@link android.content.Intent} to {@link
|
|||||||
android.content.Context#bindService bindService()}</code>. For more information, see the <a
|
android.content.Context#bindService bindService()}</code>. For more information, see the <a
|
||||||
href="{@docRoot}guide/components/services.html">Services</a> guide.</p></li>
|
href="{@docRoot}guide/components/services.html">Services</a> guide.</p></li>
|
||||||
|
|
||||||
<li><b>To deliver a broadcast:</b>
|
<li><b>Delivering a broadcast</b>
|
||||||
<p>A broadcast is a message that any app can receive. The system delivers various
|
<p>A broadcast is a message that any app can receive. The system delivers various
|
||||||
broadcasts for system events, such as when the system boots up or the device starts charging.
|
broadcasts for system events, such as when the system boots up or the device starts charging.
|
||||||
You can deliver a broadcast to other apps by passing an {@link android.content.Intent}
|
You can deliver a broadcast to other apps by passing an {@link android.content.Intent}
|
||||||
@@ -89,7 +96,7 @@ android.content.Context#sendStickyBroadcast sendStickyBroadcast()}.</p>
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h2 id="Types">Intent Types</h2>
|
<h2 id="Types">Intent types</h2>
|
||||||
|
|
||||||
<p>There are two types of intents:</p>
|
<p>There are two types of intents:</p>
|
||||||
|
|
||||||
@@ -97,7 +104,7 @@ android.content.Context#sendStickyBroadcast sendStickyBroadcast()}.</p>
|
|||||||
<li><b>Explicit intents</b> specify the component to start by name (the
|
<li><b>Explicit intents</b> specify the component to start by name (the
|
||||||
fully-qualified class name). You'll typically use an explicit intent to start a component in
|
fully-qualified class name). You'll typically use an explicit intent to start a component in
|
||||||
your own app, because you know the class name of the activity or service you want to start. For
|
your own app, because you know the class name of the activity or service you want to start. For
|
||||||
example, start a new activity in response to a user action or start a service to download
|
example, you can start a new activity in response to a user action or start a service to download
|
||||||
a file in the background.</li>
|
a file in the background.</li>
|
||||||
|
|
||||||
<li><b>Implicit intents</b> do not name a specific component, but instead declare a general action
|
<li><b>Implicit intents</b> do not name a specific component, but instead declare a general action
|
||||||
@@ -106,12 +113,13 @@ show the user a location on a map, you can use an implicit intent to request tha
|
|||||||
app show a specified location on a map.</li>
|
app show a specified location on a map.</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<p>When you create an explicit intent to start an activity or service, the system immediately
|
<p>Figure 1 shows how an intent is delivered to start an activity. When you create an
|
||||||
|
explicit intent to start an activity or service, the system immediately
|
||||||
starts the app component specified in the {@link android.content.Intent} object.</p>
|
starts the app component specified in the {@link android.content.Intent} object.</p>
|
||||||
|
|
||||||
<div class="figure" style="width:446px">
|
<div class="figure" style="width:446px">
|
||||||
<img src="{@docRoot}images/components/intent-filters@2x.png" width="446" alt=""/>
|
<img src="{@docRoot}images/components/intent-filters@2x.png" width="446" alt=""/>
|
||||||
<p class="img-caption"><strong>Figure 1.</strong> Illustration of how an implicit intent is
|
<p class="img-caption"><strong>Figure 1.</strong> How an implicit intent is
|
||||||
delivered through the system to start another activity: <b>[1]</b> <em>Activity A</em> creates an
|
delivered through the system to start another activity: <b>[1]</b> <em>Activity A</em> creates an
|
||||||
{@link android.content.Intent} with an action description and passes it to {@link
|
{@link android.content.Intent} with an action description and passes it to {@link
|
||||||
android.content.Context#startActivity startActivity()}. <b>[2]</b> The Android System searches all
|
android.content.Context#startActivity startActivity()}. <b>[2]</b> The Android System searches all
|
||||||
@@ -135,11 +143,12 @@ you make it possible for other apps to directly start your activity with a certa
|
|||||||
Likewise, if you do <em>not</em> declare any intent filters for an activity, then it can be started
|
Likewise, if you do <em>not</em> declare any intent filters for an activity, then it can be started
|
||||||
only with an explicit intent.</p>
|
only with an explicit intent.</p>
|
||||||
|
|
||||||
<p class="caution"><strong>Caution:</strong> To ensure your app is secure, always use an explicit
|
<p class="caution"><strong>Caution:</strong> To ensure that your app is secure, always
|
||||||
|
use an explicit
|
||||||
intent when starting a {@link android.app.Service} and do not
|
intent when starting a {@link android.app.Service} and do not
|
||||||
declare intent filters for your services. Using an implicit intent to start a service is a
|
declare intent filters for your services. Using an implicit intent to start a service is a
|
||||||
security hazard because you cannot be certain what service will respond to the intent,
|
security hazard because you can't be certain what service will respond to the intent,
|
||||||
and the user cannot see which service starts. Beginning with Android 5.0 (API level 21), the system
|
and the user can't see which service starts. Beginning with Android 5.0 (API level 21), the system
|
||||||
throws an exception if you call {@link android.content.Context#bindService bindService()}
|
throws an exception if you call {@link android.content.Context#bindService bindService()}
|
||||||
with an implicit intent.</p>
|
with an implicit intent.</p>
|
||||||
|
|
||||||
@@ -147,7 +156,7 @@ with an implicit intent.</p>
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h2 id="Building">Building an Intent</h2>
|
<h2 id="Building">Building an intent</h2>
|
||||||
|
|
||||||
<p>An {@link android.content.Intent} object carries information that the Android system uses
|
<p>An {@link android.content.Intent} object carries information that the Android system uses
|
||||||
to determine which component to start (such as the exact component name or component
|
to determine which component to start (such as the exact component name or component
|
||||||
@@ -163,22 +172,23 @@ order to properly perform the action (such as the action to take and the data to
|
|||||||
<dd>The name of the component to start.
|
<dd>The name of the component to start.
|
||||||
|
|
||||||
<p>This is optional, but it's the critical piece of information that makes an intent
|
<p>This is optional, but it's the critical piece of information that makes an intent
|
||||||
<b>explicit</b>, meaning that the intent should be delivered only to the app component
|
<em>explicit</em>, meaning that the intent should be delivered only to the app component
|
||||||
defined by the component name. Without a component name, the intent is <b>implicit</b> and the
|
defined by the component name. Without a component name, the intent is <em>implicit</em> and the
|
||||||
system decides which component should receive the intent based on the other intent information
|
system decides which component should receive the intent based on the other intent information
|
||||||
(such as the action, data, and category—described below). So if you need to start a specific
|
(such as the action, data, and category—described below). If you need to start a specific
|
||||||
component in your app, you should specify the component name.</p>
|
component in your app, you should specify the component name.</p>
|
||||||
|
|
||||||
<p class="note"><strong>Note:</strong> When starting a {@link android.app.Service}, you should
|
<p class="note"><strong>Note:</strong> When starting a {@link android.app.Service},
|
||||||
<strong>always specify the component name</strong>. Otherwise, you cannot be certain what service
|
<em>always specify the component name</em>. Otherwise, you cannot be certain what service
|
||||||
will respond to the intent, and the user cannot see which service starts.</p>
|
will respond to the intent, and the user cannot see which service starts.</p>
|
||||||
|
|
||||||
<p>This field of the {@link android.content.Intent} is a
|
<p>This field of the {@link android.content.Intent} is a
|
||||||
{@link android.content.ComponentName} object, which you can specify using a fully
|
{@link android.content.ComponentName} object, which you can specify using a fully
|
||||||
qualified class name of the target component, including the package name of the app. For example,
|
qualified class name of the target component, including the package name of the app, for example,
|
||||||
{@code com.example.ExampleActivity}. You can set the component name with {@link
|
{@code com.example.ExampleActivity}. You can set the component name with {@link
|
||||||
android.content.Intent#setComponent setComponent()}, {@link android.content.Intent#setClass
|
android.content.Intent#setComponent setComponent()}, {@link android.content.Intent#setClass
|
||||||
setClass()}, {@link android.content.Intent#setClassName(String, String) setClassName()}, or with the
|
setClass()}, {@link android.content.Intent#setClassName(String, String) setClassName()},
|
||||||
|
or with the
|
||||||
{@link android.content.Intent} constructor.</p>
|
{@link android.content.Intent} constructor.</p>
|
||||||
|
|
||||||
</dd>
|
</dd>
|
||||||
@@ -188,10 +198,10 @@ setClass()}, {@link android.content.Intent#setClassName(String, String) setClass
|
|||||||
|
|
||||||
<p>In the case of a broadcast intent, this is the action that took place and is being reported.
|
<p>In the case of a broadcast intent, this is the action that took place and is being reported.
|
||||||
The action largely determines how the rest of the intent is structured—particularly
|
The action largely determines how the rest of the intent is structured—particularly
|
||||||
what is contained in the data and extras.
|
the information that is contained in the data and extras.
|
||||||
|
|
||||||
<p>You can specify your own actions for use by intents within your app (or for use by other
|
<p>You can specify your own actions for use by intents within your app (or for use by other
|
||||||
apps to invoke components in your app), but you should usually use action constants
|
apps to invoke components in your app), but you usually specify action constants
|
||||||
defined by the {@link android.content.Intent} class or other framework classes. Here are some
|
defined by the {@link android.content.Intent} class or other framework classes. Here are some
|
||||||
common actions for starting an activity:</p>
|
common actions for starting an activity:</p>
|
||||||
|
|
||||||
@@ -203,7 +213,7 @@ common actions for starting an activity:</p>
|
|||||||
view in a map app.</dd>
|
view in a map app.</dd>
|
||||||
|
|
||||||
<dt>{@link android.content.Intent#ACTION_SEND}</dt>
|
<dt>{@link android.content.Intent#ACTION_SEND}</dt>
|
||||||
<dd>Also known as the "share" intent, you should use this in an intent with {@link
|
<dd>Also known as the <em>share</em> intent, you should use this in an intent with {@link
|
||||||
android.content.Context#startActivity startActivity()} when you have some data that the user can
|
android.content.Context#startActivity startActivity()} when you have some data that the user can
|
||||||
share through another app, such as an email app or social sharing app.</dd>
|
share through another app, such as an email app or social sharing app.</dd>
|
||||||
</dl>
|
</dl>
|
||||||
@@ -217,12 +227,13 @@ that open specific screens in the system's Settings app.</p>
|
|||||||
setAction()} or with an {@link android.content.Intent} constructor.</p>
|
setAction()} or with an {@link android.content.Intent} constructor.</p>
|
||||||
|
|
||||||
<p>If you define your own actions, be sure to include your app's package name
|
<p>If you define your own actions, be sure to include your app's package name
|
||||||
as a prefix. For example:</p>
|
as a prefix, as shown in the following example:</p>
|
||||||
<pre>static final String ACTION_TIMETRAVEL = "com.example.action.TIMETRAVEL";</pre>
|
<pre>static final String ACTION_TIMETRAVEL = "com.example.action.TIMETRAVEL";</pre>
|
||||||
</dd>
|
</dd>
|
||||||
|
|
||||||
<dt><b>Data</b></dt>
|
<dt><b>Data</b></dt>
|
||||||
<dd>The URI (a {@link android.net.Uri} object) that references the data to be acted on and/or the
|
<dd>The URI (a {@link android.net.Uri} object) that references the data to
|
||||||
|
be acted on and/or the
|
||||||
MIME type of that data. The type of data supplied is generally dictated by the intent's action. For
|
MIME type of that data. The type of data supplied is generally dictated by the intent's action. For
|
||||||
example, if the action is {@link android.content.Intent#ACTION_EDIT}, the data should contain the
|
example, if the action is {@link android.content.Intent#ACTION_EDIT}, the data should contain the
|
||||||
URI of the document to edit.
|
URI of the document to edit.
|
||||||
@@ -231,10 +242,11 @@ URI of the document to edit.
|
|||||||
it's often important to specify the type of data (its MIME type) in addition to its URI.
|
it's often important to specify the type of data (its MIME type) in addition to its URI.
|
||||||
For example, an activity that's able to display images probably won't be able
|
For example, an activity that's able to display images probably won't be able
|
||||||
to play an audio file, even though the URI formats could be similar.
|
to play an audio file, even though the URI formats could be similar.
|
||||||
So specifying the MIME type of your data helps the Android
|
Specifying the MIME type of your data helps the Android
|
||||||
system find the best component to receive your intent.
|
system find the best component to receive your intent.
|
||||||
However, the MIME type can sometimes be inferred from the URI—particularly when the data is a
|
However, the MIME type can sometimes be inferred from the URI—particularly when the data is a
|
||||||
{@code content:} URI, which indicates the data is located on the device and controlled by a
|
{@code content:} URI. A {@code content:} URI indicates the data is located on the device
|
||||||
|
and controlled by a
|
||||||
{@link android.content.ContentProvider}, which makes the data MIME type visible to the system.</p>
|
{@link android.content.ContentProvider}, which makes the data MIME type visible to the system.</p>
|
||||||
|
|
||||||
<p>To set only the data URI, call {@link android.content.Intent#setData setData()}.
|
<p>To set only the data URI, call {@link android.content.Intent#setData setData()}.
|
||||||
@@ -243,7 +255,7 @@ can set both explicitly with {@link
|
|||||||
android.content.Intent#setDataAndType setDataAndType()}.</p>
|
android.content.Intent#setDataAndType setDataAndType()}.</p>
|
||||||
|
|
||||||
<p class="caution"><strong>Caution:</strong> If you want to set both the URI and MIME type,
|
<p class="caution"><strong>Caution:</strong> If you want to set both the URI and MIME type,
|
||||||
<strong>do not</strong> call {@link android.content.Intent#setData setData()} and
|
<em>don't</em> call {@link android.content.Intent#setData setData()} and
|
||||||
{@link android.content.Intent#setType setType()} because they each nullify the value of the other.
|
{@link android.content.Intent#setType setType()} because they each nullify the value of the other.
|
||||||
Always use {@link android.content.Intent#setDataAndType setDataAndType()} to set both
|
Always use {@link android.content.Intent#setDataAndType setDataAndType()} to set both
|
||||||
URI and MIME type.</p>
|
URI and MIME type.</p>
|
||||||
@@ -258,7 +270,7 @@ Here are some common categories:
|
|||||||
<dl>
|
<dl>
|
||||||
<dt>{@link android.content.Intent#CATEGORY_BROWSABLE}</dt>
|
<dt>{@link android.content.Intent#CATEGORY_BROWSABLE}</dt>
|
||||||
<dd>The target activity allows itself to be started by a web browser to display data
|
<dd>The target activity allows itself to be started by a web browser to display data
|
||||||
referenced by a link—such as an image or an e-mail message.
|
referenced by a link, such as an image or an e-mail message.
|
||||||
</dd>
|
</dd>
|
||||||
<dt>{@link android.content.Intent#CATEGORY_LAUNCHER}</dt>
|
<dt>{@link android.content.Intent#CATEGORY_LAUNCHER}</dt>
|
||||||
<dd>The activity is the initial activity of a task and is listed in
|
<dd>The activity is the initial activity of a task and is listed in
|
||||||
@@ -276,14 +288,14 @@ categories.</p>
|
|||||||
|
|
||||||
<p>These properties listed above (component name, action, data, and category) represent the
|
<p>These properties listed above (component name, action, data, and category) represent the
|
||||||
defining characteristics of an intent. By reading these properties, the Android system
|
defining characteristics of an intent. By reading these properties, the Android system
|
||||||
is able to resolve which app component it should start.</p>
|
is able to resolve which app component it should start. However, an intent can carry
|
||||||
|
additional information that does not affect
|
||||||
<p>However, an intent can carry additional information that does not affect
|
how it is resolved to an app component. An intent can also supply the following information:</p>
|
||||||
how it is resolved to an app component. An intent can also supply:</p>
|
|
||||||
|
|
||||||
<dl>
|
<dl>
|
||||||
<dt><b>Extras</b></dt>
|
<dt><b>Extras</b></dt>
|
||||||
<dd>Key-value pairs that carry additional information required to accomplish the requested action.
|
<dd>Key-value pairs that carry additional information required to accomplish
|
||||||
|
the requested action.
|
||||||
Just as some actions use particular kinds of data URIs, some actions also use particular extras.
|
Just as some actions use particular kinds of data URIs, some actions also use particular extras.
|
||||||
|
|
||||||
<p>You can add extra data with various {@link android.content.Intent#putExtra putExtra()} methods,
|
<p>You can add extra data with various {@link android.content.Intent#putExtra putExtra()} methods,
|
||||||
@@ -293,21 +305,22 @@ the {@link android.os.Bundle} in the {@link android.content.Intent} with {@link
|
|||||||
android.content.Intent#putExtras putExtras()}.</p>
|
android.content.Intent#putExtras putExtras()}.</p>
|
||||||
|
|
||||||
<p>For example, when creating an intent to send an email with
|
<p>For example, when creating an intent to send an email with
|
||||||
{@link android.content.Intent#ACTION_SEND}, you can specify the "to" recipient with the
|
{@link android.content.Intent#ACTION_SEND}, you can specify the <em>to</em> recipient with the
|
||||||
{@link android.content.Intent#EXTRA_EMAIL} key, and specify the "subject" with the
|
{@link android.content.Intent#EXTRA_EMAIL} key, and specify the <em>subject</em> with the
|
||||||
{@link android.content.Intent#EXTRA_SUBJECT} key.</p>
|
{@link android.content.Intent#EXTRA_SUBJECT} key.</p>
|
||||||
|
|
||||||
<p>The {@link android.content.Intent} class specifies many {@code EXTRA_*} constants
|
<p>The {@link android.content.Intent} class specifies many {@code EXTRA_*} constants
|
||||||
for standardized data types. If you need to declare your own extra keys (for intents that
|
for standardized data types. If you need to declare your own extra keys (for intents that
|
||||||
your app receives), be sure to include your app's package name
|
your app receives), be sure to include your app's package name
|
||||||
as a prefix. For example:</p>
|
as a prefix, as shown in the following example:</p>
|
||||||
<pre>static final String EXTRA_GIGAWATTS = "com.example.EXTRA_GIGAWATTS";</pre>
|
<pre>static final String EXTRA_GIGAWATTS = "com.example.EXTRA_GIGAWATTS";</pre>
|
||||||
</dd>
|
</dd>
|
||||||
|
|
||||||
<dt><b>Flags</b></dt>
|
<dt><b>Flags</b></dt>
|
||||||
<dd>Flags defined in the {@link android.content.Intent} class that function as metadata for the
|
<dd>Flags are defined in the {@link android.content.Intent} class that function as metadata for the
|
||||||
intent. The flags may instruct the Android system how to launch an activity (for example, which
|
intent. The flags may instruct the Android system how to launch an activity (for example, which
|
||||||
<a href="{@docRoot}guide/components/tasks-and-back-stack.html">task</a> the activity should belong
|
<a href="{@docRoot}guide/components/tasks-and-back-stack.html">task</a>
|
||||||
|
the activity should belong
|
||||||
to) and how to treat it after it's launched (for example, whether it belongs in the list of recent
|
to) and how to treat it after it's launched (for example, whether it belongs in the list of recent
|
||||||
activities).
|
activities).
|
||||||
|
|
||||||
@@ -354,7 +367,8 @@ this intent explicitly starts the {@code DownloadService} class in the app.</p>
|
|||||||
to perform the action. Using an implicit intent is useful when your app cannot perform the
|
to perform the action. Using an implicit intent is useful when your app cannot perform the
|
||||||
action, but other apps probably can and you'd like the user to pick which app to use.</p>
|
action, but other apps probably can and you'd like the user to pick which app to use.</p>
|
||||||
|
|
||||||
<p>For example, if you have content you want the user to share with other people, create an intent
|
<p>For example, if you have content that you want the user to share with other people,
|
||||||
|
create an intent
|
||||||
with the {@link android.content.Intent#ACTION_SEND} action
|
with the {@link android.content.Intent#ACTION_SEND} action
|
||||||
and add extras that specify the content to share. When you call
|
and add extras that specify the content to share. When you call
|
||||||
{@link android.content.Context#startActivity startActivity()} with that intent, the user can
|
{@link android.content.Context#startActivity startActivity()} with that intent, the user can
|
||||||
@@ -362,13 +376,15 @@ pick an app through which to share the content.</p>
|
|||||||
|
|
||||||
<p class="caution"><strong>Caution:</strong> It's possible that a user won't have <em>any</em>
|
<p class="caution"><strong>Caution:</strong> It's possible that a user won't have <em>any</em>
|
||||||
apps that handle the implicit intent you send to {@link android.content.Context#startActivity
|
apps that handle the implicit intent you send to {@link android.content.Context#startActivity
|
||||||
startActivity()}. If that happens, the call will fail and your app will crash. To verify
|
startActivity()}. If that happens, the call fails and your app crashes. To verify
|
||||||
that an activity will receive the intent, call {@link android.content.Intent#resolveActivity
|
that an activity will receive the intent, call {@link android.content.Intent#resolveActivity
|
||||||
resolveActivity()} on your {@link android.content.Intent} object. If the result is non-null,
|
resolveActivity()} on your {@link android.content.Intent} object. If the result is non-null,
|
||||||
then there is at least one app that can handle the intent and it's safe to call
|
there is at least one app that can handle the intent and it's safe to call
|
||||||
{@link android.content.Context#startActivity startActivity()}. If the result is null,
|
{@link android.content.Context#startActivity startActivity()}. If the result is null,
|
||||||
you should not use the intent and, if possible, you should disable the feature that issues
|
do not use the intent and, if possible, you should disable the feature that issues
|
||||||
the intent.</p>
|
the intent. The following example shows how to verify that the intent resolves
|
||||||
|
to an activity. This example doesn't use a URI, but the intent's data type
|
||||||
|
is declared to specify the content carried by the extras.</p>
|
||||||
|
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
@@ -384,8 +400,7 @@ if (sendIntent.resolveActivity(getPackageManager()) != null) {
|
|||||||
}
|
}
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
<p class="note"><strong>Note:</strong> In this case, a URI is not used, but the intent's data type
|
|
||||||
is declared to specify the content carried by the extras.</p>
|
|
||||||
|
|
||||||
|
|
||||||
<p>When {@link android.content.Context#startActivity startActivity()} is called, the system
|
<p>When {@link android.content.Context#startActivity startActivity()} is called, the system
|
||||||
@@ -393,7 +408,7 @@ examines all of the installed apps to determine which ones can handle this kind
|
|||||||
intent with the {@link android.content.Intent#ACTION_SEND} action and that carries "text/plain"
|
intent with the {@link android.content.Intent#ACTION_SEND} action and that carries "text/plain"
|
||||||
data). If there's only one app that can handle it, that app opens immediately and is given the
|
data). If there's only one app that can handle it, that app opens immediately and is given the
|
||||||
intent. If multiple activities accept the intent, the system
|
intent. If multiple activities accept the intent, the system
|
||||||
displays a dialog so the user can pick which app to use..</p>
|
displays a dialog such as the one shown in Figure 2, so the user can pick which app to use.</p>
|
||||||
|
|
||||||
|
|
||||||
<div class="figure" style="width:200px">
|
<div class="figure" style="width:200px">
|
||||||
@@ -405,23 +420,26 @@ displays a dialog so the user can pick which app to use..</p>
|
|||||||
|
|
||||||
<p>When there is more than one app that responds to your implicit intent,
|
<p>When there is more than one app that responds to your implicit intent,
|
||||||
the user can select which app to use and make that app the default choice for the
|
the user can select which app to use and make that app the default choice for the
|
||||||
action. This is nice when performing an action for which the user
|
action. The ability to select a default is helpful when performing an action for which the user
|
||||||
probably wants to use the same app from now on, such as when opening a web page (users
|
probably wants to use the same app every time, such as when opening a web page (users
|
||||||
often prefer just one web browser) .</p>
|
often prefer just one web browser).</p>
|
||||||
|
|
||||||
<p>However, if multiple apps can respond to the intent and the user might want to use a different
|
<p>However, if multiple apps can respond to the intent and the user might want to use a different
|
||||||
app each time, you should explicitly show a chooser dialog. The chooser dialog asks the
|
app each time, you should explicitly show a chooser dialog. The chooser dialog asks the
|
||||||
user to select which app to use for the action every time (the user cannot select a default app for
|
user to select which app to use for the action (the user cannot select a default app for
|
||||||
the action). For example, when your app performs "share" with the {@link
|
the action). For example, when your app performs "share" with the {@link
|
||||||
android.content.Intent#ACTION_SEND} action, users may want to share using a different app depending
|
android.content.Intent#ACTION_SEND} action, users may want to share using a different app depending
|
||||||
on their current situation, so you should always use the chooser dialog, as shown in figure 2.</p>
|
on their current situation, so you should always use the chooser dialog, as shown in Figure 2.</p>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<p>To show the chooser, create an {@link android.content.Intent} using {@link
|
<p>To show the chooser, create an {@link android.content.Intent} using {@link
|
||||||
android.content.Intent#createChooser createChooser()} and pass it to {@link
|
android.content.Intent#createChooser createChooser()} and pass it to {@link
|
||||||
android.app.Activity#startActivity startActivity()}. For example:</p>
|
android.app.Activity#startActivity startActivity()}, as shown in the following example.
|
||||||
|
This example displays a dialog with a list of apps that respond to the intent passed to the {@link
|
||||||
|
android.content.Intent#createChooser createChooser()} method and uses the supplied text as the
|
||||||
|
dialog title.</p>
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
Intent sendIntent = new Intent(Intent.ACTION_SEND);
|
Intent sendIntent = new Intent(Intent.ACTION_SEND);
|
||||||
@@ -439,26 +457,16 @@ if (sendIntent.resolveActivity(getPackageManager()) != null) {
|
|||||||
}
|
}
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
<p>This displays a dialog with a list of apps that respond to the intent passed to the {@link
|
|
||||||
android.content.Intent#createChooser createChooser()} method and uses the supplied text as the
|
|
||||||
dialog title.</p>
|
|
||||||
|
|
||||||
|
|
||||||
|
<h2 id="Receiving">Receiving an implicit intent</h2>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h2 id="Receiving">Receiving an Implicit Intent</h2>
|
|
||||||
|
|
||||||
<p>To advertise which implicit intents your app can receive, declare one or more intent filters for
|
<p>To advertise which implicit intents your app can receive, declare one or more intent filters for
|
||||||
each of your app components with an <a href=
|
each of your app components with an <a href=
|
||||||
"{@docRoot}guide/topics/manifest/intent-filter-element.html">{@code <intent-filter>}</a>
|
"{@docRoot}guide/topics/manifest/intent-filter-element.html">{@code <intent-filter>}</a>
|
||||||
element in your <a href="{@docRoot}guide/topics/manifest/manifest-intro.html">manifest file</a>.
|
element in your <a href="{@docRoot}guide/topics/manifest/manifest-intro.html">manifest file</a>.
|
||||||
Each intent filter specifies the type of intents it accepts based on the intent's action,
|
Each intent filter specifies the type of intents it accepts based on the intent's action,
|
||||||
data, and category. The system will deliver an implicit intent to your app component only if the
|
data, and category. The system delivers an implicit intent to your app component only if the
|
||||||
intent can pass through one of your intent filters.</p>
|
intent can pass through one of your intent filters.</p>
|
||||||
|
|
||||||
<p class="note"><strong>Note:</strong> An explicit intent is always delivered to its target,
|
<p class="note"><strong>Note:</strong> An explicit intent is always delivered to its target,
|
||||||
@@ -471,28 +479,28 @@ it inspects the {@link android.content.Intent} and decides how to behave based o
|
|||||||
in the {@link android.content.Intent} (such as to show the editor controls or not).</p>
|
in the {@link android.content.Intent} (such as to show the editor controls or not).</p>
|
||||||
|
|
||||||
<p>Each intent filter is defined by an <a
|
<p>Each intent filter is defined by an <a
|
||||||
href="{@docRoot}guide/topics/manifest/intent-filter-element.html">{@code <intent-filter>}</a>
|
href="{@docRoot}guide/topics/manifest/intent-filter-element.html">{@code <intent-filter>}</a>
|
||||||
element in the app's manifest file, nested in the corresponding app component (such
|
element in the app's manifest file, nested in the corresponding app component (such
|
||||||
as an <a href="{@docRoot}guide/topics/manifest/activity-element.html">{@code <activity>}</a>
|
as an <a href="{@docRoot}guide/topics/manifest/activity-element.html">{@code <activity>}</a>
|
||||||
element). Inside the <a
|
element). Inside the <a
|
||||||
href="{@docRoot}guide/topics/manifest/intent-filter-element.html">{@code <intent-filter>}</a>,
|
href="{@docRoot}guide/topics/manifest/intent-filter-element.html">{@code <intent-filter>}</a>,
|
||||||
you can specify the type of intents to accept using one or more
|
you can specify the type of intents to accept using one or more
|
||||||
of these three elements:</p>
|
of these three elements:</p>
|
||||||
|
|
||||||
<dl>
|
<dl>
|
||||||
<dt><a href="{@docRoot}guide/topics/manifest/action-element.html">{@code <action>}</a></dt>
|
<dt><a href="{@docRoot}guide/topics/manifest/action-element.html">{@code <action>}</a></dt>
|
||||||
<dd>Declares the intent action accepted, in the {@code name} attribute. The value
|
<dd>Declares the intent action accepted, in the {@code name} attribute. The value
|
||||||
must be the literal string value of an action, not the class constant.</dd>
|
must be the literal string value of an action, not the class constant.</dd>
|
||||||
<dt><a href="{@docRoot}guide/topics/manifest/data-element.html">{@code <data>}</a></dt>
|
<dt><a href="{@docRoot}guide/topics/manifest/data-element.html">{@code <data>}</a></dt>
|
||||||
<dd>Declares the type of data accepted, using one or more attributes that specify various
|
<dd>Declares the type of data accepted, using one or more attributes that specify various
|
||||||
aspects of the data URI (<code>scheme</code>, <code>host</code>, <code>port</code>,
|
aspects of the data URI (<code>scheme</code>, <code>host</code>, <code>port</code>,
|
||||||
<code>path</code>, etc.) and MIME type.</dd>
|
<code>path</code>) and MIME type.</dd>
|
||||||
<dt><a href="{@docRoot}guide/topics/manifest/category-element.html">{@code <category>}</a></dt>
|
<dt><a href="{@docRoot}guide/topics/manifest/category-element.html">{@code <category>}</a></dt>
|
||||||
<dd>Declares the intent category accepted, in the {@code name} attribute. The value
|
<dd>Declares the intent category accepted, in the {@code name} attribute. The value
|
||||||
must be the literal string value of an action, not the class constant.
|
must be the literal string value of an action, not the class constant.
|
||||||
|
|
||||||
<p class="note"><strong>Note:</strong> In order to receive implicit intents, you
|
<p class="note"><strong>Note:</strong> To receive implicit intents, you
|
||||||
<strong>must include</strong> the
|
<em>must include</em> the
|
||||||
{@link android.content.Intent#CATEGORY_DEFAULT} category in the intent filter. The methods
|
{@link android.content.Intent#CATEGORY_DEFAULT} category in the intent filter. The methods
|
||||||
{@link android.app.Activity#startActivity startActivity()} and
|
{@link android.app.Activity#startActivity startActivity()} and
|
||||||
{@link android.app.Activity#startActivityForResult startActivityForResult()} treat all intents
|
{@link android.app.Activity#startActivityForResult startActivityForResult()} treat all intents
|
||||||
@@ -515,12 +523,12 @@ of these three elements:</p>
|
|||||||
</activity>
|
</activity>
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
<p>It's okay to create a filter that includes more than one instance of
|
<p>You can create a filter that includes more than one instance of
|
||||||
<a href="{@docRoot}guide/topics/manifest/action-element.html">{@code <action>}</a>,
|
<a href="{@docRoot}guide/topics/manifest/action-element.html">{@code <action>}</a>,
|
||||||
<a href="{@docRoot}guide/topics/manifest/data-element.html">{@code <data>}</a>, or
|
<a href="{@docRoot}guide/topics/manifest/data-element.html">{@code <data>}</a>, or
|
||||||
<a href="{@docRoot}guide/topics/manifest/category-element.html">{@code <category>}</a>.
|
<a href="{@docRoot}guide/topics/manifest/category-element.html">{@code <category>}</a>.
|
||||||
If you do, you simply need to be certain that the component can handle any and all combinations
|
If you do, you need to be certain that the component can handle any and all
|
||||||
of those filter elements.</p>
|
combinations of those filter elements.</p>
|
||||||
|
|
||||||
<p>When you want to handle multiple kinds of intents, but only in specific combinations of
|
<p>When you want to handle multiple kinds of intents, but only in specific combinations of
|
||||||
action, data, and category type, then you need to create multiple intent filters.</p>
|
action, data, and category type, then you need to create multiple intent filters.</p>
|
||||||
@@ -569,8 +577,8 @@ is running.</p>
|
|||||||
|
|
||||||
<h3 id="ExampleFilters">Example filters</h3>
|
<h3 id="ExampleFilters">Example filters</h3>
|
||||||
|
|
||||||
<p>To better understand some of the intent filter behaviors, look at the following snippet
|
<p>To demonstrate some of the intent filter behaviors, here is an example
|
||||||
from the manifest file of a social-sharing app.</p>
|
from the manifest file of a social-sharing app:</p>
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
<activity android:name="MainActivity">
|
<activity android:name="MainActivity">
|
||||||
@@ -607,9 +615,9 @@ opens when the user initially launches the app with the launcher icon:</p>
|
|||||||
indicates this is the main entry point and does not expect any intent data.</li>
|
indicates this is the main entry point and does not expect any intent data.</li>
|
||||||
<li>The {@link android.content.Intent#CATEGORY_LAUNCHER} category indicates that this activity's
|
<li>The {@link android.content.Intent#CATEGORY_LAUNCHER} category indicates that this activity's
|
||||||
icon should be placed in the system's app launcher. If the <a
|
icon should be placed in the system's app launcher. If the <a
|
||||||
href="{@docRoot}guide/topics/manifest/activity-element.html">{@code <activity>}</a> element
|
href="{@docRoot}guide/topics/manifest/activity-element.html">{@code <activity>}</a> element
|
||||||
does not specify an icon with {@code icon}, then the system uses the icon from the <a
|
does not specify an icon with {@code icon}, then the system uses the icon from the <a
|
||||||
href="{@docRoot}guide/topics/manifest/application-element.html">{@code <application>}</a>
|
href="{@docRoot}guide/topics/manifest/application-element.html">{@code <application>}</a>
|
||||||
element.</li>
|
element.</li>
|
||||||
</ul>
|
</ul>
|
||||||
<p>These two must be paired together in order for the activity to appear in the app launcher.</p>
|
<p>These two must be paired together in order for the activity to appear in the app launcher.</p>
|
||||||
@@ -620,7 +628,7 @@ they can also enter {@code ShareActivity} directly from another app that issues
|
|||||||
intent matching one of the two intent filters.</p>
|
intent matching one of the two intent filters.</p>
|
||||||
|
|
||||||
<p class="note"><strong>Note:</strong> The MIME type,
|
<p class="note"><strong>Note:</strong> The MIME type,
|
||||||
<a href="https://developers.google.com/panorama/android/">{@code
|
<a href="https://developers.google.com/panorama/android/" class="external-link">{@code
|
||||||
application/vnd.google.panorama360+jpg}</a>, is a special data type that specifies
|
application/vnd.google.panorama360+jpg}</a>, is a special data type that specifies
|
||||||
panoramic photos, which you can handle with the <a
|
panoramic photos, which you can handle with the <a
|
||||||
href="{@docRoot}reference/com/google/android/gms/panorama/package-summary.html">Google
|
href="{@docRoot}reference/com/google/android/gms/panorama/package-summary.html">Google
|
||||||
@@ -638,7 +646,7 @@ panorama</a> APIs.</p>
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h2 id="PendingIntent">Using a Pending Intent</h2>
|
<h2 id="PendingIntent">Using a pending intent</h2>
|
||||||
|
|
||||||
<p>A {@link android.app.PendingIntent} object is a wrapper around an {@link
|
<p>A {@link android.app.PendingIntent} object is a wrapper around an {@link
|
||||||
android.content.Intent} object. The primary purpose of a {@link android.app.PendingIntent}
|
android.content.Intent} object. The primary purpose of a {@link android.app.PendingIntent}
|
||||||
@@ -646,25 +654,25 @@ is to grant permission to a foreign application
|
|||||||
to use the contained {@link android.content.Intent} as if it were executed from your
|
to use the contained {@link android.content.Intent} as if it were executed from your
|
||||||
app's own process.</p>
|
app's own process.</p>
|
||||||
|
|
||||||
<p>Major use cases for a pending intent include:</p>
|
<p>Major use cases for a pending intent include the following:</p>
|
||||||
<ul>
|
<ul>
|
||||||
<li>Declare an intent to be executed when the user performs an action with your <a
|
<li>Declaring an intent to be executed when the user performs an action with your <a
|
||||||
href="{@docRoot}guide/topics/ui/notifiers/notifications.html">Notification</a>
|
href="{@docRoot}guide/topics/ui/notifiers/notifications.html">Notification</a>
|
||||||
(the Android system's {@link android.app.NotificationManager}
|
(the Android system's {@link android.app.NotificationManager}
|
||||||
executes the {@link android.content.Intent}).
|
executes the {@link android.content.Intent}).
|
||||||
<li>Declare an intent to be executed when the user performs an action with your
|
<li>Declaring an intent to be executed when the user performs an action with your
|
||||||
<a href="{@docRoot}guide/topics/appwidgets/index.html">App Widget</a>
|
<a href="{@docRoot}guide/topics/appwidgets/index.html">App Widget</a>
|
||||||
(the Home screen app executes the {@link android.content.Intent}).
|
(the Home screen app executes the {@link android.content.Intent}).
|
||||||
<li>Declare an intent to be executed at a specified time in the future (the Android
|
<li>Declaring an intent to be executed at a specified future time (the Android
|
||||||
system's {@link android.app.AlarmManager} executes the {@link android.content.Intent}).
|
system's {@link android.app.AlarmManager} executes the {@link android.content.Intent}).
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<p>Because each {@link android.content.Intent} object is designed to be handled by a specific
|
<p>Just as each {@link android.content.Intent} object is designed to be handled by a specific
|
||||||
type of app component (either an {@link android.app.Activity}, a {@link android.app.Service}, or
|
type of app component (either an {@link android.app.Activity}, a {@link android.app.Service}, or
|
||||||
a {@link android.content.BroadcastReceiver}), so too must a {@link android.app.PendingIntent} be
|
a {@link android.content.BroadcastReceiver}), so too must a {@link android.app.PendingIntent} be
|
||||||
created with the same consideration. When using a pending intent, your app will not
|
created with the same consideration. When using a pending intent, your app doesn't
|
||||||
execute the intent with a call such as {@link android.content.Context#startActivity
|
execute the intent with a call such as {@link android.content.Context#startActivity
|
||||||
startActivity()}. You must instead declare the intended component type when you create the
|
startActivity()}. Instead, you must declare the intended component type when you create the
|
||||||
{@link android.app.PendingIntent} by calling the respective creator method:</p>
|
{@link android.app.PendingIntent} by calling the respective creator method:</p>
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
@@ -677,14 +685,14 @@ startActivity()}. You must instead declare the intended component type when you
|
|||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<p>Unless your app is <em>receiving</em> pending intents from other apps,
|
<p>Unless your app is <em>receiving</em> pending intents from other apps,
|
||||||
the above methods to create a {@link android.app.PendingIntent} are the only
|
the above methods to create a {@link android.app.PendingIntent} are probably the only
|
||||||
{@link android.app.PendingIntent} methods you'll probably ever need.</p>
|
{@link android.app.PendingIntent} methods you'll ever need.</p>
|
||||||
|
|
||||||
<p>Each method takes the current app {@link android.content.Context}, the
|
<p>Each method takes the current app {@link android.content.Context}, the
|
||||||
{@link android.content.Intent} you want to wrap, and one or more flags that specify
|
{@link android.content.Intent} you want to wrap, and one or more flags that specify
|
||||||
how the intent should be used (such as whether the intent can be used more than once).</p>
|
how the intent should be used (such as whether the intent can be used more than once).</p>
|
||||||
|
|
||||||
<p>More information about using pending intents is provided with the documentation for each
|
<p>For more information about using pending intents, see the documentation for each
|
||||||
of the respective use cases, such as in the <a
|
of the respective use cases, such as in the <a
|
||||||
href="{@docRoot}guide/topics/ui/notifiers/notifications.html">Notifications</a>
|
href="{@docRoot}guide/topics/ui/notifiers/notifications.html">Notifications</a>
|
||||||
and <a href="{@docRoot}guide/topics/appwidgets/index.html">App Widgets</a> API guides.</p>
|
and <a href="{@docRoot}guide/topics/appwidgets/index.html">App Widgets</a> API guides.</p>
|
||||||
@@ -695,27 +703,27 @@ and <a href="{@docRoot}guide/topics/appwidgets/index.html">App Widgets</a> API g
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h2 id="Resolution">Intent Resolution</h2>
|
<h2 id="Resolution">Intent resolution</h2>
|
||||||
|
|
||||||
|
|
||||||
<p>When the system receives an implicit intent to start an activity, it searches for the
|
<p>When the system receives an implicit intent to start an activity, it searches for the
|
||||||
best activity for the intent by comparing the intent to intent filters based on three aspects:</p>
|
best activity for the intent by comparing the it to intent filters based on three aspects:</p>
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<li>The intent action
|
<li>Action.
|
||||||
<li>The intent data (both URI and data type)
|
<li>Data (both URI and data type).
|
||||||
<li>The intent category
|
<li>Category.
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<p>The following sections describe how intents are matched to the appropriate component(s)
|
<p>The following sections describe how intents are matched to the appropriate components
|
||||||
in terms of how the intent filter is declared in an app's manifest file.</p>
|
according to the intent filter declaration in an app's manifest file.</p>
|
||||||
|
|
||||||
|
|
||||||
<h3 id="ActionTest">Action test</h3>
|
<h3 id="ActionTest">Action test</h3>
|
||||||
|
|
||||||
<p>To specify accepted intent actions, an intent filter can declare zero or more
|
<p>To specify accepted intent actions, an intent filter can declare zero or more
|
||||||
<a href="{@docRoot}guide/topics/manifest/action-element.html">{@code
|
<a href="{@docRoot}guide/topics/manifest/action-element.html">{@code
|
||||||
<action>}</a> elements. For example:</p>
|
<action>}</a> elements, as shown in the following example:</p>
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
@@ -725,13 +733,13 @@ in terms of how the intent filter is declared in an app's manifest file.</p>
|
|||||||
</intent-filter>
|
</intent-filter>
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
<p>To get through this filter, the action specified in the {@link android.content.Intent}
|
<p>To pass this filter, the action specified in the {@link android.content.Intent}
|
||||||
must match one of the actions listed in the filter.</p>
|
must match one of the actions listed in the filter.</p>
|
||||||
|
|
||||||
<p>If the filter does not list any actions, there is nothing for an
|
<p>If the filter does not list any actions, there is nothing for an
|
||||||
intent to match, so all intents fail the test. However, if an {@link android.content.Intent}
|
intent to match, so all intents fail the test. However, if an {@link android.content.Intent}
|
||||||
does not specify an action, it will pass the test (as long as the filter
|
does not specify an action, it passes the test as long as the filter
|
||||||
contains at least one action).</p>
|
contains at least one action.</p>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -739,7 +747,7 @@ contains at least one action).</p>
|
|||||||
|
|
||||||
<p>To specify accepted intent categories, an intent filter can declare zero or more
|
<p>To specify accepted intent categories, an intent filter can declare zero or more
|
||||||
<a href="{@docRoot}guide/topics/manifest/category-element.html">{@code
|
<a href="{@docRoot}guide/topics/manifest/category-element.html">{@code
|
||||||
<category>}</a> elements. For example:</p>
|
<category>}</a> elements, as shown in the following example:</p>
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
@@ -752,17 +760,17 @@ contains at least one action).</p>
|
|||||||
<p>For an intent to pass the category test, every category in the {@link android.content.Intent}
|
<p>For an intent to pass the category test, every category in the {@link android.content.Intent}
|
||||||
must match a category in the filter. The reverse is not necessary—the intent filter may
|
must match a category in the filter. The reverse is not necessary—the intent filter may
|
||||||
declare more categories than are specified in the {@link android.content.Intent} and the
|
declare more categories than are specified in the {@link android.content.Intent} and the
|
||||||
{@link android.content.Intent} will still pass. Therefore, an intent with no categories should
|
{@link android.content.Intent} still passes. Therefore, an intent with no categories
|
||||||
always pass this test, regardless of what categories are declared in the filter.</p>
|
always passes this test, regardless of what categories are declared in the filter.</p>
|
||||||
|
|
||||||
<p class="note"><strong>Note:</strong>
|
<p class="note"><strong>Note:</strong>
|
||||||
Android automatically applies the the {@link android.content.Intent#CATEGORY_DEFAULT} category
|
Android automatically applies the {@link android.content.Intent#CATEGORY_DEFAULT} category
|
||||||
to all implicit intents passed to {@link
|
to all implicit intents passed to {@link
|
||||||
android.content.Context#startActivity startActivity()} and {@link
|
android.content.Context#startActivity startActivity()} and {@link
|
||||||
android.app.Activity#startActivityForResult startActivityForResult()}.
|
android.app.Activity#startActivityForResult startActivityForResult()}.
|
||||||
So if you want your activity to receive implicit intents, it must
|
If you want your activity to receive implicit intents, it must
|
||||||
include a category for {@code "android.intent.category.DEFAULT"} in its intent filters (as
|
include a category for {@code "android.intent.category.DEFAULT"} in its intent filters, as
|
||||||
shown in the previous {@code <intent-filter>} example.</p>
|
shown in the previous {@code <intent-filter>} example.</p>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -770,7 +778,7 @@ shown in the previous {@code <intent-filter>} example.</p>
|
|||||||
|
|
||||||
<p>To specify accepted intent data, an intent filter can declare zero or more
|
<p>To specify accepted intent data, an intent filter can declare zero or more
|
||||||
<a href="{@docRoot}guide/topics/manifest/data-element.html">{@code
|
<a href="{@docRoot}guide/topics/manifest/data-element.html">{@code
|
||||||
<data>}</a> elements. For example:</p>
|
<data>}</a> elements, as shown in the following example:</p>
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
@@ -781,15 +789,16 @@ shown in the previous {@code <intent-filter>} example.</p>
|
|||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
<p>Each <code><a href="{@docRoot}guide/topics/manifest/data-element.html"><data></a></code>
|
<p>Each <code><a href="{@docRoot}guide/topics/manifest/data-element.html"><data></a></code>
|
||||||
element can specify a URI structure and a data type (MIME media type). There are separate
|
element can specify a URI structure and a data type (MIME media type).
|
||||||
attributes — {@code scheme}, {@code host}, {@code port},
|
Each part of the URI is a separate
|
||||||
and {@code path} — for each part of the URI:
|
attribute: {@code scheme}, {@code host}, {@code port},
|
||||||
|
and {@code path}:
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p style="margin-left: 2em">{@code <scheme>://<host>:<port>/<path>}</p>
|
<p style="margin-left: 2em">{@code <scheme>://<host>:<port>/<path>}</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
For example:
|
The following example shows possible values for these attributes:
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p style="margin-left: 2em">{@code content://com.example.project:200/folder/subfolder/etc}</p>
|
<p style="margin-left: 2em">{@code content://com.example.project:200/folder/subfolder/etc}</p>
|
||||||
@@ -799,7 +808,7 @@ the port is {@code 200}, and the path is {@code folder/subfolder/etc}.
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>Each of these attributes is optional in a <a
|
<p>Each of these attributes is optional in a <a
|
||||||
href="{@docRoot}guide/topics/manifest/data-element.html">{@code <data>}</a> element,
|
href="{@docRoot}guide/topics/manifest/data-element.html">{@code <data>}</a> element,
|
||||||
but there are linear dependencies:</p>
|
but there are linear dependencies:</p>
|
||||||
<ul>
|
<ul>
|
||||||
<li>If a scheme is not specified, the host is ignored.</li>
|
<li>If a scheme is not specified, the host is ignored.</li>
|
||||||
@@ -842,17 +851,17 @@ type matches a type listed in the filter. It passes the URI part of the test
|
|||||||
either if its URI matches a URI in the filter or if it has a {@code content:}
|
either if its URI matches a URI in the filter or if it has a {@code content:}
|
||||||
or {@code file:} URI and the filter does not specify a URI. In other words,
|
or {@code file:} URI and the filter does not specify a URI. In other words,
|
||||||
a component is presumed to support {@code content:} and {@code file:} data if
|
a component is presumed to support {@code content:} and {@code file:} data if
|
||||||
its filter lists <em>only</em> a MIME type.</p></li>
|
its filter lists <em>only</em> a MIME type.</li>
|
||||||
</ol>
|
</ol>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
This last rule, rule (d), reflects the expectation
|
This last rule, rule (d), reflects the expectation
|
||||||
that components are able to get local data from a file or content provider.
|
that components are able to get local data from a file or content provider.
|
||||||
Therefore, their filters can list just a data type and do not need to explicitly
|
Therefore, their filters can list just a data type and don't need to explicitly
|
||||||
name the {@code content:} and {@code file:} schemes.
|
name the {@code content:} and {@code file:} schemes.
|
||||||
This is a typical case. A <a
|
The following example shows a typical case in which a <a
|
||||||
href="{@docRoot}guide/topics/manifest/data-element.html">{@code <data>}</a> element
|
href="{@docRoot}guide/topics/manifest/data-element.html">{@code <data>}</a> element
|
||||||
like the following, for example, tells Android that the component can get image data from a content
|
tells Android that the component can get image data from a content
|
||||||
provider and display it:
|
provider and display it:
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
@@ -863,14 +872,15 @@ provider and display it:
|
|||||||
</intent-filter></pre>
|
</intent-filter></pre>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
Because most available data is dispensed by content providers, filters that
|
Filters that
|
||||||
specify a data type but not a URI are perhaps the most common.
|
specify a data type but not a URI are perhaps the most common because most available
|
||||||
|
data is dispensed by content providers.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
Another common configuration is filters with a scheme and a data type. For
|
Another common configuration is a filter with a scheme and a data type. For
|
||||||
example, a <a
|
example, a <a
|
||||||
href="{@docRoot}guide/topics/manifest/data-element.html">{@code <data>}</a>
|
href="{@docRoot}guide/topics/manifest/data-element.html">{@code <data>}</a>
|
||||||
element like the following tells Android that
|
element like the following tells Android that
|
||||||
the component can retrieve video data from the network in order to perform the action:
|
the component can retrieve video data from the network in order to perform the action:
|
||||||
</p>
|
</p>
|
||||||
@@ -894,7 +904,7 @@ by finding all the activities with intent filters that specify the
|
|||||||
|
|
||||||
<p>Your application can use intent matching in a similar way.
|
<p>Your application can use intent matching in a similar way.
|
||||||
The {@link android.content.pm.PackageManager} has a set of {@code query...()}
|
The {@link android.content.pm.PackageManager} has a set of {@code query...()}
|
||||||
methods that return all components that can accept a particular intent, and
|
methods that return all components that can accept a particular intent and
|
||||||
a similar series of {@code resolve...()} methods that determine the best
|
a similar series of {@code resolve...()} methods that determine the best
|
||||||
component to respond to an intent. For example,
|
component to respond to an intent. For example,
|
||||||
{@link android.content.pm.PackageManager#queryIntentActivities
|
{@link android.content.pm.PackageManager#queryIntentActivities
|
||||||
@@ -907,7 +917,3 @@ can respond. There's a similar method,
|
|||||||
{@link android.content.pm.PackageManager#queryBroadcastReceivers
|
{@link android.content.pm.PackageManager#queryBroadcastReceivers
|
||||||
queryBroadcastReceivers()}, for broadcast receivers.
|
queryBroadcastReceivers()}, for broadcast receivers.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -5,11 +5,11 @@ page.title=Services
|
|||||||
<ol id="qv">
|
<ol id="qv">
|
||||||
<h2>In this document</h2>
|
<h2>In this document</h2>
|
||||||
<ol>
|
<ol>
|
||||||
<li><a href="#Basics">The Basics</a></li>
|
<li><a href="#Basics">The basics</a></li>
|
||||||
<ol>
|
<ol>
|
||||||
<li><a href="#Declaring">Declaring a service in the manifest</a></li>
|
<li><a href="#Declaring">Declaring a service in the manifest</a></li>
|
||||||
</ol>
|
</ol>
|
||||||
<li><a href="#CreatingAService">Creating a Started Service</a>
|
<li><a href="#CreatingAService">Creating a started service</a>
|
||||||
<ol>
|
<ol>
|
||||||
<li><a href="#ExtendingIntentService">Extending the IntentService class</a></li>
|
<li><a href="#ExtendingIntentService">Extending the IntentService class</a></li>
|
||||||
<li><a href="#ExtendingService">Extending the Service class</a></li>
|
<li><a href="#ExtendingService">Extending the Service class</a></li>
|
||||||
@@ -17,10 +17,10 @@ page.title=Services
|
|||||||
<li><a href="#Stopping">Stopping a service</a></li>
|
<li><a href="#Stopping">Stopping a service</a></li>
|
||||||
</ol>
|
</ol>
|
||||||
</li>
|
</li>
|
||||||
<li><a href="#CreatingBoundService">Creating a Bound Service</a></li>
|
<li><a href="#CreatingBoundService">Creating a bound service</a></li>
|
||||||
<li><a href="#Notifications">Sending Notifications to the User</a></li>
|
<li><a href="#Notifications">Sending notifications to the user</a></li>
|
||||||
<li><a href="#Foreground">Running a Service in the Foreground</a></li>
|
<li><a href="#Foreground">Running a service in the foreground</a></li>
|
||||||
<li><a href="#Lifecycle">Managing the Lifecycle of a Service</a>
|
<li><a href="#Lifecycle">Managing the lifecycle of a service</a>
|
||||||
<ol>
|
<ol>
|
||||||
<li><a href="#LifecycleCallbacks">Implementing the lifecycle callbacks</a></li>
|
<li><a href="#LifecycleCallbacks">Implementing the lifecycle callbacks</a></li>
|
||||||
</ol>
|
</ol>
|
||||||
@@ -48,70 +48,80 @@ page.title=Services
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<p>A {@link android.app.Service} is an application component that can perform
|
<p>A {@link android.app.Service} is an application component that can perform
|
||||||
long-running operations in the background and does not provide a user interface. Another
|
long-running operations in the background, and it does not provide a user interface. Another
|
||||||
application component can start a service and it will continue to run in the background even if the
|
application component can start a service, and it continues to run in the background even if the
|
||||||
user switches to another application. Additionally, a component can bind to a service to
|
user switches to another application. Additionally, a component can bind to a service to
|
||||||
interact with it and even perform interprocess communication (IPC). For example, a service might
|
interact with it and even perform interprocess communication (IPC). For example, a service can
|
||||||
handle network transactions, play music, perform file I/O, or interact with a content provider, all
|
handle network transactions, play music, perform file I/O, or interact with a content provider, all
|
||||||
from the background.</p>
|
from the background.</p>
|
||||||
|
|
||||||
<p>A service can essentially take two forms:</p>
|
<p>These are the three different types of services:</p>
|
||||||
|
|
||||||
<dl>
|
<dl>
|
||||||
|
<dt>Scheduled</dt>
|
||||||
|
<dd>A service is <em>scheduled</em> when an API such as the {@link android.app.job.JobScheduler},
|
||||||
|
introduced in Android 5.0 (API level 21), launches the service. You can use the
|
||||||
|
{@link android.app.job.JobScheduler} by registering jobs and specifying their requirements for
|
||||||
|
network and timing. The system then gracefully schedules the jobs for execution at the
|
||||||
|
appropriate times. The {@link android.app.job.JobScheduler} provides many methods to define
|
||||||
|
service-execution conditions.
|
||||||
|
<p class="note"><strong>Note:</strong> If your app targets Android 5.0 (API level 21), Google
|
||||||
|
recommends that you use the {@link android.app.job.JobScheduler} to execute background
|
||||||
|
services. For more information about using this class, see the
|
||||||
|
{@link android.app.job.JobScheduler} reference documentation.</p></dd>
|
||||||
<dt>Started</dt>
|
<dt>Started</dt>
|
||||||
<dd>A service is "started" when an application component (such as an activity) starts it by
|
<dd>A service is <em>started</em> when an application component (such as an activity)
|
||||||
calling {@link android.content.Context#startService startService()}. Once started, a service
|
calls {@link android.content.Context#startService startService()}. After it's started, a
|
||||||
can run in the background indefinitely, even if the component that started it is destroyed. Usually,
|
service can run in the background indefinitely, even if the component that started it is
|
||||||
a started service performs a single operation and does not return a result to the caller.
|
destroyed. Usually, a started service performs a single operation and does not return a result to
|
||||||
For example, it might download or upload a file over the network. When the operation is done, the
|
the caller. For example, it can download or upload a file over the network. When the operation is
|
||||||
service should stop itself.</dd>
|
complete, the service should stop itself.</dd>
|
||||||
<dt>Bound</dt>
|
<dt>Bound</dt>
|
||||||
<dd>A service is "bound" when an application component binds to it by calling {@link
|
<dd>A service is <em>bound</em> when an application component binds to it by calling {@link
|
||||||
android.content.Context#bindService bindService()}. A bound service offers a client-server
|
android.content.Context#bindService bindService()}. A bound service offers a client-server
|
||||||
interface that allows components to interact with the service, send requests, get results, and even
|
interface that allows components to interact with the service, send requests, receive results,
|
||||||
do so across processes with interprocess communication (IPC). A bound service runs only as long as
|
and even do so across processes with interprocess communication (IPC). A bound service runs only
|
||||||
another application component is bound to it. Multiple components can bind to the service at once,
|
as long as another application component is bound to it. Multiple components can bind to the
|
||||||
but when all of them unbind, the service is destroyed.</dd>
|
service at once, but when all of them unbind, the service is destroyed.</dd>
|
||||||
</dl>
|
</dl>
|
||||||
|
|
||||||
<p>Although this documentation generally discusses these two types of services separately, your
|
<p>Although this documentation generally discusses started and bound services separately,
|
||||||
service can work both ways—it can be started (to run indefinitely) and also allow binding.
|
your service can work both ways—it can be started (to run indefinitely) and also allow
|
||||||
It's simply a matter of whether you implement a couple callback methods: {@link
|
binding. It's simply a matter of whether you implement a couple of callback methods: {@link
|
||||||
android.app.Service#onStartCommand onStartCommand()} to allow components to start it and {@link
|
android.app.Service#onStartCommand onStartCommand()} to allow components to start it and {@link
|
||||||
android.app.Service#onBind onBind()} to allow binding.</p>
|
android.app.Service#onBind onBind()} to allow binding.</p>
|
||||||
|
|
||||||
<p>Regardless of whether your application is started, bound, or both, any application component
|
<p>Regardless of whether your application is started, bound, or both, any application component
|
||||||
can use the service (even from a separate application), in the same way that any component can use
|
can use the service (even from a separate application) in the same way that any component can use
|
||||||
an activity—by starting it with an {@link android.content.Intent}. However, you can declare
|
an activity—by starting it with an {@link android.content.Intent}. However, you can declare
|
||||||
the service as private, in the manifest file, and block access from other applications. This is
|
the service as <em>private</em> in the manifest file and block access from other applications.
|
||||||
discussed more in the section about <a href="#Declaring">Declaring the service in the
|
This is discussed more in the section about <a href="#Declaring">Declaring the service in the
|
||||||
manifest</a>.</p>
|
manifest</a>.</p>
|
||||||
|
|
||||||
<p class="caution"><strong>Caution:</strong> A service runs in the
|
<p class="caution"><strong>Caution:</strong> A service runs in the
|
||||||
main thread of its hosting process—the service does <strong>not</strong> create its own thread
|
main thread of its hosting process; the service does <strong>not</strong> create its own
|
||||||
and does <strong>not</strong> run in a separate process (unless you specify otherwise). This means
|
thread and does <strong>not</strong> run in a separate process unless you specify otherwise. If
|
||||||
that, if your service is going to do any CPU intensive work or blocking operations (such as MP3
|
your service is going to perform any CPU-intensive work or blocking operations, such as MP3
|
||||||
playback or networking), you should create a new thread within the service to do that work. By using
|
playback or networking, you should create a new thread within the service to complete that work.
|
||||||
a separate thread, you will reduce the risk of Application Not Responding (ANR) errors and the
|
By using a separate thread, you can reduce the risk of Application Not Responding (ANR) errors,
|
||||||
application's main thread can remain dedicated to user interaction with your activities.</p>
|
and the application's main thread can remain dedicated to user interaction with your
|
||||||
|
activities.</p>
|
||||||
|
|
||||||
|
<h2 id="Basics">The basics</h2>
|
||||||
<h2 id="Basics">The Basics</h2>
|
|
||||||
|
|
||||||
<div class="sidebox-wrapper">
|
<div class="sidebox-wrapper">
|
||||||
<div class="sidebox">
|
<div class="sidebox">
|
||||||
<h3>Should you use a service or a thread?</h3>
|
<h3>Should you use a service or a thread?</h3>
|
||||||
<p>A service is simply a component that can run in the background even when the user is not
|
<p>A service is simply a component that can run in the background, even when the user is not
|
||||||
interacting with your application. Thus, you should create a service only if that is what you
|
interacting with your application, so you should create a service only if that is what you
|
||||||
need.</p>
|
need.</p>
|
||||||
<p>If you need to perform work outside your main thread, but only while the user is interacting
|
<p>If you must perform work outside of your main thread, but only while the user is interacting
|
||||||
with your application, then you should probably instead create a new thread and not a service. For
|
with your application, you should instead create a new thread. For example, if you want to
|
||||||
example, if you want to play some music, but only while your activity is running, you might create
|
play some music, but only while your activity is running, you might create
|
||||||
a thread in {@link android.app.Activity#onCreate onCreate()}, start running it in {@link
|
a thread in {@link android.app.Activity#onCreate onCreate()}, start running it in {@link
|
||||||
android.app.Activity#onStart onStart()}, then stop it in {@link android.app.Activity#onStop
|
android.app.Activity#onStart onStart()}, and stop it in {@link android.app.Activity#onStop
|
||||||
onStop()}. Also consider using {@link android.os.AsyncTask} or {@link android.os.HandlerThread},
|
onStop()}. Also consider using {@link android.os.AsyncTask} or {@link android.os.HandlerThread}
|
||||||
instead of the traditional {@link java.lang.Thread} class. See the <a
|
instead of the traditional {@link java.lang.Thread} class. See the <a
|
||||||
href="{@docRoot}guide/components/processes-and-threads.html#Threads">Processes and
|
href="{@docRoot}guide/components/processes-and-threads.html#Threads">Processes and
|
||||||
Threading</a> document for more information about threads.</p>
|
Threading</a> document for more information about threads.</p>
|
||||||
@@ -121,78 +131,81 @@ blocking operations.</p>
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p>To create a service, you must create a subclass of {@link android.app.Service} (or one
|
<p>To create a service, you must create a subclass of {@link android.app.Service} or use one
|
||||||
of its existing subclasses). In your implementation, you need to override some callback methods that
|
of its existing subclasses. In your implementation, you must override some callback methods that
|
||||||
handle key aspects of the service lifecycle and provide a mechanism for components to bind to
|
handle key aspects of the service lifecycle and provide a mechanism that allows the components to
|
||||||
the service, if appropriate. The most important callback methods you should override are:</p>
|
bind to the service, if appropriate. These are the most important callback methods that you should
|
||||||
|
override:</p>
|
||||||
|
|
||||||
<dl>
|
<dl>
|
||||||
<dt>{@link android.app.Service#onStartCommand onStartCommand()}</dt>
|
<dt>{@link android.app.Service#onStartCommand onStartCommand()}</dt>
|
||||||
<dd>The system calls this method when another component, such as an activity,
|
<dd>The system invokes this method by calling {@link android.content.Context#startService
|
||||||
requests that the service be started, by calling {@link android.content.Context#startService
|
startService()} when another component (such as an activity) requests that the service be started.
|
||||||
startService()}. Once this method executes, the service is started and can run in the
|
When this method executes, the service is started and can run in the
|
||||||
background indefinitely. If you implement this, it is your responsibility to stop the service when
|
background indefinitely. If you implement this, it is your responsibility to stop the service when
|
||||||
its work is done, by calling {@link android.app.Service#stopSelf stopSelf()} or {@link
|
its work is complete by calling {@link android.app.Service#stopSelf stopSelf()} or {@link
|
||||||
android.content.Context#stopService stopService()}. (If you only want to provide binding, you don't
|
android.content.Context#stopService stopService()}. If you only want to provide binding, you don't
|
||||||
need to implement this method.)</dd>
|
need to implement this method.</dd>
|
||||||
<dt>{@link android.app.Service#onBind onBind()}</dt>
|
<dt>{@link android.app.Service#onBind onBind()}</dt>
|
||||||
<dd>The system calls this method when another component wants to bind with the
|
<dd>The system invokes this method by calling {@link android.content.Context#bindService
|
||||||
service (such as to perform RPC), by calling {@link android.content.Context#bindService
|
bindService()} when another component wants to bind with the service (such as to perform RPC).
|
||||||
bindService()}. In your implementation of this method, you must provide an interface that clients
|
In your implementation of this method, you must provide an interface that clients
|
||||||
use to communicate with the service, by returning an {@link android.os.IBinder}. You must always
|
use to communicate with the service by returning an {@link android.os.IBinder}. You must always
|
||||||
implement this method, but if you don't want to allow binding, then you should return null.</dd>
|
implement this method; however, if you don't want to allow binding, you should return
|
||||||
|
null.</dd>
|
||||||
<dt>{@link android.app.Service#onCreate()}</dt>
|
<dt>{@link android.app.Service#onCreate()}</dt>
|
||||||
<dd>The system calls this method when the service is first created, to perform one-time setup
|
<dd>The system invokes this method to perform one-time setup procedures when the service is
|
||||||
procedures (before it calls either {@link android.app.Service#onStartCommand onStartCommand()} or
|
initially created (before it calls either
|
||||||
|
{@link android.app.Service#onStartCommand onStartCommand()} or
|
||||||
{@link android.app.Service#onBind onBind()}). If the service is already running, this method is not
|
{@link android.app.Service#onBind onBind()}). If the service is already running, this method is not
|
||||||
called.</dd>
|
called.</dd>
|
||||||
<dt>{@link android.app.Service#onDestroy()}</dt>
|
<dt>{@link android.app.Service#onDestroy()}</dt>
|
||||||
<dd>The system calls this method when the service is no longer used and is being destroyed.
|
<dd>The system invokes this method when the service is no longer used and is being destroyed.
|
||||||
Your service should implement this to clean up any resources such as threads, registered
|
Your service should implement this to clean up any resources such as threads, registered
|
||||||
listeners, receivers, etc. This is the last call the service receives.</dd>
|
listeners, or receivers. This is the last call that the service receives.</dd>
|
||||||
</dl>
|
</dl>
|
||||||
|
|
||||||
<p>If a component starts the service by calling {@link
|
<p>If a component starts the service by calling {@link
|
||||||
android.content.Context#startService startService()} (which results in a call to {@link
|
android.content.Context#startService startService()} (which results in a call to {@link
|
||||||
android.app.Service#onStartCommand onStartCommand()}), then the service
|
android.app.Service#onStartCommand onStartCommand()}), the service
|
||||||
remains running until it stops itself with {@link android.app.Service#stopSelf()} or another
|
continues to run until it stops itself with {@link android.app.Service#stopSelf()} or another
|
||||||
component stops it by calling {@link android.content.Context#stopService stopService()}.</p>
|
component stops it by calling {@link android.content.Context#stopService stopService()}.</p>
|
||||||
|
|
||||||
<p>If a component calls
|
<p>If a component calls
|
||||||
{@link android.content.Context#bindService bindService()} to create the service (and {@link
|
{@link android.content.Context#bindService bindService()} to create the service and {@link
|
||||||
android.app.Service#onStartCommand onStartCommand()} is <em>not</em> called), then the service runs
|
android.app.Service#onStartCommand onStartCommand()} is <em>not</em> called, the service runs
|
||||||
only as long as the component is bound to it. Once the service is unbound from all clients, the
|
only as long as the component is bound to it. After the service is unbound from all of its clients,
|
||||||
system destroys it.</p>
|
the system destroys it.</p>
|
||||||
|
|
||||||
<p>The Android system will force-stop a service only when memory is low and it must recover system
|
<p>The Android system force-stops a service only when memory is low and it must recover system
|
||||||
resources for the activity that has user focus. If the service is bound to an activity that has user
|
resources for the activity that has user focus. If the service is bound to an activity that has user
|
||||||
focus, then it's less likely to be killed, and if the service is declared to <a
|
focus, it's less likely to be killed; if the service is declared to <a
|
||||||
href="#Foreground">run in the foreground</a> (discussed later), then it will almost never be killed.
|
href="#Foreground">run in the foreground</a>, it's rarely killed.
|
||||||
Otherwise, if the service was started and is long-running, then the system will lower its position
|
If the service is started and is long-running, the system lowers its position
|
||||||
in the list of background tasks over time and the service will become highly susceptible to
|
in the list of background tasks over time, and the service becomes highly susceptible to
|
||||||
killing—if your service is started, then you must design it to gracefully handle restarts
|
killing—if your service is started, you must design it to gracefully handle restarts
|
||||||
by the system. If the system kills your service, it restarts it as soon as resources become
|
by the system. If the system kills your service, it restarts it as soon as resources become
|
||||||
available again (though this also depends on the value you return from {@link
|
available, but this also depends on the value that you return from {@link
|
||||||
android.app.Service#onStartCommand onStartCommand()}, as discussed later). For more information
|
android.app.Service#onStartCommand onStartCommand()}. For more information
|
||||||
about when the system might destroy a service, see the <a
|
about when the system might destroy a service, see the <a
|
||||||
href="{@docRoot}guide/components/processes-and-threads.html">Processes and Threading</a>
|
href="{@docRoot}guide/components/processes-and-threads.html">Processes and Threading</a>
|
||||||
document.</p>
|
document.</p>
|
||||||
|
|
||||||
<p>In the following sections, you'll see how you can create each type of service and how to use
|
<p>In the following sections, you'll see how you can create the
|
||||||
it from other application components.</p>
|
{@link android.content.Context#startService startService()} and
|
||||||
|
{@link android.content.Context#bindService bindService()} service methods, as well as how to use
|
||||||
|
them from other application components.</p>
|
||||||
|
|
||||||
<h3 id="Declaring">Declaring a service in the manifest</h3>
|
<h3 id="Declaring">Declaring a service in the manifest</h3>
|
||||||
|
|
||||||
<p>Like activities (and other components), you must declare all services in your application's
|
<p>You must declare all services in your application's
|
||||||
manifest file.</p>
|
manifest file, just as you do for activities and other components.</p>
|
||||||
|
|
||||||
<p>To declare your service, add a <a
|
<p>To declare your service, add a <a
|
||||||
href="{@docRoot}guide/topics/manifest/service-element.html">{@code <service>}</a> element
|
href="{@docRoot}guide/topics/manifest/service-element.html">{@code <service>}</a> element
|
||||||
as a child of the <a
|
as a child of the <a
|
||||||
href="{@docRoot}guide/topics/manifest/application-element.html">{@code <application>}</a>
|
href="{@docRoot}guide/topics/manifest/application-element.html">{@code <application>}</a>
|
||||||
element. For example:</p>
|
element. Here is an example:</p>
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
<manifest ... >
|
<manifest ... >
|
||||||
@@ -205,48 +218,44 @@ element. For example:</p>
|
|||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
<p>See the <a
|
<p>See the <a
|
||||||
href="{@docRoot}guide/topics/manifest/service-element.html">{@code <service>}</a> element
|
href="{@docRoot}guide/topics/manifest/service-element.html">{@code <service>}</a> element
|
||||||
reference for more information about declaring your service in the manifest.</p>
|
reference for more information about declaring your service in the manifest.</p>
|
||||||
|
|
||||||
<p>There are other attributes you can include in the <a
|
<p>There are other attributes that you can include in the <a
|
||||||
href="{@docRoot}guide/topics/manifest/service-element.html">{@code <service>}</a> element to
|
href="{@docRoot}guide/topics/manifest/service-element.html">{@code <service>}</a> element to
|
||||||
define properties such as permissions required to start the service and the process in
|
define properties such as the permissions that are required to start the service and the process in
|
||||||
which the service should run. The <a
|
which the service should run. The <a
|
||||||
href="{@docRoot}guide/topics/manifest/service-element.html#nm">{@code android:name}</a>
|
href="{@docRoot}guide/topics/manifest/service-element.html#nm">{@code android:name}</a>
|
||||||
attribute is the only required attribute—it specifies the class name of the service. Once
|
attribute is the only required attribute—it specifies the class name of the service. After
|
||||||
you publish your application, you should not change this name, because if you do, you risk breaking
|
you publish your application, leave this name unchanged to avoid the risk of breaking
|
||||||
code due to dependence on explicit intents to start or bind the service (read the blog post, <a
|
code due to dependence on explicit intents to start or bind the service (read the blog post, <a
|
||||||
href="http://android-developers.blogspot.com/2011/06/things-that-cannot-change.html">Things
|
href="http://android-developers.blogspot.com/2011/06/things-that-cannot-change.html">Things
|
||||||
That Cannot Change</a>).
|
That Cannot Change</a>).
|
||||||
|
|
||||||
<p>To ensure your app is secure, <strong>always use an explicit intent when starting or binding
|
<p class="caution"><strong>Caution</strong>: To ensure that your app is secure, always use an
|
||||||
your {@link android.app.Service}</strong> and do not declare intent filters for the service. If
|
explicit intent when starting a {@link android.app.Service} and do not declare intent filters for
|
||||||
it's critical that you allow for some amount of ambiguity as to which service starts, you can
|
your services. Using an implicit intent to start a service is a security hazard because you cannot
|
||||||
supply intent filters for your services and exclude the component name from the {@link
|
be certain of the service that will respond to the intent, and the user cannot see which service
|
||||||
android.content.Intent}, but you then must set the package for the intent with {@link
|
starts. Beginning with Android 5.0 (API level 21), the system throws an exception if you call
|
||||||
android.content.Intent#setPackage setPackage()}, which provides sufficient disambiguation for the
|
{@link android.content.Context#bindService bindService()} with an implicit intent.</p>
|
||||||
target service.</p>
|
|
||||||
|
|
||||||
<p>Additionally, you can ensure that your service is available to only your app by
|
<p>You can ensure that your service is available to only your app by
|
||||||
including the <a
|
including the <a
|
||||||
href="{@docRoot}guide/topics/manifest/service-element.html#exported">{@code android:exported}</a>
|
href="{@docRoot}guide/topics/manifest/service-element.html#exported">{@code android:exported}</a>
|
||||||
attribute and setting it to {@code "false"}. This effectively stops other apps from starting your
|
attribute and setting it to {@code false}. This effectively stops other apps from starting your
|
||||||
service, even when using an explicit intent.</p>
|
service, even when using an explicit intent.</p>
|
||||||
|
|
||||||
|
<h2 id="CreatingStartedService">Creating a started service</h2>
|
||||||
|
|
||||||
|
|
||||||
<h2 id="CreatingStartedService">Creating a Started Service</h2>
|
|
||||||
|
|
||||||
<p>A started service is one that another component starts by calling {@link
|
<p>A started service is one that another component starts by calling {@link
|
||||||
android.content.Context#startService startService()}, resulting in a call to the service's
|
android.content.Context#startService startService()}, which results in a call to the service's
|
||||||
{@link android.app.Service#onStartCommand onStartCommand()} method.</p>
|
{@link android.app.Service#onStartCommand onStartCommand()} method.</p>
|
||||||
|
|
||||||
<p>When a service is started, it has a lifecycle that's independent of the
|
<p>When a service is started, it has a lifecycle that's independent of the
|
||||||
component that started it and the service can run in the background indefinitely, even if
|
component that started it. The service can run in the background indefinitely, even if
|
||||||
the component that started it is destroyed. As such, the service should stop itself when its job
|
the component that started it is destroyed. As such, the service should stop itself when its job
|
||||||
is done by calling {@link android.app.Service#stopSelf stopSelf()}, or another component can stop it
|
is complete by calling {@link android.app.Service#stopSelf stopSelf()}, or another component can
|
||||||
by calling {@link android.content.Context#stopService stopService()}.</p>
|
stop it by calling {@link android.content.Context#stopService stopService()}.</p>
|
||||||
|
|
||||||
<p>An application component such as an activity can start the service by calling {@link
|
<p>An application component such as an activity can start the service by calling {@link
|
||||||
android.content.Context#startService startService()} and passing an {@link android.content.Intent}
|
android.content.Context#startService startService()} and passing an {@link android.content.Intent}
|
||||||
@@ -254,65 +263,65 @@ that specifies the service and includes any data for the service to use. The ser
|
|||||||
this {@link android.content.Intent} in the {@link android.app.Service#onStartCommand
|
this {@link android.content.Intent} in the {@link android.app.Service#onStartCommand
|
||||||
onStartCommand()} method.</p>
|
onStartCommand()} method.</p>
|
||||||
|
|
||||||
<p>For instance, suppose an activity needs to save some data to an online database. The activity can
|
<p>For instance, suppose an activity needs to save some data to an online database. The activity
|
||||||
start a companion service and deliver it the data to save by passing an intent to {@link
|
can start a companion service and deliver it the data to save by passing an intent to {@link
|
||||||
android.content.Context#startService startService()}. The service receives the intent in {@link
|
android.content.Context#startService startService()}. The service receives the intent in {@link
|
||||||
android.app.Service#onStartCommand onStartCommand()}, connects to the Internet and performs the
|
android.app.Service#onStartCommand onStartCommand()}, connects to the Internet, and performs the
|
||||||
database transaction. When the transaction is done, the service stops itself and it is
|
database transaction. When the transaction is complete, the service stops itself and is
|
||||||
destroyed.</p>
|
destroyed.</p>
|
||||||
|
|
||||||
<p class="caution"><strong>Caution:</strong> A service runs in the same process as the application
|
<p class="caution"><strong>Caution:</strong> A service runs in the same process as the application
|
||||||
in which it is declared and in the main thread of that application, by default. So, if your service
|
in which it is declared and in the main thread of that application by default. If your service
|
||||||
performs intensive or blocking operations while the user interacts with an activity from the same
|
performs intensive or blocking operations while the user interacts with an activity from the same
|
||||||
application, the service will slow down activity performance. To avoid impacting application
|
application, the service slows down activity performance. To avoid impacting application
|
||||||
performance, you should start a new thread inside the service.</p>
|
performance, start a new thread inside the service.</p>
|
||||||
|
|
||||||
<p>Traditionally, there are two classes you can extend to create a started service:</p>
|
<p>Traditionally, there are two classes you can extend to create a started service:</p>
|
||||||
|
|
||||||
<dl>
|
<dl>
|
||||||
<dt>{@link android.app.Service}</dt>
|
<dt>{@link android.app.Service}</dt>
|
||||||
<dd>This is the base class for all services. When you extend this class, it's important that
|
<dd>This is the base class for all services. When you extend this class, it's important to
|
||||||
you create a new thread in which to do all the service's work, because the service uses your
|
create a new thread in which the service can complete all of its work; the service uses your
|
||||||
application's main thread, by default, which could slow the performance of any activity your
|
application's main thread by default, which can slow the performance of any activity that your
|
||||||
application is running.</dd>
|
application is running.</dd>
|
||||||
<dt>{@link android.app.IntentService}</dt>
|
<dt>{@link android.app.IntentService}</dt>
|
||||||
<dd>This is a subclass of {@link android.app.Service} that uses a worker thread to handle all
|
<dd>This is a subclass of {@link android.app.Service} that uses a worker thread to handle all of
|
||||||
start requests, one at a time. This is the best option if you don't require that your service
|
the start requests, one at a time. This is the best option if you don't require that your service
|
||||||
handle multiple requests simultaneously. All you need to do is implement {@link
|
handle multiple requests simultaneously. Implement {@link
|
||||||
android.app.IntentService#onHandleIntent onHandleIntent()}, which receives the intent for each
|
android.app.IntentService#onHandleIntent onHandleIntent()}, which receives the intent for each
|
||||||
start request so you can do the background work.</dd>
|
start request so that you can complete the background work.</dd>
|
||||||
</dl>
|
</dl>
|
||||||
|
|
||||||
<p>The following sections describe how you can implement your service using either one for these
|
<p>The following sections describe how you can implement your service using either one for these
|
||||||
classes.</p>
|
classes.</p>
|
||||||
|
|
||||||
|
|
||||||
<h3 id="ExtendingIntentService">Extending the IntentService class</h3>
|
<h3 id="ExtendingIntentService">Extending the IntentService class</h3>
|
||||||
|
|
||||||
<p>Because most started services don't need to handle multiple requests simultaneously
|
<p>Because most of the started services don't need to handle multiple requests simultaneously
|
||||||
(which can actually be a dangerous multi-threading scenario), it's probably best if you
|
(which can actually be a dangerous multi-threading scenario), it's best that you
|
||||||
implement your service using the {@link android.app.IntentService} class.</p>
|
implement your service using the {@link android.app.IntentService} class.</p>
|
||||||
|
|
||||||
<p>The {@link android.app.IntentService} does the following:</p>
|
<p>The {@link android.app.IntentService} class does the following:</p>
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<li>Creates a default worker thread that executes all intents delivered to {@link
|
<li>It creates a default worker thread that executes all of the intents that are delivered to
|
||||||
android.app.Service#onStartCommand onStartCommand()} separate from your application's main
|
{@link android.app.Service#onStartCommand onStartCommand()}, separate from your application's main
|
||||||
thread.</li>
|
thread.</li>
|
||||||
<li>Creates a work queue that passes one intent at a time to your {@link
|
<li>Creates a work queue that passes one intent at a time to your {@link
|
||||||
android.app.IntentService#onHandleIntent onHandleIntent()} implementation, so you never have to
|
android.app.IntentService#onHandleIntent onHandleIntent()} implementation, so you never have to
|
||||||
worry about multi-threading.</li>
|
worry about multi-threading.</li>
|
||||||
<li>Stops the service after all start requests have been handled, so you never have to call
|
<li>Stops the service after all of the start requests are handled, so you never have to call
|
||||||
{@link android.app.Service#stopSelf}.</li>
|
{@link android.app.Service#stopSelf}.</li>
|
||||||
<li>Provides default implementation of {@link android.app.IntentService#onBind onBind()} that
|
<li>Provides a default implementation of {@link android.app.IntentService#onBind onBind()}
|
||||||
returns null.</li>
|
that returns null.</li>
|
||||||
<li>Provides a default implementation of {@link android.app.IntentService#onStartCommand
|
<li>Provides a default implementation of {@link android.app.IntentService#onStartCommand
|
||||||
onStartCommand()} that sends the intent to the work queue and then to your {@link
|
onStartCommand()} that sends the intent to the work queue and then to your {@link
|
||||||
android.app.IntentService#onHandleIntent onHandleIntent()} implementation.</li>
|
android.app.IntentService#onHandleIntent onHandleIntent()} implementation.</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<p>All this adds up to the fact that all you need to do is implement {@link
|
<p>To complete the work that is provided by the client, implement {@link
|
||||||
android.app.IntentService#onHandleIntent onHandleIntent()} to do the work provided by the
|
android.app.IntentService#onHandleIntent onHandleIntent()}.
|
||||||
client. (Though, you also need to provide a small constructor for the service.)</p>
|
However, you also need to provide a small constructor for the service.</p>
|
||||||
|
|
||||||
<p>Here's an example implementation of {@link android.app.IntentService}:</p>
|
<p>Here's an example implementation of {@link android.app.IntentService}:</p>
|
||||||
|
|
||||||
@@ -352,12 +361,12 @@ android.app.IntentService#onHandleIntent onHandleIntent()}.</p>
|
|||||||
<p>If you decide to also override other callback methods, such as {@link
|
<p>If you decide to also override other callback methods, such as {@link
|
||||||
android.app.IntentService#onCreate onCreate()}, {@link
|
android.app.IntentService#onCreate onCreate()}, {@link
|
||||||
android.app.IntentService#onStartCommand onStartCommand()}, or {@link
|
android.app.IntentService#onStartCommand onStartCommand()}, or {@link
|
||||||
android.app.IntentService#onDestroy onDestroy()}, be sure to call the super implementation, so
|
android.app.IntentService#onDestroy onDestroy()}, be sure to call the super implementation so
|
||||||
that the {@link android.app.IntentService} can properly handle the life of the worker thread.</p>
|
that the {@link android.app.IntentService} can properly handle the life of the worker thread.</p>
|
||||||
|
|
||||||
<p>For example, {@link android.app.IntentService#onStartCommand onStartCommand()} must return
|
<p>For example, {@link android.app.IntentService#onStartCommand onStartCommand()} must return
|
||||||
the default implementation (which is how the intent gets delivered to {@link
|
the default implementation, which is how the intent is delivered to {@link
|
||||||
android.app.IntentService#onHandleIntent onHandleIntent()}):</p>
|
android.app.IntentService#onHandleIntent onHandleIntent()}:</p>
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
@Override
|
@Override
|
||||||
@@ -369,22 +378,21 @@ public int onStartCommand(Intent intent, int flags, int startId) {
|
|||||||
|
|
||||||
<p>Besides {@link android.app.IntentService#onHandleIntent onHandleIntent()}, the only method
|
<p>Besides {@link android.app.IntentService#onHandleIntent onHandleIntent()}, the only method
|
||||||
from which you don't need to call the super class is {@link android.app.IntentService#onBind
|
from which you don't need to call the super class is {@link android.app.IntentService#onBind
|
||||||
onBind()} (but you only need to implement that if your service allows binding).</p>
|
onBind()}. You need to implement this only if your service allows binding.</p>
|
||||||
|
|
||||||
<p>In the next section, you'll see how the same kind of service is implemented when extending
|
<p>In the next section, you'll see how the same kind of service is implemented when extending
|
||||||
the base {@link android.app.Service} class, which is a lot more code, but which might be
|
the base {@link android.app.Service} class, which uses more code, but might be
|
||||||
appropriate if you need to handle simultaneous start requests.</p>
|
appropriate if you need to handle simultaneous start requests.</p>
|
||||||
|
|
||||||
|
|
||||||
<h3 id="ExtendingService">Extending the Service class</h3>
|
<h3 id="ExtendingService">Extending the Service class</h3>
|
||||||
|
|
||||||
<p>As you saw in the previous section, using {@link android.app.IntentService} makes your
|
<p>Using {@link android.app.IntentService} makes your
|
||||||
implementation of a started service very simple. If, however, you require your service to
|
implementation of a started service very simple. If, however, you require your service to
|
||||||
perform multi-threading (instead of processing start requests through a work queue), then you
|
perform multi-threading (instead of processing start requests through a work queue), you
|
||||||
can extend the {@link android.app.Service} class to handle each intent.</p>
|
can extend the {@link android.app.Service} class to handle each intent.</p>
|
||||||
|
|
||||||
<p>For comparison, the following example code is an implementation of the {@link
|
<p>For comparison, the following example code shows an implementation of the {@link
|
||||||
android.app.Service} class that performs the exact same work as the example above using {@link
|
android.app.Service} class that performs the same work as the previous example using {@link
|
||||||
android.app.IntentService}. That is, for each start request, it uses a worker thread to perform the
|
android.app.IntentService}. That is, for each start request, it uses a worker thread to perform the
|
||||||
job and processes only one request at a time.</p>
|
job and processes only one request at a time.</p>
|
||||||
|
|
||||||
@@ -460,20 +468,20 @@ public class HelloService extends Service {
|
|||||||
|
|
||||||
<p>However, because you handle each call to {@link android.app.Service#onStartCommand
|
<p>However, because you handle each call to {@link android.app.Service#onStartCommand
|
||||||
onStartCommand()} yourself, you can perform multiple requests simultaneously. That's not what
|
onStartCommand()} yourself, you can perform multiple requests simultaneously. That's not what
|
||||||
this example does, but if that's what you want, then you can create a new thread for each
|
this example does, but if that's what you want, you can create a new thread for each
|
||||||
request and run them right away (instead of waiting for the previous request to finish).</p>
|
request and run them right away instead of waiting for the previous request to finish.</p>
|
||||||
|
|
||||||
<p>Notice that the {@link android.app.Service#onStartCommand onStartCommand()} method must return an
|
<p>Notice that the {@link android.app.Service#onStartCommand onStartCommand()} method must return an
|
||||||
integer. The integer is a value that describes how the system should continue the service in the
|
integer. The integer is a value that describes how the system should continue the service in the
|
||||||
event that the system kills it (as discussed above, the default implementation for {@link
|
event that the system kills it. The default implementation for {@link
|
||||||
android.app.IntentService} handles this for you, though you are able to modify it). The return value
|
android.app.IntentService} handles this for you, but you are able to modify it. The return value
|
||||||
from {@link android.app.Service#onStartCommand onStartCommand()} must be one of the following
|
from {@link android.app.Service#onStartCommand onStartCommand()} must be one of the following
|
||||||
constants:</p>
|
constants:</p>
|
||||||
|
|
||||||
<dl>
|
<dl>
|
||||||
<dt>{@link android.app.Service#START_NOT_STICKY}</dt>
|
<dt>{@link android.app.Service#START_NOT_STICKY}</dt>
|
||||||
<dd>If the system kills the service after {@link android.app.Service#onStartCommand
|
<dd>If the system kills the service after {@link android.app.Service#onStartCommand
|
||||||
onStartCommand()} returns, <em>do not</em> recreate the service, unless there are pending
|
onStartCommand()} returns, <em>do not</em> recreate the service unless there are pending
|
||||||
intents to deliver. This is the safest option to avoid running your service when not necessary
|
intents to deliver. This is the safest option to avoid running your service when not necessary
|
||||||
and when your application can simply restart any unfinished jobs.</dd>
|
and when your application can simply restart any unfinished jobs.</dd>
|
||||||
<dt>{@link android.app.Service#START_STICKY}</dt>
|
<dt>{@link android.app.Service#START_STICKY}</dt>
|
||||||
@@ -481,9 +489,9 @@ and when your application can simply restart any unfinished jobs.</dd>
|
|||||||
onStartCommand()} returns, recreate the service and call {@link
|
onStartCommand()} returns, recreate the service and call {@link
|
||||||
android.app.Service#onStartCommand onStartCommand()}, but <em>do not</em> redeliver the last intent.
|
android.app.Service#onStartCommand onStartCommand()}, but <em>do not</em> redeliver the last intent.
|
||||||
Instead, the system calls {@link android.app.Service#onStartCommand onStartCommand()} with a
|
Instead, the system calls {@link android.app.Service#onStartCommand onStartCommand()} with a
|
||||||
null intent, unless there were pending intents to start the service, in which case,
|
null intent unless there are pending intents to start the service. In that case,
|
||||||
those intents are delivered. This is suitable for media players (or similar services) that are not
|
those intents are delivered. This is suitable for media players (or similar services) that are not
|
||||||
executing commands, but running indefinitely and waiting for a job.</dd>
|
executing commands but are running indefinitely and waiting for a job.</dd>
|
||||||
<dt>{@link android.app.Service#START_REDELIVER_INTENT}</dt>
|
<dt>{@link android.app.Service#START_REDELIVER_INTENT}</dt>
|
||||||
<dd>If the system kills the service after {@link android.app.Service#onStartCommand
|
<dd>If the system kills the service after {@link android.app.Service#onStartCommand
|
||||||
onStartCommand()} returns, recreate the service and call {@link
|
onStartCommand()} returns, recreate the service and call {@link
|
||||||
@@ -494,35 +502,35 @@ actively performing a job that should be immediately resumed, such as downloadin
|
|||||||
<p>For more details about these return values, see the linked reference documentation for each
|
<p>For more details about these return values, see the linked reference documentation for each
|
||||||
constant.</p>
|
constant.</p>
|
||||||
|
|
||||||
|
<h3 id="StartingAService">Starting a service</h3>
|
||||||
|
|
||||||
<h3 id="StartingAService">Starting a Service</h3>
|
|
||||||
|
|
||||||
<p>You can start a service from an activity or other application component by passing an
|
<p>You can start a service from an activity or other application component by passing an
|
||||||
{@link android.content.Intent} (specifying the service to start) to {@link
|
{@link android.content.Intent} (specifying the service to start) to {@link
|
||||||
android.content.Context#startService startService()}. The Android system calls the service's {@link
|
android.content.Context#startService startService()}. The Android system calls the service's {@link
|
||||||
android.app.Service#onStartCommand onStartCommand()} method and passes it the {@link
|
android.app.Service#onStartCommand onStartCommand()} method and passes it the {@link
|
||||||
android.content.Intent}. (You should never call {@link android.app.Service#onStartCommand
|
android.content.Intent}.
|
||||||
onStartCommand()} directly.)</p>
|
|
||||||
|
<p class="note"><strong>Note</strong>: Never call
|
||||||
|
{@link android.app.Service#onStartCommand onStartCommand()} directly.</p>
|
||||||
|
|
||||||
<p>For example, an activity can start the example service in the previous section ({@code
|
<p>For example, an activity can start the example service in the previous section ({@code
|
||||||
HelloService}) using an explicit intent with {@link android.content.Context#startService
|
HelloService}) using an explicit intent with {@link android.content.Context#startService
|
||||||
startService()}:</p>
|
startService()}, as shown here:</p>
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
Intent intent = new Intent(this, HelloService.class);
|
Intent intent = new Intent(this, HelloService.class);
|
||||||
startService(intent);
|
startService(intent);
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
<p>The {@link android.content.Context#startService startService()} method returns immediately and
|
<p>The {@link android.content.Context#startService startService()} method returns immediately, and
|
||||||
the Android system calls the service's {@link android.app.Service#onStartCommand
|
the Android system calls the service's {@link android.app.Service#onStartCommand
|
||||||
onStartCommand()} method. If the service is not already running, the system first calls {@link
|
onStartCommand()} method. If the service is not already running, the system first calls {@link
|
||||||
android.app.Service#onCreate onCreate()}, then calls {@link android.app.Service#onStartCommand
|
android.app.Service#onCreate onCreate()}, and then it calls
|
||||||
onStartCommand()}.</p>
|
{@link android.app.Service#onStartCommand onStartCommand()}.</p>
|
||||||
|
|
||||||
<p>If the service does not also provide binding, the intent delivered with {@link
|
<p>If the service does not also provide binding, the intent that is delivered with {@link
|
||||||
android.content.Context#startService startService()} is the only mode of communication between the
|
android.content.Context#startService startService()} is the only mode of communication between the
|
||||||
application component and the service. However, if you want the service to send a result back, then
|
application component and the service. However, if you want the service to send a result back,
|
||||||
the client that starts the service can create a {@link android.app.PendingIntent} for a broadcast
|
the client that starts the service can create a {@link android.app.PendingIntent} for a broadcast
|
||||||
(with {@link android.app.PendingIntent#getBroadcast getBroadcast()}) and deliver it to the service
|
(with {@link android.app.PendingIntent#getBroadcast getBroadcast()}) and deliver it to the service
|
||||||
in the {@link android.content.Intent} that starts the service. The service can then use the
|
in the {@link android.content.Intent} that starts the service. The service can then use the
|
||||||
@@ -533,109 +541,102 @@ broadcast to deliver a result.</p>
|
|||||||
the service (with {@link android.app.Service#stopSelf stopSelf()} or {@link
|
the service (with {@link android.app.Service#stopSelf stopSelf()} or {@link
|
||||||
android.content.Context#stopService stopService()}) is required to stop it.</p>
|
android.content.Context#stopService stopService()}) is required to stop it.</p>
|
||||||
|
|
||||||
|
|
||||||
<h3 id="Stopping">Stopping a service</h3>
|
<h3 id="Stopping">Stopping a service</h3>
|
||||||
|
|
||||||
<p>A started service must manage its own lifecycle. That is, the system does not stop or
|
<p>A started service must manage its own lifecycle. That is, the system does not stop or
|
||||||
destroy the service unless it must recover system memory and the service
|
destroy the service unless it must recover system memory and the service
|
||||||
continues to run after {@link android.app.Service#onStartCommand onStartCommand()} returns. So,
|
continues to run after {@link android.app.Service#onStartCommand onStartCommand()} returns. The
|
||||||
the service must stop itself by calling {@link android.app.Service#stopSelf stopSelf()} or another
|
service must stop itself by calling {@link android.app.Service#stopSelf stopSelf()}, or another
|
||||||
component can stop it by calling {@link android.content.Context#stopService stopService()}.</p>
|
component can stop it by calling {@link android.content.Context#stopService stopService()}.</p>
|
||||||
|
|
||||||
<p>Once requested to stop with {@link android.app.Service#stopSelf stopSelf()} or {@link
|
<p>Once requested to stop with {@link android.app.Service#stopSelf stopSelf()} or {@link
|
||||||
android.content.Context#stopService stopService()}, the system destroys the service as soon as
|
android.content.Context#stopService stopService()}, the system destroys the service as soon as
|
||||||
possible.</p>
|
possible.</p>
|
||||||
|
|
||||||
<p>However, if your service handles multiple requests to {@link
|
<p>If your service handles multiple requests to {@link
|
||||||
android.app.Service#onStartCommand onStartCommand()} concurrently, then you shouldn't stop the
|
android.app.Service#onStartCommand onStartCommand()} concurrently, you shouldn't stop the
|
||||||
service when you're done processing a start request, because you might have since received a new
|
service when you're done processing a start request, as you might have received a new
|
||||||
start request (stopping at the end of the first request would terminate the second one). To avoid
|
start request (stopping at the end of the first request would terminate the second one). To avoid
|
||||||
this problem, you can use {@link android.app.Service#stopSelf(int)} to ensure that your request to
|
this problem, you can use {@link android.app.Service#stopSelf(int)} to ensure that your request to
|
||||||
stop the service is always based on the most recent start request. That is, when you call {@link
|
stop the service is always based on the most recent start request. That is, when you call {@link
|
||||||
android.app.Service#stopSelf(int)}, you pass the ID of the start request (the <code>startId</code>
|
android.app.Service#stopSelf(int)}, you pass the ID of the start request (the <code>startId</code>
|
||||||
delivered to {@link android.app.Service#onStartCommand onStartCommand()}) to which your stop request
|
delivered to {@link android.app.Service#onStartCommand onStartCommand()}) to which your stop request
|
||||||
corresponds. Then if the service received a new start request before you were able to call {@link
|
corresponds. Then, if the service receives a new start request before you are able to call {@link
|
||||||
android.app.Service#stopSelf(int)}, then the ID will not match and the service will not stop.</p>
|
android.app.Service#stopSelf(int)}, the ID does not match and the service does not stop.</p>
|
||||||
|
|
||||||
<p class="caution"><strong>Caution:</strong> It's important that your application stops its services
|
<p class="caution"><strong>Caution:</strong> To avoid wasting system resources and consuming
|
||||||
when it's done working, to avoid wasting system resources and consuming battery power. If necessary,
|
battery power, ensure that your application stops its services when it's done working.
|
||||||
other components can stop the service by calling {@link
|
If necessary, other components can stop the service by calling {@link
|
||||||
android.content.Context#stopService stopService()}. Even if you enable binding for the service,
|
android.content.Context#stopService stopService()}. Even if you enable binding for the service,
|
||||||
you must always stop the service yourself if it ever received a call to {@link
|
you must always stop the service yourself if it ever receives a call to {@link
|
||||||
android.app.Service#onStartCommand onStartCommand()}.</p>
|
android.app.Service#onStartCommand onStartCommand()}.</p>
|
||||||
|
|
||||||
<p>For more information about the lifecycle of a service, see the section below about <a
|
<p>For more information about the lifecycle of a service, see the section below about <a
|
||||||
href="#Lifecycle">Managing the Lifecycle of a Service</a>.</p>
|
href="#Lifecycle">Managing the Lifecycle of a Service</a>.</p>
|
||||||
|
|
||||||
|
<h2 id="CreatingBoundService">Creating a bound service</h2>
|
||||||
|
|
||||||
<h2 id="CreatingBoundService">Creating a Bound Service</h2>
|
|
||||||
|
|
||||||
<p>A bound service is one that allows application components to bind to it by calling {@link
|
<p>A bound service is one that allows application components to bind to it by calling {@link
|
||||||
android.content.Context#bindService bindService()} in order to create a long-standing connection
|
android.content.Context#bindService bindService()} to create a long-standing connection.
|
||||||
(and generally does not allow components to <em>start</em> it by calling {@link
|
It generally doesn't allow components to <em>start</em> it by calling {@link
|
||||||
android.content.Context#startService startService()}).</p>
|
android.content.Context#startService startService()}.</p>
|
||||||
|
|
||||||
<p>You should create a bound service when you want to interact with the service from activities
|
<p>Create a bound service when you want to interact with the service from activities
|
||||||
and other components in your application or to expose some of your application's functionality to
|
and other components in your application or to expose some of your application's functionality to
|
||||||
other applications, through interprocess communication (IPC).</p>
|
other applications through interprocess communication (IPC).</p>
|
||||||
|
|
||||||
<p>To create a bound service, you must implement the {@link
|
<p>To create a bound service, implement the {@link
|
||||||
android.app.Service#onBind onBind()} callback method to return an {@link android.os.IBinder} that
|
android.app.Service#onBind onBind()} callback method to return an {@link android.os.IBinder} that
|
||||||
defines the interface for communication with the service. Other application components can then call
|
defines the interface for communication with the service. Other application components can then call
|
||||||
{@link android.content.Context#bindService bindService()} to retrieve the interface and
|
{@link android.content.Context#bindService bindService()} to retrieve the interface and
|
||||||
begin calling methods on the service. The service lives only to serve the application component that
|
begin calling methods on the service. The service lives only to serve the application component that
|
||||||
is bound to it, so when there are no components bound to the service, the system destroys it
|
is bound to it, so when there are no components bound to the service, the system destroys it.
|
||||||
(you do <em>not</em> need to stop a bound service in the way you must when the service is started
|
You do <em>not</em> need to stop a bound service in the same way that you must when the service is
|
||||||
through {@link android.app.Service#onStartCommand onStartCommand()}).</p>
|
started through {@link android.app.Service#onStartCommand onStartCommand()}.</p>
|
||||||
|
|
||||||
<p>To create a bound service, the first thing you must do is define the interface that specifies
|
<p>To create a bound service, you must define the interface that specifies how a client can
|
||||||
how a client can communicate with the service. This interface between the service
|
communicate with the service. This interface between the service
|
||||||
and a client must be an implementation of {@link android.os.IBinder} and is what your service must
|
and a client must be an implementation of {@link android.os.IBinder} and is what your service must
|
||||||
return from the {@link android.app.Service#onBind
|
return from the {@link android.app.Service#onBind
|
||||||
onBind()} callback method. Once the client receives the {@link android.os.IBinder}, it can begin
|
onBind()} callback method. After the client receives the {@link android.os.IBinder}, it can begin
|
||||||
interacting with the service through that interface.</p>
|
interacting with the service through that interface.</p>
|
||||||
|
|
||||||
<p>Multiple clients can bind to the service at once. When a client is done interacting with the
|
<p>Multiple clients can bind to the service simultaneously. When a client is done interacting with
|
||||||
service, it calls {@link android.content.Context#unbindService unbindService()} to unbind. Once
|
the service, it calls {@link android.content.Context#unbindService unbindService()} to unbind.
|
||||||
there are no clients bound to the service, the system destroys the service.</p>
|
When there are no clients bound to the service, the system destroys the service.</p>
|
||||||
|
|
||||||
<p>There are multiple ways to implement a bound service and the implementation is more
|
<p>There are multiple ways to implement a bound service, and the implementation is more
|
||||||
complicated than a started service, so the bound service discussion appears in a separate
|
complicated than a started service. For these reasons, the bound service discussion appears in a
|
||||||
document about <a
|
separate document about <a
|
||||||
href="{@docRoot}guide/components/bound-services.html">Bound Services</a>.</p>
|
href="{@docRoot}guide/components/bound-services.html">Bound Services</a>.</p>
|
||||||
|
|
||||||
|
<h2 id="Notifications">Sending notifications to the user</h2>
|
||||||
|
|
||||||
|
<p>When a service is running, it can notify the user of events using <a
|
||||||
<h2 id="Notifications">Sending Notifications to the User</h2>
|
|
||||||
|
|
||||||
<p>Once running, a service can notify the user of events using <a
|
|
||||||
href="{@docRoot}guide/topics/ui/notifiers/toasts.html">Toast Notifications</a> or <a
|
href="{@docRoot}guide/topics/ui/notifiers/toasts.html">Toast Notifications</a> or <a
|
||||||
href="{@docRoot}guide/topics/ui/notifiers/notifications.html">Status Bar Notifications</a>.</p>
|
href="{@docRoot}guide/topics/ui/notifiers/notifications.html">Status Bar Notifications</a>.</p>
|
||||||
|
|
||||||
<p>A toast notification is a message that appears on the surface of the current window for a
|
<p>A toast notification is a message that appears on the surface of the current window for only a
|
||||||
moment then disappears, while a status bar notification provides an icon in the status bar with a
|
moment before disappearing. A status bar notification provides an icon in the status bar with a
|
||||||
message, which the user can select in order to take an action (such as start an activity).</p>
|
message, which the user can select in order to take an action (such as start an activity).</p>
|
||||||
|
|
||||||
<p>Usually, a status bar notification is the best technique when some background work has completed
|
<p>Usually, a status bar notification is the best technique to use when background work such as
|
||||||
(such as a file completed
|
a file download has completed, and the user can now act on it. When the user
|
||||||
downloading) and the user can now act on it. When the user selects the notification from the
|
selects the notification from the expanded view, the notification can start an activity
|
||||||
expanded view, the notification can start an activity (such as to view the downloaded file).</p>
|
(such as to display the downloaded file).</p>
|
||||||
|
|
||||||
<p>See the <a
|
<p>See the <a
|
||||||
href="{@docRoot}guide/topics/ui/notifiers/toasts.html">Toast Notifications</a> or <a
|
href="{@docRoot}guide/topics/ui/notifiers/toasts.html">Toast Notifications</a> or <a
|
||||||
href="{@docRoot}guide/topics/ui/notifiers/notifications.html">Status Bar Notifications</a>
|
href="{@docRoot}guide/topics/ui/notifiers/notifications.html">Status Bar Notifications</a>
|
||||||
developer guides for more information.</p>
|
developer guides for more information.</p>
|
||||||
|
|
||||||
|
<h2 id="Foreground">Running a service in the foreground</h2>
|
||||||
|
|
||||||
|
<p>A foreground service is a service that the
|
||||||
<h2 id="Foreground">Running a Service in the Foreground</h2>
|
user is actively aware of and is not a candidate for the system to kill when low on memory. A
|
||||||
|
|
||||||
<p>A foreground service is a service that's considered to be something the
|
|
||||||
user is actively aware of and thus not a candidate for the system to kill when low on memory. A
|
|
||||||
foreground service must provide a notification for the status bar, which is placed under the
|
foreground service must provide a notification for the status bar, which is placed under the
|
||||||
"Ongoing" heading, which means that the notification cannot be dismissed unless the service is
|
<em>Ongoing</em> heading. This means that the notification cannot be dismissed unless the service
|
||||||
either stopped or removed from the foreground.</p>
|
is either stopped or removed from the foreground.</p>
|
||||||
|
|
||||||
<p>For example, a music player that plays music from a service should be set to run in the
|
<p>For example, a music player that plays music from a service should be set to run in the
|
||||||
foreground, because the user is explicitly aware
|
foreground, because the user is explicitly aware
|
||||||
@@ -643,9 +644,9 @@ of its operation. The notification in the status bar might indicate the current
|
|||||||
the user to launch an activity to interact with the music player.</p>
|
the user to launch an activity to interact with the music player.</p>
|
||||||
|
|
||||||
<p>To request that your service run in the foreground, call {@link
|
<p>To request that your service run in the foreground, call {@link
|
||||||
android.app.Service#startForeground startForeground()}. This method takes two parameters: an integer
|
android.app.Service#startForeground startForeground()}. This method takes two parameters: an
|
||||||
that uniquely identifies the notification and the {@link
|
integer that uniquely identifies the notification and the {@link
|
||||||
android.app.Notification} for the status bar. For example:</p>
|
android.app.Notification} for the status bar. Here is an example:</p>
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
Notification notification = new Notification(R.drawable.icon, getText(R.string.ticker_text),
|
Notification notification = new Notification(R.drawable.icon, getText(R.string.ticker_text),
|
||||||
@@ -657,30 +658,27 @@ notification.setLatestEventInfo(this, getText(R.string.notification_title),
|
|||||||
startForeground(ONGOING_NOTIFICATION_ID, notification);
|
startForeground(ONGOING_NOTIFICATION_ID, notification);
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
<p class="caution"><strong>Caution:</strong> The integer ID you give to {@link
|
<p class="caution"><strong>Caution:</strong> The integer ID that you give to {@link
|
||||||
android.app.Service#startForeground startForeground()} must not be 0.</p>
|
android.app.Service#startForeground startForeground()} must not be 0.</p>
|
||||||
|
|
||||||
|
|
||||||
<p>To remove the service from the foreground, call {@link
|
<p>To remove the service from the foreground, call {@link
|
||||||
android.app.Service#stopForeground stopForeground()}. This method takes a boolean, indicating
|
android.app.Service#stopForeground stopForeground()}. This method takes a boolean, which indicates
|
||||||
whether to remove the status bar notification as well. This method does <em>not</em> stop the
|
whether to remove the status bar notification as well. This method does <em>not</em> stop the
|
||||||
service. However, if you stop the service while it's still running in the foreground, then the
|
service. However, if you stop the service while it's still running in the foreground, the
|
||||||
notification is also removed.</p>
|
notification is also removed.</p>
|
||||||
|
|
||||||
<p>For more information about notifications, see <a
|
<p>For more information about notifications, see <a
|
||||||
href="{@docRoot}guide/topics/ui/notifiers/notifications.html">Creating Status Bar
|
href="{@docRoot}guide/topics/ui/notifiers/notifications.html">Creating Status Bar
|
||||||
Notifications</a>.</p>
|
Notifications</a>.</p>
|
||||||
|
|
||||||
|
<h2 id="Lifecycle">Managing the lifecycle of a service</h2>
|
||||||
|
|
||||||
|
<p>The lifecycle of a service is much simpler than that of an activity. However, it's even more
|
||||||
|
important that you pay close attention to how your service is created and destroyed because a
|
||||||
|
service can run in the background without the user being aware.</p>
|
||||||
|
|
||||||
<h2 id="Lifecycle">Managing the Lifecycle of a Service</h2>
|
<p>The service lifecycle—from when it's created to when it's destroyed—can follow
|
||||||
|
either of these two paths:</p>
|
||||||
<p>The lifecycle of a service is much simpler than that of an activity. However, it's even more important
|
|
||||||
that you pay close attention to how your service is created and destroyed, because a service
|
|
||||||
can run in the background without the user being aware.</p>
|
|
||||||
|
|
||||||
<p>The service lifecycle—from when it's created to when it's destroyed—can follow two
|
|
||||||
different paths:</p>
|
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<li>A started service
|
<li>A started service
|
||||||
@@ -689,27 +687,26 @@ android.content.Context#startService startService()}. The service then runs inde
|
|||||||
stop itself by calling {@link
|
stop itself by calling {@link
|
||||||
android.app.Service#stopSelf() stopSelf()}. Another component can also stop the
|
android.app.Service#stopSelf() stopSelf()}. Another component can also stop the
|
||||||
service by calling {@link android.content.Context#stopService
|
service by calling {@link android.content.Context#stopService
|
||||||
stopService()}. When the service is stopped, the system destroys it..</p></li>
|
stopService()}. When the service is stopped, the system destroys it.</p></li>
|
||||||
|
|
||||||
<li>A bound service
|
<li>A bound service
|
||||||
<p>The service is created when another component (a client) calls {@link
|
<p>The service is created when another component (a client) calls {@link
|
||||||
android.content.Context#bindService bindService()}. The client then communicates with the service
|
android.content.Context#bindService bindService()}. The client then communicates with the service
|
||||||
through an {@link android.os.IBinder} interface. The client can close the connection by calling
|
through an {@link android.os.IBinder} interface. The client can close the connection by calling
|
||||||
{@link android.content.Context#unbindService unbindService()}. Multiple clients can bind to
|
{@link android.content.Context#unbindService unbindService()}. Multiple clients can bind to
|
||||||
the same service and when all of them unbind, the system destroys the service. (The service
|
the same service and when all of them unbind, the system destroys the service. The service
|
||||||
does <em>not</em> need to stop itself.)</p></li>
|
does <em>not</em> need to stop itself.</p></li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<p>These two paths are not entirely separate. That is, you can bind to a service that was already
|
<p>These two paths are not entirely separate. You can bind to a service that is already
|
||||||
started with {@link android.content.Context#startService startService()}. For example, a background
|
started with {@link android.content.Context#startService startService()}. For example, you can
|
||||||
music service could be started by calling {@link android.content.Context#startService
|
start a background music service by calling {@link android.content.Context#startService
|
||||||
startService()} with an {@link android.content.Intent} that identifies the music to play. Later,
|
startService()} with an {@link android.content.Intent} that identifies the music to play. Later,
|
||||||
possibly when the user wants to exercise some control over the player or get information about the
|
possibly when the user wants to exercise some control over the player or get information about the
|
||||||
current song, an activity can bind to the service by calling {@link
|
current song, an activity can bind to the service by calling {@link
|
||||||
android.content.Context#bindService bindService()}. In cases like this, {@link
|
android.content.Context#bindService bindService()}. In cases such as this, {@link
|
||||||
android.content.Context#stopService stopService()} or {@link android.app.Service#stopSelf
|
android.content.Context#stopService stopService()} or {@link android.app.Service#stopSelf
|
||||||
stopSelf()} does not actually stop the service until all clients unbind. </p>
|
stopSelf()} doesn't actually stop the service until all of the clients unbind.</p>
|
||||||
|
|
||||||
|
|
||||||
<h3 id="LifecycleCallbacks">Implementing the lifecycle callbacks</h3>
|
<h3 id="LifecycleCallbacks">Implementing the lifecycle callbacks</h3>
|
||||||
|
|
||||||
@@ -763,20 +760,30 @@ shows the lifecycle when the service is created with {@link android.content.Cont
|
|||||||
startService()} and the diagram on the right shows the lifecycle when the service is created
|
startService()} and the diagram on the right shows the lifecycle when the service is created
|
||||||
with {@link android.content.Context#bindService bindService()}.</p>
|
with {@link android.content.Context#bindService bindService()}.</p>
|
||||||
|
|
||||||
<p>By implementing these methods, you can monitor two nested loops of the service's lifecycle: </p>
|
<p>Figure 2 illustrates the typical callback methods for a service. Although the figure separates
|
||||||
|
services that are created by {@link android.content.Context#startService startService()} from those
|
||||||
|
created by {@link android.content.Context#bindService bindService()}, keep
|
||||||
|
in mind that any service, no matter how it's started, can potentially allow clients to bind to it.
|
||||||
|
A service that was initially started with {@link android.app.Service#onStartCommand
|
||||||
|
onStartCommand()} (by a client calling {@link android.content.Context#startService startService()})
|
||||||
|
can still receive a call to {@link android.app.Service#onBind onBind()} (when a client calls
|
||||||
|
{@link android.content.Context#bindService bindService()}).</p>
|
||||||
|
|
||||||
|
<p>By implementing these methods, you can monitor these two nested loops of the service's
|
||||||
|
lifecycle:</p>
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<li>The <strong>entire lifetime</strong> of a service happens between the time {@link
|
<li>The <strong>entire lifetime</strong> of a service occurs between the time that {@link
|
||||||
android.app.Service#onCreate onCreate()} is called and the time {@link
|
android.app.Service#onCreate onCreate()} is called and the time that {@link
|
||||||
android.app.Service#onDestroy} returns. Like an activity, a service does its initial setup in
|
android.app.Service#onDestroy} returns. Like an activity, a service does its initial setup in
|
||||||
{@link android.app.Service#onCreate onCreate()} and releases all remaining resources in {@link
|
{@link android.app.Service#onCreate onCreate()} and releases all remaining resources in {@link
|
||||||
android.app.Service#onDestroy onDestroy()}. For example, a
|
android.app.Service#onDestroy onDestroy()}. For example, a
|
||||||
music playback service could create the thread where the music will be played in {@link
|
music playback service can create the thread where the music is played in {@link
|
||||||
android.app.Service#onCreate onCreate()}, then stop the thread in {@link
|
android.app.Service#onCreate onCreate()}, and then it can stop the thread in {@link
|
||||||
android.app.Service#onDestroy onDestroy()}.
|
android.app.Service#onDestroy onDestroy()}.
|
||||||
|
|
||||||
<p>The {@link android.app.Service#onCreate onCreate()} and {@link android.app.Service#onDestroy
|
<p class="note"><strong>Note</strong>: The {@link android.app.Service#onCreate onCreate()}
|
||||||
onDestroy()} methods are called for all services, whether
|
and {@link android.app.Service#onDestroy onDestroy()} methods are called for all services, whether
|
||||||
they're created by {@link android.content.Context#startService startService()} or {@link
|
they're created by {@link android.content.Context#startService startService()} or {@link
|
||||||
android.content.Context#bindService bindService()}.</p></li>
|
android.content.Context#bindService bindService()}.</p></li>
|
||||||
|
|
||||||
@@ -784,8 +791,8 @@ android.content.Context#bindService bindService()}.</p></li>
|
|||||||
android.app.Service#onStartCommand onStartCommand()} or {@link android.app.Service#onBind onBind()}.
|
android.app.Service#onStartCommand onStartCommand()} or {@link android.app.Service#onBind onBind()}.
|
||||||
Each method is handed the {@link
|
Each method is handed the {@link
|
||||||
android.content.Intent} that was passed to either {@link android.content.Context#startService
|
android.content.Intent} that was passed to either {@link android.content.Context#startService
|
||||||
startService()} or {@link android.content.Context#bindService bindService()}, respectively.
|
startService()} or {@link android.content.Context#bindService bindService()}.
|
||||||
<p>If the service is started, the active lifetime ends the same time that the entire lifetime
|
<p>If the service is started, the active lifetime ends at the same time that the entire lifetime
|
||||||
ends (the service is still active even after {@link android.app.Service#onStartCommand
|
ends (the service is still active even after {@link android.app.Service#onStartCommand
|
||||||
onStartCommand()} returns). If the service is bound, the active lifetime ends when {@link
|
onStartCommand()} returns). If the service is bound, the active lifetime ends when {@link
|
||||||
android.app.Service#onUnbind onUnbind()} returns.</p>
|
android.app.Service#onUnbind onUnbind()} returns.</p>
|
||||||
@@ -795,26 +802,16 @@ android.app.Service#onUnbind onUnbind()} returns.</p>
|
|||||||
<p class="note"><strong>Note:</strong> Although a started service is stopped by a call to
|
<p class="note"><strong>Note:</strong> Although a started service is stopped by a call to
|
||||||
either {@link android.app.Service#stopSelf stopSelf()} or {@link
|
either {@link android.app.Service#stopSelf stopSelf()} or {@link
|
||||||
android.content.Context#stopService stopService()}, there is not a respective callback for the
|
android.content.Context#stopService stopService()}, there is not a respective callback for the
|
||||||
service (there's no {@code onStop()} callback). So, unless the service is bound to a client,
|
service (there's no {@code onStop()} callback). Unless the service is bound to a client,
|
||||||
the system destroys it when the service is stopped—{@link
|
the system destroys it when the service is stopped—{@link
|
||||||
android.app.Service#onDestroy onDestroy()} is the only callback received.</p>
|
android.app.Service#onDestroy onDestroy()} is the only callback received.</p>
|
||||||
|
|
||||||
<p>Figure 2 illustrates the typical callback methods for a service. Although the figure separates
|
|
||||||
services that are created by {@link android.content.Context#startService startService()} from those
|
|
||||||
created by {@link android.content.Context#bindService bindService()}, keep
|
|
||||||
in mind that any service, no matter how it's started, can potentially allow clients to bind to it.
|
|
||||||
So, a service that was initially started with {@link android.app.Service#onStartCommand
|
|
||||||
onStartCommand()} (by a client calling {@link android.content.Context#startService startService()})
|
|
||||||
can still receive a call to {@link android.app.Service#onBind onBind()} (when a client calls
|
|
||||||
{@link android.content.Context#bindService bindService()}).</p>
|
|
||||||
|
|
||||||
<p>For more information about creating a service that provides binding, see the <a
|
<p>For more information about creating a service that provides binding, see the <a
|
||||||
href="{@docRoot}guide/components/bound-services.html">Bound Services</a> document,
|
href="{@docRoot}guide/components/bound-services.html">Bound Services</a> document,
|
||||||
which includes more information about the {@link android.app.Service#onRebind onRebind()}
|
which includes more information about the {@link android.app.Service#onRebind onRebind()}
|
||||||
callback method in the section about <a
|
callback method in the section about <a
|
||||||
href="{@docRoot}guide/components/bound-services.html#Lifecycle">Managing the Lifecycle of
|
href="{@docRoot}guide/components/bound-services.html#Lifecycle">Managing the lifecycle of
|
||||||
a Bound Service</a>.</p>
|
a bound service</a>.</p>
|
||||||
|
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
<h2>Beginner's Path</h2>
|
<h2>Beginner's Path</h2>
|
||||||
|
|||||||
@@ -6,34 +6,32 @@ page.article=true
|
|||||||
<div id="tb">
|
<div id="tb">
|
||||||
<h2>In this document</h2>
|
<h2>In this document</h2>
|
||||||
<ol class="nolist">
|
<ol class="nolist">
|
||||||
<li><a href="#StoringData">Storing Data</a></li>
|
<li><a href="#StoringData">Storing data</a></li>
|
||||||
<li><a href="#Permissions">Using Permissions</a></li>
|
<li><a href="#Permissions">Using permissions</a></li>
|
||||||
<li><a href="#Networking">Using Networking</a></li>
|
<li><a href="#Networking">Using networking</a></li>
|
||||||
<li><a href="#InputValidation">Performing Input Validation</a></li>
|
<li><a href="#InputValidation">Performing input validation</a></li>
|
||||||
<li><a href="#UserData">Handling User Data</a></li>
|
<li><a href="#UserData">Handling user data</a></li>
|
||||||
<li><a href="#WebView">Using WebView</a></li>
|
<li><a href="#WebView">Using WebView</a></li>
|
||||||
<li><a href="#Crypto">Using Cryptography</a></li>
|
<li><a href="#Crypto">Using cryptography</a></li>
|
||||||
<li><a href="#IPC">Using Interprocess Communication</a></li>
|
<li><a href="#IPC">Using interprocess communication</a></li>
|
||||||
<li><a href="#DynamicCode">Dynamically Loading Code</a></li>
|
<li><a href="#DynamicCode">Dynamically loading code</a></li>
|
||||||
<li><a href="#Dalvik">Security in a Virtual Machine</a></li>
|
<li><a href="#Dalvik">Security in a virtual machine</a></li>
|
||||||
<li><a href="#Native">Security in Native Code</a></li>
|
<li><a href="#Native">Security in native code</a></li>
|
||||||
</ol>
|
</ol>
|
||||||
<h2>See also</h2>
|
<h2>See also</h2>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="http://source.android.com/tech/security/index.html">Android
|
<li><a href="http://source.android.com/tech/security/index.html">Android
|
||||||
Security Overview</a></li>
|
Security Overview</a></li>
|
||||||
<li><a href="{@docRoot}guide/topics/security/permissions.html">Permissions</a></li>
|
<li><a href="{@docRoot}guide/topics/security/permissions.html">Permissions</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div></div>
|
</div></div>
|
||||||
|
|
||||||
|
|
||||||
<p>Android has security features built
|
<p>Android has built-in security features that significantly reduce the frequency and impact of
|
||||||
into the operating system that significantly reduce the frequency and impact of
|
application security issues. The system is designed so that you can typically build your apps with
|
||||||
application security issues. The system is designed so you can typically build your apps with
|
the default system and file permissions and avoid difficult decisions about security.</p>
|
||||||
default system and file permissions and avoid difficult decisions about security.</p>
|
|
||||||
|
|
||||||
<p>Some of the core security features that help you build secure apps
|
<p>The following core security features help you build secure apps:
|
||||||
include:
|
|
||||||
<ul>
|
<ul>
|
||||||
<li>The Android Application Sandbox, which isolates your app data and code execution
|
<li>The Android Application Sandbox, which isolates your app data and code execution
|
||||||
from other apps.</li>
|
from other apps.</li>
|
||||||
@@ -43,47 +41,54 @@ security functionality such as cryptography, permissions, and secure
|
|||||||
<li>Technologies like ASLR, NX, ProPolice, safe_iop, OpenBSD dlmalloc, OpenBSD
|
<li>Technologies like ASLR, NX, ProPolice, safe_iop, OpenBSD dlmalloc, OpenBSD
|
||||||
calloc, and Linux mmap_min_addr to mitigate risks associated with common memory
|
calloc, and Linux mmap_min_addr to mitigate risks associated with common memory
|
||||||
management errors.</li>
|
management errors.</li>
|
||||||
<li>An encrypted filesystem that can be enabled to protect data on lost or
|
<li>An encrypted file system that can be enabled to protect data on lost or
|
||||||
stolen devices.</li>
|
stolen devices.</li>
|
||||||
<li>User-granted permissions to restrict access to system features and user data.</li>
|
<li>User-granted permissions to restrict access to system features and user data.</li>
|
||||||
<li>Application-defined permissions to control application data on a per-app basis.</li>
|
<li>Application-defined permissions to control application data on a per-app basis.</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<p>Nevertheless, it is important that you be familiar with the Android
|
<p>It is important that you be familiar with the Android
|
||||||
security best practices in this document. Following these practices as general coding habits
|
security best practices in this document. Following these practices as general coding habits
|
||||||
will reduce the likelihood of inadvertently introducing security issues that
|
reduces the likelihood of inadvertently introducing security issues that
|
||||||
adversely affect your users.</p>
|
adversely affect your users.</p>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h2 id="StoringData">Storing Data</h2>
|
<h2 id="StoringData">Storing data</h2>
|
||||||
|
|
||||||
<p>The most common security concern for an application on Android is whether the data
|
<p>The most common security concern for an application on Android is whether the data
|
||||||
that you save on the device is accessible to other apps. There are three fundamental
|
that you save on the device is accessible to other apps. There are three fundamental
|
||||||
ways to save data on the device:</p>
|
ways to save data on the device:</p>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li>Internal storage.</li>
|
||||||
|
<li>External storage.</li>
|
||||||
|
<li>Content providers.</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
The following paragraphs describe the security issues associated with each approach.
|
||||||
|
|
||||||
<h3 id="InternalStorage">Using internal storage</h3>
|
<h3 id="InternalStorage">Using internal storage</h3>
|
||||||
|
|
||||||
<p>By default, files that you create on <a
|
<p>By default, files that you create on <a
|
||||||
href="{@docRoot}guide/topics/data/data-storage.html#filesInternal">internal
|
href="{@docRoot}guide/topics/data/data-storage.html#filesInternal">internal
|
||||||
storage</a> are accessible only to your app. This
|
storage</a> are accessible only to your app.
|
||||||
protection is implemented by Android and is sufficient for most
|
Android implements this protection, and it's sufficient for most applications.</p>
|
||||||
applications.</p>
|
|
||||||
|
|
||||||
<p>You should generally avoid using the {@link android.content.Context#MODE_WORLD_WRITEABLE} or
|
<p>Generally, avoid the {@link android.content.Context#MODE_WORLD_WRITEABLE} or
|
||||||
{@link android.content.Context#MODE_WORLD_READABLE} modes for
|
{@link android.content.Context#MODE_WORLD_READABLE} modes for
|
||||||
<acronym title="Interprocess Communication">IPC</acronym> files because they do not provide
|
<acronym title="Interprocess Communication">IPC</acronym> files because they do not provide
|
||||||
the ability to limit data access to particular applications, nor do they
|
the ability to limit data access to particular applications, nor do they
|
||||||
provide any control on data format. If you want to share your data with other
|
provide any control of data format. If you want to share your data with other
|
||||||
app processes, you might instead consider using a
|
app processes, instead consider using a
|
||||||
<a href="{@docRoot}guide/topics/providers/content-providers.html">content provider</a>, which
|
<a href="{@docRoot}guide/topics/providers/content-providers.html">content provider</a>, which
|
||||||
offers read and write permissions to other apps and can make
|
offers read and write permissions to other apps and can make
|
||||||
dynamic permission grants on a case-by-case basis.</p>
|
dynamic permission grants on a case-by-case basis.</p>
|
||||||
|
|
||||||
<p>To provide additional protection for sensitive data, you might
|
<p>To provide additional protection for sensitive data, you can
|
||||||
choose to encrypt local files using a key that is not directly accessible to the
|
encrypt local files using a key that is not directly accessible to the
|
||||||
application. For example, a key can be placed in a {@link java.security.KeyStore}
|
application. For example, you can place a key in a {@link java.security.KeyStore}
|
||||||
and protected with a user password that is not stored on the device. While this
|
and protect it with a user password that is not stored on the device. While this
|
||||||
does not protect data from a root compromise that can monitor the user
|
does not protect data from a root compromise that can monitor the user
|
||||||
inputting the password, it can provide protection for a lost device without <a
|
inputting the password, it can provide protection for a lost device without <a
|
||||||
href="http://source.android.com/tech/encryption/index.html">file system
|
href="http://source.android.com/tech/encryption/index.html">file system
|
||||||
@@ -94,14 +99,14 @@ encryption</a>.</p>
|
|||||||
|
|
||||||
<p>Files created on <a
|
<p>Files created on <a
|
||||||
href="{@docRoot}guide/topics/data/data-storage.html#filesExternal">external
|
href="{@docRoot}guide/topics/data/data-storage.html#filesExternal">external
|
||||||
storage</a>, such as SD Cards, are globally readable and writable. Because
|
storage</a>, such as SD cards, are globally readable and writable. Because
|
||||||
external storage can be removed by the user and also modified by any
|
external storage can be removed by the user and also modified by any
|
||||||
application, you should not store sensitive information using
|
application, don't store sensitive information using
|
||||||
external storage.</p>
|
external storage.</p>
|
||||||
|
|
||||||
<p>As with data from any untrusted source, you should <a href="#InputValidation">perform input
|
<p>You should <a href="#InputValidation">Perform input validation</a> when handling
|
||||||
validation</a> when handling data from external storage.
|
data from external storage as you would with data from any untrusted source.
|
||||||
We strongly recommend that you not store executables or
|
You should not store executables or
|
||||||
class files on external storage prior to dynamic loading. If your app
|
class files on external storage prior to dynamic loading. If your app
|
||||||
does retrieve executable files from external storage, the files should be signed and
|
does retrieve executable files from external storage, the files should be signed and
|
||||||
cryptographically verified prior to dynamic loading.</p>
|
cryptographically verified prior to dynamic loading.</p>
|
||||||
@@ -117,22 +122,22 @@ applications with access to your {@link android.content.ContentProvider}, mark t
|
|||||||
href="{@docRoot}guide/topics/manifest/provider-element.html#exported">
|
href="{@docRoot}guide/topics/manifest/provider-element.html#exported">
|
||||||
android:exported=false</a></code> in the application manifest. Otherwise, set the <code><a
|
android:exported=false</a></code> in the application manifest. Otherwise, set the <code><a
|
||||||
href="{@docRoot}guide/topics/manifest/provider-element.html#exported">android:exported</a></code>
|
href="{@docRoot}guide/topics/manifest/provider-element.html#exported">android:exported</a></code>
|
||||||
attribute {@code "true"} to allow other apps to access the stored data.
|
attribute to {@code true} to allow other apps to access the stored data.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>When creating a {@link android.content.ContentProvider}
|
<p>When creating a {@link android.content.ContentProvider}
|
||||||
that will be exported for use by other applications, you can specify a single
|
that is exported for use by other applications, you can specify a single
|
||||||
<a href="{@docRoot}guide/topics/manifest/provider-element.html#prmsn">permission
|
<a href="{@docRoot}guide/topics/manifest/provider-element.html#prmsn">permission
|
||||||
</a> for reading and writing, or distinct permissions for reading and writing
|
</a> for reading and writing, or you can specify distinct permissions for reading and writing.
|
||||||
within the manifest. We recommend that you limit your permissions to those
|
You should limit your permissions to those
|
||||||
required to accomplish the task at hand. Keep in mind that it’s usually
|
required to accomplish the task at hand. Keep in mind that it’s usually
|
||||||
easier to add permissions later to expose new functionality than it is to take
|
easier to add permissions later to expose new functionality than it is to take
|
||||||
them away and break existing users.</p>
|
them away and impact existing users.</p>
|
||||||
|
|
||||||
<p>If you are using a content provider
|
<p>If you are using a content provider
|
||||||
for sharing data between only your own apps, it is preferable to use the
|
for sharing data between only your own apps, it is preferable to use the
|
||||||
<a href="{@docRoot}guide/topics/manifest/permission-element.html#plevel">{@code
|
<a href="{@docRoot}guide/topics/manifest/permission-element.html#plevel">{@code
|
||||||
android:protectionLevel}</a> attribute set to {@code "signature"} protection.
|
android:protectionLevel}</a> attribute set to {@code signature} protection.
|
||||||
Signature permissions do not require user confirmation,
|
Signature permissions do not require user confirmation,
|
||||||
so they provide a better user experience and more controlled access to the
|
so they provide a better user experience and more controlled access to the
|
||||||
content provider data when the apps accessing the data are
|
content provider data when the apps accessing the data are
|
||||||
@@ -148,7 +153,7 @@ android.content.Intent#FLAG_GRANT_WRITE_URI_PERMISSION} flags in the
|
|||||||
that activates the component. The scope of these permissions can be further
|
that activates the component. The scope of these permissions can be further
|
||||||
limited by the <code><a
|
limited by the <code><a
|
||||||
href="{@docRoot}guide/topics/manifest/grant-uri-permission-element.html">
|
href="{@docRoot}guide/topics/manifest/grant-uri-permission-element.html">
|
||||||
<grant-uri-permission element></a></code>.</p>
|
<grant-uri-permission></a></code> element.</p>
|
||||||
|
|
||||||
<p>When accessing a content provider, use parameterized query methods such as
|
<p>When accessing a content provider, use parameterized query methods such as
|
||||||
{@link android.content.ContentProvider#query(Uri,String[],String,String[],String) query()},
|
{@link android.content.ContentProvider#query(Uri,String[],String,String[],String) query()},
|
||||||
@@ -158,11 +163,11 @@ potential SQL injection from untrusted sources. Note that using parameterized me
|
|||||||
sufficient if the <code>selection</code> argument is built by concatenating user data
|
sufficient if the <code>selection</code> argument is built by concatenating user data
|
||||||
prior to submitting it to the method.</p>
|
prior to submitting it to the method.</p>
|
||||||
|
|
||||||
<p>Do not have a false sense of security about the write permission. Consider
|
<p>Don't have a false sense of security about the write permission.
|
||||||
that the write permission allows SQL statements which make it possible for some
|
The write permission allows SQL statements that make it possible for some
|
||||||
data to be confirmed using creative <code>WHERE</code> clauses and parsing the
|
data to be confirmed using creative <code>WHERE</code> clauses and parsing the
|
||||||
results. For example, an attacker might probe for presence of a specific phone
|
results. For example, an attacker might probe for the presence of a specific phone
|
||||||
number in a call-log by modifying a row only if that phone number already
|
number in a call log by modifying a row only if that phone number already
|
||||||
exists. If the content provider data has predictable structure, the write
|
exists. If the content provider data has predictable structure, the write
|
||||||
permission may be equivalent to providing both reading and writing.</p>
|
permission may be equivalent to providing both reading and writing.</p>
|
||||||
|
|
||||||
@@ -172,7 +177,7 @@ permission may be equivalent to providing both reading and writing.</p>
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h2 id="Permissions">Using Permissions</h2>
|
<h2 id="Permissions">Using permissions</h2>
|
||||||
|
|
||||||
<p>Because Android sandboxes applications from each other, applications must explicitly
|
<p>Because Android sandboxes applications from each other, applications must explicitly
|
||||||
share resources and data. They do this by declaring the permissions they need for additional
|
share resources and data. They do this by declaring the permissions they need for additional
|
||||||
@@ -180,25 +185,25 @@ capabilities not provided by the basic sandbox, including access to device featu
|
|||||||
the camera.</p>
|
the camera.</p>
|
||||||
|
|
||||||
|
|
||||||
<h3 id="RequestingPermissions">Requesting Permissions</h3>
|
<h3 id="RequestingPermissions">Requesting permissions</h3>
|
||||||
|
|
||||||
<p>We recommend minimizing the number of permissions that your app requests.
|
<p>You should minimize the number of permissions that your app requests.
|
||||||
Not having access to sensitive permissions reduces the risk of
|
Restricting access to sensitive permissions reduces the risk of
|
||||||
inadvertently misusing those permissions, can improve user adoption, and makes
|
inadvertently misusing those permissions, improves user adoption, and makes
|
||||||
your app less vulnerable for attackers. Generally,
|
your app less vulnerable for attackers. Generally,
|
||||||
if a permission is not required for your app to function, do not request it.</p>
|
if a permission is not required for your app to function, don't request it.</p>
|
||||||
|
|
||||||
<p>If it's possible to design your application in a way that does not require
|
<p>If it's possible to design your application in a way that does not require
|
||||||
any permissions, that is preferable. For example, rather than requesting access
|
any permissions, that is preferable. For example, rather than requesting access
|
||||||
to device information to create a unique identifier, create a <a
|
to device information to create a unique identifier, create a <a
|
||||||
href="{@docRoot}reference/java/util/UUID.html">GUID</a> for your application
|
href="{@docRoot}reference/java/util/UUID.html">GUID</a> for your application
|
||||||
(see the section about <a href="#UserData">Handling User Data</a>). Or, rather than
|
(see the section about <a href="#UserData">Handling user data</a>). Or, rather than
|
||||||
using external storage (which requires permission), store data
|
using external storage (which requires permission), store data
|
||||||
on the internal storage.</p>
|
on the internal storage.</p>
|
||||||
|
|
||||||
<p>In addition to requesting permissions, your application can use the <a
|
<p>In addition to requesting permissions, your application can use the <a
|
||||||
href="{@docRoot}guide/topics/manifest/permission-element.html">{@code <permissions>}</a>
|
href="{@docRoot}guide/topics/manifest/permission-element.html">{@code <permission>}</a>
|
||||||
to protect IPC that is security sensitive and will be exposed to other
|
element to protect IPC that is security sensitive and is exposed to other
|
||||||
applications, such as a {@link android.content.ContentProvider}.
|
applications, such as a {@link android.content.ContentProvider}.
|
||||||
In general, we recommend using access controls
|
In general, we recommend using access controls
|
||||||
other than user confirmed permissions where possible because permissions can
|
other than user confirmed permissions where possible because permissions can
|
||||||
@@ -211,13 +216,14 @@ provided by a single developer.</p>
|
|||||||
data over IPC that is available only because your app has permission to access
|
data over IPC that is available only because your app has permission to access
|
||||||
that data. The clients of your app's IPC interface may not have that same
|
that data. The clients of your app's IPC interface may not have that same
|
||||||
data-access permission. More details on the frequency and potential effects
|
data-access permission. More details on the frequency and potential effects
|
||||||
of this issue appear in <a class="external-link"
|
of this issue appear in the research paper <a
|
||||||
href="https://www.usenix.org/legacy/event/sec11/tech/full_papers/Felt.pdf"> this
|
href="https://www.usenix.org/legacy/event/sec11/tech/full_papers/Felt.pdf" class="external-link">
|
||||||
research paper</a>, published at USENIX.
|
Permission Re-Delegation: Attacks and Defenses
|
||||||
|
</a>, published at USENIX.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h3 id="CreatingPermissions">Creating Permissions</h3>
|
<h3 id="CreatingPermissions">Creating permissions</h3>
|
||||||
|
|
||||||
<p>Generally, you should strive to define as few permissions as possible while
|
<p>Generally, you should strive to define as few permissions as possible while
|
||||||
satisfying your security requirements. Creating a new permission is relatively
|
satisfying your security requirements. Creating a new permission is relatively
|
||||||
@@ -228,18 +234,18 @@ perform access checks using existing permissions.</p>
|
|||||||
|
|
||||||
<p>If you must create a new permission, consider whether you can accomplish
|
<p>If you must create a new permission, consider whether you can accomplish
|
||||||
your task with a <a
|
your task with a <a
|
||||||
href="{@docRoot}guide/topics/manifest/permission-element.html#plevel">"signature"
|
href="{@docRoot}guide/topics/manifest/permission-element.html#plevel">signature
|
||||||
protection level</a>. Signature permissions are transparent
|
protection level</a>. Signature permissions are transparent
|
||||||
to the user and only allow access by applications signed by the same developer
|
to the user and allow access only by applications signed by the same developer
|
||||||
as application performing the permission check.</p>
|
as the application performing the permission check.</p>
|
||||||
|
|
||||||
<p>If you create a permission with the <a
|
<p>If you create a permission with the <a
|
||||||
href="{@docRoot}guide/topics/manifest/permission-element.html#plevel">"dangerous"
|
href="{@docRoot}guide/topics/manifest/permission-element.html#plevel">dangerous
|
||||||
protection level</a>, there are a number of complexities
|
protection level</a>, there are a number of complexities
|
||||||
that you need to consider:
|
that you need to consider:
|
||||||
<ul>
|
<ul>
|
||||||
<li>The permission must have a string that concisely expresses to a user the
|
<li>The permission must have a string that concisely expresses to a user the
|
||||||
security decision they will be required to make.</li>
|
security decision they are required to make.</li>
|
||||||
<li>The permission string must be localized to many different languages.</li>
|
<li>The permission string must be localized to many different languages.</li>
|
||||||
<li>Users may choose not to install an application because a permission is
|
<li>Users may choose not to install an application because a permission is
|
||||||
confusing or perceived as risky.</li>
|
confusing or perceived as risky.</li>
|
||||||
@@ -247,28 +253,28 @@ confusing or perceived as risky.</li>
|
|||||||
has not been installed.</li>
|
has not been installed.</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<p>Each of these poses a significant non-technical challenge for you as the developer
|
<p>Each of these poses a significant nontechnical challenge for you as the developer
|
||||||
while also confusing your users,
|
while also confusing your users,
|
||||||
which is why we discourage the use of the "dangerous" permission level.</p>
|
which is why we discourages the use of the <em>dangerous</em> permission level.</p>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h2 id="Networking">Using Networking</h2>
|
<h2 id="Networking">Using networking</h2>
|
||||||
|
|
||||||
<p>Network transactions are inherently risky for security, because it involves transmitting
|
<p>Network transactions are inherently risky for security, because they involve transmitting
|
||||||
data that is potentially private to the user. People are increasingly aware of the privacy
|
data that is potentially private to the user. People are increasingly aware of the privacy
|
||||||
concerns of a mobile device, especially when the device performs network transactions,
|
concerns of a mobile device, especially when the device performs network transactions,
|
||||||
so it's very important that your app implement all best practices toward keeping the user's
|
so it's very important that your app implement all best practices toward keeping the user's
|
||||||
data secure at all times.</p>
|
data secure at all times.</p>
|
||||||
|
|
||||||
<h3 id="IPNetworking">Using IP Networking</h3>
|
<h3 id="IPNetworking">Using IP networking</h3>
|
||||||
|
|
||||||
<p>Networking on Android is not significantly different from other Linux
|
<p>Networking on Android is not significantly different from other Linux
|
||||||
environments. The key consideration is making sure that appropriate protocols
|
environments. The key consideration is making sure that appropriate protocols
|
||||||
are used for sensitive data, such as {@link javax.net.ssl.HttpsURLConnection} for
|
are used for sensitive data, such as {@link javax.net.ssl.HttpsURLConnection} for
|
||||||
secure web traffic. We prefer use of HTTPS over HTTP anywhere that HTTPS is
|
secure web traffic. You should use HTTPS over HTTP anywhere that HTTPS is
|
||||||
supported on the server, because mobile devices frequently connect on networks
|
supported on the server, because mobile devices frequently connect on networks
|
||||||
that are not secured, such as public Wi-Fi hotspots.</p>
|
that are not secured, such as public Wi-Fi hotspots.</p>
|
||||||
|
|
||||||
@@ -278,32 +284,32 @@ class. Given the frequency with which Android devices connect to unsecured
|
|||||||
wireless networks using Wi-Fi, the use of secure networking is strongly
|
wireless networks using Wi-Fi, the use of secure networking is strongly
|
||||||
encouraged for all applications that communicate over the network.</p>
|
encouraged for all applications that communicate over the network.</p>
|
||||||
|
|
||||||
<p>We have seen some applications use <a
|
<p>Some applications use <a
|
||||||
href="http://en.wikipedia.org/wiki/Localhost">localhost</a> network ports for
|
href="http://en.wikipedia.org/wiki/Localhost" class="external-link">localhost</a> network ports for
|
||||||
handling sensitive IPC. We discourage this approach since these interfaces are
|
handling sensitive IPC. You should not use this approach because these interfaces are
|
||||||
accessible by other applications on the device. Instead, you should use an Android IPC
|
accessible by other applications on the device. Instead, use an Android IPC
|
||||||
mechanism where authentication is possible such as with a {@link android.app.Service}. (Even
|
mechanism where authentication is possible, such as with a {@link android.app.Service}.
|
||||||
worse than using loopback is to bind to INADDR_ANY since then your application
|
Binding to INADDR_ANY is worse than using loopback because then your application
|
||||||
may receive requests from anywhere.)</p>
|
may receive requests from anywhere.</p>
|
||||||
|
|
||||||
<p>Also, one common issue that warrants repeating is to make sure that you do
|
<p>Make sure that you don't
|
||||||
not trust data downloaded from HTTP or other insecure protocols. This includes
|
trust data downloaded from HTTP or other insecure protocols. This includes
|
||||||
validation of input in {@link android.webkit.WebView} and
|
validation of input in {@link android.webkit.WebView} and
|
||||||
any responses to intents issued against HTTP.</p>
|
any responses to intents issued against HTTP.</p>
|
||||||
|
|
||||||
|
|
||||||
<h3>Using Telephony Networking</h3>
|
<h3>Using telephony networking</h3>
|
||||||
|
|
||||||
<p>The <acronym title="Short Message Service">SMS</acronym> protocol was primarily designed for
|
<p>The <acronym title="Short Message Service">SMS</acronym> protocol was primarily designed for
|
||||||
user-to-user communication and is not well-suited for apps that want to transfer data.
|
user-to-user communication and is not well-suited for apps that want to transfer data.
|
||||||
Due to the limitations of SMS, we strongly recommend the use of <a
|
Due to the limitations of SMS, you should use <a
|
||||||
href="{@docRoot}google/gcm/index.html">Google Cloud Messaging</a> (GCM)
|
href="{@docRoot}google/gcm/index.html">Google Cloud Messaging</a> (GCM)
|
||||||
and IP networking for sending data messages from a web server to your app on a user device.</p>
|
and IP networking for sending data messages from a web server to your app on a user device.</p>
|
||||||
|
|
||||||
<p>Beware that SMS is neither encrypted nor strongly
|
<p>Beware that SMS is neither encrypted nor strongly
|
||||||
authenticated on either the network or the device. In particular, any SMS receiver
|
authenticated on either the network or the device. In particular, any SMS receiver
|
||||||
should expect that a malicious user may have sent the SMS to your application—Do
|
should expect that a malicious user may have sent the SMS to your application. Don't
|
||||||
not rely on unauthenticated SMS data to perform sensitive commands.
|
rely on unauthenticated SMS data to perform sensitive commands.
|
||||||
Also, you should be aware that SMS may be subject to spoofing and/or
|
Also, you should be aware that SMS may be subject to spoofing and/or
|
||||||
interception on the network. On the Android-powered device itself, SMS
|
interception on the network. On the Android-powered device itself, SMS
|
||||||
messages are transmitted as broadcast intents, so they may be read or captured
|
messages are transmitted as broadcast intents, so they may be read or captured
|
||||||
@@ -314,32 +320,32 @@ permission.</p>
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h2 id="InputValidation">Performing Input Validation</h2>
|
<h2 id="InputValidation">Performing input validation</h2>
|
||||||
|
|
||||||
<p>Insufficient input validation is one of the most common security problems
|
<p>Insufficient input validation is one of the most common security problems
|
||||||
affecting applications, regardless of what platform they run on. Android does
|
affecting applications, regardless of what platform they run on. Android
|
||||||
have platform-level countermeasures that reduce the exposure of applications to
|
has platform-level countermeasures that reduce the exposure of applications to
|
||||||
input validation issues and you should use those features where possible. Also
|
input validation issues, and you should use those features where possible. Also
|
||||||
note that selection of type-safe languages tends to reduce the likelihood of
|
note that the selection of type-safe languages tends to reduce the likelihood of
|
||||||
input validation issues.</p>
|
input validation issues.</p>
|
||||||
|
|
||||||
<p>If you are using native code, then any data read from files, received over
|
<p>If you are using native code, any data read from files, received over
|
||||||
the network, or received from an IPC has the potential to introduce a security
|
the network, or received from an IPC has the potential to introduce a security
|
||||||
issue. The most common problems are <a
|
issue. The most common problems are <a
|
||||||
href="http://en.wikipedia.org/wiki/Buffer_overflow">buffer overflows</a>, <a
|
href="http://en.wikipedia.org/wiki/Buffer_overflow" class="external-link">buffer overflows</a>, <a
|
||||||
href="http://en.wikipedia.org/wiki/Double_free#Use_after_free">use after
|
href="http://en.wikipedia.org/wiki/Double_free#Use_after_free" class="external-link">use after
|
||||||
free</a>, and <a
|
free</a>, and <a
|
||||||
href="http://en.wikipedia.org/wiki/Off-by-one_error">off-by-one errors</a>.
|
href="http://en.wikipedia.org/wiki/Off-by-one_error" class="external-link">off-by-one errors</a>.
|
||||||
Android provides a number of technologies like <acronym
|
Android provides a number of technologies like <acronym
|
||||||
title="Address Space Layout Randomization">ASLR</acronym> and <acronym
|
title="Address Space Layout Randomization">ASLR</acronym> and <acronym
|
||||||
title="Data Execution Prevention">DEP</acronym> that reduce the
|
title="Data Execution Prevention">DEP</acronym> that reduce the
|
||||||
exploitability of these errors, but they do not solve the underlying problem.
|
exploitability of these errors, but they don't solve the underlying problem.
|
||||||
You can prevent these vulneratbilities by careful handling pointers and managing
|
You can prevent these vulnerabilities by carefully handling pointers and managing
|
||||||
buffers.</p>
|
buffers.</p>
|
||||||
|
|
||||||
<p>Dynamic, string based languages such as JavaScript and SQL are also subject
|
<p>Dynamic, string-based languages such as JavaScript and SQL are also subject
|
||||||
to input validation problems due to escape characters and <a
|
to input validation problems due to escape characters and <a
|
||||||
href="http://en.wikipedia.org/wiki/Code_injection">script injection</a>.</p>
|
href="http://en.wikipedia.org/wiki/Code_injection" class="external-link">script injection</a>.</p>
|
||||||
|
|
||||||
<p>If you are using data within queries that are submitted to an SQL database or a
|
<p>If you are using data within queries that are submitted to an SQL database or a
|
||||||
content provider, SQL injection may be an issue. The best defense is to use
|
content provider, SQL injection may be an issue. The best defense is to use
|
||||||
@@ -348,60 +354,59 @@ href="#ContentProviders">content providers</a>.
|
|||||||
Limiting permissions to read-only or write-only can also reduce the potential
|
Limiting permissions to read-only or write-only can also reduce the potential
|
||||||
for harm related to SQL injection.</p>
|
for harm related to SQL injection.</p>
|
||||||
|
|
||||||
<p>If you cannot use the security features above, we strongly recommend the use
|
<p>If you can't use the security features above, you should make sure to use
|
||||||
of well-structured data formats and verifying that the data conforms to the
|
well-structured data formats and verify that the data conforms to the
|
||||||
expected format. While blacklisting of characters or character-replacement can
|
expected format. While blacklisting of characters or character-replacement can
|
||||||
be an effective strategy, these techniques are error-prone in practice and
|
be an effective strategy, these techniques are error prone in practice and
|
||||||
should be avoided when possible.</p>
|
should be avoided when possible.</p>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h2 id="UserData">Handling User Data</h2>
|
<h2 id="UserData">Handling user data</h2>
|
||||||
|
|
||||||
<p>In general, the best approach for user data security is to minimize the use of APIs that access
|
<p>In general, the best approach for user data security is to minimize the use of APIs that access
|
||||||
sensitive or personal user data. If you have access to user data and can avoid
|
sensitive or personal user data. If you have access to user data and can avoid
|
||||||
storing or transmitting the information, do not store or transmit the data.
|
storing or transmitting it, don't store or transmit the data.
|
||||||
Finally, consider if there is a way that your application logic can be
|
Consider if there is a way that your application logic can be
|
||||||
implemented using a hash or non-reversible form of the data. For example, your
|
implemented using a hash or non-reversible form of the data. For example, your
|
||||||
application might use the hash of an an email address as a primary key, to
|
application might use the hash of an email address as a primary key to
|
||||||
avoid transmitting or storing the email address. This reduces the chances of
|
avoid transmitting or storing the email address. This reduces the chances of
|
||||||
inadvertently exposing data, and it also reduces the chance of attackers
|
inadvertently exposing data, and it also reduces the chance of attackers
|
||||||
attempting to exploit your application.</p>
|
attempting to exploit your application.</p>
|
||||||
|
|
||||||
<p>If your application accesses personal information such as passwords or
|
<p>If your application accesses personal information such as passwords or
|
||||||
usernames, keep in mind that some jurisdictions may require you to provide a
|
user names, keep in mind that some jurisdictions may require you to provide a
|
||||||
privacy policy explaining your use and storage of that data. So following the
|
privacy policy explaining your use and storage of that data. Following the
|
||||||
security best practice of minimizing access to user data may also simplify
|
security best practice of minimizing access to user data may also simplify
|
||||||
compliance.</p>
|
compliance.</p>
|
||||||
|
|
||||||
<p>You should also consider whether your application might be inadvertently
|
<p>You should also consider whether your application might be inadvertently
|
||||||
exposing personal information to other parties such as third-party components
|
exposing personal information to other parties such as third-party components
|
||||||
for advertising or third-party services used by your application. If you don't
|
for advertising or third-party services used by your application. If you don't
|
||||||
know why a component or service requires a personal information, don’t
|
know why a component or service requires personal information, don’t
|
||||||
provide it. In general, reducing the access to personal information by your
|
provide it. In general, reducing the access to personal information by your
|
||||||
application will reduce the potential for problems in this area.</p>
|
application reduces the potential for problems in this area.</p>
|
||||||
|
|
||||||
<p>If access to sensitive data is required, evaluate whether that information
|
<p>If your app requires access to sensitive data, evaluate whether you need to
|
||||||
must be transmitted to a server, or whether the operation can be performed on
|
transmit it to a server or you can run the operation on
|
||||||
the client. Consider running any code using sensitive data on the client to
|
the client. Consider running any code using sensitive data on the client to
|
||||||
avoid transmitting user data.</p>
|
avoid transmitting user data. Also, make sure that you do not inadvertently expose user
|
||||||
|
data to other
|
||||||
<p>Also, make sure that you do not inadvertently expose user data to other
|
applications on the device through overly permissive IPC, world-writable files,
|
||||||
application on the device through overly permissive IPC, world writable files,
|
or network sockets. Overly permissive IPC is a special case of leaking permission-protected data,
|
||||||
or network sockets. This is a special case of leaking permission-protected data,
|
|
||||||
discussed in the <a href="#RequestingPermissions">Requesting Permissions</a> section.</p>
|
discussed in the <a href="#RequestingPermissions">Requesting Permissions</a> section.</p>
|
||||||
|
|
||||||
<p>If a <acronym title="Globally Unique Identifier">GUID</acronym>
|
<p>If a <acronym title="Globally Unique Identifier">GUID</acronym>
|
||||||
is required, create a large, unique number and store it. Do not
|
is required, create a large, unique number and store it. Don't
|
||||||
use phone identifiers such as the phone number or IMEI which may be associated
|
use phone identifiers such as the phone number or IMEI, which may be associated
|
||||||
with personal information. This topic is discussed in more detail in the <a
|
with personal information. This topic is discussed in more detail in the <a
|
||||||
href="http://android-developers.blogspot.com/2011/03/identifying-app-installations.html">Android
|
href="http://android-developers.blogspot.com/2011/03/identifying-app-installations.html"
|
||||||
Developer Blog</a>.</p>
|
>Android Developer Blog</a>.</p>
|
||||||
|
|
||||||
<p>Be careful when writing to on-device logs.
|
<p>Be careful when writing to on-device logs.
|
||||||
In Android, logs are a shared resource, and are available
|
In Android, logs are a shared resource and are available
|
||||||
to an application with the {@link android.Manifest.permission#READ_LOGS} permission.
|
to an application with the {@link android.Manifest.permission#READ_LOGS} permission.
|
||||||
Even though the phone log data
|
Even though the phone log data
|
||||||
is temporary and erased on reboot, inappropriate logging of user information
|
is temporary and erased on reboot, inappropriate logging of user information
|
||||||
@@ -414,19 +419,23 @@ could inadvertently leak user data to other applications.</p>
|
|||||||
|
|
||||||
<h2 id="WebView">Using WebView</h2>
|
<h2 id="WebView">Using WebView</h2>
|
||||||
|
|
||||||
<p>Because {@link android.webkit.WebView} consumes web content that can include HTML and JavaScript,
|
<p>Because {@link android.webkit.WebView} consumes web content that can include HTML
|
||||||
|
and JavaScript,
|
||||||
improper use can introduce common web security issues such as <a
|
improper use can introduce common web security issues such as <a
|
||||||
href="http://en.wikipedia.org/wiki/Cross_site_scripting">cross-site-scripting</a>
|
href="http://en.wikipedia.org/wiki/Cross_site_scripting" class="external-link">
|
||||||
|
cross-site-scripting</a>
|
||||||
(JavaScript injection). Android includes a number of mechanisms to reduce
|
(JavaScript injection). Android includes a number of mechanisms to reduce
|
||||||
the scope of these potential issues by limiting the capability of {@link android.webkit.WebView} to
|
the scope of these potential issues by limiting the capability of
|
||||||
|
{@link android.webkit.WebView} to
|
||||||
the minimum functionality required by your application.</p>
|
the minimum functionality required by your application.</p>
|
||||||
|
|
||||||
<p>If your application does not directly use JavaScript within a {@link android.webkit.WebView}, do
|
<p>If your application doesn't directly use JavaScript within a {@link android.webkit.WebView},
|
||||||
<em>not</em> call {@link android.webkit.WebSettings#setJavaScriptEnabled setJavaScriptEnabled()}.
|
<em>do not</em> call
|
||||||
|
{@link android.webkit.WebSettings#setJavaScriptEnabled setJavaScriptEnabled()}.
|
||||||
Some sample code uses this method, which you might repurpose in production
|
Some sample code uses this method, which you might repurpose in production
|
||||||
application, so remove that method call if it's not required. By default,
|
application, so remove that method call if it's not required. By default,
|
||||||
{@link android.webkit.WebView} does
|
{@link android.webkit.WebView} does
|
||||||
not execute JavaScript so cross-site-scripting is not possible.</p>
|
not execute JavaScript, so cross-site-scripting is not possible.</p>
|
||||||
|
|
||||||
<p>Use {@link android.webkit.WebView#addJavascriptInterface
|
<p>Use {@link android.webkit.WebView#addJavascriptInterface
|
||||||
addJavaScriptInterface()} with
|
addJavaScriptInterface()} with
|
||||||
@@ -441,55 +450,55 @@ addJavaScriptInterface()} only to JavaScript that is contained within your appli
|
|||||||
<p>If your application accesses sensitive data with a
|
<p>If your application accesses sensitive data with a
|
||||||
{@link android.webkit.WebView}, you may want to use the
|
{@link android.webkit.WebView}, you may want to use the
|
||||||
{@link android.webkit.WebView#clearCache clearCache()} method to delete any files stored
|
{@link android.webkit.WebView#clearCache clearCache()} method to delete any files stored
|
||||||
locally. Server-side
|
locally. You can also use server-side
|
||||||
headers like <code>no-cache</code> can also be used to indicate that an application should
|
headers such as <code>no-cache</code> to indicate that an application should
|
||||||
not cache particular content.</p>
|
not cache particular content.</p>
|
||||||
|
|
||||||
<p>Devices running platforms older than Android 4.4 (API level 19)
|
<p>Devices running platforms older than Android 4.4 (API level 19)
|
||||||
use a version of {@link android.webkit webkit} that has a number of security issues.
|
use a version of {@link android.webkit webkit} that has a number of security issues.
|
||||||
As a workaround, if your app is running on these devices, it
|
As a workaround, if your app is running on these devices, it
|
||||||
should confirm that {@link android.webkit.WebView} objects display only trusted
|
must confirm that {@link android.webkit.WebView} objects display only trusted
|
||||||
content. You should also use the updatable security {@link
|
content. To make sure your app isn’t exposed to
|
||||||
java.security.Provider Provider} object to make sure your app isn’t exposed to
|
potential vulnerabilities in SSL, use the updatable security {@link
|
||||||
potential vulnerabilities in SSL, as described in <a
|
java.security.Provider Provider} object as described in <a
|
||||||
href="{@docRoot}training/articles/security-gms-provider.html">Updating Your
|
href="{@docRoot}training/articles/security-gms-provider.html">Updating Your
|
||||||
Security Provider to Protect Against SSL Exploits</a>. If your application must
|
Security Provider to Protect Against SSL Exploits</a>. If your application must
|
||||||
render content from the open web, consider providing your own renderer so
|
render content from the open web, consider providing your own renderer so
|
||||||
you can keep it up to date with the latest security patches.</p>
|
you can keep it up to date with the latest security patches.</p>
|
||||||
|
|
||||||
|
|
||||||
<h3 id="Credentials">Handling Credentials</h3>
|
<h3 id="Credentials">Handling credentials</h3>
|
||||||
|
|
||||||
<p>In general, we recommend minimizing the frequency of asking for user
|
<p>To make phishing attacks more conspicuous and less likely to be
|
||||||
credentials—to make phishing attacks more conspicuous, and less likely to be
|
successful, minimize the frequency of asking for user
|
||||||
successful. Instead use an authorization token and refresh it.</p>
|
credentials. Instead use an authorization token and refresh it.</p>
|
||||||
|
|
||||||
<p>Where possible, username and password should not be stored on the device.
|
<p>Where possible, don't store user names and passwords on the device.
|
||||||
Instead, perform initial authentication using the username and password
|
Instead, perform initial authentication using the user name and password
|
||||||
supplied by the user, and then use a short-lived, service-specific
|
supplied by the user, and then use a short-lived, service-specific
|
||||||
authorization token.</p>
|
authorization token.</p>
|
||||||
|
|
||||||
<p>Services that will be accessible to multiple applications should be accessed
|
<p>Services that are accessible to multiple applications should be accessed
|
||||||
using {@link android.accounts.AccountManager}. If possible, use the
|
using {@link android.accounts.AccountManager}. If possible, use the
|
||||||
{@link android.accounts.AccountManager} class to invoke a cloud-based service and do not store
|
{@link android.accounts.AccountManager} class to invoke a cloud-based service and don't store
|
||||||
passwords on the device.</p>
|
passwords on the device.</p>
|
||||||
|
|
||||||
<p>After using {@link android.accounts.AccountManager} to retrieve an
|
<p>After using {@link android.accounts.AccountManager} to retrieve an
|
||||||
{@link android.accounts.Account}, {@link android.accounts.Account#CREATOR}
|
{@link android.accounts.Account}, use {@link android.accounts.Account#CREATOR}
|
||||||
before passing in any credentials, so that you do not inadvertently pass
|
before passing in any credentials so that you do not inadvertently pass
|
||||||
credentials to the wrong application.</p>
|
credentials to the wrong application.</p>
|
||||||
|
|
||||||
<p>If credentials are to be used only by applications that you create, then you
|
<p>If credentials are used only by applications that you create, you
|
||||||
can verify the application which accesses the {@link android.accounts.AccountManager} using
|
can verify the application that accesses the {@link android.accounts.AccountManager} using
|
||||||
{@link android.content.pm.PackageManager#checkSignatures checkSignature()}.
|
{@link android.content.pm.PackageManager#checkSignatures checkSignature()}.
|
||||||
Alternatively, if only one application will use the credential, you might use a
|
Alternatively, if only one application uses the credential, you might use a
|
||||||
{@link java.security.KeyStore} for storage.</p>
|
{@link java.security.KeyStore} for storage.</p>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h2 id="Crypto">Using Cryptography</h2>
|
<h2 id="Crypto">Using cryptography</h2>
|
||||||
|
|
||||||
<p>In addition to providing data isolation, supporting full-filesystem
|
<p>In addition to providing data isolation, supporting full-filesystem
|
||||||
encryption, and providing secure communications channels, Android provides a
|
encryption, and providing secure communications channels, Android provides a
|
||||||
@@ -500,21 +509,21 @@ implementation that can support your use case. If you need to securely
|
|||||||
retrieve a file from a known location, a simple HTTPS URI may be adequate and
|
retrieve a file from a known location, a simple HTTPS URI may be adequate and
|
||||||
requires no knowledge of cryptography. If you need a secure
|
requires no knowledge of cryptography. If you need a secure
|
||||||
tunnel, consider using {@link javax.net.ssl.HttpsURLConnection} or
|
tunnel, consider using {@link javax.net.ssl.HttpsURLConnection} or
|
||||||
{@link javax.net.ssl.SSLSocket}, rather than writing your own protocol.</p>
|
{@link javax.net.ssl.SSLSocket} rather than writing your own protocol.</p>
|
||||||
|
|
||||||
<p>If you do find yourself needing to implement your own protocol, we strongly
|
<p>If you do need to implement your own protocol, you should <em>not</em>
|
||||||
recommend that you <em>not</em> implement your own cryptographic algorithms. Use
|
implement your own cryptographic algorithms. Use
|
||||||
existing cryptographic algorithms such as those in the implementation of AES or
|
existing cryptographic algorithms such as those in the implementation of AES or
|
||||||
RSA provided in the {@link javax.crypto.Cipher} class.</p>
|
RSA provided in the {@link javax.crypto.Cipher} class.</p>
|
||||||
|
|
||||||
<p>Use a secure random number generator, {@link java.security.SecureRandom},
|
<p>Use a secure random number generator, {@link java.security.SecureRandom},
|
||||||
to initialize any cryptographic keys, {@link javax.crypto.KeyGenerator}.
|
to initialize any cryptographic keys generated by {@link javax.crypto.KeyGenerator}.
|
||||||
Use of a key that is not generated with a secure random
|
Use of a key that is not generated with a secure random
|
||||||
number generator significantly weakens the strength of the algorithm, and may
|
number generator significantly weakens the strength of the algorithm and may
|
||||||
allow offline attacks.</p>
|
allow offline attacks.</p>
|
||||||
|
|
||||||
<p>If you need to store a key for repeated use, use a mechanism like
|
<p>If you need to store a key for repeated use, use a mechanism, such as
|
||||||
{@link java.security.KeyStore} that
|
{@link java.security.KeyStore}, that
|
||||||
provides a mechanism for long term storage and retrieval of cryptographic
|
provides a mechanism for long term storage and retrieval of cryptographic
|
||||||
keys.</p>
|
keys.</p>
|
||||||
|
|
||||||
@@ -522,10 +531,10 @@ keys.</p>
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h2 id="IPC">Using Interprocess Communication</h2>
|
<h2 id="IPC">Using interprocess communication</h2>
|
||||||
|
|
||||||
<p>Some apps attempt to implement IPC using traditional Linux
|
<p>Some apps attempt to implement IPC using traditional Linux
|
||||||
techniques such as network sockets and shared files. We strongly encourage you to instead
|
techniques such as network sockets and shared files. However, you should instead
|
||||||
use Android system functionality for IPC such as {@link android.content.Intent},
|
use Android system functionality for IPC such as {@link android.content.Intent},
|
||||||
{@link android.os.Binder} or {@link android.os.Messenger} with a {@link
|
{@link android.os.Binder} or {@link android.os.Messenger} with a {@link
|
||||||
android.app.Service}, and {@link android.content.BroadcastReceiver}.
|
android.app.Service}, and {@link android.content.BroadcastReceiver}.
|
||||||
@@ -535,19 +544,19 @@ mechanism.</p>
|
|||||||
|
|
||||||
<p>Many of the security elements are shared across IPC mechanisms.
|
<p>Many of the security elements are shared across IPC mechanisms.
|
||||||
If your IPC mechanism is not intended for use by other applications, set the
|
If your IPC mechanism is not intended for use by other applications, set the
|
||||||
{@code android:exported} attribute to {@code "false"} in the component's manifest element,
|
{@code android:exported} attribute to {@code false} in the component's manifest element,
|
||||||
such as for the <a
|
such as for the <a
|
||||||
href="{@docRoot}guide/topics/manifest/service-element.html#exported">{@code <service>}</a>
|
href="{@docRoot}guide/topics/manifest/service-element.html#exported">{@code <service>}</a>
|
||||||
element. This is useful for applications that consist of multiple processes
|
element. This is useful for applications that consist of multiple processes
|
||||||
within the same UID, or if you decide late in development that you do not
|
within the same UID or if you decide late in development that you don't
|
||||||
actually want to expose functionality as IPC but you don’t want to rewrite
|
actually want to expose functionality as IPC, but you don’t want to rewrite
|
||||||
the code.</p>
|
the code.</p>
|
||||||
|
|
||||||
<p>If your IPC is intended to be accessible to other applications, you can
|
<p>If your IPC is accessible to other applications, you can
|
||||||
apply a security policy by using the <a
|
apply a security policy by using the <a
|
||||||
href="{@docRoot}guide/topics/manifest/permission-element.html">{@code <permission>}</a>
|
href="{@docRoot}guide/topics/manifest/permission-element.html">{@code <permission>}</a>
|
||||||
element. If IPC is between your own separate apps that are signed with the same key,
|
element. If IPC is between your own separate apps that are signed with the same key,
|
||||||
it is preferable to use {@code "signature"} level permission in the <a
|
it is preferable to use {@code signature} level permission in the <a
|
||||||
href="{@docRoot}guide/topics/manifest/permission-element.html#plevel">{@code
|
href="{@docRoot}guide/topics/manifest/permission-element.html#plevel">{@code
|
||||||
android:protectionLevel}</a>.</p>
|
android:protectionLevel}</a>.</p>
|
||||||
|
|
||||||
@@ -556,31 +565,42 @@ android:protectionLevel}</a>.</p>
|
|||||||
|
|
||||||
<h3>Using intents</h3>
|
<h3>Using intents</h3>
|
||||||
|
|
||||||
<p>Intents are the preferred mechanism for asynchronous IPC in Android.
|
<p>For activities and broadcast receivers, intents are the preferred mechanism for
|
||||||
|
asynchronous IPC in Android.
|
||||||
Depending on your application requirements, you might use {@link
|
Depending on your application requirements, you might use {@link
|
||||||
android.content.Context#sendBroadcast sendBroadcast()}, {@link
|
android.content.Context#sendBroadcast sendBroadcast()}, {@link
|
||||||
android.content.Context#sendOrderedBroadcast sendOrderedBroadcast()},
|
android.content.Context#sendOrderedBroadcast sendOrderedBroadcast()},
|
||||||
or an explicit intent to a specific application component.</p>
|
or an explicit intent to a specific application component.</p>
|
||||||
|
|
||||||
<p>Note that ordered broadcasts can be “consumed” by a recipient, so they
|
<p class="caution"><strong>Caution:</strong> If you use an intent to bind to a
|
||||||
may not be delivered to all applications. If you are sending an intent that must be delivered
|
{@link android.app.Service}, ensure that your app is secure by using an
|
||||||
to a specific receiver, then you must use an explicit intent that declares the receiver
|
<a href="{@docRoot}guide/components/intents-filters.html#Types">explicit</a>
|
||||||
by nameintent.</p>
|
intent. Using an implicit intent to start a service is a
|
||||||
|
security hazard because you can't be certain what service will respond to the intent,
|
||||||
|
and the user can't see which service starts. Beginning with Android 5.0 (API level 21),
|
||||||
|
the system
|
||||||
|
throws an exception if you call {@link android.content.Context#bindService bindService()}
|
||||||
|
with an implicit intent.</p>
|
||||||
|
|
||||||
<p>Senders of an intent can verify that the recipient has a permission
|
<p>Note that ordered broadcasts can be <em>consumed</em> by a recipient, so they
|
||||||
specifying a non-Null permission with the method call. Only applications with that
|
may not be delivered to all applications. If you are sending an intent that must be delivered
|
||||||
permission will receive the intent. If data within a broadcast intent may be
|
to a specific receiver, you must use an explicit intent that declares the receiver
|
||||||
|
by name.</p>
|
||||||
|
|
||||||
|
<p>Senders of an intent can verify that the recipient has permission
|
||||||
|
by specifying a non-null permission with the method call. Only applications with that
|
||||||
|
permission receive the intent. If data within a broadcast intent may be
|
||||||
sensitive, you should consider applying a permission to make sure that
|
sensitive, you should consider applying a permission to make sure that
|
||||||
malicious applications cannot register to receive those messages without
|
malicious applications can't register to receive those messages without
|
||||||
appropriate permissions. In those circumstances, you may also consider
|
appropriate permissions. In those circumstances, you may also consider
|
||||||
invoking the receiver directly, rather than raising a broadcast.</p>
|
invoking the receiver directly, rather than raising a broadcast.</p>
|
||||||
|
|
||||||
<p class="note"><strong>Note:</strong> Intent filters should not be considered
|
<p class="note"><strong>Note:</strong> Intent filters should not be considered
|
||||||
a security feature—components
|
a security feature. Components
|
||||||
can be invoked with explicit intents and may not have data that would conform to the intent
|
can be invoked with explicit intents and may not have data that would conform to the intent
|
||||||
filter. You should perform input validation within your intent receiver to
|
filter. To
|
||||||
confirm that it is properly formatted for the invoked receiver, service, or
|
confirm that it is properly formatted for the invoked receiver, service, or
|
||||||
activity.</p>
|
activity, perform input validation within your intent receiver.</p>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -589,26 +609,32 @@ activity.</p>
|
|||||||
|
|
||||||
<p>A {@link android.app.Service} is often used to supply functionality for other applications to
|
<p>A {@link android.app.Service} is often used to supply functionality for other applications to
|
||||||
use. Each service class must have a corresponding <a
|
use. Each service class must have a corresponding <a
|
||||||
href="{@docRoot}guide/topics/manifest/service-element.html">{@code <service>}</a> declaration in its
|
href="{@docRoot}guide/topics/manifest/service-element.html">{@code <service>}</a>
|
||||||
|
declaration in its
|
||||||
manifest file.</p>
|
manifest file.</p>
|
||||||
|
|
||||||
<p>By default, services are not exported and cannot be invoked by any other
|
<p>By default, services are not exported and cannot be invoked by any other
|
||||||
application. However, if you add any intent filters to the service declaration, then it is exported
|
application. However, if you add any intent filters to the service declaration, it is exported
|
||||||
by default. It's best if you explicitly declare the <a
|
by default. It's best if you explicitly declare the <a
|
||||||
href="{@docRoot}guide/topics/manifest/service-element.html#exported">{@code
|
href="{@docRoot}guide/topics/manifest/service-element.html#exported">{@code
|
||||||
android:exported}</a> attribute to be sure it behaves as you'd like.
|
android:exported}</a> attribute to be sure it behaves as you'd like.
|
||||||
Services can also be protected using the <a
|
Services can also be protected using the <a
|
||||||
href="{@docRoot}guide/topics/manifest/service-element.html#prmsn">{@code android:permission}</a>
|
href="{@docRoot}guide/topics/manifest/service-element.html#prmsn">{@code android:permission}</a>
|
||||||
attribute. By doing so, other applications will need to declare
|
attribute. By doing so, other applications need to declare
|
||||||
a corresponding <code><a
|
a corresponding <code><a
|
||||||
href="{@docRoot}guide/topics/manifest/uses-permission-element.html"><uses-permission></a>
|
href="{@docRoot}guide/topics/manifest/uses-permission-element.html"><uses-permission></a>
|
||||||
</code> element in their own manifest to be
|
</code> element in their own manifest to be
|
||||||
able to start, stop, or bind to the service.</p>
|
able to start, stop, or bind to the service.</p>
|
||||||
|
|
||||||
|
<p class="note"><strong>Note:</strong> If your app targets Android 5.0 (API level 21) or later,
|
||||||
|
you should use the {@link android.app.job.JobScheduler} to execute background
|
||||||
|
services. For more information about {@link android.app.job.JobScheduler}, see its
|
||||||
|
{@link android.app.job.JobScheduler API-reference documentation}.</p>
|
||||||
|
|
||||||
<p>A service can protect individual IPC calls into it with permissions, by
|
<p>A service can protect individual IPC calls into it with permissions, by
|
||||||
calling {@link android.content.Context#checkCallingPermission
|
calling {@link android.content.Context#checkCallingPermission
|
||||||
checkCallingPermission()} before executing
|
checkCallingPermission()} before executing
|
||||||
the implementation of that call. We generally recommend using the
|
the implementation of that call. You should use the
|
||||||
declarative permissions in the manifest, since those are less prone to
|
declarative permissions in the manifest, since those are less prone to
|
||||||
oversight.</p>
|
oversight.</p>
|
||||||
|
|
||||||
@@ -620,24 +646,24 @@ oversight.</p>
|
|||||||
preferred mechanism for RPC-style IPC in Android. They provide a well-defined
|
preferred mechanism for RPC-style IPC in Android. They provide a well-defined
|
||||||
interface that enables mutual authentication of the endpoints, if required.</p>
|
interface that enables mutual authentication of the endpoints, if required.</p>
|
||||||
|
|
||||||
<p>We strongly encourage designing interfaces in a manner that does not require
|
<p>You should design your app interfaces in a manner that does not require
|
||||||
interface specific permission checks. {@link android.os.Binder} and
|
interface-specific permission checks. {@link android.os.Binder} and
|
||||||
{@link android.os.Messenger} objects are not declared within the
|
{@link android.os.Messenger} objects are not declared within the
|
||||||
application manifest, and therefore you cannot apply declarative permissions
|
application manifest, and therefore you cannot apply declarative permissions
|
||||||
directly to them. They generally inherit permissions declared in the
|
directly to them. They generally inherit permissions declared in the
|
||||||
application manifest for the {@link android.app.Service} or {@link
|
application manifest for the {@link android.app.Service} or {@link
|
||||||
android.app.Activity} within which they are
|
android.app.Activity} within which they are
|
||||||
implemented. If you are creating an interface that requires authentication
|
implemented. If you are creating an interface that requires authentication
|
||||||
and/or access controls, those controls must be
|
and/or access controls, you must explicitly add those controls
|
||||||
explicitly added as code in the {@link android.os.Binder} or {@link android.os.Messenger}
|
as code in the {@link android.os.Binder} or {@link android.os.Messenger}
|
||||||
interface.</p>
|
interface.</p>
|
||||||
|
|
||||||
<p>If providing an interface that does require access controls, use {@link
|
<p>If you are providing an interface that does require access controls, use {@link
|
||||||
android.content.Context#checkCallingPermission checkCallingPermission()}
|
android.content.Context#checkCallingPermission checkCallingPermission()}
|
||||||
to verify whether the
|
to verify whether the
|
||||||
caller has a required permission. This is especially important
|
caller has a required permission. This is especially important
|
||||||
before accessing a service on behalf of the caller, as the identify of your
|
before accessing a service on behalf of the caller, as the identify of your
|
||||||
application is passed to other interfaces. If invoking an interface provided
|
application is passed to other interfaces. If you are invoking an interface provided
|
||||||
by a {@link android.app.Service}, the {@link
|
by a {@link android.app.Service}, the {@link
|
||||||
android.content.Context#bindService bindService()}
|
android.content.Context#bindService bindService()}
|
||||||
invocation may fail if you do not have permission to access the given service.
|
invocation may fail if you do not have permission to access the given service.
|
||||||
@@ -660,8 +686,8 @@ application. If your {@link android.content.BroadcastReceiver}
|
|||||||
is intended for use by other applications, you
|
is intended for use by other applications, you
|
||||||
may want to apply security permissions to receivers using the <code><a
|
may want to apply security permissions to receivers using the <code><a
|
||||||
href="{@docRoot}guide/topics/manifest/receiver-element.html">
|
href="{@docRoot}guide/topics/manifest/receiver-element.html">
|
||||||
<receiver></a></code> element within the application manifest. This will
|
<receiver></a></code> element within the application manifest. This
|
||||||
prevent applications without appropriate permissions from sending an intent to
|
prevents applications without appropriate permissions from sending an intent to
|
||||||
the {@link android.content.BroadcastReceiver}.</p>
|
the {@link android.content.BroadcastReceiver}.</p>
|
||||||
|
|
||||||
|
|
||||||
@@ -671,57 +697,58 @@ the {@link android.content.BroadcastReceiver}.</p>
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h2 id="DynamicCode">Dynamically Loading Code</h2>
|
<h2 id="DynamicCode">Dynamically loading code</h2>
|
||||||
|
|
||||||
<p>We strongly discourage loading code from outside of your application APK.
|
<p>We strongly discourage loading code from outside of your application APK.
|
||||||
Doing so significantly increases the likelihood of application compromise due
|
Doing so significantly increases the likelihood of application compromise due
|
||||||
to code injection or code tampering. It also adds complexity around version
|
to code injection or code tampering. It also adds complexity around version
|
||||||
management and application testing. Finally, it can make it impossible to
|
management and application testing. It can also make it impossible to
|
||||||
verify the behavior of an application, so it may be prohibited in some
|
verify the behavior of an application, so it may be prohibited in some
|
||||||
environments.</p>
|
environments.</p>
|
||||||
|
|
||||||
<p>If your application does dynamically load code, the most important thing to
|
<p>If your application does dynamically load code, the most important thing to
|
||||||
keep in mind about dynamically loaded code is that it runs with the same
|
keep in mind about dynamically-loaded code is that it runs with the same
|
||||||
security permissions as the application APK. The user made a decision to
|
security permissions as the application APK. The user makes a decision to
|
||||||
install your application based on your identity, and they are expecting that
|
install your application based on your identity, and the user expects that
|
||||||
you provide any code run within the application, including code that is
|
you provide any code run within the application, including code that is
|
||||||
dynamically loaded.</p>
|
dynamically loaded.</p>
|
||||||
|
|
||||||
<p>The major security risk associated with dynamically loading code is that the
|
<p>The major security risk associated with dynamically loading code is that the
|
||||||
code needs to come from a verifiable source. If the modules are included
|
code needs to come from a verifiable source. If the modules are included
|
||||||
directly within your APK, then they cannot be modified by other applications.
|
directly within your APK, they cannot be modified by other applications.
|
||||||
This is true whether the code is a native library or a class being loaded using
|
This is true whether the code is a native library or a class being loaded using
|
||||||
{@link dalvik.system.DexClassLoader}. We have seen many instances of applications
|
{@link dalvik.system.DexClassLoader}. Many applications
|
||||||
attempting to load code from insecure locations, such as downloaded from the
|
attempt to load code from insecure locations, such as downloaded from the
|
||||||
network over unencrypted protocols or from world writable locations such as
|
network over unencrypted protocols or from world-writable locations such as
|
||||||
external storage. These locations could allow someone on the network to modify
|
external storage. These locations could allow someone on the network to modify
|
||||||
the content in transit, or another application on a users device to modify the
|
the content in transit or another application on a user's device to modify the
|
||||||
content on the device, respectively.</p>
|
content on the device.</p>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h2 id="Dalvik">Security in a Virtual Machine</h2>
|
<h2 id="Dalvik">Security in a virtual machine</h2>
|
||||||
|
|
||||||
<p>Dalvik is Android's runtime virtual machine (VM). Dalvik was built specifically for Android,
|
<p>Dalvik is Android's runtime virtual machine (VM). Dalvik was built specifically for Android,
|
||||||
but many of the concerns regarding secure code in other virtual machines also apply to Android.
|
but many of the concerns regarding secure code in other virtual machines also apply to Android.
|
||||||
In general, you shouldn't concern yourself with security issues relating to the virtual machine.
|
In general, you shouldn't concern yourself with security issues relating to the virtual machine.
|
||||||
Your application runs in a secure sandbox environment, so other processes on the system cannnot
|
Your application runs in a secure sandbox environment, so other processes on the system can't
|
||||||
access your code or private data.</p>
|
access your code or private data.</p>
|
||||||
|
|
||||||
<p>If you're interested in diving deeper on the subject of virtual machine security,
|
<p>If you're interested in learning more about virtual machine security,
|
||||||
we recommend that you familiarize yourself with some
|
familiarize yourself with some
|
||||||
existing literature on the subject. Two of the more popular resources are:
|
existing literature on the subject. Two of the more popular resources are:
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="http://www.securingjava.com/toc.html">
|
<li><a href="http://www.securingjava.com/toc.html" class="external-link">
|
||||||
http://www.securingjava.com/toc.html</a></li>
|
Securing Java</a></li>
|
||||||
<li><a
|
<li><a
|
||||||
href="https://www.owasp.org/index.php/Java_Security_Resources">
|
href="https://www.owasp.org/index.php/Category:Java#tab=Related_3rd_Party_Projects"
|
||||||
https://www.owasp.org/index.php/Java_Security_Resources</a></li>
|
class="external-link">
|
||||||
|
Related 3rd party Projects</a></li>
|
||||||
</ul></p>
|
</ul></p>
|
||||||
|
|
||||||
<p>This document is focused on the areas which are Android specific or
|
<p>This document focuses on areas that are Android specific or
|
||||||
different from other VM environments. For developers experienced with VM
|
different from other VM environments. For developers experienced with VM
|
||||||
programming in other environments, there are two broad issues that may be
|
programming in other environments, there are two broad issues that may be
|
||||||
different about writing apps for Android:
|
different about writing apps for Android:
|
||||||
@@ -742,21 +769,19 @@ because that code might be modified to include malicious behavior.</li>
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h2 id="Native">Security in Native Code</h2>
|
<h2 id="Native">Security in native code</h2>
|
||||||
|
|
||||||
<p>In general, we encourage developers to use the Android SDK for
|
<p>In general, you should use the Android SDK for
|
||||||
application development, rather than using native code with the
|
application development, rather than using native code with the
|
||||||
<a href="{@docRoot}tools/sdk/ndk/index.html">Android NDK</a>. Applications built
|
<a href="{@docRoot}tools/sdk/ndk/index.html">Android NDK</a>. Applications built
|
||||||
with native code are more complex, less portable, and more like to include
|
with native code are more complex, less portable, and more like to include
|
||||||
common memory corruption errors such as buffer overflows.</p>
|
common memory-corruption errors such as buffer overflows.</p>
|
||||||
|
|
||||||
<p>Android is built using the Linux kernel and being familiar with Linux
|
<p>Android is built using the Linux kernel, and being familiar with Linux
|
||||||
development security best practices is especially useful if you are going to
|
development security best practices is especially useful if you are
|
||||||
use native code. Linux security practices are beyond the scope of this document,
|
using native code. Linux security practices are beyond the scope of this document,
|
||||||
but one of the most popular resources is “Secure Programming for
|
but one of the most popular resources is <a href="http://www.dwheeler.com/secure-programs"
|
||||||
Linux and Unix HOWTO”, available at <a
|
class="external-link">Secure Programming HOWTO - Creating Secure Software</a>.</p>
|
||||||
href="http://www.dwheeler.com/secure-programs">
|
|
||||||
http://www.dwheeler.com/secure-programs</a>.</p>
|
|
||||||
|
|
||||||
<p>An important difference between Android and most Linux environments is the
|
<p>An important difference between Android and most Linux environments is the
|
||||||
Application Sandbox. On Android, all applications run in the Application
|
Application Sandbox. On Android, all applications run in the Application
|
||||||
@@ -765,6 +790,5 @@ good way to think about it for developers familiar with Linux is to know that
|
|||||||
every application is given a unique <acronym title="User Identifier">UID</acronym>
|
every application is given a unique <acronym title="User Identifier">UID</acronym>
|
||||||
with very limited permissions. This is discussed in more detail in the <a
|
with very limited permissions. This is discussed in more detail in the <a
|
||||||
href="http://source.android.com/tech/security/index.html">Android Security
|
href="http://source.android.com/tech/security/index.html">Android Security
|
||||||
Overview</a> and you should be familiar with application permissions even if
|
Overview</a>, and you should be familiar with application permissions even if
|
||||||
you are using native code.</p>
|
you are using native code.</p>
|
||||||
|
|
||||||
|
|||||||
@@ -7,11 +7,11 @@ trainingnavtop=true
|
|||||||
|
|
||||||
<h2>This lesson teaches you how to</h2>
|
<h2>This lesson teaches you how to</h2>
|
||||||
<ol>
|
<ol>
|
||||||
<li><a href="#connect">Get a Geographic Location</a></li>
|
<li><a href="#connect">Get a geographic location</a></li>
|
||||||
<li><a href="#fetch-address">Define an Intent Service to Fetch the
|
<li><a href="#fetch-address">Define an intent service to fetch the
|
||||||
Address</a></li>
|
address</a></li>
|
||||||
<li><a href="#start-intent">Start the Intent Service</a></li>
|
<li><a href="#start-intent">Start the intent service</a></li>
|
||||||
<li><a href="#result-receiver">Receive the Geocoding Results</a></li>
|
<li><a href="#result-receiver">Receive the geocoding results</a></li>
|
||||||
</ol>
|
</ol>
|
||||||
|
|
||||||
<h2>You should also read</h2>
|
<h2>You should also read</h2>
|
||||||
@@ -58,7 +58,7 @@ trainingnavtop=true
|
|||||||
convert a geographic location to an address. The method returns an estimated
|
convert a geographic location to an address. The method returns an estimated
|
||||||
street address corresponding to a given latitude and longitude.</p>
|
street address corresponding to a given latitude and longitude.</p>
|
||||||
|
|
||||||
<h2 id="connect">Get a Geographic Location</h2>
|
<h2 id="connect">Get a geographic location</h2>
|
||||||
|
|
||||||
<p>The last known location of the device is a useful starting point for the
|
<p>The last known location of the device is a useful starting point for the
|
||||||
address lookup feature. The lesson on
|
address lookup feature. The lesson on
|
||||||
@@ -69,12 +69,12 @@ trainingnavtop=true
|
|||||||
<a href="{@docRoot}reference/com/google/android/gms/location/FusedLocationProviderApi.html">fused
|
<a href="{@docRoot}reference/com/google/android/gms/location/FusedLocationProviderApi.html">fused
|
||||||
location provider</a> to find the latest location of the device.</p>
|
location provider</a> to find the latest location of the device.</p>
|
||||||
|
|
||||||
<p>To access the fused location provider, you need to create an instance of the
|
<p>To access the fused location provider, create an instance of the
|
||||||
Google Play services API client. To learn how to connect your client, see
|
Google Play services API client. To learn how to connect your client, see
|
||||||
<a href="{@docRoot}training/location/retrieve-current.html#play-services">Connect
|
<a href="{@docRoot}training/location/retrieve-current.html#play-services">Connect
|
||||||
to Google Play Services</a>.</p>
|
to Google Play Services</a>.</p>
|
||||||
|
|
||||||
<p>In order for the fused location provider to retrieve a precise street
|
<p>To enable the fused location provider to retrieve a precise street
|
||||||
address, set the location permission in your app manifest to
|
address, set the location permission in your app manifest to
|
||||||
{@code ACCESS_FINE_LOCATION}, as shown in the following example:</p>
|
{@code ACCESS_FINE_LOCATION}, as shown in the following example:</p>
|
||||||
|
|
||||||
@@ -86,12 +86,12 @@ trainingnavtop=true
|
|||||||
</manifest>
|
</manifest>
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
<h2 id="fetch-address">Define an Intent Service to Fetch the Address</h2>
|
<h2 id="fetch-address">Define an intent service to fetch the address</h2>
|
||||||
|
|
||||||
<p>The {@link android.location.Geocoder#getFromLocation getFromLocation()}
|
<p>The {@link android.location.Geocoder#getFromLocation getFromLocation()}
|
||||||
method provided by the {@link android.location.Geocoder} class accepts a
|
method provided by the {@link android.location.Geocoder} class accepts a
|
||||||
latitude and longitude, and returns a list of addresses. The method is
|
latitude and longitude and returns a list of addresses. The method is
|
||||||
synchronous, and may take a long time to do its work, so you should not call
|
synchronous and may take a long time to do its work, so you should not call
|
||||||
it from the main, user interface (UI) thread of your app.</p>
|
it from the main, user interface (UI) thread of your app.</p>
|
||||||
|
|
||||||
<p>The {@link android.app.IntentService IntentService} class provides a
|
<p>The {@link android.app.IntentService IntentService} class provides a
|
||||||
@@ -100,23 +100,23 @@ trainingnavtop=true
|
|||||||
Note that the {@link android.os.AsyncTask AsyncTask} class also allows you to
|
Note that the {@link android.os.AsyncTask AsyncTask} class also allows you to
|
||||||
perform background operations, but it's designed for short operations. An
|
perform background operations, but it's designed for short operations. An
|
||||||
{@link android.os.AsyncTask AsyncTask} shouldn't keep a reference to the UI if
|
{@link android.os.AsyncTask AsyncTask} shouldn't keep a reference to the UI if
|
||||||
the activity is recreated, for example when the device is rotated. In
|
the activity is re-created, such as when the device is rotated. In
|
||||||
contrast, an {@link android.app.IntentService IntentService} doesn't need to
|
contrast, an {@link android.app.IntentService IntentService} doesn't need to
|
||||||
be cancelled when the activity is rebuilt.</p>
|
be cancelled when the activity is rebuilt.</p>
|
||||||
|
|
||||||
<p>Define a {@code FetchAddressIntentService} class that extends
|
<p>Define a {@code FetchAddressIntentService} class that extends
|
||||||
{@link android.app.IntentService}. This class is your address lookup service.
|
{@link android.app.IntentService}. This class is your address lookup service.
|
||||||
The intent service handles an intent asynchronously on a worker thread, and
|
The intent service handles an intent asynchronously on a worker thread and
|
||||||
stops itself when it runs out of work. The intent extras provide the data
|
stops itself when it runs out of work. The intent extras provide the data
|
||||||
needed by the service, including a {@link android.location.Location} object
|
needed by the service, including a {@link android.location.Location} object
|
||||||
for conversion to an address, and a {@link android.os.ResultReceiver} object
|
for conversion to an address and a {@link android.os.ResultReceiver} object
|
||||||
to handle the results of the address lookup. The service uses a {@link
|
to handle the results of the address lookup. The service uses a {@link
|
||||||
android.location.Geocoder} to fetch the address for the location, and sends
|
android.location.Geocoder} to fetch the address for the location and sends
|
||||||
the results to the {@link android.os.ResultReceiver}.</p>
|
the results to the {@link android.os.ResultReceiver}.</p>
|
||||||
|
|
||||||
<h3>Define the Intent Service in your App Manifest</h3>
|
<h3>Define the intent service in your app manifest</h3>
|
||||||
|
|
||||||
<p>Add an entry to your app manifest defining the intent service:</p>
|
<p>Add an entry to your app manifest that defines the intent service, as shown here:</p>
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
@@ -131,26 +131,26 @@ trainingnavtop=true
|
|||||||
</manifest>
|
</manifest>
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
<p class="note"><strong>Note:</strong> The {@code <service>} element in
|
<p class="note"><strong>Note:</strong> The {@code <service>} element in
|
||||||
the manifest doesn't need to include an intent filter, because your main
|
the manifest doesn't need to include an intent filter because your main
|
||||||
activity creates an explicit intent by specifying the name of the class to use
|
activity creates an explicit intent by specifying the name of the class to use
|
||||||
for the intent.</p>
|
for the intent.</p>
|
||||||
|
|
||||||
<h3>Create a Geocoder</h3>
|
<h3>Create a geocoder</h3>
|
||||||
|
|
||||||
<p>The process of converting a geographic location to an address is called
|
<p>The process of converting a geographic location to an address is called
|
||||||
<em>reverse geocoding</em>. To perform the main work of the intent service,
|
<em>reverse geocoding</em>. To perform the main work of the intent service (your reverse
|
||||||
that is, your reverse geocoding request, implement
|
geocoding request), implement
|
||||||
{@link android.app.IntentService#onHandleIntent onHandleIntent()} within the
|
{@link android.app.IntentService#onHandleIntent onHandleIntent()} within the
|
||||||
{@code FetchAddressIntentService} class. Create a
|
{@code FetchAddressIntentService} class. Create a
|
||||||
{@link android.location.Geocoder} object to handle the reverse geocoding.</p>
|
{@link android.location.Geocoder} object to handle the reverse geocoding.</p>
|
||||||
|
|
||||||
<p>A locale represents a specific geographical or linguistic region. Locale
|
<p>A locale represents a specific geographical or linguistic region. Locale
|
||||||
objects are used to adjust the presentation of information, such as numbers or
|
objects adjust the presentation of information, such as numbers or
|
||||||
dates, to suit the conventions in the region represented by the locale. Pass a
|
dates, to suit the conventions in the region that is represented by the locale. Pass a
|
||||||
<a href="{@docRoot}reference/java/util/Locale.html">{@code Locale}</a> object
|
<a href="{@docRoot}reference/java/util/Locale.html">{@code Locale}</a> object
|
||||||
to the {@link android.location.Geocoder} object, to ensure that the resulting
|
to the {@link android.location.Geocoder} object to ensure that the resulting
|
||||||
address is localized to the user's geographic region.</p>
|
address is localized to the user's geographic region. Here is an example:</p>
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
@Override
|
@Override
|
||||||
@@ -162,7 +162,7 @@ protected void onHandleIntent(Intent intent) {
|
|||||||
|
|
||||||
<h3 id="retrieve-street-address">Retrieve the street address data</h3>
|
<h3 id="retrieve-street-address">Retrieve the street address data</h3>
|
||||||
|
|
||||||
<p>The next step is to retrieve the street address from the geocoder, handle
|
<p>You can now retrieve the street address from the geocoder, handle
|
||||||
any errors that may occur, and send the results back to the activity that
|
any errors that may occur, and send the results back to the activity that
|
||||||
requested the address. To report the results of the geocoding
|
requested the address. To report the results of the geocoding
|
||||||
process, you need two numeric constants that indicate success or failure.
|
process, you need two numeric constants that indicate success or failure.
|
||||||
@@ -185,32 +185,34 @@ public final class Constants {
|
|||||||
|
|
||||||
<p>To get a street address corresponding to a geographical location, call
|
<p>To get a street address corresponding to a geographical location, call
|
||||||
{@link android.location.Geocoder#getFromLocation getFromLocation()},
|
{@link android.location.Geocoder#getFromLocation getFromLocation()},
|
||||||
passing it the latitude and longitude from the location object, and the
|
passing it the latitude and longitude from the location object and the
|
||||||
maximum number of addresses you want returned. In this case, you want just one
|
maximum number of addresses that you want returned. In this case, you want just one
|
||||||
address. The geocoder returns an array of addresses. If no addresses were
|
address. The geocoder returns an array of addresses. If no addresses are
|
||||||
found to match the given location, it returns an empty list. If there is no
|
found to match the given location, it returns an empty list. If there is no
|
||||||
backend geocoding service available, the geocoder returns null.</p>
|
backend geocoding service available, the geocoder returns null.</p>
|
||||||
|
|
||||||
<p>Check for the following errors as shown in the code sample below. If an error
|
<p>Check for the following errors, as shown in the code sample below:</p>
|
||||||
occurs, place the corresponding error message in the {@code errorMessage}
|
|
||||||
variable, so you can send it back to the requesting activity:</p>
|
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<li><strong>No location data provided</strong> - The intent extras do not
|
<li><strong>No location data provided</strong> – The intent extras do not
|
||||||
include the {@link android.location.Location} object required for reverse
|
include the {@link android.location.Location} object that is required for reverse
|
||||||
geocoding.</li>
|
geocoding.</li>
|
||||||
<li><strong>Invalid latitude or longitude used</strong> - The latitude
|
<li><strong>Invalid latitude or longitude used</strong> – The latitude
|
||||||
and/or longitude values provided in the {@link android.location.Location}
|
and/or longitude values that are provided in the {@link android.location.Location}
|
||||||
object are invalid.</li>
|
object are invalid.</li>
|
||||||
<li><strong>No geocoder available</strong> - The background geocoding service
|
<li><strong>No geocoder available</strong> – The background geocoding service
|
||||||
is not available, due to a network error or IO exception.</li>
|
is not available due to a network error or IO exception.</li>
|
||||||
<li><strong>Sorry, no address found</strong> - The geocoder could not find an
|
<li><strong>Sorry, no address found</strong> – The geocoder can't find an
|
||||||
address for the given latitude/longitude.</li>
|
address for the given latitude/longitude.</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
<p>If an error
|
||||||
|
occurs, place the corresponding error message in the {@code errorMessage}
|
||||||
|
variable so that you can send it back to the requesting activity.
|
||||||
|
|
||||||
<p>To get the individual lines of an address object, use the
|
<p>To get the individual lines of an address object, use the
|
||||||
{@link android.location.Address#getAddressLine getAddressLine()}
|
{@link android.location.Address#getAddressLine getAddressLine()}
|
||||||
method provided by the {@link android.location.Address} class. Then join the
|
method that is provided by the {@link android.location.Address} class. Join the
|
||||||
lines into a list of address fragments ready to return to the activity that
|
lines into a list of address fragments ready to return to the activity that
|
||||||
requested the address.</p>
|
requested the address.</p>
|
||||||
|
|
||||||
@@ -220,7 +222,7 @@ public final class Constants {
|
|||||||
results consist of the previously-mentioned numeric success/failure code and
|
results consist of the previously-mentioned numeric success/failure code and
|
||||||
a string. In the case of a successful reverse geocoding, the string contains
|
a string. In the case of a successful reverse geocoding, the string contains
|
||||||
the address. In the case of a failure, the string contains the error message,
|
the address. In the case of a failure, the string contains the error message,
|
||||||
as shown in the code sample below:</p>
|
as shown in this code sample:</p>
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
@Override
|
@Override
|
||||||
@@ -280,18 +282,18 @@ protected void onHandleIntent(Intent intent) {
|
|||||||
|
|
||||||
<h3 id="return-address">Return the address to the requestor</h3>
|
<h3 id="return-address">Return the address to the requestor</h3>
|
||||||
|
|
||||||
<p>The final thing the intent service must do is send the address back to a
|
<p>The final action that the intent service must complete is sending the address back to a
|
||||||
{@link android.os.ResultReceiver} in the activity that started the service.
|
{@link android.os.ResultReceiver} in the activity that started the service.
|
||||||
The {@link android.os.ResultReceiver} class allows you to send a
|
The {@link android.os.ResultReceiver} class allows you to send a
|
||||||
numeric result code as well as a message containing the result data. The
|
numeric result code as well as a message containing the result data. The
|
||||||
numeric code is useful for reporting the success or failure of the geocoding
|
numeric code is useful for reporting the success or failure of the geocoding
|
||||||
request. In the case of a successful reverse geocoding, the message contains
|
request. In the case of a successful reverse geocoding, the message contains
|
||||||
the address. In the case of a failure, the message contains some text
|
the address. In the case of a failure, the message contains some text
|
||||||
describing the reason for failure.</p>
|
describing the reason for the failure.</p>
|
||||||
|
|
||||||
<p>You have already retrieved the address from the geocoder, trapped any errors
|
<p>You have already retrieved the address from the geocoder, trapped any errors
|
||||||
that may occur, and called the {@code deliverResultToReceiver()} method. Now
|
that may occur, and called the {@code deliverResultToReceiver()} method, so now
|
||||||
you need to define the {@code deliverResultToReceiver()} method that sends
|
you must define the {@code deliverResultToReceiver()} method that sends
|
||||||
a result code and message bundle to the result receiver.</p>
|
a result code and message bundle to the result receiver.</p>
|
||||||
|
|
||||||
<p>For the result code, use the value that you've passed to the
|
<p>For the result code, use the value that you've passed to the
|
||||||
@@ -299,7 +301,7 @@ protected void onHandleIntent(Intent intent) {
|
|||||||
To construct the message bundle, concatenate the {@code RESULT_DATA_KEY}
|
To construct the message bundle, concatenate the {@code RESULT_DATA_KEY}
|
||||||
constant from your {@code Constants} class (defined in
|
constant from your {@code Constants} class (defined in
|
||||||
<a href="#retrieve-street-address">Retrieve the street address data</a>) and
|
<a href="#retrieve-street-address">Retrieve the street address data</a>) and
|
||||||
the value in the {@code message} parameter passed to the
|
the value in the {@code message} parameter that is passed to the
|
||||||
{@code deliverResultToReceiver()} method, as shown in the following sample:
|
{@code deliverResultToReceiver()} method, as shown in the following sample:
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
@@ -315,26 +317,26 @@ public class FetchAddressIntentService extends IntentService {
|
|||||||
}
|
}
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
<h2 id="start-intent">Start the Intent Service</h2>
|
<h2 id="start-intent">Start the intent service</h2>
|
||||||
|
|
||||||
<p>The intent service, as defined in the previous section, runs in the
|
<p>The intent service, as defined in the previous section, runs in the
|
||||||
background and is responsible for fetching the address corresponding to a
|
background and fetches the address corresponding to a
|
||||||
given geographic location. When you start the service, the Android framework
|
given geographic location. When you start the service, the Android framework
|
||||||
instantiates and starts the service if it isn't already running, and creates a
|
instantiates and starts the service if it isn't already running, and it creates a
|
||||||
process if needed. If the service is already running then it remains running.
|
process if needed. If the service is already running, it remains running.
|
||||||
Because the service extends {@link android.app.IntentService IntentService},
|
Because the service extends {@link android.app.IntentService IntentService},
|
||||||
it shuts down automatically when all intents have been processed.</p>
|
it shuts down automatically after all intents are processed.</p>
|
||||||
|
|
||||||
<p>Start the service from your app's main activity,
|
<p>Start the service from your app's main activity
|
||||||
and create an {@link android.content.Intent} to pass data to the service. You
|
and create an {@link android.content.Intent} to pass data to the service. You
|
||||||
need an <em>explicit</em> intent, because you want only your service
|
need an <em>explicit</em> intent because you want only your service
|
||||||
to respond to the intent. For more information, see
|
to respond to the intent. For more information, see
|
||||||
<a href="{@docRoot}guide/components/intents-filters.html#Types">Intent
|
<a href="{@docRoot}guide/components/intents-filters.html#Types">Intent
|
||||||
Types</a>.</p>
|
Types</a>.</p>
|
||||||
|
|
||||||
<p>To create an explicit intent, specify the name of the
|
<p>To create an explicit intent, specify the name of the
|
||||||
class to use for the service: {@code FetchAddressIntentService.class}.
|
class to use for the service: {@code FetchAddressIntentService.class}.
|
||||||
Pass two pieces of information in the intent extras:</p>
|
Pass this information in the intent extras:</p>
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<li>A {@link android.os.ResultReceiver} to handle the results of the address
|
<li>A {@link android.os.ResultReceiver} to handle the results of the address
|
||||||
@@ -362,6 +364,12 @@ public class MainActivity extends ActionBarActivity implements
|
|||||||
}
|
}
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
|
<p class="caution"><strong>Caution</strong>: To ensure that your app is secure, always use an
|
||||||
|
explicit intent when starting a {@link android.app.Service} and do not declare intent filters for
|
||||||
|
your services. Using an implicit intent to start a service is a security hazard because you cannot
|
||||||
|
be certain of the service that will respond to the intent, and the user cannot see which service
|
||||||
|
starts.</p>
|
||||||
|
|
||||||
<p>Call the above {@code startIntentService()} method when the
|
<p>Call the above {@code startIntentService()} method when the
|
||||||
user takes an action that requires a geocoding address lookup. For example,
|
user takes an action that requires a geocoding address lookup. For example,
|
||||||
the user may press a <em>Fetch address</em> button on your app's UI. Before
|
the user may press a <em>Fetch address</em> button on your app's UI. Before
|
||||||
@@ -391,7 +399,7 @@ public void fetchAddressButtonHandler(View view) {
|
|||||||
app's UI. The following code snippet shows the call to the
|
app's UI. The following code snippet shows the call to the
|
||||||
{@code startIntentService()} method in the
|
{@code startIntentService()} method in the
|
||||||
<a href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.ConnectionCallbacks.html#onConnected(android.os.Bundle)">{@code onConnected()}</a>
|
<a href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.ConnectionCallbacks.html#onConnected(android.os.Bundle)">{@code onConnected()}</a>
|
||||||
callback provided by the Google API Client:</p>
|
callback that is provided by the Google API Client:</p>
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
public class MainActivity extends ActionBarActivity implements
|
public class MainActivity extends ActionBarActivity implements
|
||||||
@@ -420,9 +428,9 @@ public class MainActivity extends ActionBarActivity implements
|
|||||||
}
|
}
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
<h2 id="result-receiver">Receive the Geocoding Results</h2>
|
<h2 id="result-receiver">Receive the geocoding results</h2>
|
||||||
|
|
||||||
<p>The intent service has handled the geocoding request, and uses a
|
<p>After the intent service handles the geocoding request, it uses a
|
||||||
{@link android.os.ResultReceiver} to return the results to the activity that
|
{@link android.os.ResultReceiver} to return the results to the activity that
|
||||||
made the request. In the activity that makes the request, define an
|
made the request. In the activity that makes the request, define an
|
||||||
{@code AddressResultReceiver} that extends {@link android.os.ResultReceiver}
|
{@code AddressResultReceiver} that extends {@link android.os.ResultReceiver}
|
||||||
@@ -430,14 +438,14 @@ public class MainActivity extends ActionBarActivity implements
|
|||||||
|
|
||||||
<p>The result includes a numeric result code (<code>resultCode</code>) as well
|
<p>The result includes a numeric result code (<code>resultCode</code>) as well
|
||||||
as a message containing the result data (<code>resultData</code>). If the
|
as a message containing the result data (<code>resultData</code>). If the
|
||||||
reverse geocoding process was successful, the <code>resultData</code> contains
|
reverse geocoding process is successful, the <code>resultData</code> contains
|
||||||
the address. In the case of a failure, the <code>resultData</code> contains
|
the address. In the case of a failure, the <code>resultData</code> contains
|
||||||
text describing the reason for failure. For details of the possible errors,
|
text describing the reason for the failure. For details of the possible errors,
|
||||||
see <a href="#return-address">Return the address to the requestor</a>.</p>
|
see <a href="#return-address">Return the address to the requestor</a>.</p>
|
||||||
|
|
||||||
<p>Override the
|
<p>Override the
|
||||||
{@link android.os.ResultReceiver#onReceiveResult onReceiveResult()} method
|
{@link android.os.ResultReceiver#onReceiveResult onReceiveResult()} method
|
||||||
to handle the results delivered to the result receiver, as shown in the
|
to handle the results that are delivered to the result receiver, as shown in the
|
||||||
following code sample:</p>
|
following code sample:</p>
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
|
|||||||
@@ -35,16 +35,22 @@ startpage=true
|
|||||||
<!-- ------------------------------------------------------------------------------------------- -->
|
<!-- ------------------------------------------------------------------------------------------- -->
|
||||||
<p>
|
<p>
|
||||||
Unless you specify otherwise, most of the operations you do in an app run in the foreground on
|
Unless you specify otherwise, most of the operations you do in an app run in the foreground on
|
||||||
a special thread called the UI thread. This can cause problems, because long-running operations
|
a special thread called the UI thread. Long-running foreground operations can cause problems
|
||||||
will interfere with the responsiveness of your user interface. This annoys your users, and can
|
and interfere with the responsiveness of your user interface, which annoys your users and can
|
||||||
even cause system errors. To avoid this, the Android framework offers several classes that
|
even cause system errors. To avoid this, the Android framework offers several classes that
|
||||||
help you off-load operations onto a separate thread running in the background. The most useful
|
help you off-load operations onto a separate thread that runs in the background. The most
|
||||||
of these is {@link android.app.IntentService}.
|
useful of these is {@link android.app.IntentService}.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
This class describes how to implement an {@link android.app.IntentService}, send it work
|
This class describes how to implement an {@link android.app.IntentService}, send it work
|
||||||
requests, and report its results to other components.
|
requests, and report its results to other components.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
<p class="note"><strong>Note:</strong> If your app targets Android 5.0 (API level 21),
|
||||||
|
you should use {@link android.app.job.JobScheduler} to execute background
|
||||||
|
services. For more information about this class,
|
||||||
|
see the {@link android.app.job.JobScheduler} reference documentation.</p>
|
||||||
|
|
||||||
<h2>Lessons</h2>
|
<h2>Lessons</h2>
|
||||||
<dl>
|
<dl>
|
||||||
<dt>
|
<dt>
|
||||||
|
|||||||
Reference in New Issue
Block a user