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

來源:互聯網
上載者:User

標籤:

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傳遞過去。

intent-filters是manifest檔案中組件內部的一個標籤,該標籤描述了組件具備什麼特性,如果您未配置intent-filters,那個該組件只能被顯式啟動。

建立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 stringIntent 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 activityif (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 dialogIntent chooser = Intent.createChooser(sendIntent, title);// Verify the original intent will resolve to at least one activityif (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如下配置:

<activity android:name="ShareActivity">    <intent-filter>        <action android:name="android.intent.action.SEND"/>        <category android:name="android.intent.category.DEFAULT"/>        <data android:mimeType="text/plain"/>    </intent-filter></activity>

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

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

intent-filter舉例(Example filters)

下面是一個社交APP的manifest檔案樣本:

<activity android:name="MainActivity">    <!-- This activity is the main entry, should appear in app launcher -->    <intent-filter>        <action android:name="android.intent.action.MAIN" />        <category android:name="android.intent.category.LAUNCHER" />    </intent-filter></activity><activity android:name="ShareActivity">    <!-- This activity handles "SEND" actions with text data -->    <intent-filter>        <action android:name="android.intent.action.SEND"/>        <category android:name="android.intent.category.DEFAULT"/>        <data android:mimeType="text/plain"/>    </intent-filter>    <!-- This activity also handles "SEND" and "SEND_MULTIPLE" with media data -->    <intent-filter>        <action android:name="android.intent.action.SEND"/>        <action android:name="android.intent.action.SEND_MULTIPLE"/>        <category android:name="android.intent.category.DEFAULT"/>        <data android:mimeType="application/vnd.google.panorama360+jpg"/>        <data android:mimeType="image/*"/>        <data android:mimeType="video/*"/>    </intent-filter></activity>

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-filter>    <action android:name="android.intent.action.EDIT" />    <action android:name="android.intent.action.VIEW" />    ...</intent-filter>

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

匹配Category(Category test)

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

<intent-filter>    <category android:name="android.intent.category.DEFAULT" />    <category android:name="android.intent.category.BROWSABLE" />    ...</intent-filter>

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標籤:

<intent-filter>    <data android:mimeType="video/mpeg" android:scheme="http" ... />    <data android:mimeType="audio/mpeg" android:scheme="http" ... />    ...</intent-filter>

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

<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類型的規則如下:

  1. 如果intent-filter中未指定data,則未添加data的intent可以匹配;
  2. 如果intent-filter中指定了URI,但未指定mimeType,則按照上一段的規則匹配(intent中也應未指定mimeType);
  3. 如果intent-filter中指定了mimeType,而未指定URI,則可以匹配intent中指定了相同mimeType,而未指定URI的組件;
  4. 如果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

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

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.