An intent lets you start an activity in another app by describing an
action you'd like to perform, such as "view a map" or "take a
picture," in an Intent object. This type of intent
is called an implicit intent because it doesn't specify the app
component to start, but instead specifies an action and provides
some data with which to perform the action.
When you call startActivity()
or startActivityForResult() and pass it an implicit intent, the system
resolves
the intent to an app that can handle the intent and starts its
corresponding Activity. If there's more than one app
that can handle the intent, the system presents the user with a dialog to
pick which app to use.
This page describes several implicit intents that you can use to perform common actions, organized by the type of app that handles the intent. Each section also shows how you can create an intent filter to advertise your app's ability to perform the action.
Caution: If there are no apps on the device that can
receive an implicit intent, an app crashes when it calls startActivity(). To first verify that
an app exists to receive the intent, call resolveActivity() on your Intent object. If the result is non-null, there is at least
one app that can handle the intent, and it's safe to call startActivity(). If the result is
null, don't use the intent and, if possible, disable the
feature that invokes the intent.
If you're not familiar with how to create intents or intent filters, first read Intents and Intent Filters.
To learn how to fire the intents listed on this page from your development host, see the Verify intents with the Android Debug Bridge section.
Google Voice Actions fires some of the intents listed on this page in response to voice commands. For more information, see Get Started with System Voice Actions.
The following are common actions for alarm clock apps, including the information you need to create an intent filter to advertise your app's ability to perform each action.
To create a new alarm, use the ACTION_SET_ALARM
action and specify alarm details such as the time and message using the following extras.
Note: Only the hour, minutes, and message extras are available in Android 2.3 (API level 9) and lower. The other extras are available in higher versions of the platform.
ACTION_SET_ALARMEXTRA_HOUREXTRA_MINUTESEXTRA_MESSAGEEXTRA_DAYSArrayList including each week day on which this alarm
repeats. Each day must be declared with an integer from the Calendar
class, such as MONDAY.
For a one-time alarm, don't specify this extra.
EXTRA_RINGTONEcontent: URI specifying a ringtone to use with the alarm, or VALUE_RINGTONE_SILENT for no ringtone.
To use the default ringtone, don't specify this extra.
EXTRA_VIBRATEEXTRA_SKIP_UIExample intent:
fun createAlarm(message: String, hour: Int, minutes: Int) { val intent = Intent(AlarmClock.ACTION_SET_ALARM).apply { putExtra(AlarmClock.EXTRA_MESSAGE, message) putExtra(AlarmClock.EXTRA_HOUR, hour) putExtra(AlarmClock.EXTRA_MINUTES, minutes) } if (intent.resolveActivity(packageManager) != null) { startActivity(intent) } }
public void createAlarm(String message, int hour, int minutes) { Intent intent = new Intent(AlarmClock.ACTION_SET_ALARM) .putExtra(AlarmClock.EXTRA_MESSAGE, message) .putExtra(AlarmClock.EXTRA_HOUR, hour) .putExtra(AlarmClock.EXTRA_MINUTES, minutes); if (intent.resolveActivity(getPackageManager()) != null) { startActivity(intent); } }
To invoke the ACTION_SET_ALARM intent, your app must have the
SET_ALARM permission:
<uses-permission android:name="com.android.alarm.permission.SET_ALARM" />
Example intent filter:
<activity ...> <intent-filter> <action android:name="android.intent.action.SET_ALARM" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </activity>
To create a countdown timer, use the ACTION_SET_TIMER action and specify timer
details such as the duration using the following extras.
Note: This intent is available in Android 4.4 (API level 19) and higher.
ACTION_SET_TIMEREXTRA_LENGTHEXTRA_MESSAGEEXTRA_SKIP_UIExample intent:
fun startTimer(message: String, seconds: Int) { val intent = Intent(AlarmClock.ACTION_SET_TIMER).apply { putExtra(AlarmClock.EXTRA_MESSAGE, message) putExtra(AlarmClock.EXTRA_LENGTH, seconds) putExtra(AlarmClock.EXTRA_SKIP_UI, true) } if (intent.resolveActivity(packageManager) != null) { startActivity(intent) } }
public void startTimer(String message, int seconds) { Intent intent = new Intent(AlarmClock.ACTION_SET_TIMER) .putExtra(AlarmClock.EXTRA_MESSAGE, message) .putExtra(AlarmClock.EXTRA_LENGTH, seconds) .putExtra(AlarmClock.EXTRA_SKIP_UI, true); if (intent.resolveActivity(getPackageManager()) != null) { startActivity(intent); } }
To invoke the ACTION_SET_TIMER intent, your app must have the
SET_ALARM permission:
<uses-permission android:name="com.android.alarm.permission.SET_ALARM" />
Example intent filter:
<activity ...> <intent-filter> <action android:name="android.intent.action.SET_TIMER" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </activity>
To show the list of alarms, use the ACTION_SHOW_ALARMS
action.
Although not many apps invoke this intent, as it's primarily used by system apps, any app that behaves as an alarm clock can implement this intent filter and respond by showing the list of current alarms.
Note: This intent is available in Android 4.4 (API level 19) and higher.
ACTION_SHOW_ALARMSExample intent filter:
<activity ...> <intent-filter> <action android:name="android.intent.action.SHOW_ALARMS" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </activity>
Adding an event is a common action for calendar apps. Create an intent filter to advertise your app's ability to perform this action using the information in the following section.
To add a new event to the user's calendar, use the
ACTION_INSERT
action and specify the data URI using
Events.CONTENT_URI.
You can then specify various event details using the following extras.
ACTION_INSERTEvents.CONTENT_URI"vnd.android.cursor.dir/event"
EXTRA_EVENT_ALL_DAYEXTRA_EVENT_BEGIN_TIMEEXTRA_EVENT_END_TIMETITLEDESCRIPTIONEVENT_LOCATIONEXTRA_EMAILMany more event details can be specified using the constants defined in the
CalendarContract.EventsColumns class.
Example intent:
fun addEvent(title: String, location: String, begin: Long, end: Long) { val intent = Intent(Intent.ACTION_INSERT).apply { data = Events.CONTENT_URI putExtra(Events.TITLE, title) putExtra(Events.EVENT_LOCATION, location) putExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME, begin) putExtra(CalendarContract.EXTRA_EVENT_END_TIME, end) } if (intent.resolveActivity(packageManager) != null) { startActivity(intent) } }
public void addEvent(String title, String location, long begin, long end) { Intent intent = new Intent(Intent.ACTION_INSERT) .setData(Events.CONTENT_URI) .putExtra(Events.TITLE, title) .putExtra(Events.EVENT_LOCATION, location) .putExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME, begin) .putExtra(CalendarContract.EXTRA_EVENT_END_TIME, end); if (intent.resolveActivity(getPackageManager()) != null) { startActivity(intent); } }
Example intent filter:
<activity ...> <intent-filter> <action android:name="android.intent.action.INSERT" /> <data android:mimeType="vnd.android.cursor.dir/event" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </activity>
The following are common actions for camera apps, including the information you need to create an intent filter to advertise your app's ability to perform each action.
To open a camera app and receive the resulting photo or video, use the ACTION_IMAGE_CAPTURE or ACTION_VIDEO_CAPTURE action. Also specify the URI location where you'd
like the camera to save the photo or video, in the EXTRA_OUTPUT
extra.
ACTION_IMAGE_CAPTURE orACTION_VIDEO_CAPTUREEXTRA_OUTPUTUri object).When the camera app successfully returns
focus to your activity—in other words, your app receives the onActivityResult() callback—you
can access the photo or video at the URI you specified
with the EXTRA_OUTPUT value.
Note: When you use ACTION_IMAGE_CAPTURE
to capture a photo, the camera might also return a
downscaled copy, or thumbnail, of the photo in the result Intent, saved as a Bitmap in an extra field named
"data".
Example intent:
const val REQUEST_IMAGE_CAPTURE = 1 val locationForPhotos: Uri = ... fun capturePhoto(targetFilename: String) { val intent = Intent(MediaStore.ACTION_IMAGE_CAPTURE).apply { putExtra(MediaStore.EXTRA_OUTPUT, Uri.withAppendedPath(locationForPhotos, targetFilename)) } if (intent.resolveActivity(packageManager) != null) { startActivityForResult(intent, REQUEST_IMAGE_CAPTURE) } } override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent) { if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == Activity.RESULT_OK) { val thumbnail: Bitmap = data.getParcelableExtra("data") // Do other work with full size photo saved in locationForPhotos. ... } }
static final int REQUEST_IMAGE_CAPTURE = 1; static final Uri locationForPhotos; public void capturePhoto(String targetFilename) { Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.withAppendedPath(locationForPhotos, targetFilename)); if (intent.resolveActivity(getPackageManager()) != null) { startActivityForResult(intent, REQUEST_IMAGE_CAPTURE); } } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK) { Bitmap thumbnail = data.getParcelableExtra("data"); // Do other work with full size photo saved in locationForPhotos. ... } }
To do this when working on Android 12 (API level 31) or higher, refer to the following intent example.
Example intent:
val REQUEST_IMAGE_CAPTURE = 1 private fun dispatchTakePictureIntent() { val takePictureIntent = Intent(MediaStore.ACTION_IMAGE_CAPTURE) try { startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE) } catch (e: ActivityNotFoundException) { // Display error state to the user. } }
static final int REQUEST_IMAGE_CAPTURE = 1; private void dispatchTakePictureIntent() { Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); try { startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE); } catch (ActivityNotFoundException e) { // Display error state to the user. } } </section></div>
For more information about how to use this intent to capture a photo, including
how to create an appropriate Uri for the output location, read
Take photos or
Take videos.
Example intent filter:
<activity ...> <intent-filter> <action android:name="android.media.action.IMAGE_CAPTURE" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </activity>
When handling this intent, have your activity check for the EXTRA_OUTPUT extra in the incoming Intent, then save the captured image or video at the
location specified by that extra and call setResult() with an Intent that includes a compressed thumbnail in an extra
named "data".
To open a camera app in still image mode, use the INTENT_ACTION_STILL_IMAGE_CAMERA action.
INTENT_ACTION_STILL_IMAGE_CAMERAExample intent:
private fun dispatchTakePictureIntent() { val takePictureIntent = Intent(MediaStore.ACTION_IMAGE_CAPTURE) try { startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE) } catch (e: ActivityNotFoundException) { // Display error state to the user. } }
public void capturePhoto(String targetFilename) { Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.withAppendedPath(locationForPhotos, targetFilename)); if (intent.resolveActivity(getPackageManager()) != null) { startActivityForResult(intent, REQUEST_IMAGE_CAPTURE); } }
Example intent filter:
<activity ...> <intent-filter> <action android:name="android.media.action.STILL_IMAGE_CAMERA" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </activity>
To open a camera app in video mode, use the INTENT_ACTION_VIDEO_CAMERA action.
INTENT_ACTION_VIDEO_CAMERAExample intent:
fun capturePhoto() { val intent = Intent(MediaStore.INTENT_ACTION_VIDEO_CAMERA) if (intent.resolveActivity(packageManager) != null) { startActivityForResult(intent, REQUEST_IMAGE_CAPTURE) } }
public void capturePhoto() { Intent intent = new Intent(MediaStore.INTENT_ACTION_VIDEO_CAMERA); if (intent.resolveActivity(getPackageManager()) != null) { startActivityForResult(intent, REQUEST_IMAGE_CAPTURE); } }
Example intent filter:
<activity ...> <intent-filter> <action android:name="android.media.action.VIDEO_CAMERA" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </activity>
The following are common actions for contacts management apps, including the information you need to create an intent filter to advertise your app's ability to perform each action.
To have the user select a contact and provide your app access to all the contact information,
use the ACTION_PICK action and specify the MIME type to
Contacts.CONTENT_TYPE.
The result Intent delivered to your onActivityResult() callback contains the
content: URI pointing to the selected contact. The response grants
your app temporary permissions to read that contact using the Contacts Provider API, even if
your app doesn't include the READ_CONTACTS permission.
Tip: If you need access to only a specific piece of contact information, such as a phone number or email address, instead see the next section about how to select specific contact data.
ACTION_PICKContacts.CONTENT_TYPE
Example intent:
const val REQUEST_SELECT_CONTACT = 1 fun selectContact() { val intent = Intent(Intent.ACTION_PICK).apply { type = ContactsContract.Contacts.CONTENT_TYPE } if (intent.resolveActivity(packageManager) != null) { startActivityForResult(intent, REQUEST_SELECT_CONTACT) } } override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent) { if (requestCode == REQUEST_SELECT_CONTACT && resultCode == RESULT_OK) { val contactUri: Uri = data.data // Do something with the selected contact at contactUri. //... } }
static final int REQUEST_SELECT_CONTACT = 1; public void selectContact() { Intent intent = new Intent(Intent.ACTION_PICK); intent.setType(ContactsContract.Contacts.CONTENT_TYPE); if (intent.resolveActivity(getPackageManager()) != null) { startActivityForResult(intent, REQUEST_SELECT_CONTACT); } } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == REQUEST_SELECT_CONTACT && resultCode == RESULT_OK) { Uri contactUri = data.getData(); // Do something with the selected contact at contactUri. ... } }
For information about how to retrieve contact details once you have the contact URI, read Retrieve details for a contact.
When you retrieve the contact URI using this intent, you generally don't
need the
READ_CONTACTS
permission to read basic details for that contact, such as display name and
whether the contact is starred. However, if you're trying to
read more specific data about a given contact—such
as their phone number or email address—you need the READ_CONTACTS
permission.
To have the user select a specific piece of information from a contact, such as
a phone number, email address, or other data type, use the
ACTION_PICK action and specify the MIME type to one
of the following content types, such as
CommonDataKinds.Phone.CONTENT_TYPE to get the contact's phone number.
Note: In many cases, your app needs to have the
READ_CONTACTS
permission to view specific information about a particular contact.
If you need to retrieve only one type of data from a contact, this technique with a
CONTENT_TYPE from the
ContactsContract.CommonDataKinds classes is more efficient than
using the Contacts.CONTENT_TYPE, as shown in the preceding section. The result provides you direct
access to the desired data without requiring you to perform a more complex query to Contacts Provider.
The result Intent delivered to your onActivityResult() callback contains the
content: URI pointing to the selected contact data. The response grants
your app temporary permissions to read that contact data even if your app doesn't include the READ_CONTACTS permission.
ACTION_PICKCommonDataKinds.Phone.CONTENT_TYPECommonDataKinds.Email.CONTENT_TYPECommonDataKinds.StructuredPostal.CONTENT_TYPEOr one of many other CONTENT_TYPE values
under ContactsContract.
Example intent:
const val REQUEST_SELECT_PHONE_NUMBER = 1 fun selectContact() { // Start an activity for the user to pick a phone number from contacts. val intent = Intent(Intent.ACTION_PICK).apply { type = CommonDataKinds.Phone.CONTENT_TYPE } if (intent.resolveActivity(packageManager) != null) { startActivityForResult(intent, REQUEST_SELECT_PHONE_NUMBER) } } override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent) { if (requestCode == REQUEST_SELECT_PHONE_NUMBER && resultCode == Activity.RESULT_OK) { // Get the URI and query the content provider for the phone number. val contactUri: Uri = data.data val projection: Array<String> = arrayOf(CommonDataKinds.Phone.NUMBER) contentResolver.query(contactUri, projection, null, null, null).use { cursor -> // If the cursor returned is valid, get the phone number. if (cursor.moveToFirst()) { val numberIndex = cursor.getColumnIndex(CommonDataKinds.Phone.NUMBER) val number = cursor.getString(numberIndex) // Do something with the phone number. ... } } } }
static final int REQUEST_SELECT_PHONE_NUMBER = 1; public void selectContact() { // Start an activity for the user to pick a phone number from contacts. Intent intent = new Intent(Intent.ACTION_PICK); intent.setType(CommonDataKinds.Phone.CONTENT_TYPE); if (intent.resolveActivity(getPackageManager()) != null) { startActivityForResult(intent, REQUEST_SELECT_PHONE_NUMBER); } } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == REQUEST_SELECT_PHONE_NUMBER && resultCode == RESULT_OK) { // Get the URI and query the content provider for the phone number. Uri contactUri = data.getData(); String[] projection = new String[]{CommonDataKinds.Phone.NUMBER}; Cursor cursor = getContentResolver().query(contactUri, projection, null, null, null); // If the cursor returned is valid, get the phone number. if (cursor != null && cursor.moveToFirst()) { int numberIndex = cursor.getColumnIndex(CommonDataKinds.Phone.NUMBER); String number = cursor.getString(numberIndex); // Do something with the phone number. //... } } }
To display the details for a known contact, use the ACTION_VIEW
action and specify the contact with a content: URI as the intent data.
There are two primary ways to initially retrieve the contact's URI:
ACTION_PICK action
shown in the preceding section. This approach doesn't require any app permissions.READ_CONTACTS
permission.ACTION_VIEWcontent:<URI>Example intent:
fun viewContact(contactUri: Uri) { val intent = Intent(Intent.ACTION_VIEW, contactUri) if (intent.resolveActivity(packageManager) != null) { startActivity(intent) } }
public void viewContact(Uri contactUri) { Intent intent = new Intent(Intent.ACTION_VIEW, contactUri); if (intent.resolveActivity(getPackageManager()) != null) { startActivity(intent); } }
To edit a known contact, use the ACTION_EDIT
action, specify the contact with a content: URI
as the intent data, and include any known contact information in extras specified by
constants in ContactsContract.Intents.Insert.
There are two primary ways to initially retrieve the contact URI:
ACTION_PICK action
shown in the preceding section. This approach doesn't require any app permissions.READ_CONTACTS
permission.ACTION_EDITcontent:<URI>ContactsContract.Intents.Insert
so you can populate fields of the contact details.
Example intent:
fun editContact(contactUri: Uri, email: String) { val intent = Intent(Intent.ACTION_EDIT).apply { data = contactUri putExtra(ContactsContract.Intents.Insert.EMAIL, email) } if (intent.resolveActivity(packageManager) != null) { startActivity(intent) } }
public void editContact(Uri contactUri, String email) { Intent intent = new Intent(Intent.ACTION_EDIT); intent.setData(contactUri); intent.putExtra(Intents.Insert.EMAIL, email); if (intent.resolveActivity(getPackageManager()) != null) { startActivity(intent); } }
For more information about how to edit a contact, read Modify contacts using intents.
To insert a new contact, use the ACTION_INSERT action,
specify Contacts.CONTENT_TYPE as
the MIME type, and include any known contact information in extras specified by
constants in ContactsContract.Intents.Insert.
ACTION_INSERTContacts.CONTENT_TYPEContactsContract.Intents.Insert.
Example intent:
fun insertContact(name: String, email: String) { val intent = Intent(Intent.ACTION_INSERT).apply { type = ContactsContract.Contacts.CONTENT_TYPE putExtra(ContactsContract.Intents.Insert.NAME, name) putExtra(ContactsContract.Intents.Insert.EMAIL, email) } if (intent.resolveActivity(packageManager) != null) { startActivity(intent) } }
public void insertContact(String name, String email) { Intent intent = new Intent(Intent.ACTION_INSERT); intent.setType(Contacts.CONTENT_TYPE); intent.putExtra(Intents.Insert.NAME, name); intent.putExtra(Intents.Insert.EMAIL, email); if (intent.resolveActivity(getPackageManager()) != null) { startActivity(intent); } }
For more information about how to insert a contact, read Modify contacts using intents.
Composing an email with optional attachments is a common action for email apps. Create an intent filter to advertise your app's ability to perform this action using the information in the following section.
To compose an email, use one of the following actions based on whether you'll include attachments or not, and include email details such as the recipient and subject using the extra keys listed.
ACTION_SENDTO (for no attachment) orACTION_SEND (for one attachment) orACTION_SEND_MULTIPLE (for multiple attachments)"text/plain"
"*/*"
Intent.EXTRA_EMAILIntent.EXTRA_CCIntent.EXTRA_BCCIntent.EXTRA_SUBJECTIntent.EXTRA_TEXTIntent.EXTRA_STREAMUri pointing to the attachment.
If using the
ACTION_SEND_MULTIPLE
action, this instead is an
ArrayList containing
multiple Uri objects.Example intent:
fun composeEmail(addresses: Array<String>, subject: String, attachment: Uri) { val intent = Intent(Intent.ACTION_SEND).apply { type = "*/*" putExtra(Intent.EXTRA_EMAIL, addresses) putExtra(Intent.EXTRA_SUBJECT, subject) putExtra(Intent.EXTRA_STREAM, attachment) } if (intent.resolveActivity(packageManager) != null) { startActivity(intent) } }
public void composeEmail(String[] addresses, String subject, Uri attachment) { Intent intent = new Intent(Intent.ACTION_SEND); intent.setType("*/*"); intent.putExtra(Intent.EXTRA_EMAIL, addresses); intent.putExtra(Intent.EXTRA_SUBJECT, subject); intent.putExtra(Intent.EXTRA_STREAM, attachment); if (intent.resolveActivity(getPackageManager()) != null) { startActivity(intent); } }
If you want to make sure that your intent is handled only by an email app, and not a
text messaging or social app, then use the ACTION_SENDTO action
and include the "mailto:" data scheme as shown in the following example:
fun composeEmail(addresses: Array<String>, subject: String) { val intent = Intent(Intent.ACTION_SENDTO).apply { data = Uri.parse("mailto:") // Only email apps handle this. putExtra(Intent.EXTRA_EMAIL, addresses) putExtra(Intent.EXTRA_SUBJECT, subject) } if (intent.resolveActivity(packageManager) != null) { startActivity(intent) } }
public void composeEmail(String[] addresses, String subject) { Intent intent = new Intent(Intent.ACTION_SENDTO); intent.setData(Uri.parse("mailto:")); // Only email apps handle this. intent.putExtra(Intent.EXTRA_EMAIL, addresses); intent.putExtra(Intent.EXTRA_SUBJECT, subject); if (intent.resolveActivity(getPackageManager()) != null) { startActivity(intent); } }
Example intent filter:
<activity ...> <intent-filter> <action android:name="android.intent.action.SEND" /> <data android:type="*/*" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> <intent-filter> <action android:name="android.intent.action.SENDTO" /> <data android:scheme="mailto" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </activity>
The following are common actions for file storage apps, including the information you need to create an intent filter to advertise your app's ability to perform each action.
To request that the user select a file such as a document or photo and return a reference to
your app, use the ACTION_GET_CONTENT action and specify your desired
MIME type. The file reference returned to your app is transient to your activity's current
lifecycle, so if you want to access it later you must import a copy that you can read later.
This intent also lets the user create a new file in the process. For example, instead of selecting an existing photo, the user can capture a new photo with the camera.
The result intent delivered to your onActivityResult() method includes data with a URI pointing to the file.
The URI can be anything, such as an http: URI, file: URI, or content:
URI. However, if you'd like to restrict selectable files to only those that are accessible
from a content provider (a content: URI) and that are available as a file stream with
openFileDescriptor(),
add
the CATEGORY_OPENABLE category to your intent.
On Android 4.3 (API level 18) and higher,
you can also let the user select multiple files by adding
EXTRA_ALLOW_MULTIPLE to the intent, set to true.
You can then access each of the selected files in a ClipData
object returned by getClipData().
ACTION_GET_CONTENTEXTRA_ALLOW_MULTIPLE
EXTRA_LOCAL_ONLY
CATEGORY_OPENABLEopenFileDescriptor().Example intent to get a photo:
const val REQUEST_IMAGE_GET = 1 fun selectImage() { val intent = Intent(Intent.ACTION_GET_CONTENT).apply { type = "image/*" } if (intent.resolveActivity(packageManager) != null) { startActivityForResult(intent, REQUEST_IMAGE_GET) } } override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent) { if (requestCode == REQUEST_IMAGE_GET && resultCode == Activity.RESULT_OK) { val thumbnail: Bitmap = data.getParcelableExtra("data") val fullPhotoUri: Uri = data.data // Do work with photo saved at fullPhotoUri. ... } }
static final int REQUEST_IMAGE_GET = 1; public void selectImage() { Intent intent = new Intent(Intent.ACTION_GET_CONTENT); intent.setType("image/*"); if (intent.resolveActivity(getPackageManager()) != null) { startActivityForResult(intent, REQUEST_IMAGE_GET); } } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == REQUEST_IMAGE_GET && resultCode == RESULT_OK) { Bitmap thumbnail = data.getParcelable("data"); Uri fullPhotoUri = data.getData(); // Do work with photo saved at fullPhotoUri. ... } }
Example intent filter to return a photo:
<activity ...> <intent-filter> <action android:name="android.intent.action.GET_CONTENT" /> <data android:type="image/*" /> <category android:name="android.intent.category.DEFAULT" /> <!-- The OPENABLE category declares that the returned file is accessible from a content provider that supportsOpenableColumnsandContentResolver.openFileDescriptor(). --> <category android:name="android.intent.category.OPENABLE" /> </intent-filter> </activity>
Instead of retrieving a copy of a file that you must import to your app, by using the ACTION_GET_CONTENT action, when running on Android
4.4 or higher you can instead request to open a file that's managed by another app by
using the ACTION_OPEN_DOCUMENT action and specifying a MIME type.
To also let the user create a new document that your app can write to, use the ACTION_CREATE_DOCUMENT action instead.
For example, instead of
selecting from existing PDF documents, the ACTION_CREATE_DOCUMENT
intent lets users select where they'd like to create a new document, such as within another app
that manages the document's storage. Your app then receives the URI location of where it
can write the new document.
Whereas the intent delivered to your onActivityResult()
method from the ACTION_GET_CONTENT action might
return a URI of any type, the result intent from ACTION_OPEN_DOCUMENT
and ACTION_CREATE_DOCUMENT always specify the chosen file as a content: URI that's backed by a DocumentsProvider. You can open the
file with openFileDescriptor() and
query its details using columns from DocumentsContract.Document.
The returned URI grants your app long-term read access to the file, also possibly
with write access. The ACTION_OPEN_DOCUMENT action is
particularly useful when you want to read an existing file without making a copy into your app
or when you want to open and edit a file in place.
You can also let the user select multiple files by adding
EXTRA_ALLOW_MULTIPLE to the intent, set to true.
If the user selects just one item, then you can retrieve the item from getData().
If the user selects more than one item, then getData() returns null and you must instead
retrieve each item from a ClipData
object that is returned by getClipData().
Note: Your intent must specify a MIME type and
must declare the CATEGORY_OPENABLE category. If
appropriate, you can specify more than one MIME type by adding an array of MIME types with the
EXTRA_MIME_TYPES extra—if you do so, you must set the
primary MIME type in setType() to "*/*".
ACTION_OPEN_DOCUMENT orACTION_CREATE_DOCUMENTEXTRA_MIME_TYPES
setType() to "*/*".EXTRA_ALLOW_MULTIPLE
EXTRA_TITLE
ACTION_CREATE_DOCUMENT to specify
an initial filename.
EXTRA_LOCAL_ONLY
CATEGORY_OPENABLEopenFileDescriptor().Example intent to get a photo:
const val REQUEST_IMAGE_OPEN = 1 fun selectImage2() { val intent = Intent(Intent.ACTION_OPEN_DOCUMENT).apply { type = "image/*" addCategory(Intent.CATEGORY_OPENABLE) } // Only the system receives the ACTION_OPEN_DOCUMENT, so no need to test. startActivityForResult(intent, REQUEST_IMAGE_OPEN) } override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent) { if (requestCode == REQUEST_IMAGE_OPEN && resultCode == Activity.RESULT_OK) { val fullPhotoUri: Uri = data.data // Do work with full size photo saved at fullPhotoUri. ... } }
static final int REQUEST_IMAGE_OPEN = 1; public void selectImage() { Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT); intent.setType("image/*"); intent.addCategory(Intent.CATEGORY_OPENABLE); // Only the system receives the ACTION_OPEN_DOCUMENT, so no need to test. startActivityForResult(intent, REQUEST_IMAGE_OPEN); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == REQUEST_IMAGE_OPEN && resultCode == RESULT_OK) { Uri fullPhotoUri = data.getData(); // Do work with full size photo saved at fullPhotoUri. ... } }
Third-party apps can't respond to an intent with the
ACTION_OPEN_DOCUMENT action. Instead, the system receives this
intent and displays all the files available from various apps in a unified user interface.
To provide your app's files in this UI and let other apps open them, you must implement
a DocumentsProvider and include an intent filter for
PROVIDER_INTERFACE
("android.content.action.DOCUMENTS_PROVIDER"), as shown in the following example:
<provider ... android:grantUriPermissions="true" android:exported="true" android:permission="android.permission.MANAGE_DOCUMENTS"> <intent-filter> <action android:name="android.content.action.DOCUMENTS_PROVIDER" /> </intent-filter> </provider>
For more information about how to make the files managed by your app openable from other apps, read Open files using storage access framework.
Calling a car is a common local action. Create an intent filter to advertise your app's ability to perform this action using the information in the following section.
To call a taxi, use the
ACTION_RESERVE_TAXI_RESERVATION
action.
Note: Apps must ask for confirmation from the user before completing this action.
ACTION_RESERVE_TAXI_RESERVATIONExample intent:
fun callCar() { val intent = Intent(ReserveIntents.ACTION_RESERVE_TAXI_RESERVATION) if (intent.resolveActivity(packageManager) != null) { startActivity(intent) } }
public void callCar() { Intent intent = new Intent(ReserveIntents.ACTION_RESERVE_TAXI_RESERVATION); if (intent.resolveActivity(getPackageManager()) != null) { startActivity(intent); } }
Example intent filter:
<activity ...> <intent-filter> <action android:name="com.google.android.gms.actions.RESERVE_TAXI_RESERVATION" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </activity>
Showing a location on a map is a common action for map apps. Create an intent filter to advertise your app's ability to perform this action using the information in the following section.
To open a map, use the ACTION_VIEW action and specify
the location information in the intent data with one of the following schemes.
ACTION_VIEWgeo:latitude,longitude"geo:47.6,-122.3"
geo:latitude,longitude?z=zoom"geo:47.6,-122.3?z=11"
geo:0,0?q=lat,lng(label)Example: "geo:0,0?q=34.99,-106.61(Treasure)"
geo:0,0?q=my+street+addressExample: "geo:0,0?q=1600+Amphitheatre+Parkway%2C+CA"
Note: All strings passed in the geo URI must
be encoded. For example, the string 1st & Pike, Seattle becomes
1st%20%26%20Pike%2C%20Seattle. Spaces in the string are encoded with
%20 or replaced with the plus sign (+).
Example intent:
fun showMap(geoLocation: Uri) { val intent = Intent(Intent.ACTION_VIEW).apply { data = geoLocation } if (intent.resolveActivity(packageManager) != null) { startActivity(intent) } }
public void showMap(Uri geoLocation) { Intent intent = new Intent(Intent.ACTION_VIEW); intent.setData(geoLocation); if (intent.resolveActivity(getPackageManager()) != null) { startActivity(intent); } }
Example intent filter:
<activity ...> <intent-filter> <action android:name="android.intent.action.VIEW" /> <data android:scheme="geo" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </activity>
The following are common actions for music and video apps, including the information you need to create an intent filter to advertise your app's ability to perform each action.
To play a music file, use the ACTION_VIEW action and
specify the URI location of the file in the intent data.
ACTION_VIEWfile:<URI>
content:<URI>
http:<URL>
"audio/*"
"application/ogg"
"application/x-ogg"
"application/itunes"
Example intent:
fun playMedia(file: Uri) { val intent = Intent(Intent.ACTION_VIEW).apply { data = file } if (intent.resolveActivity(packageManager) != null) { startActivity(intent) } }
public void playMedia(Uri file) { Intent intent = new Intent(Intent.ACTION_VIEW); intent.setData(file); if (intent.resolveActivity(getPackageManager()) != null) { startActivity(intent); } }
Example intent filter:
<activity ...> <intent-filter> <action android:name="android.intent.action.VIEW" /> <data android:type="audio/*" /> <data android:type="application/ogg" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </activity>
To play music based on a search query, use the
INTENT_ACTION_MEDIA_PLAY_FROM_SEARCH intent. An app might fire
this intent in response to the user's voice command to play music. The receiving app for this
intent performs a search within its inventory to match existing content to the given query and
starts playing that content.
In this intent, include the EXTRA_MEDIA_FOCUS string
extra, which specifies the intended search mode. For example, the search mode can specify whether
the search is for an artist name or song name.
INTENT_ACTION_MEDIA_PLAY_FROM_SEARCHMediaStore.EXTRA_MEDIA_FOCUS (required)Indicates the search mode: whether the user is looking for a particular artist, album, song,
or playlist. Most search modes take additional extras. For example, if the user
is interested in listening to a particular song, the intent might have three additional extras:
the song title, the artist, and the album. This intent supports the following search modes for
each value of EXTRA_MEDIA_FOCUS:
Any - "vnd.android.cursor.item/*"
Play any music. The receiving app plays some music based on a smart choice, such as the last playlist the user listened to.
Additional extras:
QUERY (required): an empty string. This extra is always
provided for backward compatibility. Existing apps that don't know about search modes can
process this intent as an unstructured search.Unstructured - "vnd.android.cursor.item/*"
Play a particular song, album, or genre from an unstructured search query. Apps can generate an intent with this search mode when they can't identify the type of content the user wants to listen to. Use more specific search modes when possible.
Additional extras:
QUERY (required): a string that contains any combination
of the artist, the album, the song name, or the genre.Genre -
Audio.Genres.ENTRY_CONTENT_TYPE
Play music of a particular genre.
Additional extras:
"android.intent.extra.genre" (required) - The genre.QUERY (required): the genre. This extra is always provided
for backward compatibility. Existing apps that don't know about search modes can process
this intent as an unstructured search.Artist -
Audio.Artists.ENTRY_CONTENT_TYPE
Play music from a particular artist.
Additional extras:
EXTRA_MEDIA_ARTIST (required): the artist."android.intent.extra.genre": the genre.QUERY (required): a string that contains any combination of
the artist or the genre. This extra is always provided for backward compatibility.
Existing apps that don't know about search modes can process this intent as an unstructured
search.Album -
Audio.Albums.ENTRY_CONTENT_TYPE
Play music from a particular album.
Additional extras:
EXTRA_MEDIA_ALBUM (required): the album.EXTRA_MEDIA_ARTIST: the artist."android.intent.extra.genre": the genre.QUERY (required): a string that contains any combination of
the album or the artist. This extra is always provided for backward
compatibility. Existing apps that don't know about search modes can process this intent as an
unstructured search.Song - "vnd.android.cursor.item/audio"
Play a particular song.
Additional extras:
EXTRA_MEDIA_ALBUM: the album.EXTRA_MEDIA_ARTIST: the artist."android.intent.extra.genre": the genre.EXTRA_MEDIA_TITLE (required): the song name.QUERY (required): a string that contains any combination of
the album, the artist, the genre, or the title. This extra is always provided for
backward compatibility. Existing apps that don't know about search modes can process this
intent as an unstructured search.Playlist - Audio.Playlists.ENTRY_CONTENT_TYPE
Play a particular playlist or a playlist that matches some criteria specified by additional extras.
Additional extras:
EXTRA_MEDIA_ALBUM: the album.EXTRA_MEDIA_ARTIST: the artist."android.intent.extra.genre": the genre."android.intent.extra.playlist": the playlist.EXTRA_MEDIA_TITLE: the song name that the playlist is
based on.QUERY (required): a string that contains any combination
of the album, the artist, the genre, the playlist, or the title. This extra is always
provided for backward compatibility. Existing apps that don't know about search modes can
process this intent as an unstructured search.Example intent:
If the user wants to listen to music from a particular artist, a search app might generate the following intent:
fun playSearchArtist(artist: String) { val intent = Intent(MediaStore.INTENT_ACTION_MEDIA_PLAY_FROM_SEARCH).apply { putExtra(MediaStore.EXTRA_MEDIA_FOCUS, MediaStore.Audio.Artists.ENTRY_CONTENT_TYPE) putExtra(MediaStore.EXTRA_MEDIA_ARTIST, artist) putExtra(SearchManager.QUERY, artist) } if (intent.resolveActivity(packageManager) != null) { startActivity(intent) } }
public void playSearchArtist(String artist) { Intent intent = new Intent(MediaStore.INTENT_ACTION_MEDIA_PLAY_FROM_SEARCH); intent.putExtra(MediaStore.EXTRA_MEDIA_FOCUS, MediaStore.Audio.Artists.ENTRY_CONTENT_TYPE); intent.putExtra(MediaStore.EXTRA_MEDIA_ARTIST, artist); intent.putExtra(SearchManager.QUERY, artist); if (intent.resolveActivity(getPackageManager()) != null) { startActivity(intent); } }
Example intent filter:
<activity ...> <intent-filter> <action android:name="android.media.action.MEDIA_PLAY_FROM_SEARCH" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </activity>
When handling this intent in your activity, check the value of the
EXTRA_MEDIA_FOCUS extra in the incoming
Intent to determine the search mode. Once your activity has identified
the search mode, read the values of the additional extras for that particular search mode.
With this information, your app can then perform the search within its inventory to play the
content that matches the search query. This is shown in the following example.
override fun onCreate(savedInstanceState: Bundle?) { ... if (intent.action.compareTo(MediaStore.INTENT_ACTION_MEDIA_PLAY_FROM_SEARCH) == 0) { val mediaFocus: String? = intent.getStringExtra(MediaStore.EXTRA_MEDIA_FOCUS) val query: String? = intent.getStringExtra(SearchManager.QUERY) // Some of these extras might not be available depending on the search mode. val album: String? = intent.getStringExtra(MediaStore.EXTRA_MEDIA_ALBUM) val artist: String? = intent.getStringExtra(MediaStore.EXTRA_MEDIA_ARTIST) val genre: String? = intent.getStringExtra("android.intent.extra.genre") val playlist: String? = intent.getStringExtra("android.intent.extra.playlist") val title: String? = intent.getStringExtra(MediaStore.EXTRA_MEDIA_TITLE) // Determine the search mode and use the corresponding extras. when { mediaFocus == null -> { // 'Unstructured' search mode (backward compatible) playUnstructuredSearch(query) } mediaFocus.compareTo("vnd.android.cursor.item/*") == 0 -> { if (query?.isNotEmpty() == true) { // 'Unstructured' search mode. playUnstructuredSearch(query) } else { // 'Any' search mode. playResumeLastPlaylist() } } mediaFocus.compareTo(MediaStore.Audio.Genres.ENTRY_CONTENT_TYPE) == 0 -> { // 'Genre' search mode. playGenre(genre) } mediaFocus.compareTo(MediaStore.Audio.Artists.ENTRY_CONTENT_TYPE) == 0 -> { // 'Artist' search mode. playArtist(artist, genre) } mediaFocus.compareTo(MediaStore.Audio.Albums.ENTRY_CONTENT_TYPE) == 0 -> { // 'Album' search mode. playAlbum(album, artist) } mediaFocus.compareTo("vnd.android.cursor.item/audio") == 0 -> { // 'Song' search mode. playSong(album, artist, genre, title) } mediaFocus.compareTo(MediaStore.Audio.Playlists.ENTRY_CONTENT_TYPE) == 0 -> { // 'Playlist' search mode. playPlaylist(album, artist, genre, playlist, title) } } } }
protected void onCreate(Bundle savedInstanceState) { //... Intent intent = this.getIntent(); if (intent.getAction().compareTo(MediaStore.INTENT_ACTION_MEDIA_PLAY_FROM_SEARCH) == 0) { String mediaFocus = intent.getStringExtra(MediaStore.EXTRA_MEDIA_FOCUS); String query = intent.getStringExtra(SearchManager.QUERY); // Some of these extras might not be available depending on the search mode. String album = intent.getStringExtra(MediaStore.EXTRA_MEDIA_ALBUM); String artist = intent.getStringExtra(MediaStore.EXTRA_MEDIA_ARTIST); String genre = intent.getStringExtra("android.intent.extra.genre"); String playlist = intent.getStringExtra("android.intent.extra.playlist"); String title = intent.getStringExtra(MediaStore.EXTRA_MEDIA_TITLE); // Determine the search mode and use the corresponding extras. if (mediaFocus == null) { // 'Unstructured' search mode (backward compatible). playUnstructuredSearch(query); } else if (mediaFocus.compareTo("vnd.android.cursor.item/*") == 0) { if (query.isEmpty()) { // 'Any' search mode. playResumeLastPlaylist(); } else { // 'Unstructured' search mode. playUnstructuredSearch(query); } } else if (mediaFocus.compareTo(MediaStore.Audio.Genres.ENTRY_CONTENT_TYPE) == 0) { // 'Genre' search mode. playGenre(genre); } else if (mediaFocus.compareTo(MediaStore.Audio.Artists.ENTRY_CONTENT_TYPE) == 0) { // 'Artist' search mode. playArtist(artist, genre); } else if (mediaFocus.compareTo(MediaStore.Audio.Albums.ENTRY_CONTENT_TYPE) == 0) { // 'Album' search mode. playAlbum(album, artist); } else if (mediaFocus.compareTo("vnd.android.cursor.item/audio") == 0) { // 'Song' search mode. playSong(album, artist, genre, title); } else if (mediaFocus.compareTo(MediaStore.Audio.Playlists.ENTRY_CONTENT_TYPE) == 0) { // 'Playlist' search mode. playPlaylist(album, artist, genre, playlist, title); } } }
Creating a note is a common action for note-taking apps. Create an intent filter to advertise your app's ability to perform this action using the information in the following section.
To create a new note, use the
ACTION_CREATE_NOTE action and specify note details such as the subject and text using following extras.
Note: Apps must ask for confirmation from the user before completing this action.
ACTION_CREATE_NOTE
PLAIN_TEXT_TYPEEXTRA_NAME
EXTRA_TEXT
Example intent:
fun createNote(subject: String, text: String) { val intent = Intent(NoteIntents.ACTION_CREATE_NOTE).apply { putExtra(NoteIntents.EXTRA_NAME, subject) putExtra(NoteIntents.EXTRA_TEXT, text) } if (intent.resolveActivity(packageManager) != null) { startActivity(intent) } }
public void createNote(String subject, String text) { Intent intent = new Intent(NoteIntents.ACTION_CREATE_NOTE) .putExtra(NoteIntents.EXTRA_NAME, subject) .putExtra(NoteIntents.EXTRA_TEXT, text); if (intent.resolveActivity(getPackageManager()) != null) { startActivity(intent); } }
Example intent filter:
<activity ...> <intent-filter> <action android:name="com.google.android.gms.actions.CREATE_NOTE" /> <category android:name="android.intent.category.DEFAULT" /> <data android:mimeType="*/*" /> </intent-filter> </activity>
Initiating a call is a common action for phone apps. Create an intent filter to advertise your app's ability to perform this action using the information in the following section.
To open the phone app and dial a phone number, use the ACTION_DIAL action and specify a phone number using
the following URI scheme. When the phone app opens, it displays the phone number,
and the user must tap the Call button to begin the phone call.
To place a phone call directly, use the ACTION_CALL action
and specify a phone number using the following URI scheme. When the phone app opens, it
begins the phone call. The user doesn't need to tap the Call button.
The ACTION_CALL action requires that you add the
CALL_PHONE permission to your manifest file:
<uses-permission android:name="android.permission.CALL_PHONE" />
ACTION_DIAL - Opens the dialer or phone app.ACTION_CALL - Places a phone call (requires the
CALL_PHONE permission)tel:<phone-number>voicemail:<phone-number>Valid telephone numbers are those defined in the IETF RFC 3966. Valid examples include the following:
tel:2125551212 tel:(212) 555 1212The Phone app's dialer is good at normalizing schemes, such as
telephone numbers. So the scheme described isn't strictly required in the
Uri.parse() method.
However, if you haven't tried a scheme or are unsure whether it
can be handled, use the Uri.fromParts()
method instead.
Example intent:
fun dialPhoneNumber(phoneNumber: String) { val intent = Intent(Intent.ACTION_DIAL).apply { data = Uri.parse("tel:$phoneNumber") } if (intent.resolveActivity(packageManager) != null) { startActivity(intent) } }
public void dialPhoneNumber(String phoneNumber) { Intent intent = new Intent(Intent.ACTION_DIAL); intent.setData(Uri.parse("tel:" + phoneNumber)); if (intent.resolveActivity(getPackageManager()) != null) { startActivity(intent); } }
The following are common actions for search apps, including the information you need to create an intent filter to advertise your app's ability to perform each action.
To support search within the context of your app, declare an intent filter in your app with
the SEARCH_ACTION action, as shown in the following intent filter example.
Note: We don't recommend using SEARCH_ACTION for app search.
Instead, implement the
GET_THING
action to leverage Google Assistant's built-in support for in-app search. For more information, see
the Google Assistant
App Actions documentation.
"com.google.android.gms.actions.SEARCH_ACTION"QUERYExample intent filter:
<activity android:name=".SearchActivity"> <intent-filter> <action android:name="com.google.android.gms.actions.SEARCH_ACTION"/> <category android:name="android.intent.category.DEFAULT"/> </intent-filter> </activity>
To initiate a web search, use the ACTION_WEB_SEARCH action
and specify the search string in the
SearchManager.QUERY extra.
ACTION_WEB_SEARCHSearchManager.QUERYExample intent:
fun searchWeb(query: String) { val intent = Intent(Intent.ACTION_WEB_SEARCH).apply { putExtra(SearchManager.QUERY, query) } if (intent.resolveActivity(packageManager) != null) { startActivity(intent) } }
public void searchWeb(String query) { Intent intent = new Intent(Intent.ACTION_WEB_SEARCH); intent.putExtra(SearchManager.QUERY, query); if (intent.resolveActivity(getPackageManager()) != null) { startActivity(intent); } }
To open a screen in the system Settings app when your app requires the user to change something, use one of the following intent actions:
ACTION_SETTINGSACTION_WIRELESS_SETTINGSACTION_AIRPLANE_MODE_SETTINGSACTION_WIFI_SETTINGSACTION_APN_SETTINGSACTION_BLUETOOTH_SETTINGSACTION_DATE_SETTINGSACTION_LOCALE_SETTINGSACTION_INPUT_METHOD_SETTINGSACTION_DISPLAY_SETTINGSACTION_SECURITY_SETTINGSACTION_LOCATION_SOURCE_SETTINGSACTION_INTERNAL_STORAGE_SETTINGSACTION_MEMORY_CARD_SETTINGSFor additional settings screens that are available, see the Settings documentation .
Example intent:
fun openWifiSettings() { val intent = Intent(Settings.ACTION_WIFI_SETTINGS) if (intent.resolveActivity(packageManager) != null) { startActivity(intent) } }
public void openWifiSettings() { Intent intent = new Intent(Settings.ACTION_WIFI_SETTINGS); if (intent.resolveActivity(getPackageManager()) != null) { startActivity(intent); } }
Composing an SMS/MMS message with an attachment is a common action for text messaging apps. Create an intent filter to advertise your app's ability to perform this action using the information in the following section.
To initiate an SMS or MMS text message, use one of the following intent actions and specify message details such as the phone number, subject, and message body using the following extra keys.
ACTION_SENDTO orACTION_SEND orACTION_SEND_MULTIPLEsms:<phone_number>
smsto:<phone_number>
mms:<phone_number>
mmsto:<phone_number>
These schemes are all handled the same way.
"text/plain"
"image/*"
"video/*"
"subject""sms_body"EXTRA_STREAMUri pointing to the
image or video to attach. If using the ACTION_SEND_MULTIPLE action,
this extra is an ArrayList of
Uri objects pointing to the images or videos to attach.Example intent:
fun composeMmsMessage(message: String, attachment: Uri) { val intent = Intent(Intent.ACTION_SENDTO).apply { type = HTTP.PLAIN_TEXT_TYPE putExtra("sms_body", message) putExtra(Intent.EXTRA_STREAM, attachment) } if (intent.resolveActivity(packageManager) != null) { startActivity(intent) } }
public void composeMmsMessage(String message, Uri attachment) { Intent intent = new Intent(Intent.ACTION_SENDTO); intent.setType(HTTP.PLAIN_TEXT_TYPE); intent.putExtra("sms_body", message); intent.putExtra(Intent.EXTRA_STREAM, attachment); if (intent.resolveActivity(getPackageManager()) != null) { startActivity(intent); } }
If you want to make sure that your intent is handled only by a text messaging app, and not other
email or social apps, then use the ACTION_SENDTO action
and include the "smsto:" data scheme as shown in the following example:
fun composeMmsMessage(message: String, attachment: Uri) { val intent = Intent(Intent.ACTION_SEND).apply { data = Uri.parse("smsto:") // Only SMS apps respond to this. putExtra("sms_body", message) putExtra(Intent.EXTRA_STREAM, attachment) } if (intent.resolveActivity(packageManager) != null) { startActivity(intent) } }
public void composeMmsMessage(String message, Uri attachment) { Intent intent = new Intent(Intent.ACTION_SEND); intent.setData(Uri.parse("smsto:")); // Only SMS apps respond to this. intent.putExtra("sms_body", message); intent.putExtra(Intent.EXTRA_STREAM, attachment); if (intent.resolveActivity(getPackageManager()) != null) { startActivity(intent); } }
Example intent filter:
<activity ...> <intent-filter> <action android:name="android.intent.action.SEND" /> <data android:type="text/plain" /> <data android:type="image/*" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </activity>
Note: If you're developing an SMS/MMS messaging app, you must
implement intent filters for several additional actions in order to be available as the
default SMS app on Android 4.4 and higher. For more information, see the documentation
at Telephony.
Loading a web URL is a common action for web browser apps. Create an intent filter to advertise your app's ability to perform this action using the information in the following section.
To open a web page, use the ACTION_VIEW action
and specify the web URL in the intent data.
ACTION_VIEWhttp:<URL>https:<URL>"text/plain"
"text/html"
"application/xhtml+xml"
"application/vnd.wap.xhtml+xml"
Example intent:
fun openWebPage(url: String) { val webpage: Uri = Uri.parse(url) val intent = Intent(Intent.ACTION_VIEW, webpage) if (intent.resolveActivity(packageManager) != null) { startActivity(intent) } }
public void openWebPage(String url) { Uri webpage = Uri.parse(url); Intent intent = new Intent(Intent.ACTION_VIEW, webpage); if (intent.resolveActivity(getPackageManager()) != null) { startActivity(intent); } }
Example intent filter:
<activity ...> <intent-filter> <action android:name="android.intent.action.VIEW" /> <!-- Include the host attribute if you want your app to respond only to URLs with your app's domain. --> <data android:scheme="http" android:host="www.example.com" /> <category android:name="android.intent.category.DEFAULT" /> <!-- The BROWSABLE category is required to get links from web pages. --> <category android:name="android.intent.category.BROWSABLE" /> </intent-filter> </activity>
Tip: If your Android app provides functionality similar to your web site, include an intent filter for URLs that point to your web site. Then, if users have your app installed, links from emails or other web pages pointing to your web site open your Android app instead of your web page. Learn more in Handling Android App Links.
Starting in Android 12 (API level 31), a generic web intent resolves to an activity in your app only if your app is approved for the specific domain contained in that web intent. If your app isn't approved for the domain, the web intent resolves to the user's default browser app instead.
To verify that your app responds to the intents that you want to support, you can use the
adb tool to fire specific intents by doing
the following:
adb:
adb shell am start -a <ACTION> -t <MIME_TYPE> -d <DATA> \ -e <EXTRA_NAME> <EXTRA_VALUE> -n <ACTIVITY>
For example:
adb shell am start -a android.intent.action.DIAL \ -d tel:555-5555 -n org.example.MyApp/.MyActivity
For more information, see Issue shell commands.
Content and code samples on this page are subject to the licenses described in the Content License. Java and OpenJDK are trademarks or registered trademarks of Oracle and/or its affiliates.
Last updated 2026-10-28 UTC.