Android知識點回顧之Intent/IntentFilter

定義:Intent是一個消息傳送對象,可以用它來訪問另外一個組件

可以用于以下三個場景:

  • startActivity
startActivity()
 startActivityForResult()
  • startService
    Android 5.0以上可以使用JobScheduler啟動
    所有版本可以使用:
  startService();
  bindService();
  • sendBroadcast
    三種調用方法
sendBroadCast()
sendOrderedBroadCast()
sendStickyBroadcast()

Intent 類型

  • 顯示類型
    直接指定調用組件的名字,一般用于自己的APP內部
  • 隱式類型
    沒有指定組件的名字,而是聲明一般的action行為,用此方法可以允許調用另外一個APP的組件

啟動Service最好使用顯示Intent,否則會存在安全風險,因為無法確定service什么時候被調用,而service又是用戶感知不到的組件

Android 5.0開始,如果bindService()隱式調用啟動service,會拋出異常

Intent的創建

一個Intent對象包含了Android系統應該啟動哪個組件的信息

一個Intent可以包含以下信息:

  • componentName
    指定需要啟動組件的名字
    此項是可選的,用來區分顯示Intent和隱式Intent。
    賦值的方法有以下幾種

    • Intent的構造方法
    • setComponent()
    • setClass()
    • setClassName
  • action
    指定Intent要完成的動作,為字符串常量
    action可自定義,也可使用系統的,一般自定義的話最好加上自己APP的包名前綴
    一些系統標準的Action常量
    ACTION_VIEW,startActivity(),喚起系統相冊
    ACTION_SEND,startActivity(),把一些數據發送給另外的一些APP,如email,社交軟件等
    ACTION_CALL,startActivity(),喚起打電話界面
    不定期補充...
    除了Intent定義了Action常量,其他的類也有定義,比如Settings,可以用來跳轉到系統指定的設置界面
    action賦值的方法有一下幾種:

    • Intent的構造方法
    • setAction()
  • data
    根據給定的Uri尋找匹配的目標組件,如果不給定MIME類型,會進行推導,給定MIME類型,則強制使用此類型。
    不同的Action有對應的data數據指定。
    其中data的值設置為setData(),MIME的設置為setType()
    常用值如下所示:
    tel://:      號碼數據格式,后跟電話號碼。 
    mailto://:    郵件數據格式,后跟郵件收件人地址。
    smsto://:    短息數據格式,后跟短信接收號碼。
    content://:   內容數據格式,后跟需要讀取的內容。 
    file://:      文件數據格式,后跟文件路徑。
    geo:// latitude, longitude:經緯數據格式,在地圖上顯示經緯度所指定的位置。
    Uri指定數據指向那種數據格式,MIME指定數據具體的類型。比如Image和Audio有同樣的Uri,但是MIME的類型是不同的。

setData()和setType()會互相覆蓋,所以當需要同時設置Uri和MIME時,為了避免這種情況,可以調用setDataAndType()

  • category
    執行Action的附加信息。可以放置很多category,但是大多數intent是不需要category的
    常用值如下:
    CATEGORY_DEFAULT:Android系統中默認的執行方式,按照普通Activity的執行方式執行。 
    CATEGORY_HOME:設置該組件為Home Activity。
    CATEGORY_PREFERENCE:設置該組件為Preference。 
    CATEGORY_LAUNCHER:設置該組件為在當前應用程序啟動器中優先級最高的Activity,通常為入口ACTION_MAIN配合使用。 
    CATEGORY_BROWSABLE:設置該組件可以使用瀏覽器啟動。 
    CATEGORY_GADGET:設置該組件可以內嵌到另外的Activity中。
    通過addCategory()指定
  • extras
    用來存放需要傳遞的數據,以鍵值對的形式進行存儲和訪問
    通過putExtras()方法設置
  • flags
    設置Activity的啟動模式,例如:
    FLAG_ACTIVITY_CLEAR_TOP
    FLAG_ACTIVITY_NEW_TASK
    FLAG_ACTIVITY_NO_HISTORY
    FLAG_ACTIVITY_SINGLE_TOP
    具體的筆記放到Activity上
    通過setFlags()方法設置

顯示Intent的例子

Intent downloadIntent = new Intent(this, DownloadService.class);
downloadIntent.setData(Uri.parse(fileUrl));
startService(downloadIntent);

隱式Intent的例子

其中resolveActivity()用來判斷Intent是否能夠被解析,防止APP崩潰

Intent sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_TEXT, textMessage);
sendIntent.setType("text/plain");
//Intent chooser = Intent.createChooser(sendIntent, title);//強制使用選擇器
//if (sendIntent.resolveActivity(getPackageManager()) != null) {
//    startActivity(chooser);
//}
// Verify that the intent will resolve to an activity
if (sendIntent.resolveActivity(getPackageManager()) != null) {
    startActivity(sendIntent);
}

接收一個隱式Intent

需要在manifest文件中配置<intent-filter>,<intent-filter>包含如下三個子項:
<action>
<data>
<category>

<activity android:name="ShareActivity">
    <intent-filter>
        <action android:name="android.intent.action.SEND"/>
        <category android:name="android.intent.category.DEFAULT"/>
        <data android:mimeType="text/plain"/>
    </intent-filter>
</activity>

MIME類型 application/vnd.google.panorama360+jpg為指定的全景照片數據類型

<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>

使用PendingIntent

PendingIntent是對Intent的包裝,使外部的APP能夠像在內部APP那樣對所包含的Intent進行使用
主要有如下的使用場景:

  • Notification
  • App Widget
  • AlarmManager

取得實例的方法如下:
PendingIntent.getActivity(),啟動Activity
PendingIntent.getService(),啟動Service
PendingIntent.getBroadcast(),啟動BroadcastReceiver

狀態欄通知:


  int icon = android.R.drawable.my_icon;
  long when = System.currentTimeMillis();//通知發生的時間為系統當前時間
  Notification notification = new Notification(icon, null, when);//新建一個通知,第一個參數為圖標,第二個參數為短暫提示標題,第三個為通知時間
  notification.defaults = Notification.DEFAULT_SOUND;//發出默認聲音
  notification.flags |= Notification.FLAG_AUTO_CANCEL;//點擊通知后自動清除通知
  Intent openintent = new Intent(this, OtherActivity.class);
  PendingIntent contentIntent = PendingIntent.getActivity(this, 0, openintent, 0);//當點擊消息時就會向系統發送openintent意圖
  notification.setLatestEventInfo(this, "標題", "內容", contentIntent);//setLatestEventInfo表示設置點擊該通知的事件
    int notifyCode = 0;
//獲取通知管理器
  NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
  mNotificationManager.notify(notifyCode , notification);//第一個參數為自定義的通知唯一標識

action匹配規則

如果intent-filter設置了action的過濾規則,比如下面的XML代碼,

<intent-filter>
    <action android:name="android.intent.action.EDIT" />
    <action android:name="android.intent.action.VIEW" />
    ...
</intent-filter>

那么:

  • intent不設置action,則直接不通過
  • intent設置了多個Action,則只要有一個匹配上,則可以通過
//不通過
Intent intent = new Intent();
//通過
intent.setAction("android.intent.action.EDIT");
//通過
intent.setAction("android.intent.action.EDIT");
intent.setAction("android.intent.action.test");

Category匹配規則

如果intent-filter設置了category的過濾規則,如下面的XML代碼,

<intent-filter>
    <category android:name="android.intent.category.DEFAULT" />
    <category android:name="android.intent.category.BROWSABLE" />
    ...
</intent-filter>

那么:

  • Intent不設置category,則都通過,不論intent-filter設置多少category
  • intent設置了category,intent上的category能夠匹配上intent-filter設置的category,才能夠通過

比如:

//通過
Intent intent = new Intent();
//通過
intent.addCategory("android.intent.category.DEFAULT"),可以匹配上
//通過
intent.addCategory("android.intent.category.BROWSABLE")
//不通過
intent.addCategory("android.intent.category.DEFAULT")
intent.addCategory("android.intent.category.test")

Data匹配規則

intent-filter中的<data>結構由Uri和MIME Type組成
Uri包括如下幾部分:

  • scheme:整個Uri的模式,如http,ftp,content等
    如果scheme未指定,則忽略host
    如果只指定scheme,則所有和intent-filter相同的scheme都匹配

  • host:Uri的域名,如www.google.com
    如果host未指定,則忽略port

  • port:Uri的端口

  • path:包含的路徑信息,如:folder/subfolder/etc
    如果scheme,host都未指定,則忽略path

整體組成:<scheme>://<host>:<port>/<path>,如 content://com.example.project:200/folder/subfolder/etc

MIME Type:表示image/ipeg,video/*等媒體類型

匹配規則如下:
intent中的data必須和intent-filter完全匹配才能通過。有如下幾種情況:
a.intent沒有設置Uri和MIME Type,同時intent-filter也沒有設置
b.intent只包含Uri,但未包含MIME Type,同時能夠匹配上intent-filter設置的Uri,并且intent-filter為設置MIME Type
c.intent只設置MIME Type,同時intent-filter也設置了相同的MIME Type并且未指定Uri
d.intent設置了Uri和MIME Type,intent-filter只設置了MIME Type,則intent的Uri的scheme必須為content:或是file:。即,intent-filter如果沒有設置Uri,只設置了MIME Type,則Uri為content:或file:的模式。也就是說,過濾的規則希望組件能夠從文件(file)或內容提供者(content provider)獲取到本地數據。

規則d例子,從相冊獲取圖片:

<intent-filter>
    <data android:mimeType="image/*" />
    ...
</intent-filter>

則intent的匹配規則為:

 Intent intent = new Intent();
 intent.setDataAndType(Uri.parse("file://test"), "image/*");
 startActivity(intent);

如果intent-filter設置了多個data,則intent中的data只要和其中一個匹配就可以通過

為了防止APP崩潰,所有的intent匹配規則進行調用前都要進行判斷處理:
if (intent.resolveActivity(getPackageManager()) != null) {
startActivity(intent);
}

本知識點完~

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,908評論 6 541
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,324評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,018評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,675評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,417評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,783評論 1 329
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,779評論 3 446
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,960評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,522評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,267評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,471評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,009評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,698評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,099評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,386評論 1 294
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,204評論 3 398
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,436評論 2 378

推薦閱讀更多精彩內容

  • 注:本文完全拷貝自https://developer.android.com/guide/components/i...
    RxCode閱讀 1,783評論 1 13
  • 顯示Intent和隱式Intent Android中的Intent是一個非常重要且常用的類,可以用來在一個組件中啟...
    獅_子歌歌閱讀 1,198評論 0 2
  • Intent Intent介紹 Intent是Android應用組件之間通信的消息對象,它通常表明了兩個通信組件的...
    whyles閱讀 483評論 0 4
  • 他再度夢見河畔邊的那一場血戰,那座破敗的圣光教堂,以及身著雪白披風的銀發王子。在夢中,他與從前的戰友并肩而行:高貴...
    小羊過河啦啦啦閱讀 162評論 0 0
  • 江南秋來景不同,漁夫歸來船自橫。 蟹逅黃酒忘響鐘,誰言吾輩道相從。 瘦荷寞柳醉江東,遙望洛河瀛洲虹。 一杯濁酒家皆...
    陳彬_2e50閱讀 516評論 0 0