cb0b2df114
Change-Id: I11b1d524dd2159b58c65d3ef7a76af15624ae365
254 lines
11 KiB
Plaintext
254 lines
11 KiB
Plaintext
page.title=Sending the User to Another App
|
|
parent.title=Interacting with Other Apps
|
|
parent.link=index.html
|
|
|
|
trainingnavtop=true
|
|
next.title=Getting a Result from an Activity
|
|
next.link=result.html
|
|
|
|
@jd:body
|
|
|
|
|
|
<div id="tb-wrapper">
|
|
<div id="tb">
|
|
|
|
<h2>This lesson teaches you to</h2>
|
|
<ol>
|
|
<li><a href="#Build">Build an Implicit Intent</a></li>
|
|
<li><a href="#Verify">Verify There is an App to Receive the Intent</a></li>
|
|
<li><a href="#StartActivity">Start an Activity with the Intent</a></li>
|
|
<li><a href="#AppChooser">Show an App Chooser</a></li>
|
|
</ol>
|
|
|
|
<h2>You should also read</h2>
|
|
<ul>
|
|
<li><a href="{@docRoot}training/sharing/index.html">Sharing Content</a></li>
|
|
</ul>
|
|
|
|
</div>
|
|
</div>
|
|
|
|
<p>One of Android's most important features is an app's ability to send the user to another app
|
|
based on an "action" it would like to perform. For example, if
|
|
your app has the address of a business that you'd like to show on a map, you don't have to build
|
|
an activity in your app that shows a map. Instead, you can create a request to view the address
|
|
using an {@link android.content.Intent}. The Android system then starts an app that's able to show
|
|
the address on a map.</p>
|
|
|
|
<p>As explained in the first class, <a href="{@docRoot}training/basics/firstapp/index.html">Building
|
|
Your First App</a>, you must use intents to navigate between activities in your own app. You
|
|
generally do so with an <em>explicit intent</em>, which defines the exact class name of the
|
|
component you want to start. However, when you want to have a separate app perform an action, such
|
|
as "view a map," you must use an <em>implicit intent</em>.</p>
|
|
|
|
<p>This lesson shows you how to create an implicit intent for a particular action, and how to use it
|
|
to start an activity that performs the action in another app.</p>
|
|
|
|
|
|
|
|
<h2 id="Build">Build an Implicit Intent</h2>
|
|
|
|
<p>Implicit intents do not declare the class name of the component to start, but instead declare an
|
|
action to perform. The action specifies the thing you want to do, such as <em>view</em>,
|
|
<em>edit</em>, <em>send</em>, or <em>get</em> something. Intents often also include data associated
|
|
with the action, such as the address you want to view, or the email message you want to send.
|
|
Depending on the intent you want to create, the data might be a {@link android.net.Uri},
|
|
one of several other data types, or the intent might not need data at all.</p>
|
|
|
|
<p>If your data is a {@link android.net.Uri}, there's a simple {@link
|
|
android.content.Intent#Intent(String,Uri) Intent()} constructor you can use define the action and
|
|
data.</p>
|
|
|
|
<p>For example, here's how to create an intent to initiate a phone call using the {@link
|
|
android.net.Uri} data to specify the telephone number:</p>
|
|
|
|
<pre>
|
|
Uri number = Uri.parse("tel:5551234");
|
|
Intent callIntent = new Intent(Intent.ACTION_DIAL, number);
|
|
</pre>
|
|
|
|
<p>When your app invokes this intent by calling {@link android.app.Activity#startActivity
|
|
startActivity()}, the Phone app initiates a call to the given phone number.</p>
|
|
|
|
<p>Here are a couple other intents and their action and {@link android.net.Uri} data
|
|
pairs:</p>
|
|
|
|
<ul>
|
|
<li>View a map:
|
|
<pre>
|
|
// Map point based on address
|
|
Uri location = Uri.parse("geo:0,0?q=1600+Amphitheatre+Parkway,+Mountain+View,+California");
|
|
// Or map point based on latitude/longitude
|
|
// Uri location = Uri.parse("geo:37.422219,-122.08364?z=14"); // z param is zoom level
|
|
Intent mapIntent = new Intent(Intent.ACTION_VIEW, location);
|
|
</pre>
|
|
</li>
|
|
<li>View a web page:
|
|
<pre>
|
|
Uri webpage = Uri.parse("http://www.android.com");
|
|
Intent webIntent = new Intent(Intent.ACTION_VIEW, webpage);
|
|
</pre>
|
|
</li>
|
|
</ul>
|
|
|
|
<p>Other kinds of implicit intents require "extra" data that provide different data types,
|
|
such as a string. You can add one or more pieces of extra data using the various {@link
|
|
android.content.Intent#putExtra(String,String) putExtra()} methods.</p>
|
|
|
|
<p>By default, the system determines the appropriate MIME type required by an intent based on the
|
|
{@link android.net.Uri} data that's included. If you don't include a {@link android.net.Uri} in the
|
|
intent, you should usually use {@link android.content.Intent#setType setType()} to specify the type
|
|
of data associated with the intent. Setting the MIME type further specifies which kinds of
|
|
activities should receive the intent.</p>
|
|
|
|
<p>Here are some more intents that add extra data to specify the desired action:</p>
|
|
|
|
<ul>
|
|
<li>Send an email with an attachment:
|
|
<pre>
|
|
Intent emailIntent = new Intent(Intent.ACTION_SEND);
|
|
// The intent does not have a URI, so declare the "text/plain" MIME type
|
|
emailIntent.setType(HTTP.PLAIN_TEXT_TYPE);
|
|
emailIntent.putExtra(Intent.EXTRA_EMAIL, new String[] {"jon@example.com"}); // recipients
|
|
emailIntent.putExtra(Intent.EXTRA_SUBJECT, "Email subject");
|
|
emailIntent.putExtra(Intent.EXTRA_TEXT, "Email message text");
|
|
emailIntent.putExtra(Intent.EXTRA_STREAM, Uri.parse("content://path/to/email/attachment"));
|
|
// You can also attach multiple items by passing an ArrayList of Uris
|
|
</pre>
|
|
</li>
|
|
<li>Create a calendar event:
|
|
<pre>
|
|
Intent calendarIntent = new Intent(Intent.ACTION_INSERT, Events.CONTENT_URI);
|
|
Calendar beginTime = Calendar.getInstance().set(2012, 0, 19, 7, 30);
|
|
Calendar endTime = Calendar.getInstance().set(2012, 0, 19, 10, 30);
|
|
calendarIntent.putExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME, beginTime.getTimeInMillis());
|
|
calendarIntent.putExtra(CalendarContract.EXTRA_EVENT_END_TIME, endTime.getTimeInMillis());
|
|
calendarIntent.putExtra(Events.TITLE, "Ninja class");
|
|
calendarIntent.putExtra(Events.EVENT_LOCATION, "Secret dojo");
|
|
</pre>
|
|
<p class="note"><strong>Note:</strong> This intent for a calendar event is supported only with API
|
|
level 14 and higher.</p>
|
|
</li>
|
|
</ul>
|
|
|
|
<p class="note"><strong>Note:</strong> It's important that you define your {@link
|
|
android.content.Intent} to be as specific as possible. For example, if you want to display an image
|
|
using the {@link android.content.Intent#ACTION_VIEW} intent, you should specify a MIME type of
|
|
{@code image/*}. This prevents apps that can "view" other types of data (like a map app) from being
|
|
triggered by the intent.</p>
|
|
|
|
|
|
|
|
<h2 id="Verify">Verify There is an App to Receive the Intent</h2>
|
|
|
|
<p>Although the Android platform guarantees that certain intents will resolve to one of the
|
|
built-in apps (such as the Phone, Email, or Calendar app), you should always include a
|
|
verification step before invoking an intent.</p>
|
|
|
|
<p class="caution"><strong>Caution:</strong> If you invoke an intent and there is no app
|
|
available on the device that can handle the intent, your app will crash.</p>
|
|
|
|
<p>To verify there is an activity available that can respond to the intent, call {@link
|
|
android.content.pm.PackageManager#queryIntentActivities queryIntentActivities()} to get a list
|
|
of activities capable of handling your {@link android.content.Intent}. If the returned {@link
|
|
java.util.List} is not empty, you can safely use the intent. For example:</p>
|
|
|
|
<pre>
|
|
PackageManager packageManager = {@link android.content.Context#getPackageManager()};
|
|
List<ResolveInfo> activities = packageManager.queryIntentActivities(intent, 0);
|
|
boolean isIntentSafe = activities.size() > 0;
|
|
</pre>
|
|
|
|
<p>If <code>isIntentSafe</code> is <code>true</code>, then at least one app will respond to
|
|
the intent. If it is <code>false</code>, then there aren't any apps to handle the intent.</p>
|
|
|
|
<p class="note"><strong>Note:</strong> You should perform this check when your activity first
|
|
starts in case you need to disable the feature that uses the intent before the user attempts to use
|
|
it. If you know of a specific app that can handle the intent, you can also provide a link for the
|
|
user to download the app (see how to <a
|
|
href="{@docRoot}distribute/googleplay/promote/linking.html">link to your product on Google
|
|
Play</a>).</p>
|
|
|
|
|
|
<h2 id="StartActivity">Start an Activity with the Intent</h2>
|
|
|
|
<div class="figure" style="width:200px">
|
|
<img src="{@docRoot}images/training/basics/intents-choice.png" alt="" />
|
|
<p class="img-caption"><strong>Figure 1.</strong> Example of the selection dialog that appears
|
|
when more than one app can handle an intent.</p>
|
|
</div>
|
|
|
|
<p>Once you have created your {@link android.content.Intent} and set the extra info, call {@link
|
|
android.app.Activity#startActivity startActivity()} to send it to the system. If the system
|
|
identifies more than one activity that can handle the intent, it displays a dialog for the user to
|
|
select which app to use, as shown in figure 1. If there is only one activity that handles the
|
|
intent, the system immediately starts it.</p>
|
|
|
|
<pre>
|
|
startActivity(intent);
|
|
</pre>
|
|
|
|
<p>Here's a complete example that shows how to create an intent to view a map, verify that an
|
|
app exists to handle the intent, then start it:</p>
|
|
|
|
<pre>
|
|
// Build the intent
|
|
Uri location = Uri.parse("geo:0,0?q=1600+Amphitheatre+Parkway,+Mountain+View,+California");
|
|
Intent mapIntent = new Intent(Intent.ACTION_VIEW, location);
|
|
|
|
// Verify it resolves
|
|
PackageManager packageManager = {@link android.content.Context#getPackageManager()};
|
|
List<ResolveInfo> activities = packageManager.queryIntentActivities(mapIntent, 0);
|
|
boolean isIntentSafe = activities.size() > 0;
|
|
|
|
// Start an activity if it's safe
|
|
if (isIntentSafe) {
|
|
startActivity(mapIntent);
|
|
}
|
|
</pre>
|
|
|
|
|
|
|
|
<h2 id="AppChooser">Show an App Chooser</h2>
|
|
|
|
<div class="figure" style="width:200px">
|
|
<img src="{@docRoot}images/training/basics/intent-chooser.png" alt="" />
|
|
<p class="img-caption"><strong>Figure 2.</strong> Example of the chooser dialog that appears
|
|
when you use {@link android.content.Intent#createChooser createChooser()} to ensure
|
|
that the user is always shown a list of apps that respond to your intent.</p>
|
|
</div>
|
|
|
|
<p>Notice that when you start an activity by passing your {@link android.content.Intent} to {@link
|
|
android.app.Activity#startActivity startActivity()} and there is more than one app that responds to
|
|
the intent, the user can select which app to use by default (by selecting a checkbox at the bottom
|
|
of the dialog; see figure 1). This is nice when performing an action for which the user
|
|
generally wants to use the same app every time, such as when opening a web page (users
|
|
likely use just one web browser) or taking a photo (users likely prefer one camera). However, if
|
|
the action to be performed could be handled by multiple apps and the user might
|
|
prefer a different app each time—such as a "share" action, for which users might have several
|
|
apps through which they might share an item—you should explicitly show a chooser dialog,
|
|
which forces the user to select which app to use for the action every time (the user cannot select a
|
|
default app for the action).</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>
|
|
|
|
<pre>
|
|
Intent intent = new Intent(Intent.ACTION_SEND);
|
|
...
|
|
|
|
// Always use string resources for UI text. This says something like "Share this photo with"
|
|
String title = getResources().getText(R.string.chooser_title);
|
|
// Create and start the chooser
|
|
Intent chooser = Intent.createChooser(intent, title);
|
|
startActivity(chooser);
|
|
</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>
|
|
|
|
|
|
|