標籤:ack http 判斷 需要 下載檔案 返回結果 顯式intent 應該 app
一、什麼是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機制詳解