1. 程式人生 > >Android筆記02:Intent機制詳解

Android筆記02:Intent機制詳解

tar 中一 定義 tty 一段 AI new 例如 pac

一、什麽是Intent?

Intent在Android中提供了Intent機制來協助應用間的交互與通訊,Intent負責對應用中一次操作的動作、動作涉及數據、附加數據進行描述,Android則根據此Intent的描述,負責找到對應的組件,將Intent傳遞給調用的組件,並完成組件的調用。Intent不僅可用於應用程序之間,也可用於應用程序內部的Activity/Service之間的交互。因此,可以將Intent理解為不同組件之間通信的“媒介”,專門提供組件互相調用的相關信息。

二、Intent的作用

Intent 是一個將要執行的動作的抽象的描述,一般來說是作為參數來使用,由Intent來協助完成android各個組件之間的通訊。比如說調用 startActivity()來啟動一個activity,或者由broadcaseIntent()來傳遞給所有感興趣的 BroadcaseReceiver, 再或者由startService()/bindservice()來啟動一個後臺的service.所以可以看出來,intent主要是用來啟動其他的 activity 或者service,所以可以將intent理解成activity之間的粘合劑。

三、Intent的兩種類型

Intent大致可以分為兩種類型:顯式Intent和隱式Intent。

顯式Intent:

如果在我們定義的Intent中明確包含了要啟動的組件的完整類名(包名及類名),即Intent的“意圖”非常明顯,那麽這個Intent就是顯式的。使用顯式Intent最典型的情形是在你自己的程序中啟動一個組件,因為你自己肯定知道自己的要啟動的組件的類名。比如,為了響應用戶操作通過顯式的Intent在你的程序中啟動一個Activity或啟動一個Service下載文件。

隱式Intent:

沒有明確指定組件名要啟動哪一個活動,而是系統根據動作(action)、類別(category)、數據(Uri)和數據類型來找到最合適的組件。一般來說我們需要在<intent-filter>裏設置category、action和data等信息。需要註意的是,為了確保App的安全性,我們應該總是使用顯式Intent去啟動Service並且不要為該Service設置任何的Intent Filter。通過隱式的Intent啟動Service是有風險的,因為你不確定最終哪個App中的哪個Service會啟動起來以響應你的隱式Intent,更悲催的是,由於Service沒有UI的在後臺運行,所以用戶也不知道哪個Service運行了。

Intent Filter,即Intent過濾器,一個組件可以包含0個或多個Intent Filter。Intent Filter是寫在App的manifest文件中的,其通過設置action或uri數據類型等指明了組件能夠處理接收的Intent的類型。

隱式Intent的具體方法:

<activity

           android:name=".ThreeActivity"

           >

            <intent-filter >

                <action android:name="android.intent.action.VIEW"
/> <category android:name="android.intent.category.DEFAULT"/> <data android:scheme="http"/> </intent-filter> </activity>

其中<action>標簽指明了當前活動可以響應的action。<category>標簽則附加了一些信息,更精確地指明了當前活動能響應的Intent還可能帶有的category。只有<action>和<category>同時匹配上Intent中指定的action和category時,活動才能響應該Intent。

<data>標簽能夠更精確地指定當前活動能夠響應什麽類型的數據。

<data>標簽中主要可以配置一下內容:

android:scheme。用於指定數據的協議部分,如http。

android:host。用於指定數據的主機名部分。

android:port。用於指定數據的端口部分,一般在主機名之後。

android:path。用於指定主機名和端口之後的部分,如一段網址中跟在域名之後的內容。

android:mimeType。用於指定可以處理的數據類型,允許使用通配符的方式進行指定。

只用當<data>標簽中指定的內容和Intent中攜帶的data部分完全一致時,當前活動才能夠響應intent。

顯式Intent示例:

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

上面的代碼在Intent的構造函數中指定了要啟動的組件的ComponentName是ActivityB,該intent對象是顯式的,調用startActivity(intent)時,Android系統會立即啟動ActivityB。

隱式Intent示例:

在使用隱式Intent的時候需要指定其action。如果你的App不能完成某個功能,但是其他的App可能完成該功能,那麽你就可以用隱式Intent啟動其他的App去完成相應的功能。例如,你有一段文本信息,想通過其他App分享出去,那麽隱式Intent對象去啟動潛在的支持分享的App,示例代碼如下:

Intent sendIntent = new Intent();
// 設置action, action對隱式Intent來說是非常重要的
sendIntent.setAction(Intent.ACTION_SEND);
// 設置數據的MIME類型為純文本類型
sendIntent.setType("text/plain");
// 設置額外的數據
sendIntent.putExtra(Intent.EXTRA_TEXT, textMessage);

// 獲取包管理器
PackageManager pm = getPackageManager();
// 先判斷系統中有沒有潛在的App的Activity支持對該sendIntent的接收與處理
if (pm.resolveActivity(sendIntent, 0) != null) {
    startActivity(sendIntent);
}

上面的代碼中,我們構建了一個Intent對象,並沒有給其設置component name,所以該Intent是一個隱式的Intent對象。我們首先給intent設置了action的值為Intent.ACTION_SEND,action對隱式Intent來說是非常重要的。然後我們將intent的數據的MIME類型設置為純文本類型(“text/plain”),告知Android我們的Intent持有的是文本類型的數據。最後我們將實際的文本數據通過putExtra()方法作為額外數據設置進去。
需要註意的是,在構建好了Intent對象之後,我們沒有立即執行startActivity(sendIntent)方法,而是將sendIntent作為參數傳遞給了PackageManager的resolveActivity()方法中,該方法會讓Android根據該sendIntent找到潛在的適合啟動的組件的信息,並以ResolveInfo類的對象的形式返回結果,如果返回null,表示當前系統中沒有任何組件可以接收並處理該sendIntent。如果返回不是null,就表明系統中至少存在一個組件可以接收並處理該sendIntent,只有在這種情況下,我們才會執行代碼startActivity(sendIntent),在通過intent啟動組件之前先判斷要啟動的組件存不存在是個良好的編程習慣,因為如果系統中不存在支持你的intent的組件,那麽當你調用startActivity()、startService()、bindService()等方法的時候,Android就會拋出異常。

(後續還會有修改和補充)

Android筆記02:Intent機制詳解