1page.title=Sending the User to Another App
2page.tags=intents
3helpoutsWidget=true
4
5trainingnavtop=true
6
7@jd:body
8
9
10<div id="tb-wrapper">
11  <div id="tb">
12
13<h2>This lesson teaches you to</h2>
14<ol>
15  <li><a href="#Build">Build an Implicit Intent</a></li>
16  <li><a href="#Verify">Verify There is an App to Receive the Intent</a></li>
17  <li><a href="#StartActivity">Start an Activity with the Intent</a></li>
18  <li><a href="#AppChooser">Show an App Chooser</a></li>
19</ol>
20
21<h2>You should also read</h2>
22<ul>
23    <li><a href="{@docRoot}training/sharing/index.html">Sharing Simple Data</a></li>
24</ul>
25
26  </div>
27</div>
28
29<p>One of Android's most important features is an app's ability to send the user to another app
30based on an "action" it would like to perform. For example, if
31your app has the address of a business that you'd like to show on a map, you don't have to build
32an activity in your app that shows a map. Instead, you can create a request to view the address
33using an {@link android.content.Intent}. The Android system then starts an app that's able to show
34the address on a map.</p>
35
36<p>As explained in the first class, <a href="{@docRoot}training/basics/firstapp/index.html">Building
37Your First App</a>, you must use intents to navigate between activities in your own app. You
38generally do so with an <em>explicit intent</em>, which defines the exact class name of the
39component you want to start. However, when you want to have a separate app perform an action, such
40as "view a map," you must use an <em>implicit intent</em>.</p>
41
42<p>This lesson shows you how to create an implicit intent for a particular action, and how to use it
43to start an activity that performs the action in another app.</p>
44
45
46
47<h2 id="Build">Build an Implicit Intent</h2>
48
49<p>Implicit intents do not declare the class name of the component to start, but instead declare an
50action to perform. The action specifies the thing you want to do, such as <em>view</em>,
51<em>edit</em>, <em>send</em>, or <em>get</em> something. Intents often also include data associated
52with the action, such as the address you want to view, or the email message you want to send.
53Depending on the intent you want to create, the data might be a {@link android.net.Uri},
54one of several other data types, or the intent might not need data at all.</p>
55
56<p>If your data is a {@link android.net.Uri}, there's a simple {@link
57android.content.Intent#Intent(String,Uri) Intent()} constructor you can use define the action and
58data.</p>
59
60<p>For example, here's how to create an intent to initiate a phone call using the {@link
61android.net.Uri} data to specify the telephone number:</p>
62
63<pre>
64Uri number = Uri.parse("tel:5551234");
65Intent callIntent = new Intent(Intent.ACTION_DIAL, number);
66</pre>
67
68<p>When your app invokes this intent by calling {@link android.app.Activity#startActivity
69startActivity()}, the Phone app initiates a call to the given phone number.</p>
70
71<p>Here are a couple other intents and their action and {@link android.net.Uri} data
72pairs:</p>
73
74<ul>
75  <li>View a map:
76<pre>
77// Map point based on address
78Uri location = Uri.parse("geo:0,0?q=1600+Amphitheatre+Parkway,+Mountain+View,+California");
79// Or map point based on latitude/longitude
80// Uri location = Uri.parse("geo:37.422219,-122.08364?z=14"); // z param is zoom level
81Intent mapIntent = new Intent(Intent.ACTION_VIEW, location);
82</pre>
83  </li>
84  <li>View a web page:
85<pre>
86Uri webpage = Uri.parse("http://www.android.com");
87Intent webIntent = new Intent(Intent.ACTION_VIEW, webpage);
88</pre>
89  </li>
90</ul>
91
92<p>Other kinds of implicit intents require "extra" data that provide different data types,
93such as a string. You can add one or more pieces of extra data using the various {@link
94android.content.Intent#putExtra(String,String) putExtra()} methods.</p>
95
96<p>By default, the system determines the appropriate MIME type required by an intent based on the
97{@link android.net.Uri} data that's included. If you don't include a {@link android.net.Uri} in the
98intent, you should usually use {@link android.content.Intent#setType setType()} to specify the type
99of data associated with the intent. Setting the MIME type further specifies which kinds of
100activities should receive the intent.</p>
101
102<p>Here are some more intents that add extra data to specify the desired action:</p>
103
104<ul>
105  <li>Send an email with an attachment:
106<pre>
107Intent emailIntent = new Intent(Intent.ACTION_SEND);
108// The intent does not have a URI, so declare the "text/plain" MIME type
109emailIntent.setType(HTTP.PLAIN_TEXT_TYPE);
110emailIntent.putExtra(Intent.EXTRA_EMAIL, new String[] {"jon@example.com"}); // recipients
111emailIntent.putExtra(Intent.EXTRA_SUBJECT, "Email subject");
112emailIntent.putExtra(Intent.EXTRA_TEXT, "Email message text");
113emailIntent.putExtra(Intent.EXTRA_STREAM, Uri.parse("content://path/to/email/attachment"));
114// You can also attach multiple items by passing an ArrayList of Uris
115</pre>
116  </li>
117  <li>Create a calendar event:
118<pre>
119Intent calendarIntent = new Intent(Intent.ACTION_INSERT, Events.CONTENT_URI);
120Calendar beginTime = Calendar.getInstance().set(2012, 0, 19, 7, 30);
121Calendar endTime = Calendar.getInstance().set(2012, 0, 19, 10, 30);
122calendarIntent.putExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME, beginTime.getTimeInMillis());
123calendarIntent.putExtra(CalendarContract.EXTRA_EVENT_END_TIME, endTime.getTimeInMillis());
124calendarIntent.putExtra(Events.TITLE, "Ninja class");
125calendarIntent.putExtra(Events.EVENT_LOCATION, "Secret dojo");
126</pre>
127<p class="note"><strong>Note:</strong> This intent for a calendar event is supported only with API
128level 14 and higher.</p>
129  </li>
130</ul>
131
132<p class="note"><strong>Note:</strong> It's important that you define your {@link
133android.content.Intent} to be as specific as possible. For example, if you want to display an image
134using the {@link android.content.Intent#ACTION_VIEW} intent, you should specify a MIME type of
135{@code image/*}. This prevents apps that can "view" other types of data (like a map app) from being
136triggered by the intent.</p>
137
138
139
140<h2 id="Verify">Verify There is an App to Receive the Intent</h2>
141
142<p>Although the Android platform guarantees that certain intents will resolve to one of the
143built-in apps (such as the Phone, Email, or Calendar app), you should always include a
144verification step before invoking an intent.</p>
145
146<p class="caution"><strong>Caution:</strong> If you invoke an intent and there is no app
147available on the device that can handle the intent, your app will crash.</p>
148
149<p>To verify there is an activity available that can respond to the intent, call {@link
150android.content.pm.PackageManager#queryIntentActivities queryIntentActivities()} to get a list
151of activities capable of handling your {@link android.content.Intent}. If the returned {@link
152java.util.List} is not empty, you can safely use the intent. For example:</p>
153
154<pre>
155PackageManager packageManager = {@link android.content.Context#getPackageManager()};
156List<ResolveInfo> activities = packageManager.queryIntentActivities(intent,
157        PackageManager.MATCH_DEFAULT_ONLY);
158boolean isIntentSafe = activities.size() > 0;
159</pre>
160
161<p>If <code>isIntentSafe</code> is <code>true</code>, then at least one app will respond to
162the intent. If it is <code>false</code>, then there aren't any apps to handle the intent.</p>
163
164<p class="note"><strong>Note:</strong> You should perform this check when your activity first
165starts in case you need to disable the feature that uses the intent before the user attempts to use
166it. If you know of a specific app that can handle the intent, you can also provide a link for the
167user to download the app (see how to <a
168href="{@docRoot}distribute/tools/promote/linking.html">link to your product on Google
169Play</a>).</p>
170
171
172<h2 id="StartActivity">Start an Activity with the Intent</h2>
173
174<div class="figure" style="width:200px;margin-top:-10px">
175  <img src="{@docRoot}images/training/basics/intents-choice.png" alt="" />
176  <p class="img-caption"><strong>Figure 1.</strong> Example of the selection dialog that appears
177when more than one app can handle an intent.</p>
178</div>
179
180<p>Once you have created your {@link android.content.Intent} and set the extra info, call {@link
181android.app.Activity#startActivity startActivity()} to send it to the system. If the system
182identifies more than one activity that can handle the intent, it displays a dialog for the user to
183select which app to use, as shown in figure 1. If there is only one activity that handles the
184intent, the system immediately starts it.</p>
185
186<pre>
187startActivity(intent);
188</pre>
189
190<p>Here's a complete example that shows how to create an intent to view a map, verify that an
191app exists to handle the intent, then start it:</p>
192
193<pre>
194// Build the intent
195Uri location = Uri.parse("geo:0,0?q=1600+Amphitheatre+Parkway,+Mountain+View,+California");
196Intent mapIntent = new Intent(Intent.ACTION_VIEW, location);
197
198// Verify it resolves
199PackageManager packageManager = {@link android.content.Context#getPackageManager()};
200List&lt;ResolveInfo> activities = packageManager.queryIntentActivities(mapIntent, 0);
201boolean isIntentSafe = activities.size() > 0;
202
203// Start an activity if it's safe
204if (isIntentSafe) {
205    startActivity(mapIntent);
206}
207</pre>
208
209
210
211<h2 id="AppChooser">Show an App Chooser</h2>
212
213<div class="figure" style="width:200px;margin-top:-10px">
214  <img src="{@docRoot}images/training/basics/intent-chooser.png" alt="" />
215  <p class="img-caption"><strong>Figure 2.</strong> A chooser dialog.</p>
216</div>
217
218<p>Notice that when you start an activity by passing your {@link android.content.Intent} to {@link
219android.app.Activity#startActivity startActivity()} and there is more than one app that responds to
220the intent, the user can select which app to use by default (by selecting a checkbox at the bottom
221of the dialog; see figure 1). This is nice when performing an action for which the user
222generally wants to use the same app every time, such as when opening a web page (users
223likely use just one web browser) or taking a photo (users likely prefer one camera).</p>
224
225<p>However, if the action to be performed could be handled by multiple apps and the user might
226prefer a different app each time&mdash;such as a "share" action, for which users might have several
227apps through which they might share an item&mdash;you should explicitly show a chooser dialog
228as shown in figure 2. The chooser dialog
229forces the user to select which app to use for the action every time (the user cannot select a
230default app for the action).</p>
231
232<p>To show the chooser, create an {@link android.content.Intent} using {@link
233android.content.Intent#createChooser createChooser()} and pass it to {@link
234android.app.Activity#startActivity startActivity()}. For example:</p>
235
236<pre>
237Intent intent = new Intent(Intent.ACTION_SEND);
238...
239
240// Always use string resources for UI text.
241// This says something like "Share this photo with"
242String title = getResources().getString(R.string.chooser_title);
243// Create intent to show chooser
244Intent chooser = Intent.createChooser(intent, title);
245
246// Verify the intent will resolve to at least one activity
247if (intent.resolveActivity(getPackageManager()) != null) {
248    startActivity(chooser);
249}
250</pre>
251
252<p>This displays a dialog with a list of apps that respond to the intent passed to the {@link
253android.content.Intent#createChooser createChooser()} method and uses the supplied text as the
254dialog title.</p>
255
256
257
258