一、定義
消息傳遞的對象,可以用來從其他應(yīng)用組件請求操作,基本用例如下:
- 啟動Activity
-
startActivity() 啟動新的activity,其中intent可以攜帶相應(yīng)的數(shù)據(jù)规伐,但是攜帶數(shù)據(jù)必須可序列化,String和基本數(shù)據(jù)類型匣缘。同時數(shù)據(jù)攜帶有大小限制猖闪,具體限制大小可以查看該網(wǎng)址
Intent intent = new Intent(MainActivity.this, SecondActivity.class); startActivity(intent);
-
startActivityForResult() 啟動新的Acitivity并在新頁面返回時候鲜棠,可攜帶部分?jǐn)?shù)據(jù)返回。注意①如果跳轉(zhuǎn)前頁面為fragment培慌,必須重寫它依賴的Activity或者父類fragment,否則會出現(xiàn)接收不了情況 ②如果所在fragment在viewpager下豁陆,不僅應(yīng)該重寫Acitity,而且應(yīng)該區(qū)別處理回調(diào)處理,防止所有fragment收到相關(guān)回調(diào)吵护。
Intent intent = new Intent(this, SecondActivity.class); startActivityForResult(intent, REQUEST_CODE);
- 啟動服務(wù)
- 對于API 21之前的版本盒音,可以用intent.startService()來啟動服務(wù)
- 服務(wù)旨在使用客戶端-服務(wù)端接口,通過bindService()將intent傳遞
-
傳遞廣播
啟動廣播馅而,sendBroadCast()或者sendOrderBroadCast()將intent傳遞給廣播接收者
二祥诽、Intent類型
1.顯示調(diào)用
? 通過目標(biāo)的包名稱或者組件名稱,啟動相應(yīng)組件瓮恭。
// 使用構(gòu)造函數(shù)原押,傳入context,class
// Intent intent = new Intent(MainActivity.this, SecondActivity.class);
Intent intent = new Intent();
//使用className來
intent.setClassName(MainActivity.this, "com.yobin.testintent.SecondActivity");
startActivity(intent);
2.隱式調(diào)用
不會指定特定的組件,只是聲明常規(guī)操作偎血,從而允許其他應(yīng)用中的組件來處理
三诸衔、構(gòu)建Intent
-
action
指定要執(zhí)行的通用操作的字符串,很大程度決定其余Intent的構(gòu)成颇玷,特別是數(shù)據(jù)和extra中包含的內(nèi)容笨农。通常的操作常量ACTION_VIEW(向用戶顯示信息), ACTION_SEND(向用戶共享數(shù)據(jù))
data
-
type
data是Uri類型數(shù)據(jù),type是數(shù)據(jù)MIME類型帖渠,指定數(shù)據(jù)的MIME類型數(shù)據(jù)有助于Android系統(tǒng)找到接收Intent的最佳組件
注意:調(diào)用setData和調(diào)用setType不能同時調(diào)用谒亦,因為會互相抵消彼此的值,如果需要設(shè)置用setDataAndType()同時設(shè)置URI和MIME類型
private String getMIMEType(File file) { String type = "*/*"; String fName = file.getName(); // 獲取后綴名前的分隔符"."在fName中的位置空郊。 int dotIndex = fName.lastIndexOf("."); if (dotIndex < 0) { return type; } /* 獲取文件的后綴名 */ String end = fName.substring(dotIndex, fName.length()).toLowerCase(); if (end == "") return type; // 在MIME和文件類型的匹配表中找到對應(yīng)的MIME類型份招。 for (int i = 0; i < MIME_MapTable.length; i++) { if (end.equals(MIME_MapTable[i][0])) type = MIME_MapTable[i][1]; } return type; } private final String[][] MIME_MapTable = { //名稱后綴和MIME類型 // {后綴名,MIME類型} {".3gp", "video/3gpp"}, {".apk", "application/vnd.android.package-archive"}, {".asf", "video/x-ms-asf"}, {".avi", "video/x-msvideo"}, {".bin", "application/octet-stream"}, {".bmp", "image/bmp"}, {".c", "text/plain"}, {".class", "application/octet-stream"}, {".conf", "text/plain"}, {".cpp", "text/plain"}, {".doc", "application/msword"}, {".docx", "application/vnd.openxmlformats-officedocument.wordprocessingml.document"}, {".xls", "application/vnd.ms-excel"}, {".xlsx", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"}, {".exe", "application/octet-stream"}, {".gif", "image/gif"}, {".gtar", "application/x-gtar"}, {".gz", "application/x-gzip"}, {".h", "text/plain"}, {".htm", "text/html"}, {".html", "text/html"}, {".jar", "application/java-archive"}, {".java", "text/plain"}, {".jpeg", "image/jpeg"}, {".jpg", "image/jpeg"}, {".js", "application/x-javascript"}, {".log", "text/plain"}, {".m3u", "audio/x-mpegurl"}, {".m4a", "audio/mp4a-latm"}, {".m4b", "audio/mp4a-latm"}, {".m4p", "audio/mp4a-latm"}, {".m4u", "video/vnd.mpegurl"}, {".m4v", "video/x-m4v"}, {".mov", "video/quicktime"}, {".mp2", "audio/x-mpeg"}, {".mp3", "audio/x-mpeg"}, {".mp4", "video/mp4"}, {".mpc", "application/vnd.mpohun.certificate"}, {".mpe", "video/mpeg"}, {".mpeg", "video/mpeg"}, {".mpg", "video/mpeg"}, {".mpg4", "video/mp4"}, {".mpga", "audio/mpeg"}, {".msg", "application/vnd.ms-outlook"}, {".ogg", "audio/ogg"}, {".pdf", "application/pdf"}, {".png", "image/png"}, {".pps", "application/vnd.ms-powerpoint"}, {".ppt", "application/vnd.ms-powerpoint"}, {".pptx", "application/vnd.openxmlformats-officedocument.presentationml.presentation"}, {".prop", "text/plain"}, {".rc", "text/plain"}, {".rmvb", "audio/x-pn-realaudio"}, {".rtf", "application/rtf"}, {".sh", "text/plain"}, {".tar", "application/x-tar"}, {".tgz", "application/x-compressed"}, {".txt", "text/plain"}, {".wav", "audio/x-wav"}, {".wma", "audio/x-ms-wma"}, {".wmv", "audio/x-ms-wmv"}, {".wps", "application/vnd.ms-works"}, {".xml", "text/plain"}, {".z", "application/x-compress"}, {".zip", "application/x-zip-compressed"}, {"", "*/*"}}; Uri data; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { data = FileProvider7.getUriForFile(getContext(), file); // 給目標(biāo)應(yīng)用一個臨時授權(quán) openintent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); } else { data = Uri.fromFile(file); } String type = getMIMEType(file); // 設(shè)置intent的data和Type屬性狞甚。 openintent.setDataAndType(/* uri */data, type);
-
Catgory
指定當(dāng)前動作被執(zhí)行的環(huán)境
① CATGORY_lAUNCHER 該 Activity 是任務(wù)的初始 Activity锁摔,在系統(tǒng)的應(yīng)用啟動器中列出。
② CATGORY_BROWSABLE 設(shè)置組件可以使用瀏覽器啟動哼审,表示該activity只能用來瀏覽網(wǎng)頁
③ CATGORY_DEFULT:android 默認(rèn)執(zhí)行方式谐腰,所有的Intent都可以激活它
-
Extra
攜帶數(shù)據(jù)請求
//跳轉(zhuǎn)到網(wǎng)頁 Intent intent = new Intent(); intent.setData(Uri.parse("http://www.baidu.com")); intent.setAction(Intent.ACTION_VIEW); intent.addCategory(Intent.CATEGORY_BROWSABLE); startActivity(intent); //跳轉(zhuǎn)地圖 Intent mapIntent = new Intent(); mapIntent.setData(Uri.parse("geo:38.899533,-77.036476")); mapIntent.setAction(Intent.ACTION_VIEW); mapIntent.addCategory(Intent.CATEGORY_BROWSABLE); startActivity(mapIntent); //撥打電話-調(diào)用撥號盤 Intent telIntent = new Intent(); telIntent.setData(Uri.parse("tel:18210165501")); telIntent.setAction(Intent.ACTION_DIAL); startActivity(telIntent); //撥打電話-直接撥號 //要使用這個必須在配置文件中加入<uses-permission android:name="android.permission.CALL_PHONE"/> //需要動態(tài)調(diào)用相關(guān)權(quán)限,不能僅僅在manifest中聲明 Intent telIIntent = new Intent(); telIIntent.setData(Uri.parse("tel:18210165501")); telIIntent.setAction(Intent.ACTION_CALL); startActivity(telIIntent); //調(diào)用發(fā)送短信程序(方法一) Uri uri = Uri.parse("smsto:15980665805"); Intent intent = new Intent(Intent.ACTION_SENDTO, uri); intent.putExtra("sms_body", "The SMS text"); startActivity(intent); //調(diào)用發(fā)送短信程序(方法二) Intent intent = new Intent(Intent.ACTION_VIEW); intent.putExtra("sms_body", "The SMS text"); intent.setType("vnd.android-dir/mms-sms"); startActivity(intent); //發(fā)送彩信 Uri uri = Uri.parse("content://media/external/images/media/23"); Intent intent = new Intent(Intent.ACTION_SEND); intent.putExtra("sms_body", "some text"); intent.putExtra(Intent.EXTRA_STREAM, uri); intent.setType("image/png"); startActivity(intent); //發(fā)送Email(方法一)(要在 Android 手機上才能測試) Uri uri = Uri.parse("mailto:zhangsan@gmail.com"); Intent intent = new Intent(Intent.ACTION_SENDTO, uri); startActivity(intent); //發(fā)送Email(方法二)(要在 Android 手機上才能測試) Intent intent = new Intent(Intent.ACTION_SENDTO); intent.setData(Uri.parse("mailto:zhangsan@gmail.com")); intent.putExtra(Intent.EXTRA_SUBJECT, "這是標(biāo)題"); intent.putExtra(Intent.EXTRA_TEXT, "這是內(nèi)容"); startActivity(intent); //發(fā)送Email(方法三)(要在 Android 手機上才能測試) Intent intent = new Intent(Intent.ACTION_SEND); intent.putExtra(Intent.EXTRA_EMAIL, "me@abc.com"); intent.putExtra(Intent.EXTRA_SUBJECT, "這是標(biāo)題"); intent.putExtra(Intent.EXTRA_TEXT, "這是內(nèi)容"); intent.setType("text/plain"); //選擇一個郵件客戶端 startActivity(Intent.createChooser(intent, "Choose Email Client")); // 發(fā)送Email(方法四)(要在 Android 手機上才能測試) Intent intent = new Intent(Intent.ACTION_SEND); //收件人 String[] tos = {"to1@abc.com", "to2@abc.com"}; //抄送人 String[] ccs = {"cc1@abc.com", "cc2@abc.com"}; //密送人 String[] bcc = {"bcc1@abc.com", "bcc2@abc.com"}; intent.putExtra(Intent.EXTRA_EMAIL, tos); intent.putExtra(Intent.EXTRA_CC, ccs); intent.putExtra(Intent.EXTRA_BCC, bcc); intent.putExtra(Intent.EXTRA_SUBJECT, "這是標(biāo)題"); intent.putExtra(Intent.EXTRA_TEXT, "這是內(nèi)容"); intent.setType("message/rfc822"); startActivity(Intent.createChooser(intent, "Choose Email Client")); //發(fā)送Email且發(fā)送附件(要在 Android 手機上才能測試) Intent intent = new Intent(Intent.ACTION_SEND); intent.putExtra(Intent.EXTRA_SUBJECT, "The email subject text"); intent.putExtra(Intent.EXTRA_STREAM, "file:///sdcard/mp3/醉紅顏.mp3"); intent.setType("audio/mp3"); startActivity(Intent.createChooser(intent, "Choose Email Client")); //播放媒體文件(android 對中文名的文件支持不好) Intent intent = new Intent(Intent.ACTION_VIEW); //Uri uri = Uri.parse("file:///sdcard/zhy.mp3"); Uri uri = Uri.parse("file:///sdcard/a.mp3"); intent.setDataAndType(uri, "audio/mp3"); startActivity(intent); Uri uri = Uri.withAppendedPath(MediaStore.Audio.Media.INTERNAL_CONTENT_URI, "1"); Intent intent = new Intent(Intent.ACTION_VIEW, uri); startActivity(intent) Intent intent2 = new Intent(Intent.ACTION_CHOOSER); intent2.putExtra(Intent.EXTRA_INTENT, intent1); intent2.putExtra(Intent.EXTRA_TITLE, "aaaa"); startActivity(intent2); //設(shè)置壁紙 Intent intent = new Intent(Intent.ACTION_SET_WALLPAPER); startActivity(Intent.createChooser(intent, "設(shè)置壁紙")); //卸載APK //fromParts方法 //參數(shù)1:URI 的 scheme //參數(shù)2:包路徑 //參數(shù)3: Uri uri = Uri.fromParts("package", "com.yobin.testintent", null); Intent intent = new Intent(Intent.ACTION_DELETE, uri); startActivity(intent); //安裝APK(???) Uri uri = Uri.fromParts("package", "com.great.activity_intent", null); Intent intent = new Intent(Intent.ACTION_PACKAGE_ADDED, uri); startActivity(intent); //調(diào)用搜索 Intent intent = new Intent(); intent.setAction(Intent.ACTION_WEB_SEARCH); intent.putExtra(SearchManager.QUERY, "android"); startActivity(intent);
四涩盾、CreateChooser()的作用
-
如果有多個應(yīng)用可以響應(yīng)Intent十气,選擇要使用的應(yīng)用后,并設(shè)置默認(rèn)選項后春霍,那么每次都會執(zhí)行該默認(rèn)操作砸西,但是如果用戶希望每次使用不同應(yīng)用,用createChooser()可以強制顯示選擇對話框,并且無法設(shè)置默認(rèn)操作芹枷。
Intent sendIntent = new Intent(); sendIntent.setAction(Intent.ACTION_SEND); sendIntent.putExtra(Intent.EXTRA_TEXT, "你好竟闪,是什么出現(xiàn)"); sendIntent.setType("text/plain"); //發(fā)送短信 Intent chooseIntent = Intent.createChooser(sendIntent, "這是選擇的應(yīng)用"); //包裹原始intent if (chooseIntent.resolveActivity(getPackageManager()) != null) {//判斷該intent是否有activity意圖 startActivity(chooseIntent); }
如果沒有應(yīng)用響應(yīng),使用原始的startActivtiy杖狼,如果沒有去resolveActivty方法判斷,會拋出ActivityNotFoundException妖爷,而用createChooser會顯示無應(yīng)用可以執(zhí)行操作
-
用于過濾不需要的應(yīng)用顯示在彈窗中
public void clickView(View view) { Intent sendIntent = getIntent(); //遍歷查詢所有可以打開頁面信息 List<ResolveInfo> resolveInfosNew = context.getPackageManager().queryIntentActivities(sendIntent, 0); List<Intent> targetIntents = new ArrayList<>(); if (!resolveInfosNew.isEmpty()) { for (ResolveInfo resolveInfo : resolveInfosNew) { ActivityInfo activityInfo = resolveInfo.activityInfo; String packageName = activityInfo.packageName; //可以利用packageName來進行過濾 if (!packageName.equals("com.android.bluetooth")) { //需要過濾的藍牙 Intent intent = getIntent(); intent.setComponent(new ComponentName(packageName, activityInfo.name));//設(shè)置組件信息 targetIntents.add(intent); } } } if (targetIntents.size() > 0) { Intent chooseIntent = Intent.createChooser(new Intent(), "這是選擇的應(yīng)用"); //包裹實際的應(yīng)用 //將需要的intent加入到chooseIntent中 chooseIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, targetIntents.toArray(new Parcelable[]{})); if (chooseIntent.resolveActivity(getPackageManager()) != null) { //解析是否有intent對應(yīng)的activity. startActivity(chooseIntent); } } } public Intent getIntent() { //需要加載的意圖 Intent intent = new Intent(); intent.setAction(Intent.ACTION_SEND); intent.putExtra(Intent.EXTRA_TEXT, "你好呢蝶涩,哈哈"); intent.setType("text/plain"); return intent; }
五、接收隱式Intent
要公布應(yīng)用可以接收哪些隱式Intent絮识,需要在清單文件中使用intent-filter元素為每個應(yīng)用組件聲明一個或多個Intent過濾器,每個過濾器可以有<action>,<data>,<category>三個組成
<action> 聲明可以接收的操作绿聘,可以自定義,但是該值必須是操作的文本字符串次舌,不可以是類常量
-
<data> 使用一個或多個指定數(shù)據(jù)URI(scheme熄攘、host、port彼念、path),各個方面和MIME類型屬性挪圾,聲明接收的數(shù)據(jù)類型。
注意:每個<data>元素均可以指定URI結(jié)構(gòu)和數(shù)據(jù)類型逐沙,URI包括scheme哲思、host、port吩案、path
<scheme>://<host>:<port>/<path>
content://com.yobin.project:200/folder/subfolder/etc 架構(gòu)<scheme>:content 主機<host>:com.yobin.project 端口<port>:200 路徑<path>:folder/subfolder/etc 上述屬性存在依賴關(guān)系 1. 如果沒有指定架構(gòu)棚赔,就忽略主機 2. 沒有指定主機,忽略端口 3. 未指定主機和架構(gòu)徘郭,忽略路徑 當(dāng)Intent中URI與過濾器中URI規(guī)范進行比較時候靠益,僅與過濾器包含的部分URI進行比較 1. 如果過濾器僅指定架構(gòu),則具有該架構(gòu)的所有URI均與過濾器匹配 2. 如果過濾器指定架構(gòu)和權(quán)限残揉,但未指定路徑胧后,則具有相同架構(gòu)和權(quán)限的所有 URI 都會通過過濾器,無論其路徑如何均是如此 3. 如果過濾器指定架構(gòu)抱环、權(quán)限和路徑绩卤,則僅具有相同架構(gòu)、權(quán)限和路徑的 URI 才會通過過濾器 注意: 路徑規(guī)范可以包含星號通配符 (*)江醇,因此僅需部分匹配路徑名即可 數(shù)據(jù)測試會將 Intent 中的 URI 和 MIME 類型與過濾器中指定的 URI 和 MIME 類型進行比較濒憋。規(guī)則如下: 1. 僅當(dāng)過濾器未指定任何 URI 或 MIME 類型時,不含 URI 和 MIME 類型的 Intent 才會通過測試陶夜。 2. 對于包含 URI 但不含 MIME 類型(既未顯式聲明凛驮,也無法通過 URI 推斷得出)的 Intent,僅當(dāng)其 URI 與過濾器的 URI 格式匹配条辟、且過濾器同樣未指 定 MIME 類型時黔夭,才會通過測試宏胯。 3.僅當(dāng)過濾器列出相同的 MIME 類型且未指定 URI 格式時,包含 MIME 類型但不含 URI 的 Intent 才會通過測試本姥。 4.僅當(dāng) MIME 類型與過濾器中列出的類型匹配時肩袍,同時包含 URI 類型和 MIME 類型(通過顯式聲明,或可以通過 URI 推斷得出)的 Intent 才會通過測試的 MIME 類型部分婚惫。如果 Intent 的 URI 與過濾器中的 URI 匹配氛赐,或者如果 Intent 具有 content: 或 file: URI 且過濾器未指定 URI,則 Intent 會通過測試的 URI 部分先舷。換言之艰管,如果過濾器只是列出 MIME 類型,則假定組件支持 content: 和 file: 數(shù)據(jù) 注意:指定了Intent的URI和MIME類型蒋川,如果數(shù)據(jù)中沒有<data>牲芋,則匹配失敗。
- <category> name屬性中聲明接收類別捺球,必須是可以操作的文本字符串值缸浦,不能為常量。注意氮兵,接收隱式Intent必須將CATEGORY_DEFAULT類別包括在Intent過濾器中餐济,startActivity()和startActivityForResult()將按照其聲明類別處理所有Intent,如果沒有此聲明,那么隱式Intent不會解析Activity.
<activity android:name="MainActivity">
<!-- This activity is the main entry, should appear in app launcher -->
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name="ShareActivity">
<!-- This activity handles "SEND" actions with text data -->
<intent-filter>
<action android:name="android.intent.action.SEND"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:mimeType="text/plain"/>
</intent-filter>
<!-- This activity also handles "SEND" and "SEND_MULTIPLE" with media data -->
<intent-filter>
<action android:name="android.intent.action.SEND"/>
<action android:name="android.intent.action.SEND_MULTIPLE"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:mimeType="application/vnd.google.panorama360+jpg"/>
<data android:mimeType="image/*"/>
<data android:mimeType="video/*"/>
</intent-filter>
</activity>
注意
本文是來源是Android開發(fā)者網(wǎng)站胆剧,以及部分網(wǎng)址絮姆,進行了相關(guān)的整理,增加了部分自己的東西秩霍。