Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android官方文檔之App Components(Intents and Intent Filters)

Android官方文檔之App Components(Intents and Intent Filters)

編輯:關於Android編程

Android應用框架鼓勵開發者在開發應用時重用組件,本文將闡述如何用組件構建應用程序以及如何用intent將組件聯系起來。
如需閱讀官方原文,請您點擊這個鏈接:

《App Components》。

您還可以參考這些博文:

《Using DialogFragments》

《Fragments For All》

《Multithreading For Performance》

以及這些Training:

《Managing the Activity Lifecycle》

《Building a Dynamic UI with Fragments》

《Sharing Content》


Intent 與 Intent Filters(Intents and Intent Filters)

Intent是一個傳遞消息的對象,您可以為Intent指定action來啟動其他應用組件,Intent使組件之間通信更加便利,並且通信方式有很多,這裡列舉了主要的三點:

啟動Activity:

您可以將intent作為參數調用startActivity()方法啟動一個activity。該intent描述了將要啟動的目標activity的特性並攜帶必要的數據信息。您還可以調用startActivityForResult()方法回傳信息。

啟動Service:

Service用於在後台執行任務,不與用戶交互。您可以使用startService()方法執行一次性的操作(比如後在台下載一個文件),這需要Intent參數。
如果組件之間需要向CS結構一樣通訊,您可以把Service想成一端,並調用bindService(),這同樣需要Intent參數。

傳遞一個broadcast:
broadcast是一種可以被任何應用程序截獲的廣播機制。系統會基於當前發生的事件發出各式broadcast(比如設備開機時、開始充電時等),您可以調用sendBroadcast(),、sendOrderedBroadcast()、 sendStickyBroadcast()方法發送一條廣播,這需要傳入Intent參數。


Intent的種類(Intent Types)

顯式Intent:通過指定具體類名啟動一個組件。顯式Intent一般用於同一應用程序內,因為您可以確定地知道要啟動的組件名。另外,Android 5.0以後規定必須顯式啟動Service。

隱式Intent:當希望啟動具備某種特性的組件時,可以使用隱式Intent,隱式Intent無需指定類名,通常用於啟動其他應用程序的組件,比如您打算啟動一個地圖定位的activity。


當您隱式地啟動一個service或activity時,Intent會根據其中的內容,匹配其他組件中manifest文件的Intent-filter,啟動符合條件的組件,並把Intent中的參數傳過去,如果有多個intent-filter滿足條件,那麼系統會彈出一個對話框,由用戶決定啟動哪個組件。下面是intent與intent-filters配合啟動組件的示意圖:
這裡寫圖片描述


見上圖:
1、首先Activity A利用傳入的Intent調用startActivity();
2、系統會根據該Intent的條件搜索Android系統中所有匹配的組件;
3、若找到了匹配intent的intent-filters所屬的組件(Activity B),則啟動該組件,並回調onCreate()方法,同時將Intent傳遞過去。<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD4NCjxociAvPg0KPHA+aW50ZW50LWZpbHRlcnPKx21hbmlmZXN0zsS8/tbQ1+m8/sTasr+1xNK7uPax6sepo6y4w7Hqx6nD6Mr2wcvX6bz+vt+xuMqyw7TM2NDUo6zI57n7xPrOtMXk1sNpbnRlbnQtZmlsdGVyc6OsxMe49rjD1+m8/ta7xNyxu8/Uyr3G9LavoaM8L3A+DQo8aHIgLz4NCjxoMiBpZD0="創建intent對象building-an-intent">創建Intent對象(Building an Intent)

Intent中包含了目標組件需滿足的特性。Intent中應包含以下信息:

Component name:目標組件的名字。對於顯式啟動,這是不可缺省的,您可以使用Intent的構造方法傳入組件名稱,也可以調用setComponent(), setClass(), setClassName()這些方法傳入組件名;若是隱式啟動,這是可選的,但intent應包含其他信息(action、category、data);

Action:是一個可以指明目標組件行為的字符串。action很大程度上決定了category和data中應傳入的信息;您也可以在自己的應用程序組件中指定action,以便讓其他應用程序啟動自己的組件。對應action中字符串,不建議使用硬編碼的形式,而應在所屬組件的類中設置為常量。

常見的action有:

ACTION_VIEW:用ACTION _VIEW啟動的activity一般可以向用戶展示一些信息,比如啟動一個相冊APP中展示圖片的activity,或是啟動一個地圖APP中展示地址信息的activity。 ACTION_SEND:一般需要向 通過ACTION _SEND啟動的activity 附帶著發送一些信息,這些信息由由目標activity決定該發送給誰,比如社交類APP或是發送郵件的APP。

您可以將action作為參數傳入Intent的構造方法或setAction()方法中。
如需定義在自己的組件中定義action,應以應用的包名作為前綴,比如:

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

Data:一個URI對象是一個引用的data的表現形式,或是data的MIME類型;data的類型由Intent的action決定,比如說若action是ACTION_EDIT,那麼data的URI應指向一個可編輯的文件。當創建一個Intent時,除了為data指定URI以外,還應該指定data的MIME類型,比如說,一個用於展示圖片的activity是不能用來放音樂的,如果您要啟動這個activity,就需要將data的MIME類型指定為”image/png”、”image/jpeg”等。有些時候,從data的URI中就能推斷出MIME的類型,比如當一個URI的schema是”content://”時,表明該URI指向了設備內部的一個文件並由ContentProvider管理著,系統可以根據該文件推斷出data的MIME類型。
您可以調用setData()方法設置URI,調用setType()方法設置MIME類型,或調用setDataAndType()方法同時設置URI和MIME類型。

!請注意:如果您需要同時設置URI和MIME類型,只能調用setDataAndType()方法,而不能分別調用setData()和setType(),因為調用setData()時會首先將setType()中的內容置空,反之亦然( they each nullify the value of the other)

Category:是一個字符串,表示目標組件的附加信息,大部分intent不需要category。以下是依稀而常用的category:

CATEGORY_BROWSABLE:表示目標activity可以被網頁上的某個鏈接啟動,如圖片activity或e-mail信息activity。 CATEGORY_LAUNCHER:目標activity是任務棧的第一個activity,也就是應用程序的啟示activity。

您可以將category參數傳入addCategory()方法中。

上述的參數(component name, action, data, and category)代表了intent的屬性,通過這些參數,系統可以篩選出符合條件的目標組件。除此之外,intent還可以包含下列參數,與上面的參數不同的是,系統不會使用這些參數來篩選目標組件:

Extras:一些intent可以攜帶的附加信息,以鍵值對的形式存儲。可以使用putExtra()方法將鍵值對信息傳入,也可以將鍵值對信息放在Bundle對象中,再通過將Bundle對象傳入putExtra()中。
Intent類中封裝了許多 ” EXTRA_* “形式的標准extra,如果想封裝自己的extra鍵,請您以應用程序的報名作為前綴,比如:
static final String EXTRA_GIGAWATTS = "com.example.EXTRA_GIGAWATTS";
Flags:該參數可以為intent添加元數據(meta-data),flag可以指導系統以何種方式啟動一個activity、是否將啟動的activity放在該應用的任務棧中,等等。

隱式Intent的例子(Example implicit intent)

!請注意:若系統中沒有滿足隱式Intent的目標組件,則應用將崩潰(crash),所以首先應判斷,在調用startActivity()。
以下是一個通過隱式intent啟動一個“發送信息的Activity”的例子:

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

// Verify that the intent will resolve to an activity
if (sendIntent.resolveActivity(getPackageManager()) != null) {
    startActivity(sendIntent);
}

如果有一個目標組件滿足intent,則啟動該組件;若有多個滿足intent的目標組件,則系統彈出一個列表以供選擇。


使用應用選擇器(Forcing an app chooser)

正如向上面說,系統中可能存在多個目標組件滿足隱式intent,這時會彈出一個列表供用戶選擇,有些時候,用戶希望每次都啟動一個相同的組件(比如用戶每次都想啟動chrome浏覽器而不是系統自帶的浏覽器),這時只需要勾選“不再詢問”選項就行了,下次再啟動時,列表將不再彈出;還有些時候,用戶每次都需要對列表中的Activity進行篩選,比如啟動用於分享的Activity,用戶希望每次分享到不同的平台,這時需要調用Intent.createChooser()方法以保證每次都彈出選擇列表,如下所示:

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

// Always use string resources for UI text.
// This says something like "Share this photo with"
String title = getResources().getString(R.string.chooser_title);
// Create intent to show the chooser dialog
Intent chooser = Intent.createChooser(sendIntent, title);

// Verify the original intent will resolve to at least one activity
if (sendIntent.resolveActivity(getPackageManager()) != null) {
    startActivity(chooser);
}

接收隱式Intent(Receiving an Implicit Intent)

通過在manifest文件中配置intent-filter標簽中的action, data, and category,可以設置篩選信息,只有同時符合上述三個標簽設置的篩選信息,Intent才能開啟您的應用程序組件:

action標簽:
可匹配Intent中的action參數。

data標簽:
可匹配Intent中的data參數(URI地址以及MIME 類型)。

category標簽:
可匹配Intent中的category 參數。
!請注意:如組件需要被隱式啟動,必須配置CATEGORY_DEFAULT
如想隱式啟動一個分享的Activity,則目標Activity如下配置:


    
        
        
        
    

一個intent-filter中可以包含多個 action, data, category 標簽。

若組件僅希望通過本應用啟動,可將組件中的exported屬性設為false。
!請注意:為了避免隱式intent匹配上了您的Service組件,請不要在service中配置intent-filter(Service必須顯式啟動)


intent-filter舉例(Example filters)

下面是一個社交APP的manifest文件示例:


    
    
        
        
    



    
    
        
        
        
    
    
    
        
        
        
        
        
        
    

action為 “android.intent.action.MAIN”表示該Activity是應用的主入口,且無需配置data。
category為 “android.intent.category.LAUNCHER”表示該activity的啟動圖標(通過icon屬性配置)應添加到系統的launcher中,若未配置icon,則會使用application標簽下的icon。
以上兩個屬性應成對出現。

如需隱式啟動ShareActivity,僅需匹配一個intent-filter就行了。


使用Pending Intent(Using a Pending Intent)

PendingIntent是一個包裝Intent的類,主要用於實現Intent的延時啟動,PendingIntent的主要使用場合:

包裝一個Notification的啟動Intent; 包裝一個App Widget的Intent(按Home鍵啟動的activity); 包裝一個延時啟動的activity(如AlarmManager)。

使用PendingIntent啟動的activity無需使用startActivity()就能啟動,您應當使用對應組件的方法啟動相應組件:

通過PendingIntent.getActivity()啟動一個activity; 通過PendingIntent.getService()啟動一個Service; 通過PendingIntent.getBroadcast()啟動一個BroadcastReceiver;

解析Intent(Intent Resolution)

目標組件通過以下三點匹配相應的Intent:

The intent action; The intent data (both URI and data type); The intent category。

匹配Action(Action test)

intent filter可定義零到多個action標簽:


    
    
    ...

intent需要匹配上其中一個action標簽。如果intent-filter中沒有action標簽,則intent無需action就能匹配。


匹配Category(Category test)

intent filter可定義零到多個category標簽:


    
    
    ...

intent中的定義的每一個category都需要匹配上intent-filter中的category標簽,反之不成立(intent-filter中的category標簽可能比intent中的定義的category多)。所以無論intent-filter中是否定義了category標簽,未添加category的intent總能匹配上該intent-filter。
!請注意:通過startActivity()或startActivityForResult()方法隱式啟動的intent中,將自動被添加一個CATEGORY_DEFAULT的category,所以若您希望自己的activity能夠被隱式啟動,則需要在intent-filter中添加一個android.intent.category.DEFAULT的category標簽。


匹配Data(Data test)

intent filter可定義零到多個data標簽:


    
    
    ...

每個data標簽都能設置mimeType和URI 結構,其中URI可分成四部分:scheme, host, port 和 path;其結構如下:

://:/

比如:

content://com.example.project:200/folder/subfolder/etc

其中

scheme為content; host為com.example.project; port為200; path為folder/subfolder/etc。

每一部分在data標簽中都不是必須定義的,但存在一個線性依賴:

若scheme 未指定,則host被忽略; 若host未指定,則port被忽略; 若scheme和host均未指定,則path被忽略;

在intent中添加的data只需要匹配一部分intent-filter中的data(URI匹配):

若filter只定義了scheme,則intent的data定義的URI中只要包含了相同的scheme,就能匹配; 若filter只定義了scheme和host,則intent的data定義的URI中只要包含了相同的scheme和host,就能匹配; 若filter只定義了scheme、host和port,則intent的data定義的URI中只要包含了相同的scheme、host和port,就能匹配;

intent-filter匹配intent的data中URI和mimeType類型的規則如下:

如果intent-filter中未指定data,則未添加data的intent可以匹配; 如果intent-filter中指定了URI,但未指定mimeType,則按照上一段的規則匹配(intent中也應未指定mimeType); 如果intent-filter中指定了mimeType,而未指定URI,則可以匹配intent中指定了相同mimeType,而未指定URI的組件; 如果intent-filter中同時指定了mimeType和URI,則:
intent中添加的mimeType只要能匹配上intent-filter中的某一個mimeType,就能匹配上mimeType部分; intent中添加的URI則按照上一段中的URI匹配規則,就能該匹配上URI部分;特別地:若intent中的URI的scheme 指定為content: 或者 file:,那麼即便intent-filter中未定義URI,也能匹配成功。換句話說:包含content: 或者 file: 的URI總是能匹配上只定義了mimeType的intent-filter
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved