Android中的Intent詳解


前言:

每個應用程序都有若干個Activity組成,每一個Activity都是一個應用程序與用戶進行交互的窗口,呈現不同的交互界面。因為每一個Acticity的任務不一樣,所以經常互在各個Activity之間進行跳轉,在Android中這個動作是靠Intent來完成的。你通過startActivity()方法發送一個Intent給系統,系統會根據這個Intent幫助你找到對應的Activity,即使這個Activity在其他的應用中,也可以用這種方法啟動它。

Intent的定義:

Intent是Android系統用來抽象描述要執行的一個操作,也可以在不同組件之間進行溝通和消息傳遞。

Intent意圖可以是明確的指定組件的名稱,這樣你可以精確的啟動某個系統組件,比如啟動一個Activity。它也可以是模糊的,沒有指定組件名稱,只要是能夠匹配到這個Intent的應用都可以接收到,比如發送一個拍照Intent,所有的拍照應用都會響應。

顯式Intent和隱式Intent:

顯式的Intent就是你已經知道要啟動的組件名稱,比如某個Activity的包名和類名,在Intent中明確的指定了這個組件(Activity),一般來說這種Intent經常用在一個應用中,因為你已經明確的知道要啟動的組件名稱。

隱式的Intent就是你不知道要啟動的組件名稱,只知道一個Intent動作要執行,比如:拍照,錄像,查看地圖。一般來說這種Intent用在不同的應用之間傳遞信息。

當你創建一個顯式Intent來啟動一個Activity或者Service時,系統會立刻啟動那個組件通過你的Intent對象。

當你創建一個隱式Intent,系統會根據manifest file中的intent filter找匹配的組件,如果你發送的Intent匹配到一個intent filter,系統會把你的Intent傳遞給該filter對應的組件(Activity、Service等),並且啟動它。如果找到多個匹配的intent filter對應的應用程序,則會彈出一個對話框讓你選擇哪個應用程序接受你的Intent。

 
注:
1、intent filter是一種應用程序manifest文件中的語法表達,就像是html的標簽,它是一個系統組件標簽(比如:Activity)的組成部分,可以說是子標簽吧,這個系統組件接受什么樣的intent就是用它來指定的,如果一個系統組件不寫intent filter,那么它只能通過顯式的intent來啟動。
2、出於安全的角度,你的Service組件務必不要用隱式的intent filter來進行說明,因為用隱式的intent啟動一個Service往往不能保證Service會被啟動,並且用戶也不知道哪個Service會響應你的Intent。從Android5.0(API 21),系統會拋出異常當你用隱式的Intent去調用bindService()方法。

創建一個Intent:

Android系統通過Intent對象攜帶的信息來確定啟動哪個系統組件,比如:准確的組件名稱,哪一個類別的組件會接收到這個intent,Intent還會攜帶其他的信息以便於組件正確的執行action。一個Intent主要包含以下信息:

Component name:

要啟動的組件名稱,在創建Intent的時候是可選的,但是它是顯式Intent的重要標志,有它就意味着只有Component name匹配上的那個組件才能接收你發送出來的顯示intent。如果不寫那么你創建的Intent就是隱式的,系統會根據這個intent的其他信息(比如:action、data、category)來確定哪些組件來接收這個intent,所以如果你想明確的啟動哪個組件,就通過component name來指定。

Intent的ComponentName屬性是一個類的全稱,包括包名,比如:com.example.ExampleActivity,你可以通過Intent的setComponent(),setClass(),setClassName()方法來設定,也可以通過Intent的構造方法來設定。

Action:

意圖,一個字符串變量,用來指定Intent要執行的動作類別(比如:view or pick)。你可以在你的應用程序中自定義action,但是大部分的時候你只使用在Intent中定義的action。下面是啟動Activity經常用的action:

  • ACTION_VIEW:

在調用startActivity()方法啟動Activity時,用此action來呈現一些信息給用戶,比如在相冊中查看一張照片,顯示一個地理位置在地圖中。

  • ACTION_SEND:

也被稱為"share"(共享)意圖,在調用startActivity()方法啟動Activity時,用此action來分享一些用戶想要分享的數據給其他應用程序,比如郵件app或者社交app。

想要了解更多的action可以查看Intent源碼或者api,在Intent中定義了很多action,除了在Android framework中,在別處也定義了很多action,比如在Settings應用中。

你可以通過Intent的setAction()方法或者Intent的構造方法來指定action。如果你要自定義action,最好是用你的包名做前綴,比如:

static final String ACTION_TIMETRAVEL = "com.example.action.TIMETRAVEL";

Data:

一個Uri對象,對應着一個數據,這個數據可能是MIME類型的。當創建一個intent時,除了要指定數據的URI之外,指定數據的類型(MIME type)也很重要,比如,一個activity能夠顯示照片但是無法播放視頻,雖然啟動Activity時URI格式很相似。指定MIME type是很重要的,它能夠幫助系統找到最合適的那個系統組件來處理你的intent請求。然而,MIME type有時能夠通過URI來推測出來,特別是當data是content:的URI,這樣的data表明在設備中由ContentProvider提供。

只設置數據的URI可以調用setData()方法,只設置MIME類型可以調用setType()方法,如果要同時設置這兩個可以調用setDataAndType()。

注意:如果要設置URI和MIME,不要調用setData()和setType(),因為會相互清除設置的參數數據,而是直接調用setDataAndType()。

Category:

一個包含Intent額外信息的字符串,表示哪種類型的組件來處理這個Intent。任何數量的Category 描述都可以添加到Intent中,但是很多intent不需要category,下面列舉一些常用的category:

  • CATEGORY_BROWSABLE:

目標Activity允許從web頁面上的鏈接(比如圖片鏈接)啟動來顯示數據。

  • CATEGORY_LAUNCHER:

表示這個Activity是Activity棧最初的Activity,應用程序的主Activity,可以在桌面應用程序列表找到並啟動它。

你可以通過調用addCagegory()方法來設置category。

以上Intent的屬性(component name、action、data and category)都是Intent的特征屬性,通過這些屬性Android系統可以找到哪個應用組件將會被啟動。

 

以下的屬性是Intent的額外屬性,這些屬性不會影響到intent的處理和啟動系統組件。

Extras:

Intent可以攜帶的額外key-value數據,你可以通過調用putExtra()方法設置數據,每一個key對應一個value數據。你也可以通過創建Bundle對象來存儲所有數據,然后通過調用putExtras()方法來設置數據。對於數據key的名字要盡量用包名做前綴,然后再加上其他,這樣來保證key的唯一性。

Flags:

用來指示系統如何啟動一個Activity(比如:這個Activity屬於哪個Activity棧)和Activity啟動后如何處理它(比如:是否把這個Activity歸為最近的活動列表中)。

創建顯式Intent:

一個顯式Intent明確的指定了要啟動的組件名稱,比如Activity名稱或者Service的名稱。創建一個顯式的Intent必須定義Component屬性,其他的屬性可選。下面的例子是創建一個Service在app中,名字叫DownloadService,功能是從網絡上下載文件,你可以通過下面的代碼來啟動它:

// Executed in an Activity, so 'this' is the Context
// The fileUrl is a string URL, such as "http://www.example.com/image.png"
Intent downloadIntent = new Intent(this, DownloadService.class);
downloadIntent.setData(Uri.parse(fileUrl));
startService(downloadIntent);

創建隱式Intent:

一個隱式的Intent定義了將要執行的動作,任何在設備上的app都可以響應這個動作。用隱式Intent的非常的有用,當你的app不能處理某些請求動作時,但是系統中的其他應用有這個處理的能力,用戶就能方便的利用其他應用完成這個操作。比如你用百度雲盤下載了一個pdf文檔,你在點擊打開這個文檔的時候百度雲盤是無法打開的,但是也許你系統上安裝有其他的能打開pdf文檔的閱讀器,這個時候就會彈出一個對話框,列舉了可以打開pdf文檔的應用程序,你可以自由選擇一個應用程序打開你下載的文檔。例如下面查看文檔的例子:

// Create the text message with a string
Intent sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_TEXT, textMessage);
sendIntent.setType(HTTP.PLAIN_TEXT_TYPE); // "text/plain" MIME type

// Verify that the intent will resolve to an activity
if (sendIntent.resolveActivity(getPackageManager()) != null) {
    startActivity(sendIntent);
}
注意:也許你的設備中沒有能夠執行你的隱式Intent的應用,這個時候startActivity將會失敗並且你的app會出現crash,最好的辦法是在startActivity之前調用resolveActivity檢查一下是否有Activity可以響應。
如果系統中有一個應用程序可以響應則會直接打開那個應用程序,如果系統中有多個app可以處理這個action則會彈出對話框讓你選擇哪個應用程序來處理。

總結:

以上內容主要說了Intent的定義、分類和屬性解釋,這樣讓你對Intent有一個詳細的了解,為以后學習利用Intent在應用程序之間進行交流打下基礎。

本文屬原創,轉載請注明出處,違者必究

關注微信公眾平台:程序員互動聯盟(coder_online),你可以第一時間獲取原創技術文章,和(java/C/C++/Android/Windows/Linux)技術大牛做朋友,在線交流編程經驗,獲取編程基礎知識,解決編程問題。程序員互動聯盟,開發人員自己的家。

C++ Primer快速入門之七:運算符

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM