blob: 221e31bd7718fb3ddfa78677d9c390cad18f8dc6 [file] [log] [blame]
page.title=Allowing Other Apps to Start Your Activity
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="#AddIntentFilter">Add an Intent Filter</a></li>
<li><a href="#HandleIntent">Handle the Intent in Your Activity</a></li>
<li><a href="#ReturnResult">Return a Result</a></li>
</ol>
<h2>You should also read</h2>
<ul>
<li><a href="{@docRoot}training/sharing/index.html">Sharing Simple Data</a></li>
<li><a href="{@docRoot}training/secure-file-sharing/index.html">Sharing Files</a>
</ul>
</div>
</div>
<p>The previous two lessons focused on one side of the story: starting another app's activity from
your app. But if your app can perform an action that might be useful to another app,
your app should be prepared to respond to action requests from other apps. For instance, if you
build a social app that can share messages or photos with the user's friends, it's in your best
interest to support the {@link android.content.Intent#ACTION_SEND} intent so users can initiate a
"share" action from another app and launch your app to perform the action.</p>
<p>To allow other apps to start your activity, you need to add an <a
href="{@docRoot}guide/topics/manifest/intent-filter-element.html">{@code &lt;intent-filter>}</a>
element in your manifest file for the corresponding <a
href="{@docRoot}guide/topics/manifest/activity-element.html">{@code &lt;activity>}</a> element.</p>
<p>When your app is installed on a device, the system identifies your intent
filters and adds the information to an internal catalog of intents supported by all installed apps.
When an app calls {@link android.app.Activity#startActivity
startActivity()} or {@link android.app.Activity#startActivityForResult startActivityForResult()},
with an implicit intent, the system finds which activity (or activities) can respond to the
intent.</p>
<h2 id="AddIntentFilter">Add an Intent Filter</h2>
<p>In order to properly define which intents your activity can handle, each intent filter you add
should be as specific as possible in terms of the type of action and data the activity
accepts.</p>
<p>The system may send a given {@link android.content.Intent} to an activity if that activity has
an intent filter fulfills the following criteria of the {@link android.content.Intent} object:</p>
<dl>
<dt>Action</dt>
<dd>A string naming the action to perform. Usually one of the platform-defined values such
as {@link android.content.Intent#ACTION_SEND} or {@link android.content.Intent#ACTION_VIEW}.
<p>Specify this in your intent filter with the <a
href="{@docRoot}guide/topics/manifest/action-element.html">{@code &lt;action>}</a> element.
The value you specify in this element must be the full string name for the action, instead of the
API constant (see the examples below).</p></dd>
<dt>Data</dt>
<dd>A description of the data associated with the intent.
<p>Specify this in your intent filter with the <a
href="{@docRoot}guide/topics/manifest/data-element.html">{@code &lt;data>}</a> element. Using one
or more attributes in this element, you can specify just the MIME type, just a URI prefix,
just a URI scheme, or a combination of these and others that indicate the data type
accepted.</p>
<p class="note"><strong>Note:</strong> If you don't need to declare specifics about the data
{@link android.net.Uri} (such as when your activity handles to other kind of "extra" data, instead
of a URI), you should specify only the {@code android:mimeType} attribute to declare the type of
data your activity handles, such as {@code text/plain} or {@code image/jpeg}.</p>
</dd>
<dt>Category</dt>
<dd>Provides an additional way to characterize the activity handling the intent, usually related
to the user gesture or location from which it's started. There are several different categories
supported by the system, but most are rarely used. However, all implicit intents are defined with
{@link android.content.Intent#CATEGORY_DEFAULT} by default.
<p>Specify this in your intent filter with the <a
href="{@docRoot}guide/topics/manifest/category-element.html">{@code &lt;category>}</a>
element.</p></dd>
</dl>
<p>In your intent filter, you can declare which criteria your activity accepts
by declaring each of them with corresponding XML elements nested in the <a
href="{@docRoot}guide/topics/manifest/intent-filter-element.html">{@code &lt;intent-filter>}</a>
element.</p>
<p>For example, here's an activity with an intent filter that handles the {@link
android.content.Intent#ACTION_SEND} intent when the data type is either text or an image:</p>
<pre>
&lt;activity android:name="ShareActivity">
&lt;intent-filter>
&lt;action android:name="android.intent.action.SEND"/>
&lt;category android:name="android.intent.category.DEFAULT"/>
&lt;data android:mimeType="text/plain"/>
&lt;data android:mimeType="image/*"/>
&lt;/intent-filter>
&lt;/activity>
</pre>
<p>Each incoming intent specifies only one action and one data type, but it's OK to declare multiple
instances of the <a href="{@docRoot}guide/topics/manifest/action-element.html">{@code
&lt;action>}</a>, <a href="{@docRoot}guide/topics/manifest/category-element.html">{@code
&lt;category>}</a>, and <a href="{@docRoot}guide/topics/manifest/data-element.html">{@code
&lt;data>}</a> elements in each
<a href="{@docRoot}guide/topics/manifest/intent-filter-element.html">{@code
&lt;intent-filter>}</a>.</p>
<p>If any two pairs of action and data are mutually exclusive in
their behaviors, you should create separate intent filters to specify which actions are acceptable
when paired with which data types.</p>
<p>For example, suppose your activity handles both text and images for both the {@link
android.content.Intent#ACTION_SEND} and {@link
android.content.Intent#ACTION_SENDTO} intents. In this case, you must define two separate
intent filters for the two actions because a {@link
android.content.Intent#ACTION_SENDTO} intent must use the data {@link android.net.Uri} to specify
the recipient's address using the {@code send} or {@code sendto} URI scheme. For example:</p>
<pre>
&lt;activity android:name="ShareActivity">
&lt;!-- filter for sending text; accepts SENDTO action with sms URI schemes -->
&lt;intent-filter>
&lt;action android:name="android.intent.action.SENDTO"/>
&lt;category android:name="android.intent.category.DEFAULT"/>
&lt;data android:scheme="sms" />
&lt;data android:scheme="smsto" />
&lt;/intent-filter>
&lt;!-- filter for sending text or images; accepts SEND action and text or image data -->
&lt;intent-filter>
&lt;action android:name="android.intent.action.SEND"/>
&lt;category android:name="android.intent.category.DEFAULT"/>
&lt;data android:mimeType="image/*"/>
&lt;data android:mimeType="text/plain"/>
&lt;/intent-filter>
&lt;/activity>
</pre>
<p class="note"><strong>Note:</strong> In order to receive implicit intents, you must include 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 as if they
declared the {@link android.content.Intent#CATEGORY_DEFAULT} category. If you do not declare it
in your intent filter, no implicit intents will resolve to your activity.</p>
<p>For more information about sending and receiving {@link android.content.Intent#ACTION_SEND}
intents that perform social sharing behaviors, see the lesson about <a
href="{@docRoot}training/sharing/receive.html">Receiving Simple Data from Other Apps</a>.</p>
<h2 id="HandleIntent">Handle the Intent in Your Activity</h2>
<p>In order to decide what action to take in your activity, you can read the {@link
android.content.Intent} that was used to start it.</p>
<p>As your activity starts, call {@link android.app.Activity#getIntent()} to retrieve the
{@link android.content.Intent} that started the activity. You can do so at any time during the
lifecycle of the activity, but you should generally do so during early callbacks such as
{@link android.app.Activity#onCreate onCreate()} or {@link android.app.Activity#onStart()}.</p>
<p>For example:</p>
<pre>
&#64;Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// Get the intent that started this activity
Intent intent = getIntent();
Uri data = intent.getData();
// Figure out what to do based on the intent type
if (intent.getType().indexOf("image/") != -1) {
// Handle intents with image data ...
} else if (intent.getType().equals("text/plain")) {
// Handle intents with text ...
}
}
</pre>
<h2 id="ReturnResult">Return a Result</h2>
<p>If you want to return a result to the activity that invoked yours, simply call {@link
android.app.Activity#setResult(int,Intent) setResult()} to specify the result code and result {@link
android.content.Intent}. When your operation is done and the user should return to the original
activity, call {@link android.app.Activity#finish()} to close (and destroy) your activity. For
example:</p>
<pre>
// Create intent to deliver some kind of result data
Intent result = new Intent("com.example.RESULT_ACTION", Uri.parse("content://result_uri");
setResult(Activity.RESULT_OK, result);
finish();
</pre>
<p>You must always specify a result code with the result. Generally, it's either {@link
android.app.Activity#RESULT_OK} or {@link android.app.Activity#RESULT_CANCELED}. You can then
provide additional data with an {@link android.content.Intent}, as necessary.</p>
<p class="note"><strong>Note:</strong> The result is set to {@link
android.app.Activity#RESULT_CANCELED} by default. So, if the user presses the <em>Back</em>
button before completing the action and before you set the result, the original activity receives
the "canceled" result.</p>
<p>If you simply need to return an integer that indicates one of several result options, you can set
the result code to any value higher than 0. If you use the result code to deliver an integer and you
have no need to include the {@link android.content.Intent}, you can call {@link
android.app.Activity#setResult(int) setResult()} and pass only a result code. For example:</p>
<pre>
setResult(RESULT_COLOR_RED);
finish();
</pre>
<p>In this case, there might be only a handful of possible results, so the result code is a locally
defined integer (greater than 0). This works well when you're returning a result to an activity
in your own app, because the activity that receives the result can reference the public
constant to determine the value of the result code.</p>
<p class="note"><strong>Note:</strong> There's no need to check whether your activity was started
with {@link
android.app.Activity#startActivity startActivity()} or {@link
android.app.Activity#startActivityForResult startActivityForResult()}. Simply call {@link
android.app.Activity#setResult(int,Intent) setResult()} if the intent that started your activity
might expect a result. If the originating activity had called {@link
android.app.Activity#startActivityForResult startActivityForResult()}, then the system delivers it
the result you supply to {@link android.app.Activity#setResult(int,Intent) setResult()}; otherwise,
the result is ignored.</p>