簡介
本篇包括Intent、Intent過濾器和常見的Intent
Intent在開發(fā)過程中秆乳,有著舉足輕重的作用握牧,最常見的就是界面間的跳轉(zhuǎn)。對他的翻譯中粱快,我覺得“意圖”解釋的最到位秩彤,他用代碼表示我們的想法,并讓系統(tǒng)去執(zhí)行事哭。本篇內(nèi)容包括Intent漫雷、Intent過濾器和常見的Intent,下面就依次解釋鳍咱。
Intent
官方的解釋:Intent是一個消息傳遞對象降盹,您可以使用它從其他應(yīng)用組件請求操作。在組件之間的通信主要包括:
-
啟動 Activity
startActivity(Intent intent)
startActivityForResult(Intent intent, int requestCode)
-
啟動服務(wù)
startService(Intent service)
bindService(Intent service, ServiceConnection conn, int flags)
-
傳遞廣播
- sendBroadcast(Intent intent)
Intent又分為顯示Intent和隱式Intent谤辜。
顯示是指指定了明確的要啟動的組建蓄坏,即設(shè)置了ComponentName,可以使用 setComponent()丑念、setClass()涡戳、setClassName() 或 Intent 構(gòu)造函數(shù)設(shè)置組件名稱;
隱式則就是不指定特定的組件脯倚,通過申明一些要執(zhí)行的操作渔彰,讓其它組件來處理,這里就設(shè)計到了Intent過濾器推正,用來匹配Intent是否有組件去處理恍涂,具體匹配規(guī)則在下文再分析。
注意:5.0以后如果使用隱式 Intent 調(diào)用 bindService()植榕,系統(tǒng)會引發(fā)異常乳丰。因為您無法確定哪些服務(wù)將響應(yīng) Intent,且用戶無法看到哪些服務(wù)已啟動内贮。
Intent包含了:ComponentName产园、Action、Data夜郁、Category什燕、Extra、Flag這幾個部分竞端,都提供了不同的方法去設(shè)置屎即,不外乎都是setXx或者addXx方法。
使用隱式選擇器時,如果系統(tǒng)中有多個能匹配上的組件就會通過一個對話框去選擇用哪個組件去打開技俐。由于系統(tǒng)對這種默認(rèn)的對話框提供了記住選擇的功能乘陪,所以下次再想選擇就不行了,就像分享功能雕擂,這時候就可以使用Intent.createChooser(Intent target, CharSequence title)去強制打開對話框啡邑。
注意:由于隱式Intent可能匹配不到相應(yīng)的組件,所以我們使用時最好加上一個判斷intent.resolveActivity(getPackageManager()) != null井赌,不為空表示能找到目標(biāo)組件
Intent過濾器
隱式Intent谤逼,系統(tǒng)是如何找到對應(yīng)的組件的呢?其實就是這些組件再Manifest文件中定義時仇穗,加上了<intent-filter>標(biāo)簽流部,當(dāng)然可以不定義或者定義一個或者定義多個該標(biāo)簽,其中包括了<action>纹坐、<category>和<data>三個標(biāo)簽枝冀,三個標(biāo)簽也是可以不定義的。
<action> 標(biāo)簽耘子,只需設(shè)置name屬性宾茂,內(nèi)容可自定義,字符串拴还;
<data> 標(biāo)簽使用一個或多個指定數(shù)據(jù) URI 各個方面(scheme、host欧聘、port片林、path 等)和 MIME 類型的屬性,聲明接受的數(shù)據(jù)類型怀骤;
<category> 標(biāo)簽费封,也是設(shè)置name屬性,內(nèi)容可自定義蒋伦,字符串弓摘。
對于action,只要組件中某一個intent-filter中的某一個action匹配上了即通過痕届;若沒有action標(biāo)簽韧献,則只有當(dāng)intent中也沒有設(shè)置action才算通過;
對于data研叫,比較復(fù)雜锤窑,它包含URI結(jié)構(gòu)和數(shù)據(jù)類型,首先URI的幾個屬性存在著以下的依賴關(guān)系嚷炉,
URI結(jié)構(gòu):<scheme>://<host>:<port>/<path>
- 如果未指定scheme渊啰,則會忽略host。
- 如果未指定host,則會忽略port绘证。
- 如果未指定scheme和host隧膏,則會忽略path。
Intent中的URI與過濾器中的URI規(guī)范進行比較時嚷那,它僅與過濾器中包含的部分 URI 進行比較胞枕。所以只要Intent中包含了過濾器中的URI則URI匹配通過;其中path的匹配可包含通配符(*)
URI結(jié)構(gòu)和MIME類型车酣,匹配時曲稼,需要分為四種情況,都無湖员、有其一或者都有:
僅當(dāng)過濾器未指定任何 URI 或 MIME 類型時贫悄,不含 URI 和 MIME 類型的 Intent 才會通過測試。
對于包含 URI 但不含 MIME 類型(既未顯式聲明娘摔,也無法通過 URI 推斷得出)的 Intent窄坦,僅當(dāng)其 URI 與過濾器的 URI 格式匹配、且過濾器同樣未指定 MIME 類型時凳寺,才會通過測試鸭津。
僅當(dāng)過濾器列出相同的 MIME 類型且未指定 URI 格式時,包含 MIME 類型肠缨、但不含 URI 的 Intent 才會通過測試逆趋。
僅當(dāng) MIME 類型與過濾器中列出的類型匹配時,同時包含 URI 類型和 MIME 類型的 Intent 才會通過測試的 MIME 類型部分晒奕。如果過濾器只是列出 MIME 類型闻书,則假定組件支持 content: 和 file: 數(shù)據(jù)。
對于category脑慧,intent可以不設(shè)置魄眉,也可通過,但是若是設(shè)置了闷袒,則intent的每個類別均必須與過濾器中的類別匹配才能通過坑律,而在過濾器中,必須要寫上默認(rèn)的屬性值:android.intent.category.DEFAULT囊骤;
綜上晃择,當(dāng)每一項都匹配通過時即可找到對應(yīng)的組件。
常用的Intent
1也物、發(fā)送短信/彩信
public void composeMmsMessage(String message, Uri attachment) {
Intent intent = new Intent(Intent.ACTION_SEND);
intent.setData(Uri.parse("smsto:"));
intent.putExtra("sms_body", message);
intent.putExtra(Intent.EXTRA_STREAM, attachment);//附加的圖像或視頻的 Uri
if (intent.resolveActivity(getPackageManager()) != null) {
startActivity(intent);
}
}
2藕各、打開系統(tǒng)設(shè)置
public void openSettings() {
Intent intent = new Intent(Intent.ACTION_SETTINGS);
if (intent.resolveActivity(getPackageManager()) != null) {
startActivity(intent);
}
}
3、打開電話應(yīng)用
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);
}
}
4焦除、打開瀏覽器瀏覽網(wǎng)址
/**
* @param url 需要以http或https開頭
*/
public static void toHtml(Context context, String url) {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse(url));
context.startActivity(intent);
}
5激况、打開系統(tǒng)日歷
/**
* 打開系統(tǒng)日歷
*/
public static void callCalendar(Context context) {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse("content://com.android.calendar/time"));
context.startActivity(intent);
}
6、打開系統(tǒng)計算器
@TargetApi(15)
public static void callCalculator(Context context) {
ArrayList<HashMap<String, Object>> items = new ArrayList<HashMap<String, Object>>();
final PackageManager pm = context.getPackageManager();
List<PackageInfo> packs = pm.getInstalledPackages(0);
for (PackageInfo pi : packs) {
if (pi.packageName.toLowerCase().contains("calcul")) {
HashMap<String, Object> map = new HashMap<String, Object>();
map.put("appName", pi.applicationInfo.loadLabel(pm));
map.put("packageName", pi.packageName);
items.add(map);
}
}
if (items.size() >= 1) {
String packageName = (String) items.get(0).get("packageName");
Intent i = pm.getLaunchIntentForPackage(packageName);
if (i != null)
context.startActivity(i);
} else {
Toast.makeText(context, "沒有安裝計算器", Toast.LENGTH_SHORT).show();
}
}