docs: Update startService() & bindService() documentation (Proj13)
am: 9748d76be9
Change-Id: I976128eb4c14ee2587c9cfa9c34f4b3dc006aa38
This commit is contained in:
@@ -9,18 +9,18 @@ page.tags="inapp, billing, iap"
|
||||
<h2>In this document</h2>
|
||||
<ol>
|
||||
<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-requests">Making In-app Billing Requests</a>
|
||||
<li><a href="#billing-requests">Making In-app Billing requests</a>
|
||||
<ol>
|
||||
<li><a href="#QueryDetails">Querying Items Available for Purchase</a><li>
|
||||
<li><a href="#Purchase">Purchasing an Item</a></li>
|
||||
<li><a href="#QueryPurchases">Querying Purchased Items</a></li>
|
||||
<li><a href="#Consume">Consuming a Purchase</a></li>
|
||||
<li><a href="#Subs">Implementing Subscriptions</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="#QueryPurchases">Querying purchased items</a></li>
|
||||
<li><a href="#Consume">Consuming a purchase</a></li>
|
||||
<li><a href="#Subs">Implementing subscriptions</a></li>
|
||||
</ol>
|
||||
</li>
|
||||
<li><a href="#billing-security">Securing Your App</a>
|
||||
<li><a href="#billing-security">Securing your app</a>
|
||||
</ol>
|
||||
<h2>Reference</h2>
|
||||
<ol>
|
||||
@@ -42,7 +42,7 @@ page.tags="inapp, billing, iap"
|
||||
In-app Billing on Google Play provides a straightforward, simple interface
|
||||
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
|
||||
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.
|
||||
</p>
|
||||
|
||||
@@ -51,26 +51,25 @@ page.tags="inapp, billing, iap"
|
||||
your application, see the <a href=
|
||||
"{@docRoot}training/in-app-billing/index.html">Selling In-app Products</a>
|
||||
training class. The training class provides a complete sample In-app Billing
|
||||
application, including convenience classes to handle key tasks related to
|
||||
setting up your connection, sending billing requests and processing responses
|
||||
application, including convenience classes to handle key tasks that are related to
|
||||
setting up your connection, sending billing requests, processing responses
|
||||
from Google Play, and managing background threading so that you can make
|
||||
In-app Billing calls from your main activity.
|
||||
</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
|
||||
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.
|
||||
</p>
|
||||
|
||||
<p>To implement In-app Billing in your application, you need to do the
|
||||
following:</p>
|
||||
<p>Complete these steps to implement In-app Billing in your application:</p>
|
||||
|
||||
<ol>
|
||||
<li>Add the In-app Billing library to your project.</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>
|
||||
<li>Send In-app Billing requests from your application to
|
||||
{@code IInAppBillingService}.</li>
|
||||
@@ -79,55 +78,56 @@ following:</p>
|
||||
|
||||
<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
|
||||
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>
|
||||
<p>To get the AIDL file:</p>
|
||||
|
||||
<p>Complete these steps to get the AIDL file:</p>
|
||||
<ol>
|
||||
<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>Select <strong>Google Play Billing Library</strong>.</li>
|
||||
<li>Click <strong>Install packages</strong> to complete the download.</li>
|
||||
</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>
|
||||
<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">
|
||||
<li>Select <strong>Tools > Android > SDK Manager</strong>.</li>
|
||||
<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
|
||||
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>
|
||||
<li>If you are using Android Studio:
|
||||
<li>If you are using Android Studio, complete these steps to copy the file:
|
||||
<ol type="a">
|
||||
<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
|
||||
<em>New Directory</em> window, then select <strong>OK</strong>.
|
||||
<li>Select <strong>File > New > Directory</strong>, enter {@code aidl} in the
|
||||
<em>New Directory</em> window, and select <strong>OK</strong>.
|
||||
|
||||
<li>Select <strong>File > New > Package</strong> and enter
|
||||
{@code com.android.vending.billing} in the <em>New Package</em> window, then select
|
||||
<li>Select <strong>File > New > Package</strong>, enter
|
||||
{@code com.android.vending.billing} in the <em>New Package</em> window, and select
|
||||
<strong>OK</strong>.</li>
|
||||
|
||||
<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 com.android.vending.billing} package in your project.
|
||||
</li>
|
||||
</ol>
|
||||
</li>
|
||||
|
||||
<li>If you are developing in a non-Android Studio environment: Create the
|
||||
following directory {@code /src/com/android/vending/billing} and copy the
|
||||
{@code IInAppBillingService.aidl} file into this directory. Put the AIDL
|
||||
file into your project and use the Gradle tool to build your project so that
|
||||
the <code>IInAppBillingService.java</code> file gets generated.
|
||||
<li>If you are developing in a non-Android Studio environment, create the
|
||||
following directory: {@code /src/com/android/vending/billing}. Copy the
|
||||
{@code IInAppBillingService.aidl} file into this directory. Place the AIDL
|
||||
file in your project and use the Gradle tool to build your project so that
|
||||
the <code>IInAppBillingService.java</code> file is generated.
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
@@ -137,16 +137,16 @@ method calls.</p>
|
||||
</li>
|
||||
</ol>
|
||||
|
||||
<h2 id="billing-permission">Updating Your App's Manifest</h2>
|
||||
<h2 id="billing-permission">Updating your app's manifest</h2>
|
||||
|
||||
<p>
|
||||
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.
|
||||
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
|
||||
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>
|
||||
@@ -182,7 +182,7 @@ method calls.</p>
|
||||
onServiceDisconnected} and {@link
|
||||
android.content.ServiceConnection#onServiceConnected onServiceConnected}
|
||||
methods to get a reference to the {@code IInAppBillingService} instance after
|
||||
a connection has been established.
|
||||
a connection is established.
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
@@ -208,20 +208,25 @@ ServiceConnection mServiceConn = new ServiceConnection() {
|
||||
bindService} method. Pass the method an {@link android.content.Intent} that
|
||||
references the In-app Billing service and an instance of the {@link
|
||||
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.
|
||||
</p>
|
||||
|
||||
<p class="caution">
|
||||
<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
|
||||
android.content.Intent#setPackage(java.lang.String) setPackage()} as shown in
|
||||
the example below. Setting the package name explicitly ensures that
|
||||
android.content.Intent#setPackage(java.lang.String) setPackage()}.
|
||||
Setting the package name explicitly ensures that
|
||||
<em>only</em> the Google Play app can handle billing requests from your app,
|
||||
preventing other apps from intercepting those requests.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The following code sample demonstrates how to set the intent's target package
|
||||
to protect the security of transactions:
|
||||
</p>
|
||||
|
||||
<pre>@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
@@ -233,6 +238,13 @@ public void onCreate(Bundle savedInstanceState) {
|
||||
}
|
||||
</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>
|
||||
You can now use the mService reference to communicate with the Google Play
|
||||
service.
|
||||
@@ -242,10 +254,14 @@ public void onCreate(Bundle savedInstanceState) {
|
||||
<strong>Important:</strong> Remember to unbind from the In-app Billing
|
||||
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
|
||||
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
|
||||
mServiceConn} by overriding the activity’s {@link
|
||||
android.app.Activity#onDestroy onDestroy} method.
|
||||
android.app.Activity#onDestroy onDestroy} method:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
@@ -264,29 +280,29 @@ public void onDestroy() {
|
||||
"{@docRoot}training/in-app-billing/preparing-iab-app.html">Selling In-app
|
||||
Products</a> training class and associated sample.
|
||||
</p>
|
||||
<h2 id="billing-requests">Making In-app Billing Requests</h2>
|
||||
<h2 id="billing-requests">Making In-app Billing requests</h2>
|
||||
<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
|
||||
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
|
||||
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.
|
||||
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 quickly retrieve the list of purchases that were made by the
|
||||
user. This is useful, for example, when you want to restore the user's
|
||||
Google Play to quickly retrieve the list of purchases that the
|
||||
user made. This is useful, for example, when you want to restore the user's
|
||||
purchases when your user launches your app.
|
||||
</p>
|
||||
|
||||
<h3 id="QueryDetails">Querying for Items Available for Purchase</h3>
|
||||
<h3 id="QueryDetails">Querying for items available for purchase</h3>
|
||||
|
||||
<p>
|
||||
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
|
||||
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
|
||||
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>
|
||||
|
||||
<pre>
|
||||
@@ -299,9 +315,9 @@ querySkus.putStringArrayList(“ITEM_ID_LIST”, skuList);
|
||||
|
||||
<p>
|
||||
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
|
||||
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>
|
||||
|
||||
<pre>
|
||||
@@ -310,35 +326,35 @@ Bundle skuDetails = mService.getSkuDetails(3,
|
||||
</pre>
|
||||
|
||||
<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).
|
||||
</p>
|
||||
|
||||
<p class="note">
|
||||
<strong>Warning:</strong> Do not call the {@code getSkuDetails} method on the
|
||||
main thread. Calling this method triggers a network request which could block
|
||||
<strong>Warning:</strong> Don't call the {@code getSkuDetails} method on 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
|
||||
getSkuDetails} method from inside that thread.
|
||||
getSkuDetails} method from inside of that thread.
|
||||
</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
|
||||
Billing Reference</a>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The query results are stored in a String ArrayList with key {@code
|
||||
DETAILS_LIST}. The purchase information is stored in the String in JSON
|
||||
format. To see the types of product detail information that are returned, see
|
||||
DETAILS_LIST}. The purchase information is stored within the String in JSON
|
||||
format. To view the types of product detail information that are returned, see
|
||||
<a href=
|
||||
"{@docRoot}google/play/billing/billing_reference.html#getSkuDetails">In-app
|
||||
Billing Reference</a>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
In this example, you are retrieving the prices for your in-app items from the
|
||||
skuDetails {@link android.os.Bundle} returned from the previous code snippet.
|
||||
In this example shows how to retrieve the prices for your in-app items from the
|
||||
skuDetails {@link android.os.Bundle} that is returned from the previous code snippet:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
@@ -357,15 +373,15 @@ if (response == 0) {
|
||||
}
|
||||
</pre>
|
||||
|
||||
<h3 id="Purchase">Purchasing an Item</h3>
|
||||
<h3 id="Purchase">Purchasing an item</h3>
|
||||
<p>
|
||||
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
|
||||
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
|
||||
along with the purchase information.
|
||||
along with the purchase information. Here is an example:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
@@ -377,10 +393,13 @@ Bundle buyIntentBundle = mService.getBuyIntent(3, getPackageName(),
|
||||
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
|
||||
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
|
||||
Billing Reference</a>. Next, extract a {@link android.app.PendingIntent} from
|
||||
the response {@link android.os.Bundle} with key {@code BUY_INTENT}.
|
||||
Billing Reference</a>.
|
||||
|
||||
<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>
|
||||
|
||||
<pre>
|
||||
@@ -390,8 +409,8 @@ PendingIntent pendingIntent = buyIntentBundle.getParcelable("BUY_INTENT");
|
||||
<p>
|
||||
To complete the purchase transaction, call the {@link
|
||||
android.app.Activity#startIntentSenderForResult startIntentSenderForResult}
|
||||
method and use the {@link android.app.PendingIntent} that you created. In
|
||||
this example, you are using an arbitrary value of 1001 for the request code.
|
||||
method and use the {@link android.app.PendingIntent} that you created. This
|
||||
example uses an arbitrary value of 1001 for the request code:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
@@ -404,9 +423,9 @@ startIntentSenderForResult(pendingIntent.getIntentSender(),
|
||||
Google Play sends a response to your {@link android.app.PendingIntent} to the
|
||||
{@link android.app.Activity#onActivityResult onActivityResult} method of your
|
||||
application. The {@link android.app.Activity#onActivityResult
|
||||
onActivityResult} method will have a result code of {@code
|
||||
Activity.RESULT_OK} (1) or {@code Activity.RESULT_CANCELED} (0). To see the
|
||||
types of order information that is returned in the response {@link
|
||||
onActivityResult} method has a result code of {@code
|
||||
Activity.RESULT_OK} (1) or {@code Activity.RESULT_CANCELED} (0). To view the
|
||||
types of order information that are returned in the response {@link
|
||||
android.content.Intent}, see <a href=
|
||||
"{@docRoot}google/play/billing/billing_reference.html#getBuyIntent">In-app
|
||||
Billing Reference</a>.
|
||||
@@ -415,7 +434,7 @@ startIntentSenderForResult(pendingIntent.getIntentSender(),
|
||||
<p>
|
||||
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
|
||||
android.content.Intent}, for example:
|
||||
android.content.Intent}. Here is an example:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
@@ -436,13 +455,13 @@ startIntentSenderForResult(pendingIntent.getIntentSender(),
|
||||
long. Pass this entire token to other methods, such as when you consume the
|
||||
purchase, as described in <a href=
|
||||
"{@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.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Continuing from the previous example, you get the response code, purchase
|
||||
data, and signature from the response {@link android.content.Intent}.
|
||||
Continuing from the previous example, you receive the response code, purchase
|
||||
data, and signature from the response {@link android.content.Intent}:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
@@ -472,23 +491,23 @@ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
<p class="note">
|
||||
<strong>Security Recommendation:</strong> When you send a purchase request,
|
||||
create a String token that uniquely identifies this purchase request and
|
||||
include this token in the {@code developerPayload}.You can use a randomly
|
||||
generated string as the token. When you receive the purchase response from
|
||||
Google Play, make sure to check the returned data signature, the {@code
|
||||
include this token in the {@code developerPayload}. You can use a randomly-generated
|
||||
string as the token. When you receive the purchase response from
|
||||
Google Play, ensure that you check the returned data signature, the {@code
|
||||
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
|
||||
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.
|
||||
</p>
|
||||
|
||||
<h3 id="QueryPurchases">Querying for Purchased Items</h3>
|
||||
<h3 id="QueryPurchases">Querying for purchased items</h3>
|
||||
|
||||
<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
|
||||
in to the method the In-app Billing API version (“3”), the package name of
|
||||
your calling app, and the purchase type (“inapp” or "subs").
|
||||
the In-app Billing API version (“3”), the package name of
|
||||
your calling app, and the purchase type (“inapp” or "subs") into the method. Here is an example:
|
||||
</p>
|
||||
|
||||
<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
|
||||
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
|
||||
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.
|
||||
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
|
||||
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>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">
|
||||
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>
|
||||
|
||||
<pre>
|
||||
@@ -548,26 +567,26 @@ if (response == 0) {
|
||||
</pre>
|
||||
|
||||
|
||||
<h3 id="Consume">Consuming a Purchase</h3>
|
||||
<h3 id="Consume">Consuming a purchase</h3>
|
||||
|
||||
<p>
|
||||
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, 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
|
||||
Google Play makes it available for purchase again.
|
||||
</p>
|
||||
|
||||
<p class="caution">
|
||||
<p class="note">
|
||||
<strong>Important</strong>: Managed in-app products are consumable, but
|
||||
subscriptions are not.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
How you use the consumption mechanism in your app is up to you. Typically,
|
||||
you would implement consumption for in-app products with temporary benefits
|
||||
The way that you use the consumption mechanism in your app is up to you. Typically,
|
||||
you implement consumption for in-app products with temporary benefits
|
||||
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
|
||||
example, a premium upgrade).
|
||||
</p>
|
||||
@@ -576,21 +595,21 @@ if (response == 0) {
|
||||
To record a purchase consumption, send the {@code consumePurchase} method to
|
||||
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
|
||||
of the data returned in the {@code INAPP_PURCHASE_DATA} String by the Google
|
||||
Play service following a successful purchase request. In this example, you
|
||||
are recording the consumption of a product that is identified with the {@code
|
||||
purchaseToken} in the {@code token} variable.
|
||||
of the data that is returned in the {@code INAPP_PURCHASE_DATA} String by the Google
|
||||
Play service following a successful purchase request. This example
|
||||
records the consumption of a product that is identified with the {@code
|
||||
purchaseToken} in the {@code token} variable:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
int response = mService.consumePurchase(3, getPackageName(), token);
|
||||
</pre>
|
||||
|
||||
<p class="note">
|
||||
<strong>Warning:</strong> Do not call the {@code consumePurchase} method on
|
||||
the main thread. Calling this method triggers a network request which could
|
||||
<p class="caution">
|
||||
<strong>Warning:</strong> Don't call the {@code consumePurchase} method on
|
||||
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
|
||||
consumePurchase} method from inside that thread.
|
||||
consumePurchase} method from inside of that thread.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
@@ -600,20 +619,20 @@ int response = mService.consumePurchase(3, getPackageName(), token);
|
||||
purchased.
|
||||
</p>
|
||||
|
||||
<p class="note">
|
||||
<strong>Security Recommendation:</strong> You must send a consumption request
|
||||
<p class="caution">
|
||||
<strong>Security Recommendation:</strong> Send a consumption request
|
||||
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.
|
||||
</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
|
||||
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
|
||||
{@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>
|
||||
Bundle bundle = mService.getBuyIntent(3, "com.example.myapp",
|
||||
@@ -629,18 +648,18 @@ if (bundle.getInt(RESPONSE_CODE) == BILLING_RESPONSE_RESULT_OK) {
|
||||
</pre>
|
||||
|
||||
<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>
|
||||
Bundle activeSubs = mService.getPurchases(3, "com.example.myapp",
|
||||
"subs", continueToken);
|
||||
</pre>
|
||||
|
||||
<p>The call returns a {@code Bundle} with all the active subscriptions owned by
|
||||
the user. Once a subscription expires without renewal, it will no longer appear
|
||||
<p>The call returns a {@code Bundle} with all of the active subscriptions that are owned by
|
||||
the user. When a subscription expires without renewal, it no longer appears
|
||||
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
|
||||
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
|
||||
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
|
||||
pair, open your application's details in the Developer Console, then click on
|
||||
<strong>Services & APIs</strong>, and look at the field titled
|
||||
<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, click
|
||||
<strong>Services & APIs</strong>, and review the field titled
|
||||
<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
|
||||
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.
|
||||
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
|
||||
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>
|
||||
|
||||
<p>For more information about best practices for security and design, see <a
|
||||
|
||||
@@ -8,19 +8,19 @@ parent.link=services.html
|
||||
<ol id="qv">
|
||||
<h2>In this document</h2>
|
||||
<ol>
|
||||
<li><a href="#Basics">The Basics</a></li>
|
||||
<li><a href="#Creating">Creating a Bound Service</a>
|
||||
<li><a href="#Basics">The basics</a></li>
|
||||
<li><a href="#Creating">Creating a bound service</a>
|
||||
<ol>
|
||||
<li><a href="#Binder">Extending the Binder class</a></li>
|
||||
<li><a href="#Messenger">Using a Messenger</a></li>
|
||||
</ol>
|
||||
</li>
|
||||
<li><a href="#Binding">Binding to a Service</a>
|
||||
<li><a href="#Binding">Binding to a service</a>
|
||||
<ol>
|
||||
<li><a href="#Additional_Notes">Additional notes</a></li>
|
||||
</ol>
|
||||
</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>
|
||||
|
||||
<h2>Key classes</h2>
|
||||
@@ -32,9 +32,13 @@ parent.link=services.html
|
||||
|
||||
<h2>Samples</h2>
|
||||
<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>
|
||||
<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>
|
||||
</ol>
|
||||
|
||||
@@ -45,19 +49,23 @@ parent.link=services.html
|
||||
</div>
|
||||
|
||||
|
||||
<p>A bound service is the server in a client-server interface. A bound service allows components
|
||||
(such as activities) to bind to the service, send requests, receive responses, and even perform
|
||||
<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 perform
|
||||
interprocess communication (IPC). A bound service typically lives only while it serves another
|
||||
application component and does not run in the background indefinitely.</p>
|
||||
|
||||
<p>This document shows you how to create a bound service, including how to bind
|
||||
to the service from other application components. However, you should also refer to the <a
|
||||
href="{@docRoot}guide/components/services.html">Services</a> document for additional
|
||||
information about services in general, such as how to deliver notifications from a service, set
|
||||
the service to run in the foreground, and more.</p>
|
||||
<p class="note"><strong>Note:</strong> If your app targets Android 5.0 (API level 21) or later,
|
||||
it's recommended that you 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>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
|
||||
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">
|
||||
<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>
|
||||
document, you can create a service that is both started and bound. That is, the service can be
|
||||
started by calling {@link android.content.Context#startService startService()}, which allows the
|
||||
service to run indefinitely, and also allow a client to bind to the service by calling {@link
|
||||
document, you can create a service that is both started and bound. That is, you can start a
|
||||
service by calling {@link android.content.Context#startService startService()}, which allows the
|
||||
service to run indefinitely, and you can also allow a client to bind to the service by
|
||||
calling {@link
|
||||
android.content.Context#bindService bindService()}.
|
||||
<p>If you do allow your service to be started and bound, then when the service has been
|
||||
started, the system does <em>not</em> destroy the service when all clients unbind. Instead, you must
|
||||
explicitly stop the service, by calling {@link android.app.Service#stopSelf stopSelf()} or {@link
|
||||
started, the system does <em>not</em> destroy the service when all clients unbind.
|
||||
Instead, you must
|
||||
explicitly stop the service by calling {@link android.app.Service#stopSelf stopSelf()} or {@link
|
||||
android.content.Context#stopService stopService()}.</p>
|
||||
|
||||
<p>Although you should usually implement either {@link android.app.Service#onBind onBind()}
|
||||
<em>or</em> {@link android.app.Service#onStartCommand onStartCommand()}, it's sometimes necessary to
|
||||
<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
|
||||
implement both. For example, a music player might find it useful to allow its service to run
|
||||
indefinitely and also provide binding. This way, an activity can start the service to play some
|
||||
music and the music continues to play even if the user leaves the application. Then, when the user
|
||||
returns to the application, the activity can bind to the service to regain control of playback.</p>
|
||||
returns to the application, the activity can bind to the service to regain control of
|
||||
playback.</p>
|
||||
|
||||
<p>Be sure to read the section about <a href="#Lifecycle">Managing the Lifecycle of a Bound
|
||||
Service</a>, for more information about the service lifecycle when adding binding to a
|
||||
started service.</p>
|
||||
<p>For more information about the service lifecycle when adding binding to a started service,
|
||||
see <a href="#Lifecycle">Managing the lifecycle of a bound Service</a>.</p>
|
||||
</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
|
||||
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
|
||||
client and service, it calls {@link
|
||||
android.content.ServiceConnection#onServiceConnected onServiceConnected()} on the {@link
|
||||
android.content.ServiceConnection}, to deliver the {@link android.os.IBinder} that
|
||||
the client can use to communicate with the service.</p>
|
||||
|
||||
<p>Multiple clients can connect to the service at once. However, the system calls your service's
|
||||
{@link android.app.Service#onBind onBind()} method to retrieve the {@link android.os.IBinder} only
|
||||
<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
|
||||
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
|
||||
service was also started by {@link android.content.Context#startService startService()}).</p>
|
||||
<p>When the last client unbinds from the service, the system destroys the service, unless the
|
||||
service was also started by {@link android.content.Context#startService startService()}.</p>
|
||||
|
||||
<p>When you implement your bound service, the most important part is defining the interface
|
||||
that your {@link android.app.Service#onBind onBind()} callback method returns. There are a few
|
||||
different ways you can define your service's {@link android.os.IBinder} interface and the following
|
||||
section discusses each technique.</p>
|
||||
<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. The following
|
||||
section discusses several different ways that you can define your service's
|
||||
{@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}
|
||||
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>
|
||||
<dt><a href="#Binder">Extending the Binder class</a></dt>
|
||||
<dd>If your service is private to your own application and runs in the same process as the client
|
||||
(which is common), you should create your interface by extending the {@link android.os.Binder} class
|
||||
<dd>If your service is private to your own application and runs in the same process
|
||||
as the client
|
||||
(which is common), you should create your interface by extending the {@link android.os.Binder}
|
||||
class
|
||||
and returning an instance of it from
|
||||
{@link android.app.Service#onBind onBind()}. The client receives the {@link android.os.Binder} and
|
||||
can use it to directly access public methods available in either the {@link android.os.Binder}
|
||||
implementation or even the {@link android.app.Service}.
|
||||
implementation or the {@link android.app.Service}.
|
||||
<p>This is the preferred technique when your service is merely a background worker for your own
|
||||
application. The only reason you would not create your interface this way is because
|
||||
your service is used by other applications or across separate processes.</dd>
|
||||
@@ -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}
|
||||
with the client, allowing the client to send commands to the service using {@link
|
||||
android.os.Message} objects. Additionally, the client can define a {@link android.os.Messenger} of
|
||||
its own so the service can send messages back.
|
||||
its own, so the service can send messages back.
|
||||
<p>This is the simplest way to perform interprocess communication (IPC), because the {@link
|
||||
android.os.Messenger} queues all requests into a single thread so that you don't have to design
|
||||
your service to be thread-safe.</p>
|
||||
</dd>
|
||||
|
||||
<dt>Using AIDL</dt>
|
||||
<dd>AIDL (Android Interface Definition Language) performs all the work to decompose objects into
|
||||
primitives that the operating system can understand and marshall them across processes to perform
|
||||
<dt><a href="{@docRoot}guide/components/aidl.html">Using AIDL</a></dt>
|
||||
<dd>Android Interface Definition Language (AIDL) decomposes objects into
|
||||
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
|
||||
its underlying structure. As mentioned above, the {@link android.os.Messenger} creates a queue of
|
||||
all the client requests in a single thread, so the service receives requests one at a time. If,
|
||||
however, you want your service to handle multiple requests simultaneously, then you can use AIDL
|
||||
directly. In this case, your service must be capable of multi-threading and be built thread-safe.
|
||||
directly. In this case, your service must be thread-safe and capable of multi-threading.
|
||||
<p>To use AIDL directly, you must
|
||||
create an {@code .aidl} file that defines the programming interface. The Android SDK tools use
|
||||
this file to generate an abstract class that implements the interface and handles IPC, which you
|
||||
@@ -164,19 +178,18 @@ can then extend within your service.</p>
|
||||
</dd>
|
||||
</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
|
||||
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
|
||||
to use AIDL directly, see the <a href="{@docRoot}guide/components/aidl.html">AIDL</a>
|
||||
document.</p>
|
||||
|
||||
|
||||
|
||||
|
||||
<h3 id="Binder">Extending the Binder class</h3>
|
||||
|
||||
<p>If your service is used only by the local application and does not need to work across processes,
|
||||
<p>If your service is used only by the local application and does not need to
|
||||
work across processes,
|
||||
then you can implement your own {@link android.os.Binder} class that provides your client direct
|
||||
access to public methods in the service.</p>
|
||||
|
||||
@@ -187,13 +200,14 @@ background.</p>
|
||||
|
||||
<p>Here's how to set it up:</p>
|
||||
<ol>
|
||||
<li>In your service, create an instance of {@link android.os.Binder} that either:
|
||||
<li>In your service, create an instance of {@link android.os.Binder} that does
|
||||
one of the following:
|
||||
<ul>
|
||||
<li>contains public methods that the client can call</li>
|
||||
<li>returns the current {@link android.app.Service} instance, which has public methods the
|
||||
client can call</li>
|
||||
<li>or, returns an instance of another class hosted by the service with public methods the
|
||||
client can call</li>
|
||||
<li>Contains public methods that the client can call.</li>
|
||||
<li>Returns the current {@link android.app.Service} instance, which has public methods the
|
||||
client can call.</li>
|
||||
<li>Returns an instance of another class hosted by the service with public methods the
|
||||
client can call.</li>
|
||||
</ul>
|
||||
<li>Return this instance of {@link android.os.Binder} from the {@link
|
||||
android.app.Service#onBind onBind()} callback method.</li>
|
||||
@@ -202,12 +216,13 @@ android.content.ServiceConnection#onServiceConnected onServiceConnected()} callb
|
||||
make calls to the bound service using the methods provided.</li>
|
||||
</ol>
|
||||
|
||||
<p class="note"><strong>Note:</strong> The reason the service and client must be in the same
|
||||
application is so the client can cast the returned object and properly call its APIs. The service
|
||||
<p class="note"><strong>Note:</strong> The service and client must be in the same
|
||||
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
|
||||
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>
|
||||
|
||||
<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
|
||||
{@link android.app.Activity#onStop onStop()} method unbinds the client from the service. Clients
|
||||
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>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
|
||||
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
|
||||
href="{@docRoot}resources/samples/ApiDemos/index.html">ApiDemos</a>.</p>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h3 id="Messenger">Using a Messenger</h3>
|
||||
|
||||
<div class="sidebox-wrapper">
|
||||
<div class="sidebox">
|
||||
<h4>Compared to AIDL</h4>
|
||||
<p>When you need to perform IPC, using a {@link android.os.Messenger} for your interface is
|
||||
simpler than implementing it with AIDL, because {@link android.os.Messenger} queues
|
||||
all calls to the service, whereas, a pure AIDL interface sends simultaneous requests to the
|
||||
simpler than using AIDL, because {@link android.os.Messenger} queues
|
||||
all calls to the service. A pure AIDL interface sends simultaneous requests to the
|
||||
service, which must then handle multi-threading.</p>
|
||||
<p>For most applications, the service doesn't need to perform multi-threading, so using a {@link
|
||||
android.os.Messenger} allows the service to handle one call at a time. If it's important
|
||||
that your service be multi-threaded, then you should use <a
|
||||
that your service be multi-threaded, use <a
|
||||
href="{@docRoot}guide/components/aidl.html">AIDL</a> to define your interface.</p>
|
||||
</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>
|
||||
|
||||
<ul>
|
||||
<ol>
|
||||
<li>The service implements a {@link android.os.Handler} that receives a callback for each
|
||||
call from a client.</li>
|
||||
<li>The {@link android.os.Handler} is used to create a {@link android.os.Messenger} object
|
||||
<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>
|
||||
<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>
|
||||
@@ -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
|
||||
android.os.Handler}—specifically, in the {@link android.os.Handler#handleMessage
|
||||
handleMessage()} method.</li>
|
||||
</ul>
|
||||
</ol>
|
||||
|
||||
|
||||
<p>In this way, there are no "methods" for the client to call on the service. Instead, the
|
||||
client delivers "messages" ({@link android.os.Message} objects) that the service receives in
|
||||
<p>In this way, there are no <em>methods</em> for the client to call on the service. Instead, the
|
||||
client delivers <em>messages</em> ({@link android.os.Message} objects) that the service
|
||||
receives in
|
||||
its {@link android.os.Handler}.</p>
|
||||
|
||||
<p>Here's a simple example service that uses a {@link android.os.Messenger} interface:</p>
|
||||
@@ -488,41 +503,42 @@ public class ActivityMessenger extends Activity {
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>Notice that this example does not show how the service can respond to the client. If you want the
|
||||
service to respond, then you need to also create a {@link android.os.Messenger} in the client. Then
|
||||
when the client receives the {@link android.content.ServiceConnection#onServiceConnected
|
||||
<p>Notice that this example does not show how the service can respond to the client.
|
||||
If you want the
|
||||
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
|
||||
the client's {@link android.os.Messenger} in the {@link android.os.Message#replyTo} parameter
|
||||
of the {@link android.os.Messenger#send send()} method.</p>
|
||||
|
||||
<p>You can see an example of how to provide two-way messaging in the <a
|
||||
href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/MessengerService.html">{@code
|
||||
href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/MessengerService.html">
|
||||
{@code
|
||||
MessengerService.java}</a> (service) and <a
|
||||
href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/MessengerServiceActivities.html">{@code
|
||||
href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/MessengerServiceActivities.html">
|
||||
{@code
|
||||
MessengerServiceActivities.java}</a> (client) samples.</p>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h2 id="Binding">Binding to a Service</h2>
|
||||
<h2 id="Binding">Binding to a service</h2>
|
||||
|
||||
<p>Application components (clients) can bind to a service by calling
|
||||
{@link android.content.Context#bindService bindService()}. The Android
|
||||
system then calls the service's {@link android.app.Service#onBind
|
||||
onBind()} method, which returns an {@link android.os.IBinder} for interacting with the service.</p>
|
||||
onBind()} method, which returns an {@link android.os.IBinder} for interacting with
|
||||
the service.</p>
|
||||
|
||||
<p>The binding is asynchronous. {@link android.content.Context#bindService
|
||||
bindService()} returns immediately and does <em>not</em> return the {@link android.os.IBinder} to
|
||||
the client. To receive the {@link android.os.IBinder}, the client must create an instance of {@link
|
||||
<p>The binding is asynchronous, and {@link android.content.Context#bindService
|
||||
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
|
||||
android.content.ServiceConnection} and pass it to {@link android.content.Context#bindService
|
||||
bindService()}. The {@link android.content.ServiceConnection} includes a callback method that the
|
||||
system calls to deliver the {@link android.os.IBinder}.</p>
|
||||
|
||||
<p class="note"><strong>Note:</strong> Only activities, services, and content providers can bind
|
||||
to a service—you <strong>cannot</strong> bind to a service from a broadcast receiver.</p>
|
||||
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>
|
||||
<li>Implement {@link android.content.ServiceConnection}.
|
||||
<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
|
||||
onServiceDisconnected()}</dt>
|
||||
<dd>The Android system calls this when the connection to the service is unexpectedly
|
||||
lost, such as when the service has crashed or has been killed. This is <em>not</em> called when the
|
||||
lost, such as when the service has crashed or has been killed. This is <em>not</em>
|
||||
called when the
|
||||
client unbinds.</dd>
|
||||
</dl>
|
||||
</li>
|
||||
@@ -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
|
||||
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
|
||||
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>
|
||||
</li>
|
||||
</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
|
||||
{@link android.os.IBinder} to the {@code LocalService} class and request the {@code
|
||||
LocalService} instance:</p>
|
||||
@@ -579,8 +596,9 @@ private ServiceConnection mConnection = new ServiceConnection() {
|
||||
};
|
||||
</pre>
|
||||
|
||||
<p>With this {@link android.content.ServiceConnection}, the client can bind to a service by passing
|
||||
it to {@link android.content.Context#bindService bindService()}. For example:</p>
|
||||
<p>With this {@link android.content.ServiceConnection}, the client can bind to a service
|
||||
by passing
|
||||
it to {@link android.content.Context#bindService bindService()}, as shown in the following example:</p>
|
||||
|
||||
<pre>
|
||||
Intent intent = new Intent(this, LocalService.class);
|
||||
@@ -589,11 +607,21 @@ bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
|
||||
|
||||
<ul>
|
||||
<li>The first parameter of {@link android.content.Context#bindService bindService()} is an
|
||||
{@link android.content.Intent} that explicitly names the service to bind (thought the intent
|
||||
could be implicit).</li>
|
||||
{@link android.content.Intent} that explicitly names the service to bind.
|
||||
<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 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}
|
||||
and {@link android.content.Context#BIND_NOT_FOREGROUND}, or {@code 0} for none.</li>
|
||||
</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
|
||||
when the connection has broken. This is the only exception thrown by remote methods.</li>
|
||||
<li>Objects are reference counted across processes. </li>
|
||||
<li>You should usually pair the binding and unbinding during
|
||||
matching bring-up and tear-down moments of the client's lifecycle. For example:
|
||||
<li>You usually pair the binding and unbinding during
|
||||
matching bring-up and tear-down moments of the client's lifecycle, as described in the
|
||||
following examples:
|
||||
<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
|
||||
android.app.Activity#onStop onStop()}.</li>
|
||||
<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
|
||||
more likely that the system will kill it.</li>
|
||||
</ul>
|
||||
<p class="note"><strong>Note:</strong> You should usually <strong>not</strong> bind and unbind
|
||||
<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
|
||||
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
|
||||
multiple activities in your application bind to the same service and there is a transition between
|
||||
two of those activities, the service may be destroyed and recreated as the current activity unbinds
|
||||
(during pause) before the next one binds (during resume). (This activity transition for how
|
||||
multiple activities in your application bind to the same service and there is a
|
||||
transition between
|
||||
two of those activities, the service may be destroyed and recreated as the current
|
||||
activity unbinds
|
||||
(during pause) before the next one binds (during resume). This activity transition for how
|
||||
activities coordinate their lifecycles is described in the <a
|
||||
href="{@docRoot}guide/components/activities.html#CoordinatingActivities">Activities</a>
|
||||
document.)</p>
|
||||
document.</p>
|
||||
</ul>
|
||||
|
||||
<p>For more sample code, showing how to bind to a service, see the <a
|
||||
href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/RemoteService.html">{@code
|
||||
href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/RemoteService.html">
|
||||
{@code
|
||||
RemoteService.java}</a> class in <a
|
||||
href="{@docRoot}resources/samples/ApiDemos/index.html">ApiDemos</a>.</p>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h2 id="Lifecycle">Managing the Lifecycle of a Bound Service</h2>
|
||||
<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
|
||||
started with {@link android.app.Service#onStartCommand onStartCommand()}). As such, you don't have
|
||||
to manage the lifecycle of your service if it's purely a bound
|
||||
service—the Android system manages it for you based on whether it is bound to any clients.</p>
|
||||
service—the Android system manages it for you based on whether it is bound to
|
||||
any clients.</p>
|
||||
|
||||
<p>However, if you choose to implement the {@link android.app.Service#onStartCommand
|
||||
onStartCommand()} callback method, then you must explicitly stop the service, because the
|
||||
@@ -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()} returns void, but the client still receives the {@link android.os.IBinder} in its
|
||||
{@link android.content.ServiceConnection#onServiceConnected onServiceConnected()} callback.
|
||||
Below, figure 1 illustrates the logic for this kind of lifecycle.</p>
|
||||
|
||||
The following figure illustrates the logic for this kind of lifecycle.</p>
|
||||
|
||||
<img src="{@docRoot}images/fundamentals/service_binding_tree_lifecycle.png" alt="" />
|
||||
<p class="img-caption"><strong>Figure 1.</strong> The lifecycle for a service that is started
|
||||
and also allows binding.</p>
|
||||
|
||||
|
||||
<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>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -6,28 +6,29 @@ page.title=Application Fundamentals
|
||||
|
||||
<h2>In this document</h2>
|
||||
<ol>
|
||||
<li><a href="#Components">App Components</a>
|
||||
<li><a href="#Components">App components</a>
|
||||
<ol>
|
||||
<li><a href="#ActivatingComponents">Activating components</a></li>
|
||||
</ol>
|
||||
</li>
|
||||
<li><a href="#Manifest">The Manifest File</a>
|
||||
<li><a href="#Manifest">The manifest file</a>
|
||||
<ol>
|
||||
<li><a href="#DeclaringComponents">Declaring components</a></li>
|
||||
<li><a href="#DeclaringRequirements">Declaring app requirements</a></li>
|
||||
</ol>
|
||||
</li>
|
||||
<li><a href="#Resources">App Resources</a></li>
|
||||
<li><a href="#Resources">App resources</a></li>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<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
|
||||
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>
|
||||
<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
|
||||
other apps.</li>
|
||||
|
||||
<li>By default, every app runs in its own Linux process. Android starts the process when any
|
||||
of the app's components need to be executed, then shuts down the process when it's no longer
|
||||
<li>By default, every app runs in its own Linux process. The Android system starts
|
||||
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>
|
||||
</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
|
||||
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>
|
||||
|
||||
<p>However, there are ways for an app to share data with other apps and for an
|
||||
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
|
||||
app to access system services:</p>
|
||||
|
||||
<ul>
|
||||
<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
|
||||
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>
|
||||
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>
|
||||
<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
|
||||
<a href="{@docRoot}training/permissions/index.html">Working with System Permissions</a>.</li>
|
||||
</ul>
|
||||
|
||||
<p>That covers the basics regarding how an Android app exists within the system. The rest of
|
||||
this document introduces you to:</p>
|
||||
<p>The rest of this document introduces the following concepts:</p>
|
||||
<ul>
|
||||
<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>
|
||||
<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>
|
||||
</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
|
||||
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
|
||||
as its own entity and plays a specific role—each one is a unique building block that
|
||||
helps define your app's overall behavior.</p>
|
||||
components are actual entry points for the user and some depend on each other,
|
||||
but each one exists
|
||||
as its own entity and plays a specific role.</p>
|
||||
|
||||
<p>There are four different types of app components. Each type serves a distinct purpose
|
||||
and has a distinct lifecycle that defines how the component is created and destroyed.</p>
|
||||
|
||||
<p>Here are the four types of app components:</p>
|
||||
<p>There are four different types of app components:
|
||||
<ul>
|
||||
<li>Activities.</li>
|
||||
<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>
|
||||
|
||||
@@ -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
|
||||
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
|
||||
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.
|
||||
activities if the email app allows it. For example, a camera app can start the
|
||||
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
|
||||
about it in the <a href="{@docRoot}guide/components/activities.html">Activities</a>
|
||||
<p>An activity is implemented as a subclass of {@link android.app.Activity}. You can learn more
|
||||
about {@link android.app.Activity} in the
|
||||
<a href="{@docRoot}guide/components/activities.html">Activities</a>
|
||||
developer guide.</p>
|
||||
</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
|
||||
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
|
||||
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.
|
||||
|
||||
<p>A service is implemented as a subclass of {@link android.app.Service} and you can learn more
|
||||
about it in the <a href="{@docRoot}guide/components/services.html">Services</a> developer
|
||||
<p>A service is implemented as a subclass of {@link android.app.Service}. You can learn more
|
||||
about {@link android.app.Service} in the <a href="{@docRoot}guide/components/services.html">
|
||||
Services</a> developer
|
||||
guide.</p>
|
||||
</dd>
|
||||
|
||||
@@ -125,12 +137,14 @@ guide.</p>
|
||||
<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
|
||||
the file system, an SQLite database, on the web, or any other persistent storage location your
|
||||
app can access. Through the content provider, other apps can query or even modify
|
||||
the data (if the content provider allows it). For example, the Android system provides a content
|
||||
the file system, in a SQLite database, on the web, or on any other persistent storage
|
||||
location that your
|
||||
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
|
||||
permissions can query part of the content provider (such as {@link
|
||||
android.provider.ContactsContract.Data}) to read and write information about a particular person.
|
||||
permissions can query part of the content provider, such as {@link
|
||||
android.provider.ContactsContract.Data}, to read and write information about
|
||||
a particular person.
|
||||
|
||||
<p>Content providers are also useful for reading and writing data that is private to your
|
||||
app and not shared. For example, the <a
|
||||
@@ -148,15 +162,17 @@ guide.</p>
|
||||
<dt><b>Broadcast receivers</b></dt>
|
||||
|
||||
<dd>A <i>broadcast receiver</i> is a component that responds to system-wide broadcast
|
||||
announcements. Many broadcasts originate from the system—for example, a broadcast announcing
|
||||
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.
|
||||
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
|
||||
href="{@docRoot}guide/topics/ui/notifiers/notifications.html">create a status bar notification</a>
|
||||
to alert the user when a broadcast event occurs. More commonly, though, a broadcast receiver is
|
||||
just a "gateway" to other components and is intended to do a very minimal amount of work. For
|
||||
instance, it might initiate a service to perform some work based on the event.
|
||||
just a <em>gateway</em> to other components and is intended to do a very minimal amount of work.
|
||||
For instance, it might initiate a service to perform some work based on the event.
|
||||
|
||||
<p>A broadcast receiver is implemented as a subclass of {@link android.content.BroadcastReceiver}
|
||||
and each broadcast is delivered as an {@link android.content.Intent} object. For more information,
|
||||
@@ -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
|
||||
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
|
||||
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.
|
||||
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,
|
||||
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
|
||||
already running) and instantiates the classes needed for the component. For example, if your
|
||||
<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
|
||||
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.
|
||||
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
|
||||
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, you must deliver a message to the system that specifies your <em>intent</em> to
|
||||
another app. However, the Android system can. To activate a component in
|
||||
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>
|
||||
|
||||
|
||||
<h3 id="ActivatingComponents">Activating Components</h3>
|
||||
<h3 id="ActivatingComponents">Activating components</h3>
|
||||
|
||||
<p>Three of the four component types—activities, services, and
|
||||
broadcast receivers—are activated by an asynchronous message called an <em>intent</em>.
|
||||
Intents bind individual components to each other at runtime (you can think of them
|
||||
as the messengers that request an action from other components), whether the component belongs
|
||||
Intents bind individual components to each other at runtime. You can think of them
|
||||
as the messengers that request an action from other components, whether the component belongs
|
||||
to your app or another.</p>
|
||||
|
||||
<p>An intent is created with an {@link android.content.Intent} object, which defines a message to
|
||||
activate either a specific component or a specific <em>type</em> of component—an intent
|
||||
can be either explicit or implicit, respectively.</p>
|
||||
<p class="note"><strong>Note:</strong> If your app targets Android 5.0 (API level 21) or later,
|
||||
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>
|
||||
|
||||
<p>For activities and services, an intent defines the action to perform (for example, to "view" or
|
||||
"send" something) and may specify the URI of the data to act on (among other things that the
|
||||
component being started might need to know). For example, an intent might convey a request for an
|
||||
<p>An intent is created with an {@link android.content.Intent} object, which defines a message to
|
||||
activate either a specific component (explicit intent) or a specific <em>type</em> of component
|
||||
(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 receive a result, in which case, the activity also returns
|
||||
the result in an {@link android.content.Intent} (for example, you can issue an intent to let
|
||||
the user pick a personal contact and have it returned to you—the return intent includes a
|
||||
URI pointing to the chosen contact).</p>
|
||||
activity to receive a result, in which case the activity also returns
|
||||
the result in an {@link android.content.Intent}. For example, you can issue an intent to let
|
||||
the user pick a personal contact and have it returned to you. The return intent includes a
|
||||
URI pointing to the chosen contact.</p>
|
||||
|
||||
<p>For broadcast receivers, the intent simply defines the
|
||||
announcement being broadcast (for example, a broadcast to indicate the device battery is low
|
||||
includes only a known action string that indicates "battery is low").</p>
|
||||
announcement being broadcast. For example, a broadcast to indicate the device battery is low
|
||||
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
|
||||
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
|
||||
@@ -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>
|
||||
<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
|
||||
startActivity()} or {@link android.app.Activity#startActivityForResult startActivityForResult()}
|
||||
(when you want the activity to return a result).</li>
|
||||
<li>You can start a service (or give new instructions to an ongoing service) by
|
||||
|
||||
|
||||
<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
|
||||
startService()}. Or you can bind to the service by passing an {@link android.content.Intent} to
|
||||
{@link android.content.Context#bindService bindService()}.</li>
|
||||
<li>You can initiate a broadcast by passing an {@link android.content.Intent} to methods like
|
||||
startService()}. You can bind to the service by passing an {@link android.content.Intent} to
|
||||
{@link android.content.Context#bindService bindService()}. </li>
|
||||
<li>You can initiate a broadcast by passing an {@link android.content.Intent} to methods such as
|
||||
{@link android.content.Context#sendBroadcast(Intent) sendBroadcast()}, {@link
|
||||
android.content.Context#sendOrderedBroadcast(Intent, String) sendOrderedBroadcast()}, or {@link
|
||||
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
|
||||
href="{@docRoot}guide/components/intents-filters.html">Intents and
|
||||
Intent Filters</a> document. More information about activating specific components is also provided
|
||||
in the following documents: <a
|
||||
href="{@docRoot}guide/components/activities.html">Activities</a>, <a
|
||||
href="{@docRoot}guide/components/services.html">Services</a>, {@link
|
||||
android.content.BroadcastReceiver} and <a
|
||||
href="{@docRoot}guide/topics/providers/content-providers.html">Content Providers</a>.</p>
|
||||
Intent Filters</a> document.
|
||||
The following documents provide more information about activating specifc components:
|
||||
<a href="{@docRoot}guide/components/activities.html">Activities</a>,
|
||||
<a href="{@docRoot}guide/components/services.html">Services
|
||||
{@link android.content.BroadcastReceiver}, and
|
||||
<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
|
||||
component exists by reading the app's {@code AndroidManifest.xml} file (the "manifest"
|
||||
file). Your app must declare all its components in this file, which must be at the root of
|
||||
the app project directory.</p>
|
||||
component exists by reading the app's <em>manifest file</em>, {@code AndroidManifest.xml}.
|
||||
Your app must declare all its components in this file, which must be at the root of the
|
||||
app project directory.</p>
|
||||
|
||||
<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>
|
||||
<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>
|
||||
<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>
|
||||
<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>
|
||||
<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
|
||||
href="http://code.google.com/android/add-ons/google-apis/maps-overview.html">Google Maps
|
||||
library</a>.</li>
|
||||
<li>And more</li>
|
||||
href="http://code.google.com/android/add-ons/google-apis/maps-overview.html">
|
||||
Google Maps library</a>.</li>
|
||||
|
||||
</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
|
||||
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>
|
||||
<li><code><a
|
||||
href="{@docRoot}guide/topics/manifest/activity-element.html"><activity></a></code> elements
|
||||
for activities</li>
|
||||
for activities.</li>
|
||||
<li><code><a
|
||||
href="{@docRoot}guide/topics/manifest/service-element.html"><service></a></code> elements for
|
||||
services</li>
|
||||
services.</li>
|
||||
<li><code><a
|
||||
href="{@docRoot}guide/topics/manifest/receiver-element.html"><receiver></a></code> elements
|
||||
for broadcast receivers</li>
|
||||
for broadcast receivers.</li>
|
||||
<li><code><a
|
||||
href="{@docRoot}guide/topics/manifest/provider-element.html"><provider></a></code> elements
|
||||
for content providers</li>
|
||||
for content providers.</li>
|
||||
</ul>
|
||||
|
||||
<p>Activities, services, and content providers that you include in your source but do not declare
|
||||
in the manifest are not visible to the system and, consequently, can never run. However,
|
||||
broadcast
|
||||
receivers can be either declared in the manifest or created dynamically in code (as
|
||||
{@link android.content.BroadcastReceiver} objects) and registered with the system by calling
|
||||
receivers can be either declared in the manifest or created dynamically in code as
|
||||
{@link android.content.BroadcastReceiver} objects and registered with the system by calling
|
||||
{@link android.content.Context#registerReceiver registerReceiver()}.</p>
|
||||
|
||||
<p>For more about how to structure the manifest file for your app, see <a
|
||||
href="{@docRoot}guide/topics/manifest/manifest-intro.html">The AndroidManifest.xml File</a>
|
||||
documentation. </p>
|
||||
|
||||
|
||||
|
||||
<h3 id="DeclaringComponentCapabilities">Declaring component capabilities</h3>
|
||||
|
||||
<p>As discussed above, in <a href="#ActivatingComponents">Activating Components</a>, you can use an
|
||||
{@link android.content.Intent} to start activities, services, and broadcast receivers. You can do so
|
||||
by explicitly naming the target component (using the component class name) in the intent. However,
|
||||
the real power of intents lies in the concept of <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>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.
|
||||
|
||||
<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
|
||||
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
|
||||
<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
|
||||
declare an intent filter to respond to "send" intents (in order to send a new email) like this:</p>
|
||||
<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),
|
||||
as shown in the following example:</p>
|
||||
<pre>
|
||||
<manifest ... >
|
||||
...
|
||||
@@ -368,8 +408,9 @@ declare an intent filter to respond to "send" intents (in order to send a new em
|
||||
</manifest>
|
||||
</pre>
|
||||
|
||||
<p>Then, if another app creates an intent with the {@link
|
||||
android.content.Intent#ACTION_SEND} action and passes it to {@link android.app.Activity#startActivity
|
||||
<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
|
||||
startActivity()}, the system may start your activity so the user can draft and send an
|
||||
email.</p>
|
||||
|
||||
@@ -382,7 +423,7 @@ href="{@docRoot}guide/components/intents-filters.html">Intents and Intent Filter
|
||||
<h3 id="DeclaringRequirements">Declaring app requirements</h3>
|
||||
|
||||
<p>There are a variety of devices powered by Android and not all of them provide the
|
||||
same features and capabilities. In order to prevent your 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
|
||||
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
|
||||
@@ -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
|
||||
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>
|
||||
<manifest ... >
|
||||
@@ -402,10 +443,10 @@ you should declare these as requirements in your manifest file like this:</p>
|
||||
</manifest>
|
||||
</pre>
|
||||
|
||||
<p>Now, devices that do <em>not</em> have a camera and have an
|
||||
Android version <em>lower</em> than 2.1 cannot install your app from Google Play.</p>
|
||||
|
||||
<p>However, you can also declare that your app uses the camera, but does not
|
||||
<p>With the declarations shown in the example, devices that do <em>not</em> have a
|
||||
camera and have an
|
||||
Android version <em>lower</em> than 2.1 cannot install your app from Google Play.
|
||||
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=
|
||||
"{@docRoot}guide/topics/manifest/uses-feature-element.html#required">{@code required}</a>
|
||||
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
|
||||
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
|
||||
to update various characteristics of your app without modifying code and—by providing
|
||||
sets of alternative resources—enables you to optimize your app for a variety of
|
||||
device configurations (such as different languages and screen sizes).</p>
|
||||
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
|
||||
device configurations, such as different languages and screen sizes.</p>
|
||||
|
||||
<p>For every resource that you include in your Android project, the SDK build tools define a unique
|
||||
integer ID, which you can use to reference the resource from your 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>
|
||||
|
||||
<p>One of the most important aspects of providing resources separate from your source code
|
||||
is the ability for you to provide alternative resources for different device
|
||||
configurations. For example, by defining UI strings in XML, you can translate the strings into other
|
||||
languages and save those strings in separate files. Then, based on a language <em>qualifier</em>
|
||||
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
|
||||
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
|
||||
values) and the user's language setting, the Android system applies the appropriate language strings
|
||||
to your UI.</p>
|
||||
values) and the user's language setting.</p>
|
||||
|
||||
<p>Android supports many different <em>qualifiers</em> for your alternative resources. The
|
||||
qualifier is a short string that you include in the name of your resource directories in order to
|
||||
define the device configuration for which those resources should be used. As another
|
||||
example, you should often create different layouts for your activities, depending on the
|
||||
device's screen orientation and size. For example, when the device screen is in portrait
|
||||
define the device configuration for which those resources should be used. For
|
||||
example, you should create different layouts for your activities, depending on the
|
||||
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
|
||||
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
|
||||
qualifier to each layout's directory name. Then, the system automatically applies the appropriate
|
||||
layout depending on the current device orientation.</p>
|
||||
@@ -465,15 +508,15 @@ create alternative resources for different device configurations, read <a href=
|
||||
<dl>
|
||||
<dt><a href="{@docRoot}guide/components/intents-filters.html">Intents and Intent Filters</a>
|
||||
</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
|
||||
available for use by other apps.</dd>
|
||||
<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>
|
||||
<dt><a
|
||||
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
|
||||
configurations.
|
||||
</dd>
|
||||
@@ -484,14 +527,13 @@ href="{@docRoot}guide/topics/resources/providing-resources.html">Providing Resou
|
||||
<dl>
|
||||
<dt><a href="{@docRoot}guide/practices/compatibility.html"
|
||||
>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 different devices.</dd>
|
||||
<dt><a href="{@docRoot}guide/topics/security/permissions.html"
|
||||
>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>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -7,21 +7,21 @@ page.tags="IntentFilter"
|
||||
|
||||
<h2>In this document</h2>
|
||||
<ol>
|
||||
<li><a href="#Types">Intent Types</a></li>
|
||||
<li><a href="#Building">Building an Intent</a>
|
||||
<li><a href="#Types">Intent types</a></li>
|
||||
<li><a href="#Building">Building an intent</a>
|
||||
<ol>
|
||||
<li><a href="#ExampleExplicit">Example explicit intent</a></li>
|
||||
<li><a href="#ExampleSend">Example implicit intent</a></li>
|
||||
<li><a href="#ForceChooser">Forcing an app chooser</a></li>
|
||||
</ol>
|
||||
</li>
|
||||
<li><a href="#Receiving">Receiving an Implicit Intent</a>
|
||||
<li><a href="#Receiving">Receiving an implicit intent</a>
|
||||
<ol>
|
||||
<li><a href="#ExampleFilters">Example filters</a></li>
|
||||
</ol>
|
||||
</li>
|
||||
<li><a href="#PendingIntent">Using a Pending Intent</a></li>
|
||||
<li><a href="#Resolution">Intent Resolution</a>
|
||||
<li><a href="#PendingIntent">Using a pending intent</a></li>
|
||||
<li><a href="#Resolution">Intent resolution</a>
|
||||
<ol>
|
||||
<li><a href="#ActionTest">Action 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
|
||||
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
|
||||
fundamental use-cases:</p>
|
||||
fundamental use cases:</p>
|
||||
|
||||
<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
|
||||
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>
|
||||
|
||||
<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
|
||||
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
|
||||
without a user interface. You can start a service to perform a one-time operation
|
||||
(such as download a file) by passing an {@link android.content.Intent}
|
||||
without a user interface. With Android 5.0 (API level 21) and later, you can start a service
|
||||
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}
|
||||
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
|
||||
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
|
||||
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}
|
||||
@@ -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>
|
||||
|
||||
@@ -97,7 +104,7 @@ android.content.Context#sendStickyBroadcast sendStickyBroadcast()}.</p>
|
||||
<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
|
||||
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>
|
||||
|
||||
<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>
|
||||
</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>
|
||||
|
||||
<div class="figure" style="width:446px">
|
||||
<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
|
||||
{@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
|
||||
@@ -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
|
||||
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
|
||||
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,
|
||||
and the user cannot see which service starts. Beginning with Android 5.0 (API level 21), the system
|
||||
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>
|
||||
|
||||
@@ -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
|
||||
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.
|
||||
|
||||
<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
|
||||
defined by the component name. Without a component name, the intent is <b>implicit</b> and the
|
||||
<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 <em>implicit</em> and the
|
||||
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>
|
||||
|
||||
<p class="note"><strong>Note:</strong> When starting a {@link android.app.Service}, you should
|
||||
<strong>always specify the component name</strong>. Otherwise, you cannot be certain what service
|
||||
<p class="note"><strong>Note:</strong> When starting a {@link android.app.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>
|
||||
|
||||
<p>This field of the {@link android.content.Intent} is a
|
||||
{@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
|
||||
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>
|
||||
|
||||
</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.
|
||||
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
|
||||
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
|
||||
common actions for starting an activity:</p>
|
||||
|
||||
@@ -203,7 +213,7 @@ common actions for starting an activity:</p>
|
||||
view in a map app.</dd>
|
||||
|
||||
<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
|
||||
share through another app, such as an email app or social sharing app.</dd>
|
||||
</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>
|
||||
|
||||
<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>
|
||||
</dd>
|
||||
|
||||
<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
|
||||
example, if the action is {@link android.content.Intent#ACTION_EDIT}, the data should contain the
|
||||
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.
|
||||
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.
|
||||
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.
|
||||
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>
|
||||
|
||||
<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>
|
||||
|
||||
<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.
|
||||
Always use {@link android.content.Intent#setDataAndType setDataAndType()} to set both
|
||||
URI and MIME type.</p>
|
||||
@@ -258,7 +270,7 @@ Here are some common categories:
|
||||
<dl>
|
||||
<dt>{@link android.content.Intent#CATEGORY_BROWSABLE}</dt>
|
||||
<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>
|
||||
<dt>{@link android.content.Intent#CATEGORY_LAUNCHER}</dt>
|
||||
<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
|
||||
defining characteristics of an intent. By reading these properties, the Android system
|
||||
is able to resolve which app component it should start.</p>
|
||||
|
||||
<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:</p>
|
||||
is able to resolve which app component it should start. 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>
|
||||
|
||||
<dl>
|
||||
<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.
|
||||
|
||||
<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>
|
||||
|
||||
<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#EXTRA_EMAIL} key, and specify the "subject" 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 <em>subject</em> with the
|
||||
{@link android.content.Intent#EXTRA_SUBJECT} key.</p>
|
||||
|
||||
<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
|
||||
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>
|
||||
</dd>
|
||||
|
||||
<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
|
||||
<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
|
||||
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
|
||||
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
|
||||
and add extras that specify the content to share. When you call
|
||||
{@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>
|
||||
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
|
||||
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,
|
||||
you should not use the intent and, if possible, you should disable the feature that issues
|
||||
the intent.</p>
|
||||
do not use the intent and, if possible, you should disable the feature that issues
|
||||
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>
|
||||
@@ -384,8 +400,7 @@ if (sendIntent.resolveActivity(getPackageManager()) != null) {
|
||||
}
|
||||
</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
|
||||
@@ -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"
|
||||
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
|
||||
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">
|
||||
@@ -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,
|
||||
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
|
||||
probably wants to use the same app from now on, such as when opening a web page (users
|
||||
often prefer just one web browser) .</p>
|
||||
action. The ability to select a default is helpful when performing an action for which the user
|
||||
probably wants to use the same app every time, such as when opening a web page (users
|
||||
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
|
||||
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
|
||||
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
|
||||
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>
|
||||
Intent sendIntent = new Intent(Intent.ACTION_SEND);
|
||||
@@ -439,26 +457,16 @@ if (sendIntent.resolveActivity(getPackageManager()) != null) {
|
||||
}
|
||||
</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
|
||||
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>.
|
||||
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>
|
||||
|
||||
<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>
|
||||
|
||||
<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
|
||||
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
|
||||
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
|
||||
of these three elements:</p>
|
||||
|
||||
<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
|
||||
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
|
||||
aspects of the data URI (<code>scheme</code>, <code>host</code>, <code>port</code>,
|
||||
<code>path</code>, etc.) and MIME type.</dd>
|
||||
<dt><a href="{@docRoot}guide/topics/manifest/category-element.html">{@code <category>}</a></dt>
|
||||
<code>path</code>) and MIME type.</dd>
|
||||
<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
|
||||
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
|
||||
<strong>must include</strong> the
|
||||
<p class="note"><strong>Note:</strong> To receive implicit intents, you
|
||||
<em>must include</em> the
|
||||
{@link android.content.Intent#CATEGORY_DEFAULT} category in the intent filter. The methods
|
||||
{@link android.app.Activity#startActivity startActivity()} and
|
||||
{@link android.app.Activity#startActivityForResult startActivityForResult()} treat all intents
|
||||
@@ -515,12 +523,12 @@ of these three elements:</p>
|
||||
</activity>
|
||||
</pre>
|
||||
|
||||
<p>It's okay to 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/data-element.html">{@code <data>}</a>, or
|
||||
<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
|
||||
of those filter elements.</p>
|
||||
<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/data-element.html">{@code <data>}</a>, or
|
||||
<a href="{@docRoot}guide/topics/manifest/category-element.html">{@code <category>}</a>.
|
||||
If you do, you need to be certain that the component can handle any and all
|
||||
combinations of those filter elements.</p>
|
||||
|
||||
<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>
|
||||
@@ -569,8 +577,8 @@ is running.</p>
|
||||
|
||||
<h3 id="ExampleFilters">Example filters</h3>
|
||||
|
||||
<p>To better understand some of the intent filter behaviors, look at the following snippet
|
||||
from the manifest file of a social-sharing app.</p>
|
||||
<p>To demonstrate some of the intent filter behaviors, here is an example
|
||||
from the manifest file of a social-sharing app:</p>
|
||||
|
||||
<pre>
|
||||
<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>
|
||||
<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
|
||||
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
|
||||
href="{@docRoot}guide/topics/manifest/application-element.html">{@code <application>}</a>
|
||||
href="{@docRoot}guide/topics/manifest/application-element.html">{@code <application>}</a>
|
||||
element.</li>
|
||||
</ul>
|
||||
<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>
|
||||
|
||||
<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
|
||||
panoramic photos, which you can handle with the <a
|
||||
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
|
||||
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
|
||||
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>
|
||||
<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>
|
||||
(the Android system's {@link android.app.NotificationManager}
|
||||
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>
|
||||
(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}).
|
||||
</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
|
||||
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
|
||||
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>
|
||||
|
||||
<ul>
|
||||
@@ -677,14 +685,14 @@ startActivity()}. You must instead declare the intended component type when you
|
||||
</ul>
|
||||
|
||||
<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
|
||||
{@link android.app.PendingIntent} methods you'll probably ever need.</p>
|
||||
the above methods to create a {@link android.app.PendingIntent} are probably the only
|
||||
{@link android.app.PendingIntent} methods you'll ever need.</p>
|
||||
|
||||
<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
|
||||
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
|
||||
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>
|
||||
@@ -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
|
||||
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>
|
||||
<li>The intent action
|
||||
<li>The intent data (both URI and data type)
|
||||
<li>The intent category
|
||||
<li>Action.
|
||||
<li>Data (both URI and data type).
|
||||
<li>Category.
|
||||
</ul>
|
||||
|
||||
<p>The following sections describe how intents are matched to the appropriate component(s)
|
||||
in terms of how the intent filter is declared in an app's manifest file.</p>
|
||||
<p>The following sections describe how intents are matched to the appropriate components
|
||||
according to the intent filter declaration in an app's manifest file.</p>
|
||||
|
||||
|
||||
<h3 id="ActionTest">Action test</h3>
|
||||
|
||||
<p>To specify accepted intent actions, an intent filter can declare zero or more
|
||||
<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>
|
||||
<intent-filter>
|
||||
@@ -725,13 +733,13 @@ in terms of how the intent filter is declared in an app's manifest file.</p>
|
||||
</intent-filter>
|
||||
</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>
|
||||
|
||||
<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}
|
||||
does not specify an action, it will pass the test (as long as the filter
|
||||
contains at least one action).</p>
|
||||
does not specify an action, it passes the test as long as the filter
|
||||
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
|
||||
<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>
|
||||
<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}
|
||||
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
|
||||
{@link android.content.Intent} will still pass. Therefore, an intent with no categories should
|
||||
always pass this test, regardless of what categories are declared in the filter.</p>
|
||||
{@link android.content.Intent} still passes. Therefore, an intent with no categories
|
||||
always passes this test, regardless of what categories are declared in the filter.</p>
|
||||
|
||||
<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
|
||||
android.content.Context#startActivity startActivity()} and {@link
|
||||
android.app.Activity#startActivityForResult startActivityForResult()}.
|
||||
So 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
|
||||
shown in the previous {@code <intent-filter>} example.</p>
|
||||
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
|
||||
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
|
||||
<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>
|
||||
<intent-filter>
|
||||
@@ -781,15 +789,16 @@ shown in the previous {@code <intent-filter>} example.</p>
|
||||
</pre>
|
||||
|
||||
<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
|
||||
attributes — {@code scheme}, {@code host}, {@code port},
|
||||
and {@code path} — for each part of the URI:
|
||||
element can specify a URI structure and a data type (MIME media type).
|
||||
Each part of the URI is a separate
|
||||
attribute: {@code scheme}, {@code host}, {@code port},
|
||||
and {@code path}:
|
||||
</p>
|
||||
|
||||
<p style="margin-left: 2em">{@code <scheme>://<host>:<port>/<path>}</p>
|
||||
<p style="margin-left: 2em">{@code <scheme>://<host>:<port>/<path>}</p>
|
||||
|
||||
<p>
|
||||
For example:
|
||||
The following example shows possible values for these attributes:
|
||||
</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>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>
|
||||
<ul>
|
||||
<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:}
|
||||
or {@code file:} URI and the filter does not specify a URI. In other words,
|
||||
a component is presumed to support {@code content:} and {@code file:} data if
|
||||
its filter lists <em>only</em> a MIME type.</p></li>
|
||||
its filter lists <em>only</em> a MIME type.</li>
|
||||
</ol>
|
||||
|
||||
<p>
|
||||
This last rule, rule (d), reflects the expectation
|
||||
that components are able to get local data from a file or content provider.
|
||||
Therefore, their filters can list just a data type and do not need to explicitly
|
||||
Therefore, their filters can list just a data type and don't need to explicitly
|
||||
name the {@code content:} and {@code file:} schemes.
|
||||
This is a typical case. A <a
|
||||
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
|
||||
The following example shows a typical case in which a <a
|
||||
href="{@docRoot}guide/topics/manifest/data-element.html">{@code <data>}</a> element
|
||||
tells Android that the component can get image data from a content
|
||||
provider and display it:
|
||||
</p>
|
||||
|
||||
@@ -863,14 +872,15 @@ provider and display it:
|
||||
</intent-filter></pre>
|
||||
|
||||
<p>
|
||||
Because most available data is dispensed by content providers, filters that
|
||||
specify a data type but not a URI are perhaps the most common.
|
||||
Filters that
|
||||
specify a data type but not a URI are perhaps the most common because most available
|
||||
data is dispensed by content providers.
|
||||
</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
|
||||
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
|
||||
the component can retrieve video data from the network in order to perform the action:
|
||||
</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.
|
||||
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
|
||||
component to respond to an intent. For example,
|
||||
{@link android.content.pm.PackageManager#queryIntentActivities
|
||||
@@ -907,7 +917,3 @@ can respond. There's a similar method,
|
||||
{@link android.content.pm.PackageManager#queryBroadcastReceivers
|
||||
queryBroadcastReceivers()}, for broadcast receivers.
|
||||
</p>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -5,11 +5,11 @@ page.title=Services
|
||||
<ol id="qv">
|
||||
<h2>In this document</h2>
|
||||
<ol>
|
||||
<li><a href="#Basics">The Basics</a></li>
|
||||
<li><a href="#Basics">The basics</a></li>
|
||||
<ol>
|
||||
<li><a href="#Declaring">Declaring a service in the manifest</a></li>
|
||||
</ol>
|
||||
<li><a href="#CreatingAService">Creating a Started Service</a>
|
||||
<li><a href="#CreatingAService">Creating a started service</a>
|
||||
<ol>
|
||||
<li><a href="#ExtendingIntentService">Extending the IntentService class</a></li>
|
||||
<li><a href="#ExtendingService">Extending the Service class</a></li>
|
||||
@@ -17,10 +17,10 @@ page.title=Services
|
||||
<li><a href="#Stopping">Stopping a service</a></li>
|
||||
</ol>
|
||||
</li>
|
||||
<li><a href="#CreatingBoundService">Creating a Bound Service</a></li>
|
||||
<li><a href="#Notifications">Sending Notifications to the User</a></li>
|
||||
<li><a href="#Foreground">Running a Service in the Foreground</a></li>
|
||||
<li><a href="#Lifecycle">Managing the Lifecycle of a Service</a>
|
||||
<li><a href="#CreatingBoundService">Creating a bound service</a></li>
|
||||
<li><a href="#Notifications">Sending notifications to the user</a></li>
|
||||
<li><a href="#Foreground">Running a service in the foreground</a></li>
|
||||
<li><a href="#Lifecycle">Managing the lifecycle of a service</a>
|
||||
<ol>
|
||||
<li><a href="#LifecycleCallbacks">Implementing the lifecycle callbacks</a></li>
|
||||
</ol>
|
||||
@@ -48,70 +48,80 @@ page.title=Services
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<p>A {@link android.app.Service} is an application component that can perform
|
||||
long-running operations in the background and does not provide a user interface. Another
|
||||
application component can start a service and it will continue to run in the background even if the
|
||||
long-running operations in the background, and it does not provide a user interface. Another
|
||||
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
|
||||
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
|
||||
from the background.</p>
|
||||
|
||||
<p>A service can essentially take two forms:</p>
|
||||
<p>These are the three different types of services:</p>
|
||||
|
||||
<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>
|
||||
<dd>A service is "started" when an application component (such as an activity) starts it by
|
||||
calling {@link android.content.Context#startService startService()}. Once started, a service
|
||||
can run in the background indefinitely, even if the component that started it is destroyed. Usually,
|
||||
a started service performs a single operation and does not return a result to the caller.
|
||||
For example, it might download or upload a file over the network. When the operation is done, the
|
||||
service should stop itself.</dd>
|
||||
<dd>A service is <em>started</em> when an application component (such as an activity)
|
||||
calls {@link android.content.Context#startService startService()}. After it's started, a
|
||||
service can run in the background indefinitely, even if the component that started it is
|
||||
destroyed. Usually, a started service performs a single operation and does not return a result to
|
||||
the caller. For example, it can download or upload a file over the network. When the operation is
|
||||
complete, the service should stop itself.</dd>
|
||||
<dt>Bound</dt>
|
||||
<dd>A service is "bound" when an application component binds to it by calling {@link
|
||||
android.content.Context#bindService bindService()}. A bound service offers a client-server
|
||||
interface that allows components to interact with the service, send requests, get results, and even
|
||||
do so across processes with interprocess communication (IPC). A bound service runs only as long as
|
||||
another application component is bound to it. Multiple components can bind to the service at once,
|
||||
but when all of them unbind, the service is destroyed.</dd>
|
||||
<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
|
||||
interface that allows components to interact with the service, send requests, receive results,
|
||||
and even do so across processes with interprocess communication (IPC). A bound service runs only
|
||||
as long as another application component is bound to it. Multiple components can bind to the
|
||||
service at once, but when all of them unbind, the service is destroyed.</dd>
|
||||
</dl>
|
||||
|
||||
<p>Although this documentation generally discusses these two types of services separately, your
|
||||
service can work both ways—it can be started (to run indefinitely) and also allow binding.
|
||||
It's simply a matter of whether you implement a couple callback methods: {@link
|
||||
<p>Although this documentation generally discusses started and bound services separately,
|
||||
your service can work both ways—it can be started (to run indefinitely) and also allow
|
||||
binding. It's simply a matter of whether you implement a couple of callback methods: {@link
|
||||
android.app.Service#onStartCommand onStartCommand()} to allow components to start it and {@link
|
||||
android.app.Service#onBind onBind()} to allow binding.</p>
|
||||
|
||||
<p>Regardless of whether your application is started, bound, or both, any application component
|
||||
can use the service (even from a separate application), in the same way that any component can use
|
||||
can use the service (even from a separate application) in the same way that any component can use
|
||||
an activity—by starting it with an {@link android.content.Intent}. However, you can declare
|
||||
the service as private, in the manifest file, and block access from other applications. This is
|
||||
discussed more in the section about <a href="#Declaring">Declaring the service in the
|
||||
the service as <em>private</em> in the manifest file and block access from other applications.
|
||||
This is discussed more in the section about <a href="#Declaring">Declaring the service in the
|
||||
manifest</a>.</p>
|
||||
|
||||
<p class="caution"><strong>Caution:</strong> A service runs in the
|
||||
main thread of its hosting process—the service does <strong>not</strong> create its own thread
|
||||
and does <strong>not</strong> run in a separate process (unless you specify otherwise). This means
|
||||
that, if your service is going to do any CPU intensive work or blocking operations (such as MP3
|
||||
playback or networking), you should create a new thread within the service to do that work. By using
|
||||
a separate thread, you will reduce the risk of Application Not Responding (ANR) errors and the
|
||||
application's main thread can remain dedicated to user interaction with your activities.</p>
|
||||
main thread of its hosting process; the service does <strong>not</strong> create its own
|
||||
thread and does <strong>not</strong> run in a separate process unless you specify otherwise. If
|
||||
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 complete that work.
|
||||
By using a separate thread, you can reduce the risk of Application Not Responding (ANR) errors,
|
||||
and the application's main thread can remain dedicated to user interaction with your
|
||||
activities.</p>
|
||||
|
||||
|
||||
<h2 id="Basics">The Basics</h2>
|
||||
<h2 id="Basics">The basics</h2>
|
||||
|
||||
<div class="sidebox-wrapper">
|
||||
<div class="sidebox">
|
||||
<h3>Should you use a service or a thread?</h3>
|
||||
<p>A service is simply a component that can run in the background even when the user is not
|
||||
interacting with your application. Thus, you should create a service only if that is what you
|
||||
<p>A service is simply a component that can run in the background, even when the user is not
|
||||
interacting with your application, so you should create a service only if that is what you
|
||||
need.</p>
|
||||
<p>If you need to perform work outside your main thread, but only while the user is interacting
|
||||
with your application, then you should probably instead create a new thread and not a service. For
|
||||
example, if you want to play some music, but only while your activity is running, you might create
|
||||
<p>If you must perform work outside of your main thread, but only while the user is interacting
|
||||
with your application, you should instead create a new thread. For example, if you want to
|
||||
play some music, but only while your activity is running, you might create
|
||||
a thread in {@link android.app.Activity#onCreate onCreate()}, start running it in {@link
|
||||
android.app.Activity#onStart onStart()}, then stop it in {@link android.app.Activity#onStop
|
||||
onStop()}. Also consider using {@link android.os.AsyncTask} or {@link android.os.HandlerThread},
|
||||
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}
|
||||
instead of the traditional {@link java.lang.Thread} class. See the <a
|
||||
href="{@docRoot}guide/components/processes-and-threads.html#Threads">Processes and
|
||||
Threading</a> document for more information about threads.</p>
|
||||
@@ -121,78 +131,81 @@ blocking operations.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p>To create a service, you must create a subclass of {@link android.app.Service} (or one
|
||||
of its existing subclasses). In your implementation, you need to override some callback methods that
|
||||
handle key aspects of the service lifecycle and provide a mechanism for components to bind to
|
||||
the service, if appropriate. The most important callback methods you should override are:</p>
|
||||
<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 must override some callback methods that
|
||||
handle key aspects of the service lifecycle and provide a mechanism that allows the components to
|
||||
bind to the service, if appropriate. These are the most important callback methods that you should
|
||||
override:</p>
|
||||
|
||||
<dl>
|
||||
<dt>{@link android.app.Service#onStartCommand onStartCommand()}</dt>
|
||||
<dd>The system calls this method when another component, such as an activity,
|
||||
requests that the service be started, by calling {@link android.content.Context#startService
|
||||
startService()}. Once this method executes, the service is started and can run in the
|
||||
<dd>The system invokes this method by calling {@link android.content.Context#startService
|
||||
startService()} when another component (such as an activity) requests that the service be started.
|
||||
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
|
||||
its work is done, by calling {@link android.app.Service#stopSelf stopSelf()} or {@link
|
||||
android.content.Context#stopService stopService()}. (If you only want to provide binding, you don't
|
||||
need to implement this method.)</dd>
|
||||
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
|
||||
need to implement this method.</dd>
|
||||
<dt>{@link android.app.Service#onBind onBind()}</dt>
|
||||
<dd>The system calls this method when another component wants to bind with the
|
||||
service (such as to perform RPC), by calling {@link android.content.Context#bindService
|
||||
bindService()}. In your implementation of this method, you must provide an interface that clients
|
||||
use to communicate with the service, by returning an {@link android.os.IBinder}. You must always
|
||||
implement this method, but if you don't want to allow binding, then you should return null.</dd>
|
||||
<dd>The system invokes this method by calling {@link android.content.Context#bindService
|
||||
bindService()} when another component wants to bind with the service (such as to perform RPC).
|
||||
In your implementation of this method, you must provide an interface that clients
|
||||
use to communicate with the service by returning an {@link android.os.IBinder}. You must always
|
||||
implement this method; however, if you don't want to allow binding, you should return
|
||||
null.</dd>
|
||||
<dt>{@link android.app.Service#onCreate()}</dt>
|
||||
<dd>The system calls this method when the service is first created, to perform one-time setup
|
||||
procedures (before it calls either {@link android.app.Service#onStartCommand onStartCommand()} or
|
||||
<dd>The system invokes this method to perform one-time setup procedures when the service is
|
||||
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
|
||||
called.</dd>
|
||||
<dt>{@link android.app.Service#onDestroy()}</dt>
|
||||
<dd>The system calls this method when the service is no longer used and is being destroyed.
|
||||
<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
|
||||
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>
|
||||
|
||||
<p>If a component starts the service by calling {@link
|
||||
android.content.Context#startService startService()} (which results in a call to {@link
|
||||
android.app.Service#onStartCommand onStartCommand()}), then the service
|
||||
remains running until it stops itself with {@link android.app.Service#stopSelf()} or another
|
||||
android.app.Service#onStartCommand onStartCommand()}), the service
|
||||
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>
|
||||
|
||||
<p>If a component calls
|
||||
{@link android.content.Context#bindService bindService()} to create the service (and {@link
|
||||
android.app.Service#onStartCommand onStartCommand()} is <em>not</em> called), then the service runs
|
||||
only as long as the component is bound to it. Once the service is unbound from all clients, the
|
||||
system destroys it.</p>
|
||||
{@link android.content.Context#bindService bindService()} to create the service and {@link
|
||||
android.app.Service#onStartCommand onStartCommand()} is <em>not</em> called, the service runs
|
||||
only as long as the component is bound to it. After the service is unbound from all of its clients,
|
||||
the system destroys it.</p>
|
||||
|
||||
<p>The Android system will force-stop a service only when memory is low and it must recover system
|
||||
<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
|
||||
focus, then it's less likely to be killed, and if the service is declared to <a
|
||||
href="#Foreground">run in the foreground</a> (discussed later), then it will almost never be killed.
|
||||
Otherwise, if the service was started and is long-running, then the system will lower its position
|
||||
in the list of background tasks over time and the service will become highly susceptible to
|
||||
killing—if your service is started, then you must design it to gracefully handle restarts
|
||||
focus, it's less likely to be killed; if the service is declared to <a
|
||||
href="#Foreground">run in the foreground</a>, it's rarely killed.
|
||||
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 becomes highly susceptible to
|
||||
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
|
||||
available again (though this also depends on the value you return from {@link
|
||||
android.app.Service#onStartCommand onStartCommand()}, as discussed later). For more information
|
||||
available, but this also depends on the value that you return from {@link
|
||||
android.app.Service#onStartCommand onStartCommand()}. For more information
|
||||
about when the system might destroy a service, see the <a
|
||||
href="{@docRoot}guide/components/processes-and-threads.html">Processes and Threading</a>
|
||||
document.</p>
|
||||
|
||||
<p>In the following sections, you'll see how you can create each type of service and how to use
|
||||
it from other application components.</p>
|
||||
|
||||
|
||||
<p>In the following sections, you'll see how you can create the
|
||||
{@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>
|
||||
|
||||
<p>Like activities (and other components), you must declare all services in your application's
|
||||
manifest file.</p>
|
||||
<p>You must declare all services in your application's
|
||||
manifest file, just as you do for activities and other components.</p>
|
||||
|
||||
<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
|
||||
href="{@docRoot}guide/topics/manifest/application-element.html">{@code <application>}</a>
|
||||
element. For example:</p>
|
||||
href="{@docRoot}guide/topics/manifest/application-element.html">{@code <application>}</a>
|
||||
element. Here is an example:</p>
|
||||
|
||||
<pre>
|
||||
<manifest ... >
|
||||
@@ -205,48 +218,44 @@ element. For example:</p>
|
||||
</pre>
|
||||
|
||||
<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>
|
||||
|
||||
<p>There are other attributes you can include in the <a
|
||||
href="{@docRoot}guide/topics/manifest/service-element.html">{@code <service>}</a> element to
|
||||
define properties such as permissions required to start the service and the process in
|
||||
<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
|
||||
define properties such as the permissions that are required to start the service and the process in
|
||||
which the service should run. The <a
|
||||
href="{@docRoot}guide/topics/manifest/service-element.html#nm">{@code android:name}</a>
|
||||
attribute is the only required attribute—it specifies the class name of the service. Once
|
||||
you publish your application, you should not change this name, because if you do, you risk breaking
|
||||
attribute is the only required attribute—it specifies the class name of the service. After
|
||||
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
|
||||
href="http://android-developers.blogspot.com/2011/06/things-that-cannot-change.html">Things
|
||||
That Cannot Change</a>).
|
||||
|
||||
<p>To ensure your app is secure, <strong>always use an explicit intent when starting or binding
|
||||
your {@link android.app.Service}</strong> and do not declare intent filters for the service. If
|
||||
it's critical that you allow for some amount of ambiguity as to which service starts, you can
|
||||
supply intent filters for your services and exclude the component name from the {@link
|
||||
android.content.Intent}, but you then must set the package for the intent with {@link
|
||||
android.content.Intent#setPackage setPackage()}, which provides sufficient disambiguation for the
|
||||
target service.</p>
|
||||
<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>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
|
||||
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>
|
||||
|
||||
|
||||
|
||||
|
||||
<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
|
||||
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>
|
||||
|
||||
<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
|
||||
is done by calling {@link android.app.Service#stopSelf stopSelf()}, or another component can stop it
|
||||
by calling {@link android.content.Context#stopService stopService()}.</p>
|
||||
is complete by calling {@link android.app.Service#stopSelf stopSelf()}, or another component can
|
||||
stop it by calling {@link android.content.Context#stopService stopService()}.</p>
|
||||
|
||||
<p>An application component such as an activity can start the service by calling {@link
|
||||
android.content.Context#startService startService()} and passing an {@link android.content.Intent}
|
||||
@@ -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
|
||||
onStartCommand()} method.</p>
|
||||
|
||||
<p>For instance, suppose an activity needs to save some data to an online database. The activity can
|
||||
start a companion service and deliver it the data to save by passing an intent to {@link
|
||||
<p>For instance, suppose an activity needs to save some data to an online database. The activity
|
||||
can start a companion service and deliver it the data to save by passing an intent to {@link
|
||||
android.content.Context#startService startService()}. The service receives the intent in {@link
|
||||
android.app.Service#onStartCommand onStartCommand()}, connects to the Internet and performs the
|
||||
database transaction. When the transaction is done, the service stops itself and it is
|
||||
android.app.Service#onStartCommand onStartCommand()}, connects to the Internet, and performs the
|
||||
database transaction. When the transaction is complete, the service stops itself and is
|
||||
destroyed.</p>
|
||||
|
||||
<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
|
||||
application, the service will slow down activity performance. To avoid impacting application
|
||||
performance, you should start a new thread inside the service.</p>
|
||||
application, the service slows down activity performance. To avoid impacting application
|
||||
performance, start a new thread inside the service.</p>
|
||||
|
||||
<p>Traditionally, there are two classes you can extend to create a started service:</p>
|
||||
|
||||
<dl>
|
||||
<dt>{@link android.app.Service}</dt>
|
||||
<dd>This is the base class for all services. When you extend this class, it's important that
|
||||
you create a new thread in which to do all the service's work, because the service uses your
|
||||
application's main thread, by default, which could slow the performance of any activity your
|
||||
<dd>This is the base class for all services. When you extend this class, it's important to
|
||||
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 can slow the performance of any activity that your
|
||||
application is running.</dd>
|
||||
<dt>{@link android.app.IntentService}</dt>
|
||||
<dd>This is a subclass of {@link android.app.Service} that uses a worker thread to handle all
|
||||
start requests, one at a time. This is the best option if you don't require that your service
|
||||
handle multiple requests simultaneously. All you need to do is implement {@link
|
||||
<dd>This is a subclass of {@link android.app.Service} that uses a worker thread to handle all of
|
||||
the start requests, one at a time. This is the best option if you don't require that your service
|
||||
handle multiple requests simultaneously. Implement {@link
|
||||
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>
|
||||
|
||||
<p>The following sections describe how you can implement your service using either one for these
|
||||
classes.</p>
|
||||
|
||||
|
||||
<h3 id="ExtendingIntentService">Extending the IntentService class</h3>
|
||||
|
||||
<p>Because most started services don't need to handle multiple requests simultaneously
|
||||
(which can actually be a dangerous multi-threading scenario), it's probably best if you
|
||||
<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 best that you
|
||||
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>
|
||||
<li>Creates a default worker thread that executes all intents delivered to {@link
|
||||
android.app.Service#onStartCommand onStartCommand()} separate from your application's main
|
||||
<li>It creates a default worker thread that executes all of the intents that are delivered to
|
||||
{@link android.app.Service#onStartCommand onStartCommand()}, separate from your application's main
|
||||
thread.</li>
|
||||
<li>Creates a work queue that passes one intent at a time to your {@link
|
||||
android.app.IntentService#onHandleIntent onHandleIntent()} implementation, so you never have to
|
||||
worry about multi-threading.</li>
|
||||
<li>Stops the service after all start requests have been handled, so you never have to call
|
||||
<li>Stops the service after all of the start requests are handled, so you never have to call
|
||||
{@link android.app.Service#stopSelf}.</li>
|
||||
<li>Provides default implementation of {@link android.app.IntentService#onBind onBind()} that
|
||||
returns null.</li>
|
||||
<li>Provides a default implementation of {@link android.app.IntentService#onBind onBind()}
|
||||
that returns null.</li>
|
||||
<li>Provides a default implementation of {@link android.app.IntentService#onStartCommand
|
||||
onStartCommand()} that sends the intent to the work queue and then to your {@link
|
||||
android.app.IntentService#onHandleIntent onHandleIntent()} implementation.</li>
|
||||
</ul>
|
||||
|
||||
<p>All this adds up to the fact that all you need to do is implement {@link
|
||||
android.app.IntentService#onHandleIntent onHandleIntent()} to do the work provided by the
|
||||
client. (Though, you also need to provide a small constructor for the service.)</p>
|
||||
<p>To complete the work that is provided by the client, implement {@link
|
||||
android.app.IntentService#onHandleIntent onHandleIntent()}.
|
||||
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>
|
||||
|
||||
@@ -352,12 +361,12 @@ android.app.IntentService#onHandleIntent onHandleIntent()}.</p>
|
||||
<p>If you decide to also override other callback methods, such as {@link
|
||||
android.app.IntentService#onCreate onCreate()}, {@link
|
||||
android.app.IntentService#onStartCommand onStartCommand()}, or {@link
|
||||
android.app.IntentService#onDestroy onDestroy()}, be sure to call the super implementation, so
|
||||
android.app.IntentService#onDestroy onDestroy()}, be sure to call the super implementation so
|
||||
that the {@link android.app.IntentService} can properly handle the life of the worker thread.</p>
|
||||
|
||||
<p>For example, {@link android.app.IntentService#onStartCommand onStartCommand()} must return
|
||||
the default implementation (which is how the intent gets delivered to {@link
|
||||
android.app.IntentService#onHandleIntent onHandleIntent()}):</p>
|
||||
the default implementation, which is how the intent is delivered to {@link
|
||||
android.app.IntentService#onHandleIntent onHandleIntent()}:</p>
|
||||
|
||||
<pre>
|
||||
@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
|
||||
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
|
||||
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>
|
||||
|
||||
|
||||
<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
|
||||
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>
|
||||
|
||||
<p>For comparison, the following example code is an implementation of the {@link
|
||||
android.app.Service} class that performs the exact same work as the example above using {@link
|
||||
<p>For comparison, the following example code shows an implementation of the {@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
|
||||
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
|
||||
onStartCommand()} yourself, you can perform multiple requests simultaneously. That's not what
|
||||
this example does, but if that's what you want, then you can create a new thread for each
|
||||
request and run them right away (instead of waiting for the previous request to finish).</p>
|
||||
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>
|
||||
|
||||
<p>Notice that the {@link android.app.Service#onStartCommand onStartCommand()} method must return an
|
||||
integer. The integer is a value that describes how the system should continue the service in the
|
||||
event that the system kills it (as discussed above, the default implementation for {@link
|
||||
android.app.IntentService} handles this for you, though you are able to modify it). The return value
|
||||
event that the system kills it. The default implementation for {@link
|
||||
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
|
||||
constants:</p>
|
||||
|
||||
<dl>
|
||||
<dt>{@link android.app.Service#START_NOT_STICKY}</dt>
|
||||
<dd>If the system kills the service after {@link android.app.Service#onStartCommand
|
||||
onStartCommand()} returns, <em>do not</em> recreate the service, unless there are pending
|
||||
onStartCommand()} returns, <em>do not</em> recreate the service unless there are pending
|
||||
intents to deliver. This is the safest option to avoid running your service when not necessary
|
||||
and when your application can simply restart any unfinished jobs.</dd>
|
||||
<dt>{@link android.app.Service#START_STICKY}</dt>
|
||||
@@ -481,9 +489,9 @@ and when your application can simply restart any unfinished jobs.</dd>
|
||||
onStartCommand()} returns, recreate the service and call {@link
|
||||
android.app.Service#onStartCommand onStartCommand()}, but <em>do not</em> redeliver the last intent.
|
||||
Instead, the system calls {@link android.app.Service#onStartCommand onStartCommand()} with a
|
||||
null intent, unless there were pending intents to start the service, in which case,
|
||||
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
|
||||
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>
|
||||
<dd>If the system kills the service after {@link android.app.Service#onStartCommand
|
||||
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
|
||||
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
|
||||
{@link android.content.Intent} (specifying the service to start) to {@link
|
||||
android.content.Context#startService startService()}. The Android system calls the service's {@link
|
||||
android.app.Service#onStartCommand onStartCommand()} method and passes it the {@link
|
||||
android.content.Intent}. (You should never call {@link android.app.Service#onStartCommand
|
||||
onStartCommand()} directly.)</p>
|
||||
android.content.Intent}.
|
||||
|
||||
<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
|
||||
HelloService}) using an explicit intent with {@link android.content.Context#startService
|
||||
startService()}:</p>
|
||||
startService()}, as shown here:</p>
|
||||
|
||||
<pre>
|
||||
Intent intent = new Intent(this, HelloService.class);
|
||||
startService(intent);
|
||||
</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
|
||||
onStartCommand()} method. If the service is not already running, the system first calls {@link
|
||||
android.app.Service#onCreate onCreate()}, then calls {@link android.app.Service#onStartCommand
|
||||
onStartCommand()}.</p>
|
||||
android.app.Service#onCreate onCreate()}, and then it calls
|
||||
{@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
|
||||
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
|
||||
(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
|
||||
@@ -533,109 +541,102 @@ broadcast to deliver a result.</p>
|
||||
the service (with {@link android.app.Service#stopSelf stopSelf()} or {@link
|
||||
android.content.Context#stopService stopService()}) is required to stop it.</p>
|
||||
|
||||
|
||||
<h3 id="Stopping">Stopping a service</h3>
|
||||
|
||||
<p>A started service must manage its own lifecycle. That is, the system does not stop or
|
||||
destroy the service unless it must recover system memory and the service
|
||||
continues to run after {@link android.app.Service#onStartCommand onStartCommand()} returns. So,
|
||||
the service must stop itself by calling {@link android.app.Service#stopSelf stopSelf()} or another
|
||||
continues to run after {@link android.app.Service#onStartCommand onStartCommand()} returns. The
|
||||
service must stop itself by calling {@link android.app.Service#stopSelf stopSelf()}, or another
|
||||
component can stop it by calling {@link android.content.Context#stopService stopService()}.</p>
|
||||
|
||||
<p>Once requested to stop with {@link android.app.Service#stopSelf stopSelf()} or {@link
|
||||
android.content.Context#stopService stopService()}, the system destroys the service as soon as
|
||||
possible.</p>
|
||||
|
||||
<p>However, if your service handles multiple requests to {@link
|
||||
android.app.Service#onStartCommand onStartCommand()} concurrently, then you shouldn't stop the
|
||||
service when you're done processing a start request, because you might have since received a new
|
||||
<p>If your service handles multiple requests to {@link
|
||||
android.app.Service#onStartCommand onStartCommand()} concurrently, you shouldn't stop the
|
||||
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
|
||||
this problem, you can use {@link android.app.Service#stopSelf(int)} to ensure that your request to
|
||||
stop the service is always based on the most recent start request. That is, when you call {@link
|
||||
android.app.Service#stopSelf(int)}, you pass the ID of the start request (the <code>startId</code>
|
||||
delivered to {@link android.app.Service#onStartCommand onStartCommand()}) to which your stop request
|
||||
corresponds. Then if the service received a new start request before you were able to call {@link
|
||||
android.app.Service#stopSelf(int)}, then the ID will not match and the service will not stop.</p>
|
||||
corresponds. Then, if the service receives a new start request before you are able to call {@link
|
||||
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
|
||||
when it's done working, to avoid wasting system resources and consuming battery power. If necessary,
|
||||
other components can stop the service by calling {@link
|
||||
<p class="caution"><strong>Caution:</strong> To avoid wasting system resources and consuming
|
||||
battery power, ensure that your application stops its services when it's done working.
|
||||
If necessary, other components can stop the service by calling {@link
|
||||
android.content.Context#stopService stopService()}. Even if you enable binding for the service,
|
||||
you must always stop the service yourself if it ever received a call to {@link
|
||||
you must always stop the service yourself if it ever receives a call to {@link
|
||||
android.app.Service#onStartCommand onStartCommand()}.</p>
|
||||
|
||||
<p>For more information about the lifecycle of a service, see the section below about <a
|
||||
href="#Lifecycle">Managing the Lifecycle of a Service</a>.</p>
|
||||
|
||||
|
||||
|
||||
<h2 id="CreatingBoundService">Creating a Bound Service</h2>
|
||||
<h2 id="CreatingBoundService">Creating a bound service</h2>
|
||||
|
||||
<p>A bound service is one that allows application components to bind to it by calling {@link
|
||||
android.content.Context#bindService bindService()} in order to create a long-standing connection
|
||||
(and generally does not allow components to <em>start</em> it by calling {@link
|
||||
android.content.Context#startService startService()}).</p>
|
||||
android.content.Context#bindService bindService()} to create a long-standing connection.
|
||||
It generally doesn't allow components to <em>start</em> it by calling {@link
|
||||
android.content.Context#startService startService()}.</p>
|
||||
|
||||
<p>You should create a bound service when you want to interact with the service from activities
|
||||
<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
|
||||
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
|
||||
defines the interface for communication with the service. Other application components can then call
|
||||
{@link android.content.Context#bindService bindService()} to retrieve the interface and
|
||||
begin calling methods on the service. The service lives only to serve the application component that
|
||||
is bound to it, so when there are no components bound to the service, the system destroys it
|
||||
(you do <em>not</em> need to stop a bound service in the way you must when the service is started
|
||||
through {@link android.app.Service#onStartCommand onStartCommand()}).</p>
|
||||
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 same way that you must when the service is
|
||||
started through {@link android.app.Service#onStartCommand onStartCommand()}.</p>
|
||||
|
||||
<p>To create a bound service, the first thing you must do is define the interface that specifies
|
||||
how a client can communicate with the service. This interface between the service
|
||||
<p>To create a bound service, you must define the interface that specifies how a client can
|
||||
communicate with the service. This interface between the service
|
||||
and a client must be an implementation of {@link android.os.IBinder} and is what your service must
|
||||
return from the {@link android.app.Service#onBind
|
||||
onBind()} callback method. Once the client receives the {@link android.os.IBinder}, it can begin
|
||||
onBind()} callback method. After the client receives the {@link android.os.IBinder}, it can begin
|
||||
interacting with the service through that interface.</p>
|
||||
|
||||
<p>Multiple clients can bind to the service at once. When a client is done interacting with the
|
||||
service, it calls {@link android.content.Context#unbindService unbindService()} to unbind. Once
|
||||
there are no clients bound to the service, the system destroys the service.</p>
|
||||
<p>Multiple clients can bind to the service simultaneously. When a client is done interacting with
|
||||
the service, it calls {@link android.content.Context#unbindService unbindService()} to unbind.
|
||||
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
|
||||
complicated than a started service, so the bound service discussion appears in a separate
|
||||
document about <a
|
||||
<p>There are multiple ways to implement a bound service, and the implementation is more
|
||||
complicated than a started service. For these reasons, the bound service discussion appears in a
|
||||
separate document about <a
|
||||
href="{@docRoot}guide/components/bound-services.html">Bound Services</a>.</p>
|
||||
|
||||
<h2 id="Notifications">Sending notifications to the user</h2>
|
||||
|
||||
|
||||
<h2 id="Notifications">Sending Notifications to the User</h2>
|
||||
|
||||
<p>Once running, a service can notify the user of events using <a
|
||||
<p>When a service is running, it can notify the user of events using <a
|
||||
href="{@docRoot}guide/topics/ui/notifiers/toasts.html">Toast Notifications</a> or <a
|
||||
href="{@docRoot}guide/topics/ui/notifiers/notifications.html">Status Bar Notifications</a>.</p>
|
||||
|
||||
<p>A toast notification is a message that appears on the surface of the current window for a
|
||||
moment then disappears, while a status bar notification provides an icon in the status bar with a
|
||||
<p>A toast notification is a message that appears on the surface of the current window for only 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>
|
||||
|
||||
<p>Usually, a status bar notification is the best technique when some background work has completed
|
||||
(such as a file completed
|
||||
downloading) and the user can now act on it. When the user selects the notification from the
|
||||
expanded view, the notification can start an activity (such as to view the downloaded file).</p>
|
||||
<p>Usually, a status bar notification is the best technique to use when background work such as
|
||||
a file download has completed, and the user can now act on it. When the user
|
||||
selects the notification from the expanded view, the notification can start an activity
|
||||
(such as to display the downloaded file).</p>
|
||||
|
||||
<p>See the <a
|
||||
href="{@docRoot}guide/topics/ui/notifiers/toasts.html">Toast Notifications</a> or <a
|
||||
href="{@docRoot}guide/topics/ui/notifiers/notifications.html">Status Bar Notifications</a>
|
||||
developer guides for more information.</p>
|
||||
|
||||
<h2 id="Foreground">Running a service in the foreground</h2>
|
||||
|
||||
|
||||
<h2 id="Foreground">Running a Service in the Foreground</h2>
|
||||
|
||||
<p>A foreground service is a service that's considered to be something the
|
||||
user is actively aware of and thus not a candidate for the system to kill when low on memory. A
|
||||
<p>A foreground service is a service that the
|
||||
user is actively aware of and is not a candidate for the system to kill when low on memory. A
|
||||
foreground service must provide a notification for the status bar, which is placed under the
|
||||
"Ongoing" heading, which means that the notification cannot be dismissed unless the service is
|
||||
either stopped or removed from the foreground.</p>
|
||||
<em>Ongoing</em> heading. This means that the notification cannot be dismissed unless the service
|
||||
is either stopped or removed from the foreground.</p>
|
||||
|
||||
<p>For example, a music player that plays music from a service should be set to run in the
|
||||
foreground, because the user is explicitly aware
|
||||
@@ -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>
|
||||
|
||||
<p>To request that your service run in the foreground, call {@link
|
||||
android.app.Service#startForeground startForeground()}. This method takes two parameters: an integer
|
||||
that uniquely identifies the notification and the {@link
|
||||
android.app.Notification} for the status bar. For example:</p>
|
||||
android.app.Service#startForeground startForeground()}. This method takes two parameters: an
|
||||
integer that uniquely identifies the notification and the {@link
|
||||
android.app.Notification} for the status bar. Here is an example:</p>
|
||||
|
||||
<pre>
|
||||
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);
|
||||
</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>
|
||||
|
||||
|
||||
<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
|
||||
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>
|
||||
|
||||
<p>For more information about notifications, see <a
|
||||
href="{@docRoot}guide/topics/ui/notifiers/notifications.html">Creating Status Bar
|
||||
Notifications</a>.</p>
|
||||
|
||||
<h2 id="Lifecycle">Managing the lifecycle of a service</h2>
|
||||
|
||||
<p>The lifecycle of a service is much simpler than that of an activity. However, it's even more
|
||||
important that you pay close attention to how your service is created and destroyed because a
|
||||
service can run in the background without the user being aware.</p>
|
||||
|
||||
<h2 id="Lifecycle">Managing the Lifecycle of a Service</h2>
|
||||
|
||||
<p>The lifecycle of a service is much simpler than that of an activity. However, it's even more important
|
||||
that you pay close attention to how your service is created and destroyed, because a service
|
||||
can run in the background without the user being aware.</p>
|
||||
|
||||
<p>The service lifecycle—from when it's created to when it's destroyed—can follow two
|
||||
different paths:</p>
|
||||
<p>The service lifecycle—from when it's created to when it's destroyed—can follow
|
||||
either of these two paths:</p>
|
||||
|
||||
<ul>
|
||||
<li>A started service
|
||||
@@ -689,27 +687,26 @@ android.content.Context#startService startService()}. The service then runs inde
|
||||
stop itself by calling {@link
|
||||
android.app.Service#stopSelf() stopSelf()}. Another component can also stop the
|
||||
service by calling {@link android.content.Context#stopService
|
||||
stopService()}. When the service is stopped, the system destroys it..</p></li>
|
||||
stopService()}. When the service is stopped, the system destroys it.</p></li>
|
||||
|
||||
<li>A bound service
|
||||
<p>The service is created when another component (a client) calls {@link
|
||||
android.content.Context#bindService bindService()}. The client then communicates with the service
|
||||
through an {@link android.os.IBinder} interface. The client can close the connection by calling
|
||||
{@link android.content.Context#unbindService unbindService()}. Multiple clients can bind to
|
||||
the same service and when all of them unbind, the system destroys the service. (The service
|
||||
does <em>not</em> need to stop itself.)</p></li>
|
||||
the same service and when all of them unbind, the system destroys the service. The service
|
||||
does <em>not</em> need to stop itself.</p></li>
|
||||
</ul>
|
||||
|
||||
<p>These two paths are not entirely separate. That is, you can bind to a service that was already
|
||||
started with {@link android.content.Context#startService startService()}. For example, a background
|
||||
music service could be started by calling {@link android.content.Context#startService
|
||||
<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, you can
|
||||
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,
|
||||
possibly when the user wants to exercise some control over the player or get information about the
|
||||
current song, an activity can bind to the service by calling {@link
|
||||
android.content.Context#bindService bindService()}. In cases like this, {@link
|
||||
android.content.Context#bindService bindService()}. In cases such as this, {@link
|
||||
android.content.Context#stopService stopService()} or {@link android.app.Service#stopSelf
|
||||
stopSelf()} does not actually stop the service until all clients unbind. </p>
|
||||
|
||||
stopSelf()} doesn't actually stop the service until all of the clients unbind.</p>
|
||||
|
||||
<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
|
||||
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>
|
||||
<li>The <strong>entire lifetime</strong> of a service happens between the time {@link
|
||||
android.app.Service#onCreate onCreate()} is called and the time {@link
|
||||
<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 that {@link
|
||||
android.app.Service#onDestroy} returns. Like an activity, a service does its initial setup in
|
||||
{@link android.app.Service#onCreate onCreate()} and releases all remaining resources in {@link
|
||||
android.app.Service#onDestroy onDestroy()}. For example, a
|
||||
music playback service could create the thread where the music will be played in {@link
|
||||
android.app.Service#onCreate onCreate()}, then stop the thread in {@link
|
||||
android.app.Service#onDestroy onDestroy()}. For example, a
|
||||
music playback service can create the thread where the music is played in {@link
|
||||
android.app.Service#onCreate onCreate()}, and then it can stop the thread in {@link
|
||||
android.app.Service#onDestroy onDestroy()}.
|
||||
|
||||
<p>The {@link android.app.Service#onCreate onCreate()} and {@link android.app.Service#onDestroy
|
||||
onDestroy()} methods are called for all services, whether
|
||||
<p class="note"><strong>Note</strong>: The {@link android.app.Service#onCreate onCreate()}
|
||||
and {@link android.app.Service#onDestroy onDestroy()} methods are called for all services, whether
|
||||
they're created by {@link android.content.Context#startService startService()} or {@link
|
||||
android.content.Context#bindService bindService()}.</p></li>
|
||||
|
||||
@@ -784,8 +791,8 @@ android.content.Context#bindService bindService()}.</p></li>
|
||||
android.app.Service#onStartCommand onStartCommand()} or {@link android.app.Service#onBind onBind()}.
|
||||
Each method is handed the {@link
|
||||
android.content.Intent} that was passed to either {@link android.content.Context#startService
|
||||
startService()} or {@link android.content.Context#bindService bindService()}, respectively.
|
||||
<p>If the service is started, the active lifetime ends the same time that the entire lifetime
|
||||
startService()} or {@link android.content.Context#bindService bindService()}.
|
||||
<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
|
||||
onStartCommand()} returns). If the service is bound, the active lifetime ends when {@link
|
||||
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
|
||||
either {@link android.app.Service#stopSelf stopSelf()} or {@link
|
||||
android.content.Context#stopService stopService()}, there is not a respective callback for the
|
||||
service (there's no {@code onStop()} callback). So, unless the service is bound to a client,
|
||||
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
|
||||
android.app.Service#onDestroy onDestroy()} is the only callback received.</p>
|
||||
|
||||
<p>Figure 2 illustrates the typical callback methods for a service. Although the figure separates
|
||||
services that are created by {@link android.content.Context#startService startService()} from those
|
||||
created by {@link android.content.Context#bindService bindService()}, keep
|
||||
in mind that any service, no matter how it's started, can potentially allow clients to bind to it.
|
||||
So, a service that was initially started with {@link android.app.Service#onStartCommand
|
||||
onStartCommand()} (by a client calling {@link android.content.Context#startService startService()})
|
||||
can still receive a call to {@link android.app.Service#onBind onBind()} (when a client calls
|
||||
{@link android.content.Context#bindService bindService()}).</p>
|
||||
|
||||
<p>For more information about creating a service that provides binding, see the <a
|
||||
href="{@docRoot}guide/components/bound-services.html">Bound Services</a> document,
|
||||
which includes more information about the {@link android.app.Service#onRebind onRebind()}
|
||||
callback method in the section about <a
|
||||
href="{@docRoot}guide/components/bound-services.html#Lifecycle">Managing the Lifecycle of
|
||||
a Bound Service</a>.</p>
|
||||
|
||||
href="{@docRoot}guide/components/bound-services.html#Lifecycle">Managing the lifecycle of
|
||||
a bound service</a>.</p>
|
||||
|
||||
<!--
|
||||
<h2>Beginner's Path</h2>
|
||||
|
||||
@@ -6,34 +6,32 @@ page.article=true
|
||||
<div id="tb">
|
||||
<h2>In this document</h2>
|
||||
<ol class="nolist">
|
||||
<li><a href="#StoringData">Storing Data</a></li>
|
||||
<li><a href="#Permissions">Using Permissions</a></li>
|
||||
<li><a href="#Networking">Using Networking</a></li>
|
||||
<li><a href="#InputValidation">Performing Input Validation</a></li>
|
||||
<li><a href="#UserData">Handling User Data</a></li>
|
||||
<li><a href="#StoringData">Storing data</a></li>
|
||||
<li><a href="#Permissions">Using permissions</a></li>
|
||||
<li><a href="#Networking">Using networking</a></li>
|
||||
<li><a href="#InputValidation">Performing input validation</a></li>
|
||||
<li><a href="#UserData">Handling user data</a></li>
|
||||
<li><a href="#WebView">Using WebView</a></li>
|
||||
<li><a href="#Crypto">Using Cryptography</a></li>
|
||||
<li><a href="#IPC">Using Interprocess Communication</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="#Native">Security in Native Code</a></li>
|
||||
<li><a href="#Crypto">Using cryptography</a></li>
|
||||
<li><a href="#IPC">Using interprocess communication</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="#Native">Security in native code</a></li>
|
||||
</ol>
|
||||
<h2>See also</h2>
|
||||
<ul>
|
||||
<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>
|
||||
</ul>
|
||||
</div></div>
|
||||
|
||||
|
||||
<p>Android has security features built
|
||||
into the operating system that significantly reduce the frequency and impact of
|
||||
application security issues. The system is designed so you can typically build your apps with
|
||||
default system and file permissions and avoid difficult decisions about security.</p>
|
||||
<p>Android has built-in security features that significantly reduce the frequency and impact of
|
||||
application security issues. The system is designed so that you can typically build your apps with
|
||||
the 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
|
||||
include:
|
||||
<p>The following core security features help you build secure apps:
|
||||
<ul>
|
||||
<li>The Android Application Sandbox, which isolates your app data and code execution
|
||||
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
|
||||
calloc, and Linux mmap_min_addr to mitigate risks associated with common memory
|
||||
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>
|
||||
<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>
|
||||
</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
|
||||
will reduce the likelihood of inadvertently introducing security issues that
|
||||
reduces the likelihood of inadvertently introducing security issues that
|
||||
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
|
||||
that you save on the device is accessible to other apps. There are three fundamental
|
||||
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>
|
||||
|
||||
<p>By default, files that you create on <a
|
||||
href="{@docRoot}guide/topics/data/data-storage.html#filesInternal">internal
|
||||
storage</a> are accessible only to your app. This
|
||||
protection is implemented by Android and is sufficient for most
|
||||
applications.</p>
|
||||
storage</a> are accessible only to your app.
|
||||
Android implements this protection, and it's sufficient for most 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
|
||||
<acronym title="Interprocess Communication">IPC</acronym> files because they do not provide
|
||||
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
|
||||
app processes, you might instead consider using a
|
||||
provide any control of data format. If you want to share your data with other
|
||||
app processes, instead consider using a
|
||||
<a href="{@docRoot}guide/topics/providers/content-providers.html">content provider</a>, which
|
||||
offers read and write permissions to other apps and can make
|
||||
dynamic permission grants on a case-by-case basis.</p>
|
||||
|
||||
<p>To provide additional protection for sensitive data, you might
|
||||
choose to 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}
|
||||
and protected with a user password that is not stored on the device. While this
|
||||
<p>To provide additional protection for sensitive data, you can
|
||||
encrypt local files using a key that is not directly accessible to the
|
||||
application. For example, you can place a key in a {@link java.security.KeyStore}
|
||||
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
|
||||
inputting the password, it can provide protection for a lost device without <a
|
||||
href="http://source.android.com/tech/encryption/index.html">file system
|
||||
@@ -94,14 +99,14 @@ encryption</a>.</p>
|
||||
|
||||
<p>Files created on <a
|
||||
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
|
||||
application, you should not store sensitive information using
|
||||
application, don't store sensitive information using
|
||||
external storage.</p>
|
||||
|
||||
<p>As with data from any untrusted source, you should <a href="#InputValidation">perform input
|
||||
validation</a> when handling data from external storage.
|
||||
We strongly recommend that you not store executables or
|
||||
<p>You should <a href="#InputValidation">Perform input validation</a> when handling
|
||||
data from external storage as you would with data from any untrusted source.
|
||||
You should not store executables or
|
||||
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
|
||||
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">
|
||||
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>
|
||||
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>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> for reading and writing, or distinct permissions for reading and writing
|
||||
within the manifest. We recommend that you limit your permissions to those
|
||||
</a> for reading and writing, or you can specify distinct permissions for reading and writing.
|
||||
You should limit your permissions to those
|
||||
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
|
||||
them away and break existing users.</p>
|
||||
them away and impact existing users.</p>
|
||||
|
||||
<p>If you are using a content provider
|
||||
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
|
||||
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,
|
||||
so they provide a better user experience and more controlled access to the
|
||||
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
|
||||
limited by the <code><a
|
||||
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
|
||||
{@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
|
||||
prior to submitting it to the method.</p>
|
||||
|
||||
<p>Do not have a false sense of security about the write permission. Consider
|
||||
that the write permission allows SQL statements which make it possible for some
|
||||
<p>Don't have a false sense of security about the write permission.
|
||||
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
|
||||
results. For example, an attacker might probe for presence of a specific phone
|
||||
number in a call-log by modifying a row only if that phone number already
|
||||
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
|
||||
exists. If the content provider data has predictable structure, the write
|
||||
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
|
||||
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>
|
||||
|
||||
|
||||
<h3 id="RequestingPermissions">Requesting Permissions</h3>
|
||||
<h3 id="RequestingPermissions">Requesting permissions</h3>
|
||||
|
||||
<p>We recommend minimizing the number of permissions that your app requests.
|
||||
Not having access to sensitive permissions reduces the risk of
|
||||
inadvertently misusing those permissions, can improve user adoption, and makes
|
||||
<p>You should minimize the number of permissions that your app requests.
|
||||
Restricting access to sensitive permissions reduces the risk of
|
||||
inadvertently misusing those permissions, improves user adoption, and makes
|
||||
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
|
||||
any permissions, that is preferable. For example, rather than requesting access
|
||||
to device information to create a unique identifier, create a <a
|
||||
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
|
||||
on the internal storage.</p>
|
||||
|
||||
<p>In addition to requesting permissions, your application can use the <a
|
||||
href="{@docRoot}guide/topics/manifest/permission-element.html">{@code <permissions>}</a>
|
||||
to protect IPC that is security sensitive and will be exposed to other
|
||||
href="{@docRoot}guide/topics/manifest/permission-element.html">{@code <permission>}</a>
|
||||
element to protect IPC that is security sensitive and is exposed to other
|
||||
applications, such as a {@link android.content.ContentProvider}.
|
||||
In general, we recommend using access controls
|
||||
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
|
||||
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
|
||||
of this issue appear in <a class="external-link"
|
||||
href="https://www.usenix.org/legacy/event/sec11/tech/full_papers/Felt.pdf"> this
|
||||
research paper</a>, published at USENIX.
|
||||
of this issue appear in the research paper <a
|
||||
href="https://www.usenix.org/legacy/event/sec11/tech/full_papers/Felt.pdf" class="external-link">
|
||||
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
|
||||
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
|
||||
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
|
||||
to the user and only allow access by applications signed by the same developer
|
||||
as application performing the permission check.</p>
|
||||
to the user and allow access only by applications signed by the same developer
|
||||
as the application performing the permission check.</p>
|
||||
|
||||
<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
|
||||
that you need to consider:
|
||||
<ul>
|
||||
<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>Users may choose not to install an application because a permission is
|
||||
confusing or perceived as risky.</li>
|
||||
@@ -247,28 +253,28 @@ confusing or perceived as risky.</li>
|
||||
has not been installed.</li>
|
||||
</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,
|
||||
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
|
||||
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
|
||||
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
|
||||
environments. The key consideration is making sure that appropriate protocols
|
||||
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
|
||||
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
|
||||
encouraged for all applications that communicate over the network.</p>
|
||||
|
||||
<p>We have seen some applications use <a
|
||||
href="http://en.wikipedia.org/wiki/Localhost">localhost</a> network ports for
|
||||
handling sensitive IPC. We discourage this approach since these interfaces are
|
||||
accessible by other applications on the device. Instead, you should use an Android IPC
|
||||
mechanism where authentication is possible such as with a {@link android.app.Service}. (Even
|
||||
worse than using loopback is to bind to INADDR_ANY since then your application
|
||||
may receive requests from anywhere.)</p>
|
||||
<p>Some applications use <a
|
||||
href="http://en.wikipedia.org/wiki/Localhost" class="external-link">localhost</a> network ports for
|
||||
handling sensitive IPC. You should not use this approach because these interfaces are
|
||||
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}.
|
||||
Binding to INADDR_ANY is worse than using loopback because then your application
|
||||
may receive requests from anywhere.</p>
|
||||
|
||||
<p>Also, one common issue that warrants repeating is to make sure that you do
|
||||
not trust data downloaded from HTTP or other insecure protocols. This includes
|
||||
<p>Make sure that you don't
|
||||
trust data downloaded from HTTP or other insecure protocols. This includes
|
||||
validation of input in {@link android.webkit.WebView} and
|
||||
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
|
||||
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)
|
||||
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
|
||||
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
|
||||
not rely on unauthenticated SMS data to perform sensitive commands.
|
||||
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. Don't
|
||||
rely on unauthenticated SMS data to perform sensitive commands.
|
||||
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
|
||||
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
|
||||
affecting applications, regardless of what platform they run on. Android does
|
||||
have platform-level countermeasures that reduce the exposure of applications to
|
||||
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
|
||||
affecting applications, regardless of what platform they run on. Android
|
||||
has platform-level countermeasures that reduce the exposure of applications to
|
||||
input validation issues, and you should use those features where possible. Also
|
||||
note that the selection of type-safe languages tends to reduce the likelihood of
|
||||
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
|
||||
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/Double_free#Use_after_free">use after
|
||||
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" class="external-link">use after
|
||||
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
|
||||
title="Address Space Layout Randomization">ASLR</acronym> and <acronym
|
||||
title="Data Execution Prevention">DEP</acronym> that reduce the
|
||||
exploitability of these errors, but they do not solve the underlying problem.
|
||||
You can prevent these vulneratbilities by careful handling pointers and managing
|
||||
exploitability of these errors, but they don't solve the underlying problem.
|
||||
You can prevent these vulnerabilities by carefully handling pointers and managing
|
||||
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
|
||||
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
|
||||
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
|
||||
for harm related to SQL injection.</p>
|
||||
|
||||
<p>If you cannot use the security features above, we strongly recommend the use
|
||||
of well-structured data formats and verifying that the data conforms to the
|
||||
<p>If you can't use the security features above, you should make sure to use
|
||||
well-structured data formats and verify that the data conforms to the
|
||||
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>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<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
|
||||
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.
|
||||
Finally, consider if there is a way that your application logic can be
|
||||
storing or transmitting it, don't store or transmit the data.
|
||||
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
|
||||
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
|
||||
inadvertently exposing data, and it also reduces the chance of attackers
|
||||
attempting to exploit your application.</p>
|
||||
|
||||
<p>If your application accesses personal information such as passwords or
|
||||
usernames, 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
|
||||
user names, keep in mind that some jurisdictions may require you to provide a
|
||||
privacy policy explaining your use and storage of that data. Following the
|
||||
security best practice of minimizing access to user data may also simplify
|
||||
compliance.</p>
|
||||
|
||||
<p>You should also consider whether your application might be inadvertently
|
||||
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
|
||||
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
|
||||
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
|
||||
must be transmitted to a server, or whether the operation can be performed on
|
||||
the client. Consider running any code using sensitive data on the client to
|
||||
avoid transmitting user data.</p>
|
||||
|
||||
<p>Also, make sure that you do not inadvertently expose user data to other
|
||||
application on the device through overly permissive IPC, world writable files,
|
||||
or network sockets. This is a special case of leaking permission-protected data,
|
||||
<p>If your app requires access to sensitive data, evaluate whether you need to
|
||||
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
|
||||
avoid transmitting user data. Also, make sure that you do not inadvertently expose user
|
||||
data to other
|
||||
applications 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,
|
||||
discussed in the <a href="#RequestingPermissions">Requesting Permissions</a> section.</p>
|
||||
|
||||
<p>If a <acronym title="Globally Unique Identifier">GUID</acronym>
|
||||
is required, create a large, unique number and store it. Do not
|
||||
use phone identifiers such as the phone number or IMEI which may be associated
|
||||
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
|
||||
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
|
||||
Developer Blog</a>.</p>
|
||||
href="http://android-developers.blogspot.com/2011/03/identifying-app-installations.html"
|
||||
>Android Developer Blog</a>.</p>
|
||||
|
||||
<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.
|
||||
Even though the phone log data
|
||||
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>
|
||||
|
||||
<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
|
||||
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
|
||||
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>
|
||||
|
||||
<p>If your application does not directly use JavaScript within a {@link android.webkit.WebView}, do
|
||||
<em>not</em> call {@link android.webkit.WebSettings#setJavaScriptEnabled setJavaScriptEnabled()}.
|
||||
<p>If your application doesn't directly use JavaScript within a {@link android.webkit.WebView},
|
||||
<em>do not</em> call
|
||||
{@link android.webkit.WebSettings#setJavaScriptEnabled setJavaScriptEnabled()}.
|
||||
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,
|
||||
{@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
|
||||
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
|
||||
{@link android.webkit.WebView}, you may want to use the
|
||||
{@link android.webkit.WebView#clearCache clearCache()} method to delete any files stored
|
||||
locally. Server-side
|
||||
headers like <code>no-cache</code> can also be used to indicate that an application should
|
||||
locally. You can also use server-side
|
||||
headers such as <code>no-cache</code> to indicate that an application should
|
||||
not cache particular content.</p>
|
||||
|
||||
<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.
|
||||
As a workaround, if your app is running on these devices, it
|
||||
should confirm that {@link android.webkit.WebView} objects display only trusted
|
||||
content. You should also use the updatable security {@link
|
||||
java.security.Provider Provider} object to make sure your app isn’t exposed to
|
||||
potential vulnerabilities in SSL, as described in <a
|
||||
must confirm that {@link android.webkit.WebView} objects display only trusted
|
||||
content. To make sure your app isn’t exposed to
|
||||
potential vulnerabilities in SSL, use the updatable security {@link
|
||||
java.security.Provider Provider} object as described in <a
|
||||
href="{@docRoot}training/articles/security-gms-provider.html">Updating Your
|
||||
Security Provider to Protect Against SSL Exploits</a>. If your application must
|
||||
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>
|
||||
|
||||
|
||||
<h3 id="Credentials">Handling Credentials</h3>
|
||||
<h3 id="Credentials">Handling credentials</h3>
|
||||
|
||||
<p>In general, we recommend minimizing the frequency of asking for user
|
||||
credentials—to make phishing attacks more conspicuous, and less likely to be
|
||||
successful. Instead use an authorization token and refresh it.</p>
|
||||
<p>To make phishing attacks more conspicuous and less likely to be
|
||||
successful, minimize the frequency of asking for user
|
||||
credentials. Instead use an authorization token and refresh it.</p>
|
||||
|
||||
<p>Where possible, username and password should not be stored on the device.
|
||||
Instead, perform initial authentication using the username and password
|
||||
supplied by the user, and then use a short-lived, service-specific
|
||||
<p>Where possible, don't store user names and passwords on the device.
|
||||
Instead, perform initial authentication using the user name and password
|
||||
supplied by the user, and then use a short-lived, service-specific
|
||||
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
|
||||
{@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>
|
||||
|
||||
<p>After using {@link android.accounts.AccountManager} to retrieve an
|
||||
{@link android.accounts.Account}, {@link android.accounts.Account#CREATOR}
|
||||
before passing in any credentials, so that you do not inadvertently pass
|
||||
{@link android.accounts.Account}, use {@link android.accounts.Account#CREATOR}
|
||||
before passing in any credentials so that you do not inadvertently pass
|
||||
credentials to the wrong application.</p>
|
||||
|
||||
<p>If credentials are to be used only by applications that you create, then you
|
||||
can verify the application which accesses the {@link android.accounts.AccountManager} using
|
||||
<p>If credentials are used only by applications that you create, you
|
||||
can verify the application that accesses the {@link android.accounts.AccountManager} using
|
||||
{@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>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h2 id="Crypto">Using Cryptography</h2>
|
||||
<h2 id="Crypto">Using cryptography</h2>
|
||||
|
||||
<p>In addition to providing data isolation, supporting full-filesystem
|
||||
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
|
||||
requires no knowledge of cryptography. If you need a secure
|
||||
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
|
||||
recommend that you <em>not</em> implement your own cryptographic algorithms. Use
|
||||
<p>If you do need to implement your own protocol, you should <em>not</em>
|
||||
implement your own cryptographic algorithms. Use
|
||||
existing cryptographic algorithms such as those in the implementation of AES or
|
||||
RSA provided in the {@link javax.crypto.Cipher} class.</p>
|
||||
|
||||
<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
|
||||
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>
|
||||
|
||||
<p>If you need to store a key for repeated use, use a mechanism like
|
||||
{@link java.security.KeyStore} that
|
||||
<p>If you need to store a key for repeated use, use a mechanism, such as
|
||||
{@link java.security.KeyStore}, that
|
||||
provides a mechanism for long term storage and retrieval of cryptographic
|
||||
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
|
||||
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},
|
||||
{@link android.os.Binder} or {@link android.os.Messenger} with a {@link
|
||||
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.
|
||||
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
|
||||
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
|
||||
within the same UID, or if you decide late in development that you do not
|
||||
actually want to expose functionality as IPC but you don’t want to rewrite
|
||||
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
|
||||
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
|
||||
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,
|
||||
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
|
||||
android:protectionLevel}</a>.</p>
|
||||
|
||||
@@ -556,31 +565,42 @@ android:protectionLevel}</a>.</p>
|
||||
|
||||
<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
|
||||
android.content.Context#sendBroadcast sendBroadcast()}, {@link
|
||||
android.content.Context#sendOrderedBroadcast sendOrderedBroadcast()},
|
||||
or an explicit intent to a specific application component.</p>
|
||||
|
||||
<p>Note that ordered broadcasts can be “consumed” by a recipient, so they
|
||||
may not be delivered to all applications. If you are sending an intent that must be delivered
|
||||
to a specific receiver, then you must use an explicit intent that declares the receiver
|
||||
by nameintent.</p>
|
||||
<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>
|
||||
|
||||
<p>Senders of an intent can verify that the recipient has a permission
|
||||
specifying a non-Null permission with the method call. Only applications with that
|
||||
permission will receive the intent. If data within a broadcast intent may be
|
||||
<p>Note that ordered broadcasts can be <em>consumed</em> by a recipient, so they
|
||||
may not be delivered to all applications. If you are sending an intent that must be delivered
|
||||
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
|
||||
malicious applications cannot register to receive those messages without
|
||||
appropriate permissions. In those circumstances, you may also consider
|
||||
malicious applications can't register to receive those messages without
|
||||
appropriate permissions. In those circumstances, you may also consider
|
||||
invoking the receiver directly, rather than raising a broadcast.</p>
|
||||
|
||||
<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
|
||||
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
|
||||
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
|
||||
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>
|
||||
|
||||
<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
|
||||
href="{@docRoot}guide/topics/manifest/service-element.html#exported">{@code
|
||||
android:exported}</a> attribute to be sure it behaves as you'd like.
|
||||
Services can also be protected using the <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
|
||||
href="{@docRoot}guide/topics/manifest/uses-permission-element.html"><uses-permission></a>
|
||||
</code> element in their own manifest to be
|
||||
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
|
||||
calling {@link android.content.Context#checkCallingPermission
|
||||
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
|
||||
oversight.</p>
|
||||
|
||||
@@ -620,24 +646,24 @@ oversight.</p>
|
||||
preferred mechanism for RPC-style IPC in Android. They provide a well-defined
|
||||
interface that enables mutual authentication of the endpoints, if required.</p>
|
||||
|
||||
<p>We strongly encourage designing interfaces in a manner that does not require
|
||||
interface specific permission checks. {@link android.os.Binder} and
|
||||
<p>You should design your app interfaces in a manner that does not require
|
||||
interface-specific permission checks. {@link android.os.Binder} and
|
||||
{@link android.os.Messenger} objects are not declared within the
|
||||
application manifest, and therefore you cannot apply declarative permissions
|
||||
directly to them. They generally inherit permissions declared in the
|
||||
application manifest for the {@link android.app.Service} or {@link
|
||||
android.app.Activity} within which they are
|
||||
implemented. If you are creating an interface that requires authentication
|
||||
and/or access controls, those controls must be
|
||||
explicitly added as code in the {@link android.os.Binder} or {@link android.os.Messenger}
|
||||
and/or access controls, you must explicitly add those controls
|
||||
as code in the {@link android.os.Binder} or {@link android.os.Messenger}
|
||||
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()}
|
||||
to verify whether the
|
||||
caller has a required permission. This is especially important
|
||||
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
|
||||
android.content.Context#bindService bindService()}
|
||||
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
|
||||
may want to apply security permissions to receivers using the <code><a
|
||||
href="{@docRoot}guide/topics/manifest/receiver-element.html">
|
||||
<receiver></a></code> element within the application manifest. This will
|
||||
prevent applications without appropriate permissions from sending an intent to
|
||||
<receiver></a></code> element within the application manifest. This
|
||||
prevents applications without appropriate permissions from sending an intent to
|
||||
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.
|
||||
Doing so significantly increases the likelihood of application compromise due
|
||||
to code injection or code tampering. It also adds complexity around version
|
||||
management and application testing. Finally, it can make it impossible to
|
||||
to code injection or code tampering. It also adds complexity around version
|
||||
management and application testing. It can also make it impossible to
|
||||
verify the behavior of an application, so it may be prohibited in some
|
||||
environments.</p>
|
||||
|
||||
<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
|
||||
security permissions as the application APK. The user made a decision to
|
||||
install your application based on your identity, and they are expecting that
|
||||
keep in mind about dynamically-loaded code is that it runs with the same
|
||||
security permissions as the application APK. The user makes a decision to
|
||||
install your application based on your identity, and the user expects that
|
||||
you provide any code run within the application, including code that is
|
||||
dynamically loaded.</p>
|
||||
|
||||
<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
|
||||
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
|
||||
{@link dalvik.system.DexClassLoader}. We have seen many instances of applications
|
||||
attempting to load code from insecure locations, such as downloaded from the
|
||||
network over unencrypted protocols or from world writable locations such as
|
||||
{@link dalvik.system.DexClassLoader}. Many applications
|
||||
attempt to load code from insecure locations, such as downloaded from the
|
||||
network over unencrypted protocols or from world-writable locations such as
|
||||
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
|
||||
content on the device, respectively.</p>
|
||||
the content in transit or another application on a user's device to modify the
|
||||
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,
|
||||
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.
|
||||
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>
|
||||
|
||||
<p>If you're interested in diving deeper on the subject of virtual machine security,
|
||||
we recommend that you familiarize yourself with some
|
||||
<p>If you're interested in learning more about virtual machine security,
|
||||
familiarize yourself with some
|
||||
existing literature on the subject. Two of the more popular resources are:
|
||||
<ul>
|
||||
<li><a href="http://www.securingjava.com/toc.html">
|
||||
http://www.securingjava.com/toc.html</a></li>
|
||||
<li><a href="http://www.securingjava.com/toc.html" class="external-link">
|
||||
Securing Java</a></li>
|
||||
<li><a
|
||||
href="https://www.owasp.org/index.php/Java_Security_Resources">
|
||||
https://www.owasp.org/index.php/Java_Security_Resources</a></li>
|
||||
href="https://www.owasp.org/index.php/Category:Java#tab=Related_3rd_Party_Projects"
|
||||
class="external-link">
|
||||
Related 3rd party Projects</a></li>
|
||||
</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
|
||||
programming in other environments, there are two broad issues that may be
|
||||
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
|
||||
<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
|
||||
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
|
||||
development security best practices is especially useful if you are going to
|
||||
use native code. Linux security practices are beyond the scope of this document,
|
||||
but one of the most popular resources is “Secure Programming for
|
||||
Linux and Unix HOWTO”, available at <a
|
||||
href="http://www.dwheeler.com/secure-programs">
|
||||
http://www.dwheeler.com/secure-programs</a>.</p>
|
||||
<p>Android is built using the Linux kernel, and being familiar with Linux
|
||||
development security best practices is especially useful if you are
|
||||
using native code. Linux security practices are beyond the scope of this document,
|
||||
but one of the most popular resources is <a href="http://www.dwheeler.com/secure-programs"
|
||||
class="external-link">Secure Programming HOWTO - Creating Secure Software</a>.</p>
|
||||
|
||||
<p>An important difference between Android and most Linux environments is the
|
||||
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>
|
||||
with very limited permissions. This is discussed in more detail in the <a
|
||||
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>
|
||||
|
||||
|
||||
@@ -7,11 +7,11 @@ trainingnavtop=true
|
||||
|
||||
<h2>This lesson teaches you how to</h2>
|
||||
<ol>
|
||||
<li><a href="#connect">Get a Geographic Location</a></li>
|
||||
<li><a href="#fetch-address">Define an Intent Service to Fetch the
|
||||
Address</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="#connect">Get a geographic location</a></li>
|
||||
<li><a href="#fetch-address">Define an intent service to fetch the
|
||||
address</a></li>
|
||||
<li><a href="#start-intent">Start the intent service</a></li>
|
||||
<li><a href="#result-receiver">Receive the geocoding results</a></li>
|
||||
</ol>
|
||||
|
||||
<h2>You should also read</h2>
|
||||
@@ -58,7 +58,7 @@ trainingnavtop=true
|
||||
convert a geographic location to an address. The method returns an estimated
|
||||
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
|
||||
address lookup feature. The lesson on
|
||||
@@ -69,12 +69,12 @@ trainingnavtop=true
|
||||
<a href="{@docRoot}reference/com/google/android/gms/location/FusedLocationProviderApi.html">fused
|
||||
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
|
||||
<a href="{@docRoot}training/location/retrieve-current.html#play-services">Connect
|
||||
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
|
||||
{@code ACCESS_FINE_LOCATION}, as shown in the following example:</p>
|
||||
|
||||
@@ -86,12 +86,12 @@ trainingnavtop=true
|
||||
</manifest>
|
||||
</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()}
|
||||
method provided by the {@link android.location.Geocoder} class accepts a
|
||||
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
|
||||
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
|
||||
it from the main, user interface (UI) thread of your app.</p>
|
||||
|
||||
<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
|
||||
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
|
||||
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
|
||||
be cancelled when the activity is rebuilt.</p>
|
||||
|
||||
<p>Define a {@code FetchAddressIntentService} class that extends
|
||||
{@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
|
||||
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
|
||||
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>
|
||||
|
||||
<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>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
@@ -131,26 +131,26 @@ trainingnavtop=true
|
||||
</manifest>
|
||||
</pre>
|
||||
|
||||
<p class="note"><strong>Note:</strong> The {@code <service>} element in
|
||||
the manifest doesn't need to include an intent filter, because your main
|
||||
<p class="note"><strong>Note:</strong> The {@code <service>} element in
|
||||
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
|
||||
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
|
||||
<em>reverse geocoding</em>. To perform the main work of the intent service,
|
||||
that is, your reverse geocoding request, implement
|
||||
<em>reverse geocoding</em>. To perform the main work of the intent service (your reverse
|
||||
geocoding request), implement
|
||||
{@link android.app.IntentService#onHandleIntent onHandleIntent()} within the
|
||||
{@code FetchAddressIntentService} class. Create a
|
||||
{@link android.location.Geocoder} object to handle the reverse geocoding.</p>
|
||||
|
||||
<p>A locale represents a specific geographical or linguistic region. Locale
|
||||
objects are used to adjust the presentation of information, such as numbers or
|
||||
dates, to suit the conventions in the region represented by the locale. Pass a
|
||||
objects adjust the presentation of information, such as numbers or
|
||||
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
|
||||
to the {@link android.location.Geocoder} object, to ensure that the resulting
|
||||
address is localized to the user's geographic region.</p>
|
||||
to the {@link android.location.Geocoder} object to ensure that the resulting
|
||||
address is localized to the user's geographic region. Here is an example:</p>
|
||||
|
||||
<pre>
|
||||
@Override
|
||||
@@ -162,7 +162,7 @@ protected void onHandleIntent(Intent intent) {
|
||||
|
||||
<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
|
||||
requested the address. To report the results of the geocoding
|
||||
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
|
||||
{@link android.location.Geocoder#getFromLocation getFromLocation()},
|
||||
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
|
||||
address. The geocoder returns an array of addresses. If no addresses were
|
||||
passing it the latitude and longitude from the location object and the
|
||||
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 are
|
||||
found to match the given location, it returns an empty list. If there is no
|
||||
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
|
||||
occurs, place the corresponding error message in the {@code errorMessage}
|
||||
variable, so you can send it back to the requesting activity:</p>
|
||||
<p>Check for the following errors, as shown in the code sample below:</p>
|
||||
|
||||
<ul>
|
||||
<li><strong>No location data provided</strong> - The intent extras do not
|
||||
include the {@link android.location.Location} object required for reverse
|
||||
<li><strong>No location data provided</strong> – The intent extras do not
|
||||
include the {@link android.location.Location} object that is required for reverse
|
||||
geocoding.</li>
|
||||
<li><strong>Invalid latitude or longitude used</strong> - The latitude
|
||||
and/or longitude values provided in the {@link android.location.Location}
|
||||
<li><strong>Invalid latitude or longitude used</strong> – The latitude
|
||||
and/or longitude values that are provided in the {@link android.location.Location}
|
||||
object are invalid.</li>
|
||||
<li><strong>No geocoder available</strong> - The background geocoding service
|
||||
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>No geocoder available</strong> – The background geocoding service
|
||||
is not available due to a network error or IO exception.</li>
|
||||
<li><strong>Sorry, no address found</strong> – The geocoder can't find an
|
||||
address for the given latitude/longitude.</li>
|
||||
</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
|
||||
{@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
|
||||
requested the address.</p>
|
||||
|
||||
@@ -220,7 +222,7 @@ public final class Constants {
|
||||
results consist of the previously-mentioned numeric success/failure code and
|
||||
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,
|
||||
as shown in the code sample below:</p>
|
||||
as shown in this code sample:</p>
|
||||
|
||||
<pre>
|
||||
@Override
|
||||
@@ -280,18 +282,18 @@ protected void onHandleIntent(Intent intent) {
|
||||
|
||||
<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.
|
||||
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 code is useful for reporting the success or failure of the geocoding
|
||||
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
|
||||
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
|
||||
that may occur, and called the {@code deliverResultToReceiver()} method. Now
|
||||
you need to define the {@code deliverResultToReceiver()} method that sends
|
||||
that may occur, and called the {@code deliverResultToReceiver()} method, so now
|
||||
you must define the {@code deliverResultToReceiver()} method that sends
|
||||
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
|
||||
@@ -299,7 +301,7 @@ protected void onHandleIntent(Intent intent) {
|
||||
To construct the message bundle, concatenate the {@code RESULT_DATA_KEY}
|
||||
constant from your {@code Constants} class (defined in
|
||||
<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:
|
||||
</p>
|
||||
|
||||
@@ -315,26 +317,26 @@ public class FetchAddressIntentService extends IntentService {
|
||||
}
|
||||
</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
|
||||
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
|
||||
instantiates and starts the service if it isn't already running, and creates a
|
||||
process if needed. If the service is already running then it remains running.
|
||||
instantiates and starts the service if it isn't already running, and it creates a
|
||||
process if needed. If the service is already running, it remains running.
|
||||
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
|
||||
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
|
||||
<a href="{@docRoot}guide/components/intents-filters.html#Types">Intent
|
||||
Types</a>.</p>
|
||||
|
||||
<p>To create an explicit intent, specify the name of the
|
||||
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>
|
||||
<li>A {@link android.os.ResultReceiver} to handle the results of the address
|
||||
@@ -362,6 +364,12 @@ public class MainActivity extends ActionBarActivity implements
|
||||
}
|
||||
</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
|
||||
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
|
||||
@@ -391,7 +399,7 @@ public void fetchAddressButtonHandler(View view) {
|
||||
app's UI. The following code snippet shows the call to 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>
|
||||
callback provided by the Google API Client:</p>
|
||||
callback that is provided by the Google API Client:</p>
|
||||
|
||||
<pre>
|
||||
public class MainActivity extends ActionBarActivity implements
|
||||
@@ -420,9 +428,9 @@ public class MainActivity extends ActionBarActivity implements
|
||||
}
|
||||
</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
|
||||
made the request. In the activity that makes the request, define an
|
||||
{@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
|
||||
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
|
||||
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>
|
||||
|
||||
<p>Override the
|
||||
{@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>
|
||||
|
||||
<pre>
|
||||
|
||||
@@ -35,16 +35,22 @@ startpage=true
|
||||
<!-- ------------------------------------------------------------------------------------------- -->
|
||||
<p>
|
||||
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
|
||||
will interfere with the responsiveness of your user interface. This annoys your users, and can
|
||||
a special thread called the UI thread. Long-running foreground operations can cause problems
|
||||
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
|
||||
help you off-load operations onto a separate thread running in the background. The most useful
|
||||
of these is {@link android.app.IntentService}.
|
||||
help you off-load operations onto a separate thread that runs in the background. The most
|
||||
useful of these is {@link android.app.IntentService}.
|
||||
</p>
|
||||
<p>
|
||||
This class describes how to implement an {@link android.app.IntentService}, send it work
|
||||
requests, and report its results to other components.
|
||||
</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>
|
||||
<dl>
|
||||
<dt>
|
||||
|
||||
Reference in New Issue
Block a user