Home | History | Annotate | Download | only in intents
      1 page.title=Sending the User to Another App
      2 page.tags=intents
      3 helpoutsWidget=true
      4 
      5 trainingnavtop=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
     30 based on an "action" it would like to perform. For example, if
     31 your app has the address of a business that you'd like to show on a map, you don't have to build
     32 an activity in your app that shows a map. Instead, you can create a request to view the address
     33 using an {@link android.content.Intent}. The Android system then starts an app that's able to show
     34 the address on a map.</p>
     35 
     36 <p>As explained in the first class, <a href="{@docRoot}training/basics/firstapp/index.html">Building
     37 Your First App</a>, you must use intents to navigate between activities in your own app. You
     38 generally do so with an <em>explicit intent</em>, which defines the exact class name of the
     39 component you want to start. However, when you want to have a separate app perform an action, such
     40 as "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
     43 to 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
     50 action 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
     52 with the action, such as the address you want to view, or the email message you want to send.
     53 Depending on the intent you want to create, the data might be a {@link android.net.Uri},
     54 one 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
     57 android.content.Intent#Intent(String,Uri) Intent()} constructor you can use to define the action and
     58 data.</p>
     59 
     60 <p>For example, here's how to create an intent to initiate a phone call using the {@link
     61 android.net.Uri} data to specify the telephone number:</p>
     62 
     63 <pre>
     64 Uri number = Uri.parse("tel:5551234");
     65 Intent 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
     69 startActivity()}, 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
     72 pairs:</p>
     73 
     74 <ul>
     75   <li>View a map:
     76 <pre>
     77 // Map point based on address
     78 Uri 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
     81 Intent mapIntent = new Intent(Intent.ACTION_VIEW, location);
     82 </pre>
     83   </li>
     84   <li>View a web page:
     85 <pre>
     86 Uri webpage = Uri.parse("http://www.android.com");
     87 Intent 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,
     93 such as a string. You can add one or more pieces of extra data using the various {@link
     94 android.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
     98 intent, you should usually use {@link android.content.Intent#setType setType()} to specify the type
     99 of data associated with the intent. Setting the MIME type further specifies which kinds of
    100 activities 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>
    107 Intent emailIntent = new Intent(Intent.ACTION_SEND);
    108 // The intent does not have a URI, so declare the "text/plain" MIME type
    109 emailIntent.setType(HTTP.PLAIN_TEXT_TYPE);
    110 emailIntent.putExtra(Intent.EXTRA_EMAIL, new String[] {"jon (a] example.com"}); // recipients
    111 emailIntent.putExtra(Intent.EXTRA_SUBJECT, "Email subject");
    112 emailIntent.putExtra(Intent.EXTRA_TEXT, "Email message text");
    113 emailIntent.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>
    119 Intent calendarIntent = new Intent(Intent.ACTION_INSERT, Events.CONTENT_URI);
    120 Calendar beginTime = Calendar.getInstance().set(2012, 0, 19, 7, 30);
    121 Calendar endTime = Calendar.getInstance().set(2012, 0, 19, 10, 30);
    122 calendarIntent.putExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME, beginTime.getTimeInMillis());
    123 calendarIntent.putExtra(CalendarContract.EXTRA_EVENT_END_TIME, endTime.getTimeInMillis());
    124 calendarIntent.putExtra(Events.TITLE, "Ninja class");
    125 calendarIntent.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
    128 level 14 and higher.</p>
    129   </li>
    130 </ul>
    131 
    132 <p class="note"><strong>Note:</strong> It's important that you define your {@link
    133 android.content.Intent} to be as specific as possible. For example, if you want to display an image
    134 using 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
    136 triggered 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
    143 built-in apps (such as the Phone, Email, or Calendar app), you should always include a
    144 verification step before invoking an intent.</p>
    145 
    146 <p class="caution"><strong>Caution:</strong> If you invoke an intent and there is no app
    147 available 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
    150 android.content.pm.PackageManager#queryIntentActivities queryIntentActivities()} to get a list
    151 of activities capable of handling your {@link android.content.Intent}. If the returned {@link
    152 java.util.List} is not empty, you can safely use the intent. For example:</p>
    153 
    154 <pre>
    155 PackageManager packageManager = {@link android.content.Context#getPackageManager()};
    156 List<ResolveInfo> activities = packageManager.queryIntentActivities(intent,
    157         PackageManager.MATCH_DEFAULT_ONLY);
    158 boolean 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
    162 the 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
    165 starts in case you need to disable the feature that uses the intent before the user attempts to use
    166 it. If you know of a specific app that can handle the intent, you can also provide a link for the
    167 user to download the app (see how to <a
    168 href="{@docRoot}distribute/tools/promote/linking.html">link to your product on Google
    169 Play</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
    177 when 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
    181 android.app.Activity#startActivity startActivity()} to send it to the system. If the system
    182 identifies more than one activity that can handle the intent, it displays a dialog for the user to
    183 select which app to use, as shown in figure 1. If there is only one activity that handles the
    184 intent, the system immediately starts it.</p>
    185 
    186 <pre>
    187 startActivity(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
    191 app exists to handle the intent, then start it:</p>
    192 
    193 <pre>
    194 // Build the intent
    195 Uri location = Uri.parse("geo:0,0?q=1600+Amphitheatre+Parkway,+Mountain+View,+California");
    196 Intent mapIntent = new Intent(Intent.ACTION_VIEW, location);
    197 
    198 // Verify it resolves
    199 PackageManager packageManager = {@link android.content.Context#getPackageManager()};
    200 List&lt;ResolveInfo> activities = packageManager.queryIntentActivities(mapIntent, 0);
    201 boolean isIntentSafe = activities.size() > 0;
    202 
    203 // Start an activity if it's safe
    204 if (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
    219 android.app.Activity#startActivity startActivity()} and there is more than one app that responds to
    220 the intent, the user can select which app to use by default (by selecting a checkbox at the bottom
    221 of the dialog; see figure 1). This is nice when performing an action for which the user
    222 generally wants to use the same app every time, such as when opening a web page (users
    223 likely 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
    226 prefer a different app each time&mdash;such as a "share" action, for which users might have several
    227 apps through which they might share an item&mdash;you should explicitly show a chooser dialog
    228 as shown in figure 2. The chooser dialog
    229 forces the user to select which app to use for the action every time (the user cannot select a
    230 default app for the action).</p>
    231 
    232 <p>To show the chooser, create an {@link android.content.Intent} using {@link
    233 android.content.Intent#createChooser createChooser()} and pass it to {@link
    234 android.app.Activity#startActivity startActivity()}. For example:</p>
    235 
    236 <pre>
    237 Intent 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"
    242 String title = getResources().getString(R.string.chooser_title);
    243 // Create intent to show chooser
    244 Intent chooser = Intent.createChooser(intent, title);
    245 
    246 // Verify the intent will resolve to at least one activity
    247 if (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
    253 android.content.Intent#createChooser createChooser()} method and uses the supplied text as the
    254 dialog title.</p>
    255 
    256 
    257 
    258