Android的一個非常重要的功能是,應用程序基於它要執行的一個“動作”想其它應用程序發送用戶的能力。例如,如果你的應用程序要顯示一個地圖,你沒有在你的應用程序中創建顯示地圖的Activity。相反,你使用一個Intent創建了請求查看地址。Android系統然後啟動一個應用,它能在地圖上顯示地址。
正如在第一課中解釋的,Building Your First App,你必須使用intent在你自己應用中的各個Activity之間導航。你通常使用顯式意圖來做它,它定義了你想要啟動的組件的確切類名。然而,當你想要一個分開的應用執行一個動作的時候,例如“查看地圖“,你必須使用一個隱式意圖。
這個課程向你展示了如何創建一個特殊動作的隱式意圖來,並如何使用它來啟動一個Activity,它在其它的應用中執行動作。
構建一個隱式意圖
——————————————————————————————————————————————————————————————
隱式意圖沒有聲明要啟動的組件的類名,但是聲明了要指定的動作來代替。這個動作指明了你想要做的事情,例如查看,編輯,或者獲取一些東西。意圖通常也包含數據相關的動作,例如你想要查看的地址,你想發送的郵件地址。基於你想要創建的Intent,數據可能是一個Uri,其它數據類型之一,或者意圖可能不需要數據。
如果你的數據是一個Uri,這裡有一個簡答的Intent()構造器,你能使用它來定義動作和數據。
例如,這裡展示如何創建一個Intent來初始化一個電話呼叫,使用Uri數據來指定電話號碼:
[java]
Uri number = Uri.parse("tel:5551234");
Intent callIntent = new Intent(Intent.ACTION_DIAL, number); <span style="font-size:11pt; line-height:15px; background-color:transparent; color:windowtext; font-family:宋體,sans-serif"> </span>
當你的應用通過startActivity()方法調用這個Intent的時候,Phone應用程序給這個給予的電話號碼啟動一個呼叫。
這裡是一組其它意圖和他們的動作和Uri數據對:
查看地圖:
[java]
// 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);
查看網頁:
[java]
Uri webpage = Uri.parse("http://www.android.com");
Intent webIntent = new Intent(Intent.ACTION_VIEW, webpage); <span style="background-color:transparent; color:windowtext; font-family:'Calibri Light',sans-serif; font-size:10pt; line-height:13px"> </span>
其它類型的隱式意圖要求提供不同數據類型的”額外“數據,例如一個字符串。你能使用各種各樣的putExtra()方法添加一個或者多個額外數據。
默認,系統通過Intent包含的Uri數據來決定要求的正確的MIME類型。如果你在這個Itent中不包含一個Uri,你通常應該使用setType()方法來指定這個意圖相關的數據類型。設置MIME類型指定將獲取這個意圖的Activity的類型。
這裡有更多的Intent,添加了額外的數據來指定想要的動作:
發送帶有附件的郵件:
[java]
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[] {"
[email protected]"}); // 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<span style="font-family:'Calibri Light',sans-serif; font-size:10pt; background-color:transparent; color:windowtext"> </span>
創建一個日歷事件:
[java]
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");
注意:用於日歷事件的意圖僅僅在API level 14或者更高的版本中被支持。
注意:盡可能具體的定義你的Intent是非常重要的。例如,如果你想使用ACTION_VIEW意圖來顯示一個圖片,你應該指明iamge/* IMIE類型。這阻止了能“查看”其它類型數據(如一個地圖應用)的應用程序被這個Intent觸發。
核實有獲取這個意圖的應用
——————————————————————————————————————————————————————————————
盡管Android平台保證某些意圖將會被內置的應用解析(如Phone,Email, 或者Calendar應用程序),你應該總是在調用一個意圖之前包含一個核實的步驟。
當心:如果你調用一個Intent,並且在設備上沒有應用程序可以處理這個Itent,你的應用將會崩潰。
為了核實是否有一個Activity有效響應這個Itent,調用queryItentActivities()方法來獲取能處理你的Intent的Activity。如果被返回的列表不是空的,你可以安全的使用這個Intent。例如:
[java]
PackageManager packageManager = getPackageManager();
List<ResolveInfo> activities = packageManager.queryIntentActivities(intent, 0);
boolean isIntentSafe = activities.size() > 0; <span style="font-size:11pt; line-height:15px; background-color:transparent; color:windowtext; font-family:宋體,sans-serif"> </span>
如果isIntentSafe是ture,那麼至少一個應用程序將響應這個Intent。如果它是false,那麼沒有任何應用程序能處理這個Intent。
注意:你應該執行這個檢查,當你的Activity第一次啟動
使用Intent啟動一個Activity
——————————————————————————————————————————————————————————————
一旦你創建你的Intent,並設置了額外的信息,調用startActivity()方法向系統發送它。如果系統識別超過一個Activity能處理這個intent,,它向用戶顯示一個對話框,來選擇將要使用哪個應用,如圖1所示。如果這裡僅僅有一個activity能處理這個Intent,系統立刻啟動它:
startActivity(intent);
這裡是一個完整的例子,它顯示了如何創建一個Intent來查看地圖,檢查存在一個處理這個Intent的應用,然後啟動它:
[java]
// 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 = getPackageManager();
List<ResolveInfo> activities = packageManager.queryIntentActivities(mapIntent, 0);
boolean isIntentSafe = activities.size() > 0;
// Start an activity if it's safe
if (isIntentSafe) {
startActivity(mapIntent);
}