Android知識(shí)點(diǎn)回顧之Intent/IntentFilter

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

可以用于以下三個(gè)場景:

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

Intent 類型

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

啟動(dòng)Service最好使用顯示Intent,否則會(huì)存在安全風(fēng)險(xiǎn),因?yàn)闊o法確定service什么時(shí)候被調(diào)用,而service又是用戶感知不到的組件

Android 5.0開始,如果bindService()隱式調(diào)用啟動(dòng)service,會(huì)拋出異常

Intent的創(chuàng)建

一個(gè)Intent對(duì)象包含了Android系統(tǒng)應(yīng)該啟動(dòng)哪個(gè)組件的信息

一個(gè)Intent可以包含以下信息:

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

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

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

setData()和setType()會(huì)互相覆蓋,所以當(dāng)需要同時(shí)設(shè)置Uri和MIME時(shí),為了避免這種情況,可以調(diào)用setDataAndType()

  • category
    執(zhí)行Action的附加信息??梢苑胖煤芏郼ategory,但是大多數(shù)intent是不需要category的
    常用值如下:
    CATEGORY_DEFAULT:Android系統(tǒng)中默認(rèn)的執(zhí)行方式,按照普通Activity的執(zhí)行方式執(zhí)行。 
    CATEGORY_HOME:設(shè)置該組件為Home Activity。
    CATEGORY_PREFERENCE:設(shè)置該組件為Preference?!?br> CATEGORY_LAUNCHER:設(shè)置該組件為在當(dāng)前應(yīng)用程序啟動(dòng)器中優(yōu)先級(jí)最高的Activity,通常為入口ACTION_MAIN配合使用?!?br> CATEGORY_BROWSABLE:設(shè)置該組件可以使用瀏覽器啟動(dòng)?!?br> CATEGORY_GADGET:設(shè)置該組件可以內(nèi)嵌到另外的Activity中。
    通過addCategory()指定
  • extras
    用來存放需要傳遞的數(shù)據(jù),以鍵值對(duì)的形式進(jìn)行存儲(chǔ)和訪問
    通過putExtras()方法設(shè)置
  • flags
    設(shè)置Activity的啟動(dòng)模式,例如:
    FLAG_ACTIVITY_CLEAR_TOP
    FLAG_ACTIVITY_NEW_TASK
    FLAG_ACTIVITY_NO_HISTORY
    FLAG_ACTIVITY_SINGLE_TOP
    具體的筆記放到Activity上
    通過setFlags()方法設(shè)置

顯示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);//強(qiáng)制使用選擇器
//if (sendIntent.resolveActivity(getPackageManager()) != null) {
//    startActivity(chooser);
//}
// Verify that the intent will resolve to an activity
if (sendIntent.resolveActivity(getPackageManager()) != null) {
    startActivity(sendIntent);
}

接收一個(gè)隱式Intent

需要在manifest文件中配置<intent-filter>,<intent-filter>包含如下三個(gè)子項(xiàng):
<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為指定的全景照片數(shù)據(jù)類型

<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是對(duì)Intent的包裝,使外部的APP能夠像在內(nèi)部APP那樣對(duì)所包含的Intent進(jìn)行使用
主要有如下的使用場景:

  • Notification
  • App Widget
  • AlarmManager

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

狀態(tài)欄通知:


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

action匹配規(guī)則

如果intent-filter設(shè)置了action的過濾規(guī)則,比如下面的XML代碼,

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

那么:

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

Category匹配規(guī)則

如果intent-filter設(shè)置了category的過濾規(guī)則,如下面的XML代碼,

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

那么:

  • Intent不設(shè)置category,則都通過,不論intent-filter設(shè)置多少category
  • intent設(shè)置了category,intent上的category能夠匹配上intent-filter設(shè)置的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匹配規(guī)則

intent-filter中的<data>結(jié)構(gòu)由Uri和MIME Type組成
Uri包括如下幾部分:

  • scheme:整個(gè)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/*等媒體類型

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

規(guī)則d例子,從相冊獲取圖片:

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

則intent的匹配規(guī)則為:

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

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

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

本知識(shí)點(diǎn)完~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

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

友情鏈接更多精彩內(nèi)容