page.title=Sending the User to Another App page.tags=intents helpoutsWidget=true trainingnavtop=true @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 Simple Data</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 to 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, PackageManager.MATCH_DEFAULT_ONLY); 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/tools/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;margin-top:-10px"> <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;margin-top:-10px"> <img src="{@docRoot}images/training/basics/intent-chooser.png" alt="" /> <p class="img-caption"><strong>Figure 2.</strong> A chooser dialog.</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).</p> <p>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 as shown in figure 2. The chooser dialog 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().getString(R.string.chooser_title); // Create intent to show chooser Intent chooser = Intent.createChooser(intent, title); // Verify the intent will resolve to at least one activity if (intent.resolveActivity(getPackageManager()) != null) { 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>