Skip to content

Most visited

Recently visited

navigation

意圖和意圖篩選器

Intent 是可用來向另一個應用程式元件要求動作的傳訊物件。 雖然意圖有幾種方式可加速元件間的通訊,但共有三種基本使用案例:

意圖類型

意圖類型分為兩種:

當您建立明確意圖以啟動 Activity 或服務時,系統會立即啟動 Intent 物件中指定的應用程式元件。

圖 1.說明如何透過系統傳送隱含意圖以啟動另一個 Activity:[1] Activity A 會建立含有動作描述的Intent 並傳送至 startActivity()[2] Android 系統會搜尋所有應用程式,以找出符合該意圖的意圖篩選器。 找到相符項目時,[3] 系統會呼叫其 onCreate() 方法,並將 Intent 傳送給它來啟動相符的 Activity (Activity B)。

當您建立隱含意圖時,Android 系統會比較意圖內容和裝置上其他應用程式的宣示說明檔案中宣告的「意圖篩選器」,以找出要啟動的適當元件。 如果意圖和意圖篩選器相符,系統會啟動該元件,並將 Intent 物件傳送給它。 如果有多個意圖篩選器符合意圖,系統會顯示對話方塊,供使用者挑選要使用的應用程式。

意圖篩選器是應用程式宣示說明檔案中的運算式,可指定元件要接收的意圖類型。 例如,藉由宣告 Activity 的意圖篩選器,可讓其他應用程式使用特定意圖類型直接啟動您的 Activity。 同樣地,如果您「不」為 Activity 宣告任何意圖篩選器,就只能以明確意圖啟動它。

注意:為了確保您的應用程式安全,請一律使用明確意圖啟動 Service,並且不要宣告服務的意圖篩選器。 使用隱含意圖啟動服務會危害安全性,原因在於您無法確定哪個服務會回應意圖,而且使用者無法得知系統會啟動哪項服務。 從 Android 5.0 (API 級別 21) 開始,如果您使用隱含意圖呼叫 bindService(),系統都會擲回例外狀況。

建置意圖

Intent 物件攜帶 Android 系統用來判斷要啟動哪個元件的資訊 (例如應接收意圖的確切元件名稱或元件類別),再加上接收者元件用以適當執行動作的資訊 (例如要執行的動作和據以執行的資料)。

Intent 包含的主要資訊如下:

元件名稱
要啟動元件的名稱。

雖可選擇是否使用,但這卻是讓意圖「明確」的重要資訊,表示意圖只能傳送至元件名稱所定義的應用程式元件。 如果不使用元件名稱,意圖會是「隱含」的,因此系統會根據其他意圖資訊來決定哪個元件應接收意圖 (例如動作、資料及類別 — 如下所述)。 如果您需要啟動應用程式中的特定元件,就應該指定元件名稱。

注意:啟動 Service 時,請務必指定元件名稱。 否則,您無法確定哪個服務會回應意圖,而且使用者無法得知系統會啟動哪項服務。

Intent 的這個欄位是 ComponentName 物件,您可以使用目標元件的完整類別名稱加以指定,包括應用程式的封裝名稱。例如, com.example.ExampleActivity。您可以使用 setComponent()setClass()setClassName()Intent 建構函式來設定元件名稱。

動作
以字串指定要執行的一般動作 (例如「檢視」或「挑選」)。

就廣播意圖而言,這是指已發生且系統回報的動作。動作大半決定其餘意圖的建構方式 — 特別是資料與額外資料中包含的項目。

您可以在應用程式內指定自己的動作以供意圖使用 (或由其他應用程式用來呼叫應用程式中的元件),但您應使用 Intent 類別或其他架構類別定義的動作常數。 以下是可啟動 Activity 的一些常見動作:

ACTION_VIEW
當您有一些資訊可讓 Activity 向使用者顯示時,例如要在圖庫應用程式檢視的相片或要在地圖應用程式檢視的地址,就可以透過 startActivity() 使用意圖中的這個動作。
ACTION_SEND
也稱為「分享」意圖,當您有一些資料可供使用者透過其他應用程式分享時,例如電子郵件應用程式或社交分享應用程式,才應透過 startActivity() 使用意圖中的這個動作。

如要進一步瞭解定義一般動作的常數,請參閱 Intent 類別參考文件。 其他動作則是在 Android 架構的其他位置完成定義,例如可在系統設定應用程式中開啟特定畫面的動作位在 Settings 中。

您可以透過 setAction()Intent 建構函式來指定意圖的動作。

如果您定義自己的動作,請務必加入您應用程式的封裝名稱做為前置詞。 例如:

static final String ACTION_TIMETRAVEL = "com.example.action.TIMETRAVEL";
資料
URI (Uri 物件) 可參考據以執行的資料和/或該資料的 MIME 類型。 提供的資料類型通常是由意圖的動作控制。例如,如果動作是 ACTION_EDIT,資料就應包含欲編輯文件的 URI。

建立意圖時,除了意圖的 URI 以外,請務必指定資料類型 (其 MIME 類型)。 例如,能夠顯示影像的 Activity 可能無法播放音訊檔案,即使有類似的 URI 格式。 因此,指定資料的 MIME 格式可協助 Android 系統找出最適合接收意圖的元件。 不過 — 尤其是當資料指出資料位在裝置何處且受 ContentProvider 控制讓系統看見資料 MIME 類型的 content: URI 時,有時能夠從 URI 推論出 MIME 類型。

如果您只想設定資料 URI,請呼叫 setData()。 如要設定 MIME 類型,請呼叫 setType()。您還可以視需要利用 setDataAndType() 明確設定兩者。

注意:如果您想同時設定 URI 與 MIME 類型,「請勿」呼叫 setData()setType(),原因是這兩者會抵銷彼此的值。 請務必使用 setDataAndType() 來設定 URI 與 MIME 類型。

類別
字串當中包含哪種元件應處理意圖的其他相關資訊。 意圖中可放置的類別描述數目並沒有限制,但大多數意圖都不需要類別。 以下是一些常見類別:
CATEGORY_BROWSABLE
目標 Activity 允許自己由網頁瀏覽器啟動,以顯示連結所參照的資料 — 例如影像或電子郵件訊息。
CATEGORY_LAUNCHER
Activity 是工作的初始 Activity,而且列在系統的應用程式啟動器中。

如需類別的完整清單,請參閱 Intent 類別描述。

您可以使用 addCategory() 來指定類別。

以上列出的屬性 (元件名稱、動作、資料及類別) 代表意圖的定義特性。 藉由讀取這些屬性,Android 系統就能分析出應啟動的應用程式元件。

不過,意圖還能攜帶其他不影響如何將它解析成應用程式元件的資訊。 意圖還能提供:

額外資料
鍵值對當中攜帶完成要求動作所需的其他資訊。 和有些動作會使用特定種類的資料 URI 一樣,有些動作也會使用特定的額外資料。

您可以使用各種 putExtra()方法來新增額外資料,每種方法都接受兩個參數:索引鍵名稱與值。 您也可以使用所有的額外資料建立 Bundle 物件,再透過 putExtras()Intent 插入 Bundle

例如,建立意圖以使用 ACTION_SEND 來傳送電子郵件時,您可以利用 EXTRA_EMAIL 索引鍵指定「收件者」,並使用 EXTRA_SUBJECT 索引鍵指定「主旨」。

Intent 類別指定許多用於標準化資料類型的 EXTRA_* 常數。如果您需要宣告自己的額外資料索引鍵 (用於您應用程式接收的意圖),請務必加入您應用程式的封裝名稱做為前置詞。 例如:

static final String EXTRA_GIGAWATTS = "com.example.EXTRA_GIGAWATTS";
旗標
Intent 類別中定義的旗標,可當成意圖的中繼資料使用。 旗標可指示 Android 系統如何啟動 Activity (例如,Activity 屬於哪個 工作) 以及如何處理已啟動的 Activity (例如,它是否屬於最近 Activity 清單)。

如需詳細資訊,請參閱 setFlags() 方法。

明確意圖範例

您用來啟動特定應用程式元件的就是明確意圖,例如應用程式中的特定 Activity 或服務。如要建立明確意圖,請定義 Intent物件的元件名稱 — 其他意圖屬性均為選用性質。

例如,您在應用程式中建置稱為 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(Context, Class) 建構函式提供應用程式 Context 與元件 (Class 物件)。 因此,這個意圖會明確啟動應用程式中的 DownloadService 類別。

如要進一步瞭解如何建置及啟動服務,請參閱服務指南。

隱含意圖範例

隱藏意圖指定的動作會呼叫裝置上任何能執行該動作的應用程式。 當您的應用程式無法執行該動作,但其他應用程式或許能執行,而您想讓使用者挑選要使用的應用程式時,使用隱含意圖相當有用。

例如,您有想讓使用者與其他人分享的內容,可使用 ACTION_SEND 動作來建立意圖,以及新增可指定要分享內容的額外資料。 當您使用該意圖呼叫 startActivity() 時,使用者就能挑選要用以分享內容的應用程式。

注意:使用者可能會沒有「任何」 應用程式可處理您傳送至 startActivity() 的隱含意圖。如果發生這種情況,呼叫會失敗且應用程式將會當機。如要確認 Activity 將可收到意圖,請在 Intent 物件上呼叫 resolveActivity()。如果結果不是 null,表示至少有一個應用程式能夠處理該意圖,可以放心呼叫 startActivity()。如果結果為 null,表示您不應使用該意圖,可以的話您還必須將發出該意圖的功能停用。

// 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);
}

注意:在這種情況下,不會使用 URI,但會宣告意圖的資料類型,以指定額外資料所攜帶的內容。

呼叫 startActivity() 時,系統會檢查所有安裝的應用程式,判斷哪些可以處理這種意圖 (含有 ACTION_SEND動作和攜帶「純文字」資料的意圖)。 如果只有一個應用程式能夠處理,該應用程式會立即開啟並獲派該意圖。 如果有多個 Activity 接受該意圖,系統會顯示對話方塊,供使用者挑選要使用的應用程式。

圖 2.選擇器對話方塊。

強制顯示應用程式選擇器

有多個應用程式均回應您的隱含意圖時,使用者可以選擇要使用的應用程式,並將該應用程式當成動作的預設選擇。 如果在執行動作時使用者希望之後都使用同一應用程式 (例如使用者偏好使用某個特定網頁瀏覽器開啟網頁,這項功能就非常實用。

不過,如果有多個應用程式能回應該意圖,而使用者每次都想使用不同的應用程式,您應該明確顯示選擇器對話方塊。 選擇器對話方塊每次都會要求使用者選取要用於該動作的應用程式 (使用者無法為該動作選取預設應用程式)。 例如,當您的應用程式使用 ACTION_SEND 動作執行「分享」時,使用者可能希望根據當下的情況使用不同的應用程式來分享,此時您應該一律使用選擇器對話方塊,如圖 2 所示。

如要顯示選擇器,請使用 createChooser() 建立 Intent,並將其傳送至 startActivity()。例如:

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);
}

以上範例會顯示對話方塊 (將回應意圖的應用程式清單傳送至 createChooser() 方法),並使用提供的文字做為對話方塊的標題。

接收隱含意圖

如要通知應用程式可接收的隱含內容,請在宣告說明檔案中利用 <intent-filter> 元素,針對您的每個應用程式元件宣告一或多個意圖篩選器。每個意圖篩選器都會根據意圖的動作、資料和類別,指定其接受的意圖類型。 只有在意圖通過您的其中一個意圖篩選器時,系統才會將隱含意圖傳送至您的應用程式元件。

注意:不論元件宣告的意圖篩選器為何,明確意圖一律會傳送至其目標。

應用程式元件應為其所能執行的各個獨特工作宣告不同的篩選器。例如,圖片庫應用程式中的一個 Activity 可能會有兩個篩選器:一個用於檢視圖片的篩選器,以及另一個用於編輯圖片的篩選器。 當 Activity 啟動時,它會檢查 Intent 並根據 Intent 中的資訊決定如何運作 (例如,是否要檢視編輯器控制項)。

每個意圖篩選器都是由 <intent-filter> 元素定義在應用程式的宣示說明檔案中,以巢狀方式置於對應的應用程式元件 (例如,<activity> 元素)。 在 <intent-filter> 內,您可以使用以下三個元素當中的一或多個元素,指定要接受的意圖類型:

<action>
name 屬性中,宣告接受的意圖動作。值必須是動作的常值字串值,不得為類別常數。
<data>
使用一或多項屬性指定資料 URI ( schemehostportpath 等) 與 MIME 類型的各層面,以宣告接受的資料類型。
<category>
name 屬性中,宣告接受的意圖類別。值必須是動作的常值字串值,不得為類別常數。

注意:如要接收隱含意圖,您「必須」在意圖篩選器中納入 CATEGORY_DEFAULT 類別。 startActivity()startActivityForResult() 方法對所有意圖進行處理時,就像已宣告 CATEGORY_DEFAULT 類別一樣。 如果您未在意圖篩選器中宣告此類別,任何隱含意圖都不會解析為 Activity。

例如,假設資料類型為文字,以下 Activity 宣告的意圖篩選器都可接受 ACTION_SEND 意圖:

<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>

想要建立包含多個 &lt;action&gt;&lt;data&gt;&lt;category&gt; 執行個體的篩選器也沒關係。 如果您這樣做,只需要確定該元件能處理這些篩選器元素的任何組合。

當您想要處理多種意圖,但只限特定的動作、資料及類別類型組合時,您必須建立多個意圖篩選器。

藉由將意圖與三個元素個別比較,針對篩選器來測試隱含意圖。 如要傳送至元件,意圖必須通過共三個測試。 如果無一相符,Android 系統就不會將意圖傳送至該元件。不過,由於元件可能會有多個意圖篩選器,未通過其中一個元件篩選器的意圖可能會通過另一個篩選器。 如要進一步瞭解系統如何解析意圖,請參閱下文的意圖解析

注意:如要避免一時疏忽而執行不同應用程式的 Service,請一律使用明確意圖啟動您自己的服務,同時不要宣告服務的意圖篩選器。

注意:對於所有 Activity,您都必須在宣示說明檔案中宣告意圖篩選器。 不過,廣播接收器的篩選器可以藉由呼叫 registerReceiver() 進行動態註冊。您之後可以利用 unregisterReceiver() 來取消註冊接收器。這樣做可在您的應用程式執行時,讓應用程式只能在指定期間內接聽特定廣播。

篩選器範例

如要進一步瞭解意圖篩選器行為,可以看看社交分享應用程式宣示說明檔案中的以下程式碼片段。

<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>

第一個 Activity MainActivity 是應用程式的主要進入點 — 這個 Activity 會在使用者使用啟動器圖示初次啟動應用程式時開啟:

上述兩項必須成對,Activity 才會顯示在應用程式啟動器中。

第二個 Activity ShareActivity 是用來加速分享文字與媒體內容。 雖然使用者可能藉由從 MainActivity 來瀏覽它而進入此 Activity,但它們也能從發出隱含意圖 (符合兩個意圖篩選器之一) 的另一款應用程式直接進入 ShareActivity

注意: application/vnd.google.panorama360+jpg MIME 類型是指定全景相片的特殊資料類型,您可以透過 Google 全景 API 來處理。

使用待處理意圖

PendingIntent 物件是環繞 Intent 物件的包裝函式。PendingIntent 的主要用途是將權限授予外部應用程式,以便使用包含的 Intent,有如從應用程式自己的程序執行一般。

待處理意圖的主要使用案例包括:

由於每個 Intent 物件都設計為要由特定的應用程式元件類型來處理 (ActivityServiceBroadcastReceiver),因此請務必以相同的考量建立 PendingIntent。 使用待處理意圖時,您的應用程式將不會透過像是 startActivity() 的呼叫來執行意圖。當您藉由呼叫以下的個別建立者方法建立 PendingIntent 時,您必須改為宣告意圖元件類型:

除非您的應用程式「收到」來自其他應用程式的待處理意圖,否則您可能只需要上述建立 PendingIntentPendingIntent 方法。

每個方法會採用目前的應用程式 Context、您要包裝的 Intent 以及一或多個指定應如何使用意圖的旗標 (例如該意圖是否能使用多次)。

如要進一步瞭解如何使用待處理意圖,請參閱個別使用案例的參考文件,例如通知以及應用程式小工具 API 指南。

意圖解析

當系統收到要啟動 Activity 的隱含意圖時,會根據三個層面來比較意圖與意圖篩選器,以便為該意圖搜尋最適合的 Activity。

下列各節就如何在應用程式宣示說明檔案中宣告意圖篩選器這點,說明如何比對意圖以找出適當的元件。

動作測試

如要指定接受的意圖動作,意圖篩選器可以宣告零或多個 &lt;action&gt; 元素。例如:

<intent-filter>
    <action android:name="android.intent.action.EDIT" />
    <action android:name="android.intent.action.VIEW" />
    ...
</intent-filter>

如要通過此篩選器,Intent 中指定的動作必須與篩選器中列出的其中一個動作相符。

如果篩選器未列出任何可供意圖比對的動作,所有意圖都無法通過測試。 不過,如果 Intent 未指定任何動作,它就會通過測試 (只要篩選器至少包含一個動作即可)。

類別測試

如要指定接受的意圖類別,意圖篩選器可以宣告零或多個 &lt;category&gt; 元素。例如:

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

Intent 中的每個類別都必須與篩選器中的類別相符,意圖才會通過類別測試。 不需要反向進行 — 意圖篩選器宣告的類別可以比 Intent 中指定的類別多,而 Intent 仍可通過測試。因此,不論篩選器中宣告的類別為何,未包含類別的意圖一律可通過此測試。

注意:Android 會將 CATEGORY_DEFAULT 類別自動套用到所有傳送至 startActivity()startActivityForResult() 的隱含意圖。因此,如果您希望 Activity 收到隱含意圖,Activity 的意圖篩選器就必須包含 "android.intent.category.DEFAULT" 的類別 (如先前的 &lt;intent-filter&gt; 範例中所示)。

資料測試

如要指定接受的意圖資料,意圖篩選器可以宣告零或多個 &lt;data&gt; 元素。例如:

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

每個 <data> 元素都能指定 URI 結構與資料類型 (MIME 媒體類型)。URI 的每個部分都有個別的屬性: schemehostportpath

&lt;scheme&gt;://&lt;host&gt;:&lt;port&gt;/&lt;path&gt;

例如:

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

在這個 URI 中,配置為 content、主機為 com.example.project、連接埠為 200,而路徑為 folder/subfolder/etc

&lt;data&gt; 元素中,上述所有屬性均為選用性質,但具有線性相依性:

將意圖中的 URI 與篩選器中的 URI 規格比較時,只會比較篩選器中所包含的 URI 部分。 例如:

注意:路徑規格可以包含萬用字元星號 (*),以要求僅部分相符的路徑名稱。

資料測試會比較意圖中的 URI 與 MIME 類型,以及篩選器中指定的 URI 與 MIME 類型。 以下說明規則:

  1. 只有在篩選器未指定任何 URI 或 MIME 類型時,未包含 URI 或 MIME 類型的意圖才會通過測試。
  2. 只有在其 URI 與篩選器的 URI 格式相符,而且篩選器同樣未指定 MIME 類型時,包含 URI 但沒有 MIME 類型 (既非明確也無法從 URI 推測得出) 的意圖才會通過測試。
  3. 只有在篩選器列出相同的 MIME 類型且未指定 URI 格式時,包含 MIME 類型但沒有 URI 的意圖才會通過測試。
  4. 只有在 MIME 類型與篩選器中列出的類型相符時,包含 URI 與 MIME 類型 (明確或可從 URI 推測得出) 的意圖才會通過 MIME 類型部分的測試。 如果它的 URI 與篩選器中的 URI 相符,或如果它有 content:file: URI,而且篩選器未指定 URI 時,就會通過 URI 部分的測試。換句話說,如果它的篩選器「只」列出 MIME 類型,就會假設元件支援 content:file: 資料。

最後一項規則 (規則 (d)) 可反映出希望元件能夠從檔案或內容供應程式取得本機資料的期望。 因此,其篩選器可以只列出資料類型,同時不需要明確命名 content:file: 配置。 此為典型案例。例如,如下所示的 &lt;data&gt; 元素可以告訴 Android,元件能夠從內容供應程式取得影像資料並加以顯示:

<intent-filter>
    <data android:mimeType="image/*" />
    ...
</intent-filter>

由於大部分可用資料都是由內容供應程式分配,因此指定資料類型但未指定 URI 的篩選器也許會最常見。

另一個常見的設定是含有配置與資料類型的篩選器。例如,如下所示的 &lt;data&gt;元素可以告訴 Android,元件能夠從網路擷取影片資料以執行動作:

<intent-filter>
    <data android:scheme="http" android:type="video/*" />
    ...
</intent-filter>

意圖比對

和意圖篩選器比對的意圖不只可探尋要啟動的目標元件,還能探尋裝置上元件集合的相關資料。 例如,主畫面應用程式會利用指定 ACTION_MAIN 動作與 CATEGORY_LAUNCHER 類別的意圖篩選器來尋找所有 Activity,以填入應用程式啟動器。

您的應用程式能以類似的方式使用意圖比對。 PackageManager 有一組 query...()方法可將接受特定意圖的所有元件傳回,還有一系列類似的 resolve...() 方法可決定回應意圖的最佳元件。 例如, queryIntentActivities() 會傳回所有 Activity 清單,上述的 Activity 都可以執行當成引數傳送的意圖,以及 queryIntentServices() 可傳回類似的服務清單。 這些方法不會啟動元件,只會列出可以回應的元件。類似的方法 queryBroadcastReceivers() 可用於廣播接收器。

This site uses cookies to store your preferences for site-specific language and display options.

Get the latest Android developer news and tips that will help you find success on Google Play.

* Required Fields

Hooray!

Follow Google Developers on WeChat

Browse this site in ?

You requested a page in , but your language preference for this site is .

Would you like to change your language preference and browse this site in ? If you want to change your language preference later, use the language menu at the bottom of each page.

This class requires API level or higher

This doc is hidden because your selected API level for the documentation is . You can change the documentation API level with the selector above the left navigation.

For more information about specifying the API level your app requires, read Supporting Different Platform Versions.

Take a short survey?
Help us improve the Android developer experience.
(Sep 2017 survey)