編輯:關於Android編程
Intent的真正強大之處在於它的隱式Intent,隱式Intent需要配合Intent-filters使用,有關這方面的概念和知識,您可以參考我翻譯的官方文檔:《Android官方文檔之App Components(Intents and Intent Filters)》。
隱式Intent足夠強大,以至於系統提供了大量的Intent方便開發者啟動系統應用程序,本文將介紹一些常用的隱式Intent、以及如何自定義intent-filters以匹配隱式intent。
如需閱讀官方原文,您可以點擊這個鏈接:《Common Intents》
下面將按照啟動的目標組件類別介紹隱式Intent:
要啟動鬧鐘activity,可以這樣設定Intent:
Action:ACTION_SET_ALARM
Data URI:空
MIME Type:空
Extras:
示例:
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);
}
}
若為Intent指定的action為ACTION_SET_ALARM,則需要在manifest中配置如下權限:
<uses-permission android:name="com.android.alarm.permission.SET_ALARM" />
可以響應該Intent的intent-filter如下:
...>
"android.intent.action.SET_ALARM" />
"android.intent.category.DEFAULT" />
!請注意:該Intent只兼容Android4.4 (API level 19) 及以上版本的設備。
要啟動計時器,可以這樣設定Intent:
Action:ACTION_SET_TIMER
Data URI:空
MIME Type:空
Extras:
示例:
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);
}
}
若為Intent指定的action為ACTION_SET_TIMER,則需要在manifest中配置如下權限:
<uses-permission android:name="com.android.alarm.permission.SET_ALARM" />
可以響應該Intent的intent-filter如下:
...>
"android.intent.action.SET_TIMER" />
"android.intent.category.DEFAULT" />
!請注意:該Intent只兼容 Android 4.4 (API level 19) 及以上版本的設備。
示例:
...>
"android.intent.action.SHOW_ALARMS" />
"android.intent.category.DEFAULT" />
Action:ACTION_INSERT
Data URI:Events.CONTENT_URI
MIME Type:”vnd.android.cursor.dir/event”
Extras:
示例:
public void addEvent(String title, String location, Calendar begin, Calendar 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);
}
}
可以匹配上述intent的intent-filters:
...>
"android.intent.action.INSERT" />
"vnd.android.cursor.dir/event" />
"android.intent.category.DEFAULT" />
Action:ACTION_IMAGE_CAPTURE或ACTION_VIDEO_CAPTURE
Data URI Scheme:空
MIME Type:空
!請注意:通過ACTION_IMAGE_CAPTURE啟動activity並返回的照片是一個鍵為”data”的Bitmap類型的略縮圖(downscaled copy (a thumbnail) of the photo)
示例如下:
static final int REQUEST_IMAGE_CAPTURE = 1;
static final Uri mLocationForPhotos;
public void capturePhoto(String targetFilename) {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT,
Uri.withAppendedPath(mLocationForPhotos, 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.getParcelable("data");
// Do other work with full size photo saved in mLocationForPhotos
...
}
}
關於如何通過這個Intent拍照、錄像,以及如何獲得存儲照片、錄像的Uri地址,您可以參考這些Training:
Taking Photos Simply
示例intent-filter:
...>
"android.media.action.IMAGE_CAPTURE" />
"android.intent.category.DEFAULT" />
Action:INTENT_ACTION_STILL_IMAGE_CAMERA
Data URI Scheme:空
MIME Type:空
示例:
public void capturePhoto() {
Intent intent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA);
if (intent.resolveActivity(getPackageManager()) != null) {
startActivityForResult(intent);
}
}
intent-filter:
...>
"android.media.action.STILL_IMAGE_CAMERA" />
"android.intent.category.DEFAULT" />
Action:INTENT_ACTION_VIDEO_CAMERA
Data URI Scheme:空
MIME Type:空
示例:
public void capturePhoto() {
Intent intent = new Intent(MediaStore.INTENT_ACTION_VIDEO_CAMERA);
if (intent.resolveActivity(getPackageManager()) != null) {
startActivityForResult(intent);
}
}
intent-filter:
...>
"android.media.action.VIDEO_CAMERA" />
"android.intent.category.DEFAULT" />
在onActivityResult()中可獲取您選擇的聯系人,如果只是通過Contacts Provider讀取聯系人信息,則無需申請READ_CONTACTS權限。
Action:ACTION_PICK
Data URI Scheme:None
示例:
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
...
}
}
關於如何處理返回的Uri對象contactUri ,您可以訪問這個Training:Retrieving Details for a Contact
Action:ACTION_PICK
Data URI Scheme:空
CommonDataKinds.Phone.CONTENT_TYPE,表示獲取聯系人號碼
CommonDataKinds.Email.CONTENT_TYPE,表示獲取聯系人Email
CommonDataKinds.StructuredPostal.CONTENT_TYPE,表示獲取聯系人的郵寄地址
示例:
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
...
}
}
}
Action:ACTION_VIEW
Data URI Scheme:content:
,該Uri指向了查看的聯系人地址,有兩種方法可獲得該Uri:
直接檢索通訊錄聯系人( Retrieving a List of Contacts)。此方式需要READ_CONTACTS權限。
示例:
public void viewContact(Uri contactUri) {
Intent intent = new Intent(Intent.ACTION_VIEW, contactUri);
if (intent.resolveActivity(getPackageManager()) != null) {
startActivity(intent);
}
}
Action:ACTION_EDIT
Data URI Scheme:content:
,獲取該Uri的方式和權限與上一小節的獲取方式一致。
MIME Type:由Uri決定。
示例:
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);
}
}
更多關於編輯聯系人的方法,您可以參考這個Training:Modifying Contacts Using Intents。
Action:ACTION_INSERT
Data URI Scheme:空
MIME Type:Contacts.CONTENT_TYPE
示例:
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);
}
}
Action:
"text/plain"
"*/*"
示例:
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);
}
}
若您能確定通過該隱式Intent能啟動一個郵件應用的activity(而不是社交類應用或是編輯短信的應用),那麼您可以使用action為ACTION_SENDTO並且使用”mailto”作為Uri的解析字符串發送郵件:
public void composeEmail(String[] addresses, String subject) {
Intent intent = new Intent(Intent.ACTION_SENDTO);
intent.setData(Uri.parse("mailto:")); // only email apps should handle this
intent.putExtra(Intent.EXTRA_EMAIL, addresses);
intent.putExtra(Intent.EXTRA_SUBJECT, subject);
if (intent.resolveActivity(getPackageManager()) != null) {
startActivity(intent);
}
}
Intent-filter:
<activity ...>
<intent-filter>
<action android:name="android.intent.action.SEND" />
<data android:type="*/*" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.OPENABLE" />
<data android:scheme="http" android:host="www.example.com" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />