一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

Intent以及IntentFilter詳解

 jiffes 2017-07-19

轉(zhuǎn)載注明出處:http://blog.csdn.net/xiaohanluo/article/details/52637520

1. 前言

       在Android中有四大組件,這些組件中有三個(gè)組件與Intent相關(guān),可見Intent在android整個(gè)生態(tài)中的地位高度。Intent是信息的載體,用它可以去請求組件做相應(yīng)的操作,但是相對于這個(gè)功能,Intent本身的結(jié)構(gòu)更值得我們?nèi)パ芯俊?/p>

2. Intent與組件

       Intent促進(jìn)了組件之間的交互,這對于開發(fā)者非常重要,而且它還能做為消息的載體,去指導(dǎo)組件做出相應(yīng)的行為,也就是說Intent可以攜帶數(shù)據(jù),傳遞給Activity/Service/BroadcastReceiver。

  • 啟動(dòng)Activity。Activity可以簡單的理解為手機(jī)屏幕中的一個(gè)頁面,你可以通過將Intent傳入startActivity方法來啟動(dòng)一個(gè)Activity的實(shí)例,也就是一個(gè)頁面,同時(shí),Intent也可以攜帶數(shù)據(jù),傳遞給新的Activity。如果想要獲取新建的Activity執(zhí)行結(jié)果,可以通過onActivityResult()方法去啟動(dòng)Activity。
  • 啟動(dòng)Service。Service是一個(gè)不呈現(xiàn)交互畫面的后臺(tái)執(zhí)行操作組件,可以通過將Intent穿入startService()方法來啟動(dòng)一個(gè)Service來啟動(dòng)服務(wù)。
  • 傳遞廣播BroadCast。廣播是任何應(yīng)用都可以接收到的消息,通過將Intent傳遞給 sendBroadcast()、sendOrderedBroadcast()sendStickyBroadcast()方法,可以將廣播傳遞接收方。

3. Intent類型

在Android中,Intent分為兩種類型,顯式和隱式。

  • 顯式Intent,可以通過類名來找到相應(yīng)的組件,在應(yīng)用中用顯式Intent去啟動(dòng)一個(gè)組件,通常是因?yàn)槲覀冎肋@個(gè)組件(Activity或者Service)的名字。如下代碼,我們知道具體的Activity的名字,要啟動(dòng)一個(gè)新的Activity,下面就是用的顯示Intent。

    Intent intent = new Intent(context,XXActivity.class);
    startActivity(intent);
    • 1
    • 2
    • 1
    • 2
  • 隱式Intent,不指定具體的組件,但是它會(huì)聲明將要執(zhí)行的操作,從而匹配到相應(yīng)的組件。最簡單的Android中調(diào)用系統(tǒng)撥號頁面準(zhǔn)備打電話的操作,就是隱式Intent。

    Intent intent = new Intent(Intent.ACTION_DIAL);
    Uri data = Uri.parse("tel:" + "135xxxxxxxx");
    intent.setData(data);
    startActivity(intent);
    • 1
    • 2
    • 3
    • 4
    • 1
    • 2
    • 3
    • 4

    使用顯示Intent去啟動(dòng)Activity或者Service的時(shí)候,系統(tǒng)將會(huì)立即啟動(dòng)Intent對象中指定的組件。

       使用隱式Intent的時(shí)候,系統(tǒng)通過將Intent對象中的IntentFilter與組件在AndroidManifest.xml或者代碼中動(dòng)態(tài)聲明的IntentFilter進(jìn)行比較,從而找到要啟動(dòng)的相應(yīng)組件。如果組件的IntentFilter與Intent中的IntentFilter正好匹配,系統(tǒng)就會(huì)啟動(dòng)該組件,并把Intent傳遞給它。如果有多個(gè)組件同時(shí)匹配到了,系統(tǒng)則會(huì)彈出一個(gè)選擇框,讓用戶選擇使用哪個(gè)應(yīng)用去處理這個(gè)Intent,比如有時(shí)候點(diǎn)擊一個(gè)網(wǎng)頁鏈接,會(huì)彈出多個(gè)應(yīng)用,讓用戶選擇用哪個(gè)瀏覽器去打開該鏈接,就是這種情況。

       IntentFilter通常是定義在AndroidManifest.xml文件中,也可以動(dòng)態(tài)設(shè)置,通常是用來聲明組件想要接受哪種Intent。例如,你如果為一個(gè)Activity設(shè)置了IntentFilter,你就可以在應(yīng)用內(nèi)或者其他應(yīng)用中,用特定的隱式Intent來啟動(dòng)這個(gè)Activity,如果沒有為Activity設(shè)置IntentFilter,那么你就只能通過顯示Intent來啟動(dòng)這個(gè)Activity。

注意,為了確保系統(tǒng)的穩(wěn)定性,官方建議使用顯示Intent來啟動(dòng)Service,同時(shí)也不要為Service設(shè)置IntentFilter,因?yàn)槿绻褂秒[式Intent去啟動(dòng)Service,我們并不知道那些服務(wù)會(huì)響應(yīng)Intent,而且由于服務(wù)大多是不可見的,我們也不知道那些服務(wù)被啟動(dòng)了,這是非常危險(xiǎn)的。在Android 5.0(API 21)以后,如果使用隱式的Intent去調(diào)用bindService()方法,系統(tǒng)會(huì)拋出異常。

4. Intent的屬性

       Intent作為消息的載體,系統(tǒng)根據(jù)它去決定啟動(dòng)哪個(gè)具體的組件同時(shí)將組件執(zhí)行中需要的信息傳遞過去。Intent能夠包含的屬性有Component、Action、Data、Category、Extras、Flags,關(guān)于這些屬性的更詳細(xì)信息可查看這里。

  • Component,要啟動(dòng)的組件名稱。這個(gè)屬性是可選的,但它是顯式Intent的一個(gè)重要屬性,設(shè)置了這個(gè)屬性后,該Intent只能被傳遞給由Component定義的組件。隱式Intent是沒有該屬性的,系統(tǒng)是根據(jù)其他的信息(例如,Action、Data等)來判斷該Intent應(yīng)該傳遞給哪個(gè)組件。這個(gè)屬性是目標(biāo)的組件的具體名稱(完全限定類名),例如,com.example.DemoActivity。該屬性可以通過setComonentName()setClass()、setClassName()或者Intent的構(gòu)造函數(shù)來設(shè)置。
  • Action,表明執(zhí)行操作的字符串。它會(huì)影響Intent的其余信息,比如Data、Extras。該屬性可以通過setAction()方法或者Intent的構(gòu)造函數(shù)來設(shè)置。用戶可以自定義這個(gè)屬性,也可以使用系統(tǒng)中已經(jīng)有的Action值。下面列出啟動(dòng)Activity時(shí)候的一些通用Action屬性。
    • ACTION_VIEW,當(dāng)有一些信息需要展示出來,可以設(shè)置Intent的Action為這個(gè)值,并調(diào)用startActivity()方法
    • ACTION_SEND,當(dāng)用戶有一些信息需要分享到其他應(yīng)用,可以設(shè)置Intent的Action為這個(gè)值,并調(diào)用startActivity()方法
    • ACTION_DIAL,撥打電話,可以設(shè)置Intent的Action為這個(gè)值,并調(diào)用startActivity()方法
    • ACTION_EDIT,編輯某些文件,可以設(shè)置Intent的Action為這個(gè)值,并調(diào)用startActivity()方法
  • Data,它是待操作數(shù)據(jù)的引用URI或者數(shù)據(jù)MIME類型的URI,它的值通常與Intent的Action有關(guān)聯(lián)。比如,如果設(shè)置Action的值為ACTION_EDIT,那么Data的值就必須包含被編輯文檔的URI。當(dāng)我們創(chuàng)建Intent的時(shí)候,設(shè)置MIME類型非常重要。例如,一個(gè)可以顯示圖片的Activity可能不能播放音頻,圖片和音頻的URI非常類似,如果我們設(shè)置了MIME類型,可以幫助系統(tǒng)找到最合適的組件接受Intent。有時(shí)候,MIME類型也可以從URI判斷出來,例如當(dāng)Data是一個(gè)包含content:字符串的URI時(shí)候,可以明確的知道,待處理的數(shù)據(jù)存在設(shè)備中,而且由ContentProvider控制。

    • 使用setData()方法設(shè)置數(shù)據(jù)引用的URI,使用setType()方法設(shè)置數(shù)據(jù)的MIME類型,使用setDataAndType()方法同時(shí)設(shè)置這兩個(gè)屬性。
    • 注意:如果想要設(shè)置兩個(gè)的屬性,直接用setDataAndType()方法,不要同時(shí)調(diào)用setData()setType()方法,因?yàn)檫@兩個(gè)方法設(shè)置的值會(huì)相互覆蓋

      public Intent setData(Uri data) {
          mData = data;
          mType = null;
          return this;
      }
      
      public Intent setType(String type) {
          mData = null;
          mType = type;
          return this;
      }
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
  • Category,這個(gè)屬性是對處理該Intent組件信息的補(bǔ)充。它是一個(gè)ArraySet類型的容器,所以可以向里面添加任意數(shù)量的補(bǔ)充信息,同時(shí),Intent沒有設(shè)置這個(gè)屬性不會(huì)影響解析組件信息??梢酝ㄟ^addCategory()方法來設(shè)置該屬性。下面列出一些常用的Category的值。
    • CATEGORY_BROWSABLE,設(shè)置Category為該值后,在網(wǎng)頁上點(diǎn)擊圖片或鏈接時(shí),系統(tǒng)會(huì)考慮將此目標(biāo)Activity列入可選列表,供用戶選擇以打開圖片或鏈接。
    • CATEGORY_LAUNCHER,應(yīng)用啟動(dòng)的初始Activity,這個(gè)Activity會(huì)被添加到系統(tǒng)啟動(dòng)launcher當(dāng)中。

以上列出的這些關(guān)于Intent的屬性(Component、Action、Data、Category)可以幫助系統(tǒng)來確定具體的組件,但是有一些Intent的屬性,不會(huì)影響到組件的確定。

  • Extras,以key-value鍵值對的形式來存儲(chǔ)組件執(zhí)行操作過程中需要的額外信息,可以調(diào)用putExtra()方法來設(shè)置該屬性,這個(gè)方法接受兩個(gè)參數(shù),一個(gè)是key,一個(gè)是value。也可以通過實(shí)例化一個(gè)儲(chǔ)存額外信息的Bundle對象,然后調(diào)用putExtras()方法將我們實(shí)例化的Bundle添加到Intent中。
  • Flags,這個(gè)屬性可以指示系統(tǒng)如何啟動(dòng)一個(gè)Activity,以及啟動(dòng)之后如何處理。例如Activity屬于哪一個(gè)task(參考Activity的四種啟動(dòng)方式)。

5. 顯式Intent示例

       上文說到,顯式Intent是用于啟動(dòng)某個(gè)特定的組件(Activity或者Service)的Intent,穿創(chuàng)建顯式的Intent的時(shí)候需要設(shè)置組件名稱(Component)屬性,其他的屬性都是可選屬性。

// fileUrl是一個(gè)URL字符串,例如 "http://www./image.png"
Intent downloadIntent = new Intent(context, DownloadService.class);
downloadIntent.setData(Uri.parse(fileUrl));
startService(downloadIntent);
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

這里的Intent的構(gòu)造函數(shù)傳入了兩個(gè)參數(shù),context和組件名(Component),調(diào)用了startService()方法后,會(huì)在當(dāng)前的應(yīng)用中啟動(dòng)DownloadService這個(gè)服務(wù)。
顯示Intent中設(shè)置的組件名(Component)需要在AndroidManifest.xml進(jìn)行注冊,所以它一般用來啟動(dòng)當(dāng)前應(yīng)用內(nèi)的組件。

6. 隱式Intent示例

       隱式Intent比顯示的Intent會(huì)復(fù)雜一些,它既可以啟動(dòng)當(dāng)前應(yīng)用內(nèi)的組件,也可以啟動(dòng)當(dāng)前應(yīng)用外的組件。如果當(dāng)前應(yīng)用無法處理隱式Intent,但是其他應(yīng)用中的組件可以處理,那么系統(tǒng)會(huì)彈框讓用戶選擇啟動(dòng)哪個(gè)應(yīng)用中的組件。

       例如,如果用戶有內(nèi)容想分享給其他應(yīng)用,就創(chuàng)建一個(gè)Intent,將它的Action屬性設(shè)置為ACTION_SEND,然后將要分享的內(nèi)容設(shè)置到Extras屬性中,然后調(diào)用startActivity()方法,用戶就可以選擇將內(nèi)容分享到哪一個(gè)應(yīng)用。

注意,如果沒有任何應(yīng)用能處理用戶發(fā)送的隱形Intent,調(diào)用組件失敗,應(yīng)用可能會(huì)崩潰。調(diào)用resolveActivity()方法可以確認(rèn)是否有Activity能夠處理這個(gè)Intent,如果返回為非空,那么至少有一個(gè)組件能夠處理這個(gè)Intent,調(diào)用startActivity()就很安全了;如果返回的是空(null),那么說明沒有組件能夠處理這個(gè)Intent,這個(gè)時(shí)候就不應(yīng)該使用這個(gè)隱式的Intent了。

// 要將textMessage信息分享出去
Intent sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_TEXT, textMessage);
sendIntent.setType("text/plain");

// 確認(rèn)是否有組件能夠處理這個(gè)隱式Intent
if (sendIntent.resolveActivity(getPackageManager()) != null) {
    startActivity(sendIntent);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

       調(diào)用startActivity()傳入一個(gè)隱式Intent時(shí)候,系統(tǒng)會(huì)檢查設(shè)備中所有的應(yīng)用,確定哪些應(yīng)用可以處理這個(gè)隱式的Intent(含有startActivity()操作并攜帶text/plain類型的Intent),如果只有一個(gè)應(yīng)用可以處理這個(gè)Intent,那么直接喚起這個(gè)應(yīng)用,并將Intent傳給它;如果有多個(gè)應(yīng)用可以處理這個(gè)Intent,那么系統(tǒng)會(huì)彈出一個(gè)選擇框,讓用戶選擇喚起哪個(gè)應(yīng)用。

7. 強(qiáng)制喚起選擇框

       上文說了,如果多個(gè)應(yīng)用可以處理同一個(gè)隱式Intent,系統(tǒng)會(huì)彈出選擇框,讓用戶選擇喚起哪個(gè)應(yīng)用,并設(shè)置該應(yīng)用為默認(rèn)的打開方式,以后就不會(huì)彈出選擇框了。如果用戶希望以后一直使用該用戶處理這個(gè)隱式Intent(比如打開網(wǎng)頁,用戶通常會(huì)傾向于使用同一個(gè)web瀏覽器),那么十分方便。

       但是如果用戶想每一次都用不同的應(yīng)用去處理這個(gè)隱式的Intent的,就應(yīng)該每次彈出選擇框,用戶可以在選擇框中選擇喚起的應(yīng)用,但是無法設(shè)置默認(rèn)的打開方式。例如,當(dāng)用戶想根據(jù)當(dāng)前的位置將內(nèi)容分享到不同的應(yīng)用,所以每次都需要彈出選擇框。

用戶需要通過Intent.createChooser()創(chuàng)建一個(gè)Intent,然后調(diào)用startActivity()。

Intent sendIntent = new Intent(Intent.ACTION_SEND);
...

// 分享的標(biāo)題
String title = getResources().getString(R.string.chooser_title);
// 創(chuàng)建一個(gè)調(diào)用選擇框的Intent
Intent chooser = Intent.createChooser(sendIntent, title);

// 確認(rèn)是否有應(yīng)用可以處理這個(gè)Intent
if (sendIntent.resolveActivity(getPackageManager()) != null) {
    startActivity(chooser);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

8. 接受隱式Intent

       想配置你的應(yīng)用可以處理哪些隱式的Intent,需要在AndroidManifest.xml文件中使用<intent-filter>標(biāo)簽為組件設(shè)置一個(gè)或者多個(gè)過濾器。每一個(gè)過濾器基于Action、Data、Category來指定自身可以處理的Intent類型。如果隱式Intent的能夠匹配到用戶設(shè)置的其中一個(gè)過濾器,系統(tǒng)才能喚起這個(gè)應(yīng)用相應(yīng)的組件并將Intent傳遞給這個(gè)組件。

       組件應(yīng)該為為一個(gè)它可以處理的操作單獨(dú)設(shè)置一個(gè)處理器。例如,相冊中的Activity可能有兩個(gè)過濾器,一個(gè)過濾器對應(yīng)瀏覽照片的操作,另一個(gè)過濾器對應(yīng)編輯照片的操作。當(dāng)這個(gè)Activity被啟動(dòng)的時(shí)候,根據(jù)Intent中攜帶的信息來決定執(zhí)行哪種操作。

       每一個(gè)過濾器是在AndroidManifest.xml使用<intent-filter>標(biāo)簽來定義的,嵌套在組件標(biāo)簽中,例如<activity>、<service>標(biāo)簽。在<intent-filter>標(biāo)簽中,用戶可以使用一下三個(gè)屬性中的一個(gè)或者多個(gè)來指定可以接受的Intent。

  • <action>,在這個(gè)屬性中,聲明該組件可以執(zhí)行的操作。該值必須是關(guān)于操作的一個(gè)字符串,并不是類常量
  • <data>,使用一個(gè)或者多個(gè)數(shù)據(jù)URI(scheme、host、port、path等等)和數(shù)據(jù)的MIME類型來指定接受的數(shù)據(jù)類型
  • <category>,聲明接受的Intent類型

       Activity組件要接受隱式Intent,它必須有一個(gè)<category>屬性為CATEGORY_DEFAULT的過濾器,因?yàn)?code>startActivity()和startActivityForResult()方法處理Intent時(shí)候,默認(rèn)的認(rèn)為接受組件有一個(gè)<category>屬性為CATEGORY_DEFAULT的過濾器。如果一個(gè)Activity組件不聲明這樣一個(gè)過濾器,它就接收不到隱式Intent。

例如,以下代碼聲明了一個(gè)Activity組件,這個(gè)組件可以處理action屬性為ACTION_SEND,數(shù)據(jù)類型是文本(text/plain)的隱式Intent。

<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>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

用戶也可以創(chuàng)建一個(gè)包含多個(gè)<action><data><category>標(biāo)簽的過濾器,創(chuàng)建時(shí)候僅需要確定該組件能夠處理過濾器定義的操作即可。

如果是根據(jù)<action><data>、<category>標(biāo)簽的組合來處理多個(gè)Intent,那么需要為這個(gè)組件聲明多個(gè)過濾器。

系統(tǒng)會(huì)以這三個(gè)屬性將隱式Intent與所有組件聲明的過濾器進(jìn)行對比,如果這三個(gè)屬性全部能夠匹配上,系統(tǒng)才有可能將這個(gè)隱式Intent傳遞給這個(gè)組件,因?yàn)槿绻鄠€(gè)應(yīng)用的組件都能匹配上會(huì)彈出選擇框,讓用戶選擇一個(gè)應(yīng)用去處理這個(gè)隱式Intent。

為了避免無意中啟動(dòng)了其他的Service,所以在應(yīng)用內(nèi),建議一直使用顯示的Intent去啟動(dòng)服務(wù),這樣就不必再AndroidManifest.xml文件中為Service聲明過濾器了。

對于Activity的過濾器,必須在AndroidManifest.xml文件中聲明,也可以不聲明,直接使用顯示Intent喚起Activity組件。

廣播接收器的過濾器聲明可以在AndroidManifest.xml文件中聲明,也可以使用registerReceiver()方法動(dòng)態(tài)注冊,使用完畢后,使用unregisterReceiver()方法動(dòng)態(tài)注銷。

9. 過濾器聲明示例

下面一些過濾器的聲明能夠幫助你更好的理解。

<activity android:name="MainActivity">
    <!-- 該Activity是該應(yīng)用的啟動(dòng)入口頁面,它會(huì)被儲(chǔ)存在系統(tǒng)的launcher列表中 -->
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>

<activity android:name="ShareActivity">
    <!-- 該Activity能夠處理ACTION_SEND行為且數(shù)據(jù)類型為text/plain的隱式Intent -->
    <intent-filter>
        <action android:name="android.intent.action.SEND"/>
        <category android:name="android.intent.category.DEFAULT"/>
        <data android:mimeType="text/plain"/>
    </intent-filter>
    <!-- 該Activity能夠處理ACTION_SEND行為且數(shù)據(jù)類型是媒體內(nèi)容的隱式Intent -->
    <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="image/*"/>
        <data android:mimeType="video/*"/>
    </intent-filter>
</activity>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

第一個(gè)名為MainActivity的組件,是應(yīng)用的啟動(dòng)入口頁面,當(dāng)用戶點(diǎn)擊應(yīng)用圖標(biāo),該Activity會(huì)被啟動(dòng)。

  • android.intent.action.MAIN,表示該Activity是應(yīng)用的啟動(dòng)入口,且不需要任何Intent攜帶的數(shù)據(jù)。
  • android.intent.category.LAUNCHER,表示將該Activity的圖標(biāo)設(shè)為手機(jī)主屏幕上的應(yīng)用圖標(biāo),如果它沒有圖標(biāo),就用Application的圖標(biāo)。

第二個(gè)名為ShareActivity的組件,能夠處理兩種隱式Intent,可以接受文本和媒體內(nèi)容的分享操作,也就是說如果一個(gè)隱式Intent能夠匹配到任意一個(gè)過濾器都可以喚起該Activity。當(dāng)然,也可以直接通過顯示Intent指定啟動(dòng)它。

9. PendingIntent

PendingIntent是對Intent的一種封裝。它主要作用在于,讓外部的應(yīng)用執(zhí)行內(nèi)部的Intent時(shí)候,就好像是在你的應(yīng)用中還行一樣。

通常在以下場景中會(huì)使用PendingIntent。

  • 當(dāng)用戶點(diǎn)擊通知欄時(shí)候,才執(zhí)行的Intent(系統(tǒng)的NotificationManager執(zhí)行的Intent),詳情參考這里
  • 當(dāng)用戶操作懸浮在主屏幕中的小工具,才執(zhí)行的Intent(主屏幕應(yīng)用執(zhí)行的Intent),詳情參考這里
  • 在未來某一個(gè)特定時(shí)間執(zhí)行的Intent(系統(tǒng)的AlarmManager執(zhí)行的Intent)

因?yàn)槊恳粋€(gè)Intent對象都是針對具體的組件類別(Activity/Service/BroadcastReceiver)進(jìn)行實(shí)例化,因此在創(chuàng)建PendingIntent的時(shí)候,也要基于相同的因素去實(shí)例化,使用以下方法實(shí)例化PendingIntent。

  • PendingIntent.getActivity(),返回一個(gè)適用于Activity組件的PendingIntent
  • PendingIntent.getService(),返回一個(gè)適用于Service組件的PendingIntent
  • PendingIntent.getBroadcast(),返回一個(gè)適用于BroadcastReceiver的PendingIntent

當(dāng)然官方還有一些其他獲取PendingIntent對象的方法,不過內(nèi)部也是使用上面三個(gè)方法來獲取實(shí)例化對象的。

這三個(gè)方法都需要當(dāng)前應(yīng)用的context,需要封裝的Intent,以及一個(gè)或者多個(gè)該如何使用該Intent的標(biāo)志(例如,是否可以多次使用該Intent)。

關(guān)于Pending的具體使用也不再這里展開,需要了解具體使用的可以查看Notification中PendingIntent的使用懸浮工具欄中PendingIntent的使用

10. Intent匹配規(guī)則

       上文中提到了,當(dāng)發(fā)送一個(gè)隱式Intent后,系統(tǒng)會(huì)將它與設(shè)備中的每一個(gè)組件的過濾器進(jìn)行匹配,匹配屬性有Action、Category、Data三個(gè),需要這三個(gè)屬性都匹配成功才能喚起相應(yīng)的組件。

10.1 Action匹配規(guī)則

一個(gè)過濾器可以不聲明Action屬性也可以聲明多個(gè)Action屬性。如下:

<intent-filter>
    <action android:name="android.intent.action.EDIT" />
    <action android:name="android.intent.action.VIEW" />
    ...
</intent-filter>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 1
  • 2
  • 3
  • 4
  • 5

隱式Intent中的Action屬性,與組件中的某一個(gè)過濾器的Action能夠匹配(如果一個(gè)過濾器聲明了多個(gè)Action屬性,只需要匹配其中一個(gè)就行),那么就算是匹配成功。

如果過濾器沒有聲明Action屬性,那么只有沒有設(shè)置Action屬性的隱式Intent才能匹配成功。

10.2 Category匹配規(guī)則

一個(gè)過濾器可以不聲明Category屬性也可以聲明多個(gè)Category屬性,如下:

<intent-filter>
    <category android:name="android.intent.category.DEFAULT" />
    <category android:name="android.intent.category.BROWSABLE" />
    ...
</intent-filter>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

       隱式Intent中聲明的Category必須全部能夠與某一個(gè)過濾器中的Category匹配才算匹配成功。比如說一個(gè)Category屬性設(shè)為CATEGORY_BROWSABLE的隱式Intent也可以通過上面的過濾器,也就是說,過濾器的Category屬性內(nèi)容必須是大于或者等于隱式Intent的Category屬性時(shí)候,隱式Intent才能匹配成功。

如果一個(gè)隱式Intent沒有設(shè)置Category屬性,那么它可以通過任何一個(gè)過濾器的Category匹配。

10.3 Data匹配規(guī)則

一個(gè)過濾器可以不聲明Data屬性也可以聲明多個(gè)Data屬性,如下:

<intent-filter>
    <data android:mimeType="video/mpeg" android:scheme="http" ... />
    <data android:mimeType="audio/mpeg" android:scheme="http" ... />
    ...
</intent-filter>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

每個(gè)Data屬性都可以指定數(shù)據(jù)的URI結(jié)構(gòu)和數(shù)據(jù)MIME類型。URI包括scheme、host、port 和path四個(gè)部分,host和port合起來也成authority(host:port)部分。

<scheme>://<host>:<port>/<path>
  • 1
  • 1

例如:

content://192.168.0.1:8080/folder/subfolder/etc
  • 1
  • 1

在這個(gè)URI中,scheme是content,host是192.168.0.1,port是8080,path是folder/subfolder/etc。我們平時(shí)使用的網(wǎng)絡(luò)url就是這種格式。

在URI中,每個(gè)組成部分都是可選的,但是有線性的依賴關(guān)系

  • 如果沒有scheme部分,那么host部分會(huì)被忽略
  • 如果沒有host部分,那么port部分會(huì)被忽略
  • 如果host部分和port部分都沒有,那么path部分會(huì)被忽略

當(dāng)進(jìn)行URI匹配時(shí)候,并不是比較全部,而是局部對比,以下是URI匹配規(guī)則。

  • 如果一個(gè)URI僅聲明了scheme部分,那么所有擁有與其相同的scheme的URI都會(huì)通過匹配,其他部分不做匹配
  • 如果一個(gè)URI聲明了scheme部分和authority部分,那么擁有與其相同schemeauthority的URI才能匹配成功,path部分不做匹配
  • 如果一個(gè)URI所有的部分都聲明了,那么只有所有部分都相同的URI才能匹配成功

注意:path部分可以使用通配符(*),也就是path其中的一部分進(jìn)行匹配。

Data匹配時(shí)候,MIME類型和URI兩者都會(huì)進(jìn)行匹配,匹配規(guī)則如下:

  • 如果過濾器未聲明URI和MIME類型,則只有不含URI和MIME類型的隱形Intent才能匹配成功
  • 如果過濾器中聲明URI但是未聲明MIME類型(也不能從URI中分析出MIME類型),則只有URI與過濾器URI相同且不包含IME類型的隱式Intent才能匹配成功
  • 如果過濾器聲明MIME類型但是未聲明URI,只有包含相同MIME類型但是不包含URI的隱式Intent才能匹配成功
  • 如果過濾器聲明了URI和MIME類型(既可以是直接設(shè)置,也可以是從URI分析出來),只有包含相同的URI和MIME類型的隱式Intent才能匹配成功

注意:進(jìn)行匹配時(shí)候必須以過濾器為單位進(jìn)行匹配,不能跨過濾器匹配。如果一個(gè)過濾器聲明了多個(gè)Action、Category、Data,隱式Intent包含的Action、CategoryData都能在過濾器中匹配到相應(yīng)的屬性即可,也就是說過濾器中聲明的屬性是大于或者等于Intent中包含的屬性,Intent才能匹配成功

11. 其他

       系統(tǒng)通過過濾器去匹配Intent,啟動(dòng)相應(yīng)組件,在PackageManager類中提供了一系列的查詢(queryIntentActivities()/queryIntentServices()/queryBroadcastReceivers())方法去查詢可以處理某個(gè)Intent的組件,也提供了一系列的解析(resolveActivity()/resolveService())方法來確定最佳啟動(dòng)組件。這些方法在某些場景下是非常有用的,也可以幫助我們降低程序crash風(fēng)險(xiǎn)。

12. 思考

       上文中對Intent以及IntentFilter進(jìn)行了詳細(xì)的講解,大多都是系統(tǒng)級別的處理過程。但是Intent作為一個(gè)官方已經(jīng)封裝好的信息攜帶者,我們可以用它來做很多事情。比如可以寫自己的一套匹配規(guī)則,Intent僅僅作為數(shù)據(jù)攜帶者,通過它去傳遞一些信息,實(shí)現(xiàn)Fragment/Activity的頁面跳轉(zhuǎn)邏輯。關(guān)于Intent的使用,我相信還有更多的用處,需要用戶一步一步的去探索。

    本站是提供個(gè)人知識管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多

    欧美一区二区黑人在线| 亚洲黑人精品一区二区欧美| 日本熟女中文字幕一区| 亚洲熟妇熟女久久精品| 亚洲最新一区二区三区| 国内外免费在线激情视频| 91麻豆精品欧美一区| 国产超碰在线观看免费| 好吊日成人免费视频公开| 国产又大又黄又粗的黄色| 日本女优一区二区三区免费| 偷自拍亚洲欧美一区二页| 欧美成人国产精品高清| 亚洲一区二区三区国产| 在线观看免费午夜福利| 国产内射一级一片内射高清视频| 99国产一区在线播放| 一区二区福利在线视频| 黄色片国产一区二区三区| 国产不卡的视频在线观看| 国产日韩精品激情在线观看| 日本理论片午夜在线观看| 精品国产亚洲免费91| 亚洲熟妇熟女久久精品 | 人妻中文一区二区三区| 91播色在线免费播放| 午夜精品在线观看视频午夜| 开心久久综合激情五月天| 欧美日本精品视频在线观看| 国产一区二区三区av在线| 很黄很污在线免费观看| 日本深夜福利视频在线| 成人午夜视频在线播放| 中日韩免费一区二区三区| 永久福利盒子日韩日韩| 九九九热在线免费视频| 国产亚洲精品香蕉视频播放| 国产亚洲系列91精品| 大香蕉再在线大香蕉再在线| 亚洲一区二区三区在线中文字幕| 中文字幕不卡欧美在线|