Intent在Android開發中的使用總結

關於Intent的使用,其實已經有很多文章進行了詳細的介紹,包括谷歌開發者網站也有進行很詳細的介紹。這裏再重複這個輪子的過程,主要是加深自己對Intent的認識,以及方便之後的查閱。

1、Intent是什麼

Intent是一個消息傳遞對象,可以使用它來完成對其它應用組件的請求操作。從這裏可以看出,Intent是一個對象,它的主要功能有兩個一個是傳遞消息,另外一個就是請求應用組件了,而這個傳遞消息也就是向請求的應用組件來傳遞的消息。

Inent請求的應用組件主要有三類

*請求Activity

通過將 Intent 傳遞給 startActivity(),可以啓動新的 Activity 實例。Intent 描述了要啓動的 Activity,並攜帶了任何必要的數據。

*請求Service

通過將 Intent 傳遞給 startService(),可以啓動服務執行一次性操作(例如,下載文件)。Intent 描述了要啓動的服務,並攜帶了任何必要的數據。

*請求Broadcast

通過將 Intent 傳遞給 sendBroadcast()、sendOrderedBroadcast() 或 sendStickyBroadcast(),可以將廣播傳遞給本應用或者其他應用。

2、Intent的分類

Intent在實際使用過程總可以根據其請求組件的方式來分成隱式Intent以及顯示Intent

2.1、顯示Intent

當在使用Intent請求組件時,按名稱(完全限定類名)指定要啓動的組件,我們吧這種Intent叫做顯示Intent,顯示Intent的使用範圍很廣,平時在Activity頁面跳轉時就基本都是使用的顯示Intent,如下所示

Intent intent = new Intent(this,TestActivity.class);
startActivity(intent);

這種使用方式使用的Intent,就是顯示Intent,顯示Intent傳遞數據常常通過intent.putExtra()的方式來進行

intent.putExtra("key","value");

2.2、隱式Intent

當在使用Intent請求組件時,與隱式Intent相反,顯示Intent不會指定特定的組件,而是聲明要執行的常規操作(action),從而允許其他應用中的組件來處理它,說的比較玄乎,直接看看代碼就能明白。

Intent intent = new Intent(Intent.ACTION_DIAL);
intent.setData(Uri.parse("tel:10086"));
startActivity(intent);

這裏的Intent.ACTION_DIAL對應字符串

public static final String ACTION_DIAL = "android.intent.action.DIAL";

而這裏就可以看出隱式Intent和顯示Intent的明顯不同了,但是有童鞋可能會疑惑了,根據這個Intent.ACTION_DIAL,怎麼調用起了系統的撥號界面了呢,這個就要細說隱式Intent了,這個放在下一節詳細介紹。

3、細說隱式Intent的使用

隱式Intent爲何根據字符串可以調用起來一個頁面呢,聰明的童鞋肯定能夠想那是因爲頁面和字符串存在一個對應關係,這就關係就是在被調動頁面的AndroidManifest.xml文件中進行定義了。

例如,這裏應用2中AndroidManifest.xml配置文件中對TargetActivity頁面進行如下配置

<activity android:name=".TargetActivity">
    <intent-filter>
        <action android:name="com.yoryky.intent.action.TARGET"/>
        <category android:name="android.intent.category.DEFAULT"/>
    </intent-filter>
</activity>

之類看到對activity註冊添加了一個intent-filter 的標籤,這個標籤就是關鍵了,看名字也能大概知道這個標籤是用來過濾Intent啓動的組件的(這裏是Activity),這裏TargetActivity和action對應的name就形成了一個對應關係(並不一定是一一對應關係),我們便能夠其他應用中通過

Intent intent = new Intent("com.yoryky.intent.action.TARGET");
start(intent);

這種方式來啓動TargetActivity,當還有其它模塊的Activity也通過com.yoryky.intent.action.TARGET這個字符串來進行過濾的話,那麼以上intent請求的Activity組件便有多個,系統就會彈出提示框來讓用戶指定啓動的具體使哪一個Activity組件。

到這裏可能有同學會問了,以上intent-filter 標籤中除了action過濾外,不是還有個category
這個category標籤是用來聲明對應組件的類別的,Intent 過濾器既可以不聲明任何 category 元素,也可以聲明多個此類元素,當聲明瞭一個或者多個category 元素時,用來啓動該組件的Intent必須滿足category的過濾條件,才能啓動對應的組件。

實際上intent-filter 中除了可以添加action 以及category 這兩個標籤外,還可以添加data 標籤進行過濾。

在目標data標籤中包含了以下幾種子元素,它們定義了Uri的匹配規則:

android:scheme 匹配Uri中的前綴,除了“http”、“https”、“tel”…之外,我們可以定義自己的前綴

android:host 匹配Uri中的主機名部分,如“google.com”,如果定義爲“*”則表示任意主機名

android:port 匹配Uri中的端口

android:path 匹配Uri中的路徑

android:mimeType 匹配Uri路徑所指數據的MIME類型

例如這裏再AndroidManifest.xml中對TargetActivity作如下配置

<activity android:name=".TargetActivity">
    <intent-filter>
        <action android:name="com.yoryky.intent.action.TARGET" />
        <category android:name="android.intent.category.DEFAULT" />
        <data
            android:host="com.yoryky.example.data"
            android:path="/target"
            android:port="1122"
            android:scheme="test"
            android:minmeType="text/xml"/>
    </intent-filter>
</activity>

這裏看到加入了data 標籤進行過濾,那麼在其它模塊中通過隱式Intent來請求這個TargetAcivity時,就必須嚴格按照data 標籤的過濾條件來啓動TargetActivity

Intent intent = new Intent("com.yoryky.intent.action.TARGET");  
intent.setDataAndType(Uri.parse("test://com.yoryky.example.data:1122/target"),"text/xml"); 
startActivity(intent);  

當然data 標籤不是必須的,data 標籤所包含的素數也不需要每種都使用來過濾,這樣過濾的條件也就會寬鬆一些。

需要注意的是,也是從 7.0 開始,Android SDK 中的 StrictMode 策略禁止開發人員在應用外部公開 file:// URI。具體表現爲,當我們在應用中使用包含 file:// URI 的 Intent 離開自己的應用時,程序會發生故障。

開發中,如果我們在使用 file:// URI 時忽視了這兩條規定,將導致用戶在 7.0 及更高版本系統的設備中使用到相關功能時,出現 FileUriExposedException 異常,導致應用出現崩潰閃退問題,而這兩個過程的替代解決方案便是使用 FileProvider,關於這方面的知識可以參考關於 Android 7.0 適配中 FileProvider 部分的總結 這篇文章。

到這裏我想總結的Intent知識就差不多了,有什麼問題還望各位童鞋多多指教。

參考文獻

1、Android總結篇——Intent機制詳解及示例總結

2、關於 Android 7.0 適配中 FileProvider 部分的總結

3、Intent屬性詳解三 data、type和extra

4、Intent 和 Intent 過濾器

5、Intent

6、URI

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章