Android 4.3 API

API 級別:18

Android 4.3 (JELLY_BEAN_MR2) 是 Jelly Bean 的更新版本,為使用者和應用程式開發人員提供新功能。本文件將介紹最值得注意的新 API。

應用程式開發人員應盡快從 SDK Manager 下載 Android 4.3 系統映像檔和 SDK 平台。如果您沒有搭載 Android 4.3 的裝置來測試應用程式,請使用 Android 4.3 系統映像檔,在 Android 模擬器中測試應用程式。然後針對 Android 4.3 平台建構應用程式,以便開始使用最新的 API。

更新目標 API 級別

為了針對 Android 4.3 的裝置最佳化您的應用程式,您應將 targetSdkVersion 設定為 "18",在 Android 4.3 的系統映像檔中進行安裝,然後透過此變更發布更新。

您可以在 Android 4.3 中使用 API,同時支援舊版,方法是在程式碼中新增檢查系統 API 級別的條件,然後執行 minSdkVersion 不支援的 API。如要進一步瞭解如何維持回溯相容性,請參閱「支援不同平台版本」。

Android 支援資料庫中也有各種 API,可讓您在舊版平台中實作新功能。

如要進一步瞭解 API 級別的運作方式,請參閱「什麼是 API 級別?」一文。

重要行為變更

如果您先前已發布 Android 版應用程式,請注意,您的應用程式可能會受到 Android 4.3 版的異動影響。

如果您的應用程式使用隱含意圖...

您的應用程式在設有限制的個人資料環境中可能出現異常行為。

受限制設定檔環境的使用者可能無法使用所有標準 Android 應用程式。舉例來說,設有限制的個人資料可能會停用網路瀏覽器和相機應用程式。因此,應用程式不應假設哪些應用程式可用,因為如果在未驗證應用程式是否可處理 Intent 的情況下呼叫 startActivity(),則應用程式在設有限制的設定檔中可能會異常終止。

使用隱含意圖時,請務必呼叫 resolveActivity()queryIntentActivities(),確認應用程式可處理意圖。例如:

Kotlin

val intent = Intent(Intent.ACTION_SEND)
...
if (intent.resolveActivity(packageManager) != null) {
    startActivity(intent)
} else {
    Toast.makeText(context, R.string.app_not_available, Toast.LENGTH_LONG).show()
}

Java

Intent intent = new Intent(Intent.ACTION_SEND);
...
if (intent.resolveActivity(getPackageManager()) != null) {
    startActivity(intent);
} else {
    Toast.makeText(context, R.string.app_not_available, Toast.LENGTH_LONG).show();
}

如果您的應用程式需要使用帳戶...

您的應用程式在設有限制的個人資料環境中可能出現異常行為。

根據預設,位於設有限制的個人資料環境中的使用者無法存取使用者帳戶。如果您的應用程式依附於 Account,在設有限制的設定檔中使用時,應用程式可能會當機,或出現非預期的行為。

如果不希望受限制的個人資料因為應用程式仰賴機密帳戶資訊而完全無法使用您的應用程式,請在資訊清單的 <application> 元素中指定 android:requiredAccountType 屬性。

如果您想允許受限制的個人資料繼續使用您的應用程式 (即使他們無法建立自己的帳戶),您可以停用需要帳戶的應用程式功能,或允許受限制的個人資料存取主要使用者建立的帳戶。詳情請參閱下方「在設有限制的個人資料中支援帳戶」一節。

如果您的應用程式使用 VideoView...

在 Android 4.3 裝置上,影片可能會縮小。

在先前的 Android 版本中,VideoView 小工具誤將 layout_heightlayout_width"wrap_content" 值計算為與 "match_parent" 相同。因此,當使用 "wrap_content" 做為高度或寬度時,您可能之前提供了想要的影片版面配置,但在 Android 4.3 及以上版本中,這個效果可能會縮減很多。如要修正這個問題,請將 "wrap_content" 替換為 "match_parent",並確認影片在 Android 4.3 和較舊版本中是否能正常顯示。

設有限制的個人資料

在 Android 平板電腦上,使用者現在可以根據主要使用者建立設有限制的個人資料。 使用者建立設有限制的個人資料時,可以啟用限制,例如哪些應用程式可以使用哪些應用程式。Android 4.3 中的一組全新 API 還可讓您為開發的應用程式建構精細的限制設定。舉例來說,您可以使用新的 API,讓使用者在受限制的設定檔環境中執行時,控制應用程式中可用的內容類型。

使用者可以控制您建構的限制的使用者介面,是由系統的「設定」應用程式管理。如要向使用者顯示應用程式的限制設定,您必須建立接收 ACTION_GET_RESTRICTION_ENTRIES 意圖的 BroadcastReceiver,藉此宣告應用程式提供的限制。系統會叫用這個意圖來查詢所有應用程式,然後建構 UI,讓主要使用者能夠管理每個受限制設定檔的限制。

您必須在 BroadcastReceiveronReceive() 方法中,為應用程式提供的每項限制建立 RestrictionEntry。每個 RestrictionEntry 都定義了限制標題、說明和下列其中一種資料類型:

  • TYPE_BOOLEAN 則適用於 true 或 false 的限制。
  • TYPE_CHOICE 為具有多個互斥選項的限制 (圓形按鈕選項)。
  • TYPE_MULTI_SELECT 適用於具有多個不可共同選擇的限制 (核取方塊選項)。

然後將所有 RestrictionEntry 物件放入 ArrayList 中,將其放入廣播接收器的結果中,做為 EXTRA_RESTRICTIONS_LIST 額外項目的值。

系統會在「設定」應用程式中針對應用程式的限制建立 UI,並使用您為每個 RestrictionEntry 物件提供的專屬金鑰儲存各項限制。使用者開啟應用程式時,您可以呼叫 getApplicationRestrictions() 來查詢目前的所有限制。這樣做會傳回 Bundle,其中包含您透過 RestrictionEntry 物件定義的各項限制的鍵/值組合。

如要提供布林值、單選和複選值無法處理的特定限制,您可以建立一個活動,讓使用者指定限制,並允許使用者透過限制設定開啟該活動。在廣播接收器中,請在結果 Bundle 中加入 EXTRA_RESTRICTIONS_INTENT 額外項目。此額外項目必須指定 Intent,指出要啟動的 Activity 類別 (使用 putParcelable() 方法搭配意圖傳遞 EXTRA_RESTRICTIONS_INTENT)。當主要使用者進入活動以設定自訂限制時,您的活動必須使用 EXTRA_RESTRICTIONS_LISTEXTRA_RESTRICTIONS_BUNDLE 鍵,以額外方式傳回包含限制值的結果 (取決於您分別指定 RestrictionEntry 物件或鍵/值組合)。

支援設有限制的個人資料中的帳戶

凡是新增至主要使用者的帳戶,都可以透過受限的設定檔存取,但根據預設,您無法透過 AccountManager API 存取這些帳戶。如果您在設有限制的設定檔時嘗試使用 AccountManager 新增帳戶,就會失敗結果。基於這些限制,您可以採取下列三種做法:

  • 透過設有限制的個人資料存取擁有者的帳戶。

    如要透過設有限制的設定檔存取帳戶,您必須將 android:restrictedAccountType 屬性新增至 <application> 標記:

    <application ...
        android:restrictedAccountType="com.example.account.type" >
    

    注意:啟用這項屬性後,應用程式就能從設有限制的個人資料存取主要使用者帳戶。因此,只有在應用程式顯示的資訊不會揭露視為敏感的個人識別資訊 (PII) 時,才能允許此做法。系統設定會通知主要使用者,您的應用程式將受限制的個人資料授予他們的帳戶,因此應向使用者清楚說明,帳戶存取權對應用程式功能至關重要。如果可行,您也應該為主要使用者提供充分的限制控制項,讓他們定義應用程式能存取多少帳戶。

  • 在無法修改帳戶時停用特定功能。

    如果您想使用帳戶,但實際上不需要以這些帳戶執行應用程式的主要功能,您可以檢查帳戶可用性,並在無法使用的功能時停用這些功能。首先,請檢查是否已有可用帳戶。如果沒有,請呼叫 getUserRestrictions() 並檢查結果中是否可建立新帳戶,並查看結果中的 DISALLOW_MODIFY_ACCOUNTS 額外項目。如果為 true,您應停用應用程式需要存取帳戶的任何功能。例如:

    Kotlin

    val um = context.getSystemService(Context.USER_SERVICE) as UserManager
    val restrictions: Bundle = um.userRestrictions
    if (restrictions.getBoolean(UserManager.DISALLOW_MODIFY_ACCOUNTS, false)) {
        // cannot add accounts, disable some functionality
    }
    

    Java

    UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE);
    Bundle restrictions = um.getUserRestrictions();
    if (restrictions.getBoolean(UserManager.DISALLOW_MODIFY_ACCOUNTS, false)) {
        // cannot add accounts, disable some functionality
    }
    

    注意:在這種情況下,您「不應」在資訊清單檔案中宣告任何新屬性,

  • 在無法存取私人帳戶時停用應用程式。

    如果應用程式仰賴帳戶中的機密個人資訊,且必須確保應用程式無法供設有限制的個人資料使用 (且受限制的個人資料目前無法新增帳戶),請在 <application> 標記中加入 android:requiredAccountType 屬性:

    <application ...
        android:requiredAccountType="com.example.account.type" >
    

    舉例來說,Gmail 應用程式會利用這項屬性來停用設有限制的個人資料,因為不應提供給設有限制的個人資料使用擁有者的個人電子郵件地址。

  • 無線與連線

    藍牙低功耗 (智慧型)

    Android 現在支援在 android.bluetooth 中使用新 API 的藍牙低功耗 (LE) 技術。透過新的 API,您可以建構與藍牙低功耗週邊裝置 (例如心率監測器和計步器) 通訊的 Android 應用程式。

    由於藍牙 LE 是硬體功能,並未在所有 Android 裝置上提供,因此您必須在資訊清單檔案中為 "android.hardware.bluetooth_le" 宣告 <uses-feature> 元素:

    <uses-feature android:name="android.hardware.bluetooth_le" android:required="true" />
    

    如果您已熟悉 Android 的經典藍牙 API,請注意使用 Bluetooth LE API 有點差異。最重要的是,現在有一個 BluetoothManager 類別,可用於部分高階作業,例如取得 BluetoothAdapter、取得已連結的裝置清單,以及檢查裝置狀態。舉例來說,現在應如何取得 BluetoothAdapter

    Kotlin

    val bluetoothManager = getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager
    bluetoothAdapter = bluetoothManager.adapter
    

    Java

    final BluetoothManager bluetoothManager =
            (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
    bluetoothAdapter = bluetoothManager.getAdapter();
    

    如要尋找藍牙 LE 週邊裝置,請在 BluetoothAdapter 上呼叫 startLeScan(),並向其傳遞 BluetoothAdapter.LeScanCallback 介面的實作。當藍牙轉接器偵測到藍牙 LE 週邊裝置時,您的 BluetoothAdapter.LeScanCallback 實作項目會收到對 onLeScan() 方法的呼叫。這個方法提供的 BluetoothDevice 物件代表偵測到的裝置、裝置的 RSSI 值,以及包含裝置廣告記錄的位元組陣列。

    如果只想掃描特定類型的周邊裝置,可以改為呼叫 startLeScan() 並加入 UUID 物件陣列,用於指定應用程式支援的 GATT 服務。

    注意:您只能掃描藍牙 LE 裝置,掃描使用舊版 API 的傳統版藍牙裝置。您無法同時掃描 LE 和經典藍牙裝置。

    如要連線至藍牙 LE 週邊裝置,請在對應的 BluetoothDevice 物件上呼叫 connectGatt(),並將 BluetoothGattCallback 的實作傳遞給該物件。實作的 BluetoothGattCallback 會接收與裝置和其他事件的連線狀態相關回呼。在 onConnectionStateChange() 回呼期間,如果方法傳遞 STATE_CONNECTED 做為新狀態,您可以開始與裝置通訊。

    如要存取裝置上的藍牙功能,您的應用程式也必須要求特定的藍牙使用者權限。詳情請參閱藍牙低功耗 API 指南。

    僅掃描 Wi-Fi 模式

    Android 嘗試辨識使用者的位置時,可能會掃描附近的存取點來使用 Wi-Fi 判斷所在位置。但是,使用者通常會關閉 Wi-Fi 以節省電池電力,導致位置資料準確度下降。Android 現在提供唯讀模式,讓裝置 Wi-Fi 可以在不連線至存取點的情況下掃描存取點,藉此取得位置資訊,進而大幅降低電池用量。

    如果您想取得使用者的位置資訊,但 Wi-Fi 目前處於關閉狀態,您可以使用 ACTION_REQUEST_SCAN_ALWAYS_AVAILABLE 動作呼叫 startActivity(),要求使用者啟用僅限 Wi-Fi 掃描模式。

    Wi-Fi 設定

    新的 WifiEnterpriseConfig API 可讓企業導向的服務自動為受管理裝置的 Wi-Fi 設定。

    對來電的快速回應

    自 Android 4.0 起,「快速回應」功能可讓使用者透過即時簡訊回覆來電,而不用接聽或解鎖裝置。在此之前,這些快速訊息一律是由預設的訊息應用程式處理。現在任何應用程式都能使用 ACTION_RESPOND_VIA_MESSAGE 的意圖篩選器建立 Service,藉此宣告其處理這些訊息的功能。

    當使用者使用快速回應回應來電時,「電話」應用程式會透過說明接收者 (呼叫端) 的 URI 傳送 ACTION_RESPOND_VIA_MESSAGE 意圖,並透過使用者要傳送的訊息內容傳送 EXTRA_TEXT 額外項目。服務收到意圖時,應傳送訊息並立即停止 (應用程式不應顯示活動)。

    如要接收此意圖,您必須宣告 SEND_RESPOND_VIA_MESSAGE 權限。

    多媒體

    MediaExtractor 和 MediaCodec 強化功能

    Android 現在可讓您使用 MediaCodecMediaExtractor 中的現有 API,更輕鬆根據 ISO/IEC 23009-1 標準,輕鬆透過 HTTP (DASH) 播放器編寫自己的動態自動調整串流。這些 API 的基礎架構已更新,可支援剖析片段的 MP4 檔案,但您的應用程式仍須負責剖析 MPD 中繼資料,並將個別串流傳遞至 MediaExtractor

    如要將 DASH 與加密內容搭配使用,請注意 getSampleCryptoInfo() 方法會傳回說明每個加密媒體範例結構的 MediaCodec.CryptoInfo 中繼資料。此外,getPsshInfo() 方法已新增至 MediaExtractor,方便您存取 DASH 媒體的 PSSH 中繼資料。這個方法會將 UUID 物件對應至位元組,其中 UUID 會指定加密配置,以及該配置專屬的資料位元組。

    媒體 DRM

    新的 MediaDrm 類別可將 DRM 疑慮與媒體播放分開,為您的媒體內容提供數位版權管理 (DRM) 的模組化解決方案。舉例來說,這個 API 區隔可讓您播放 Widevine 加密內容,而不必使用 Widevine 媒體格式。這項 DRM 解決方案也支援 DASH 通用加密,因此您可以搭配串流內容使用各種 DRM 配置。

    您可以使用 MediaDrm 取得不透明的金鑰要求訊息,並處理伺服器中的金鑰回應訊息,藉此取得及佈建授權。應用程式負責處理與伺服器的網路通訊,MediaDrm 類別只提供產生及處理訊息的功能。

    MediaDrm API 適合與 Android 4.1 (API 級別 16) 中引入的 MediaCodec API 搭配使用,包括用於編碼及解碼內容的 MediaCodec、處理加密內容的 MediaCrypto,以及用於擷取及解碼內容的 MediaExtractor

    您必須先建構 MediaExtractorMediaCodec 物件。接著,您可以存取 DRM 結構識別的 UUID (通常透過內容的中繼資料),然後透過其建構函式建構 MediaDrm 物件的執行個體。

    Surface 的影片編碼

    Android 4.1 (API 級別 16) 新增了 MediaCodec 類別,用於低階編碼和媒體內容解碼。對影片進行編碼時,Android 4.1 會要求您使用 ByteBuffer 陣列提供媒體,但 Android 4.3 現在可讓您使用 Surface 做為編碼器的輸入內容。舉例來說,這可讓您將現有影片檔案的輸入編碼,或使用 OpenGL ES 產生的影格進行編碼。

    如要使用 Surface 做為編碼器的輸入,請先針對 MediaCodec 呼叫 configure()。 然後呼叫 createInputSurface() 以接收可用於串流媒體的 Surface

    舉例來說,您可以將指定的 Surface 傳遞至 eglCreateWindowSurface(),做為 OpenGL 情境的視窗。然後在轉譯介面時呼叫 eglSwapBuffers(),將影格傳遞至 MediaCodec

    如要開始編碼,請在 MediaCodec 上呼叫 start()。完成後,請呼叫 signalEndOfInputStream() 終止編碼,然後在 Surface 上呼叫 release()

    媒體雜訊

    新的 MediaMuxer 類別可在一個音訊串流和一個影片串流之間啟用多工處理。這些 API 可做為 Android 4.2 中新增的 MediaExtractor 類別,用於去多工處理 (去做) 媒體。

    支援的輸出格式定義於 MediaMuxer.OutputFormat。目前,MP4 是唯一支援的輸出格式,而 MediaMuxer 目前只支援一個音訊串流和/或一個影片串流。

    MediaMuxer 主要為與 MediaCodec 搭配使用,因此您可以透過 MediaCodec 執行影片處理作業,然後透過 MediaMuxer 將輸出內容儲存至 MP4 檔案。您也可以使用 MediaMuxer 搭配 MediaExtractor 來執行媒體編輯,無需編碼或解碼。

    RemoteControlClient 的播放進度和拖曳功能

    在 Android 4.0 (API 級別 14) 中,新增了 RemoteControlClient 來啟用遠端控制用戶端的媒體播放控制項,例如螢幕鎖定畫面上可用的控制項。Android 4.3 版現在可讓這類控制器顯示播放位置和拖曳播放作業的控制項。如果您已透過 RemoteControlClient API 啟用媒體應用程式的遠端控制功能,即可實作兩個新介面來允許播放拖曳。

    首先,您必須將其傳送至 setTransportControlsFlags() 來啟用 FLAG_KEY_MEDIA_POSITION_UPDATE 標記。

    然後實作下列兩個新介面:

    RemoteControlClient.OnGetPlaybackPositionListener
    這包括回呼 onGetPlaybackPosition(),在遙控器需要更新 UI 的進度時,會要求媒體目前的位置。
    RemoteControlClient.OnPlaybackPositionUpdateListener
    這包括回呼 onPlaybackPositionUpdate(),可在使用者透過遙控器 UI 拖曳播放時,通知應用程式媒體的新時間碼。

    使用新的位置更新播放作業後,請呼叫 setPlaybackState() 來表示新的播放狀態、位置和速度。

    定義這些介面後,您可以分別呼叫 setOnGetPlaybackPositionListener()setPlaybackPositionUpdateListener(),為 RemoteControlClient 設定這些介面。

    顯示卡

    支援 OpenGL ES 3.0

    Android 4.3 版新增 Java 介面,並針對 OpenGL ES 3.0 提供原生支援。OpenGL ES 3.0 提供的主要新功能包括:

    • 進階視覺效果
    • 以高品質 ETC2/EAC 紋理壓縮做為標準功能
    • 新版 GLSL ES 陰影語言,支援整數和 32 位元浮點
    • 進階紋理算繪
    • 讓紋理大小和轉譯緩衝區格式有更多標準化

    Android 上的 OpenGL ES 3.0 適用的 Java 介面提供 GLES30。使用 OpenGL ES 3.0 時,請務必在資訊清單檔案中使用 <uses-feature> 標記和 android:glEsVersion 屬性,進行宣告,例如:

    <manifest>
        <uses-feature android:glEsVersion="0x00030000" />
        ...
    </manifest>
    

    請記得呼叫 setEGLContextClientVersion(),並將 3 做為版本傳遞,藉此指定 OpenGL ES 結構定義。

    如要進一步瞭解如何使用 OpenGL ES,包括如何在執行階段檢查裝置支援的 OpenGL ES 版本,請參閱 OpenGL ES API 指南。

    可繪項目的 Mipmap

    使用 mipmap 做為點陣圖或可繪項目的來源,可輕鬆提供高品質的圖片和各種圖像比例。如果您預期圖片會在動畫播放期間縮放,這種做法就特別實用。

    Android 4.2 (API 級別 17) 在 Bitmap 類別中新增了對 mipmap 的支援:當您提供 mipmap 來源並啟用 setHasMipMap() 後,Android 會切換 Bitmap 中的 mip 圖片。在 Android 4.3 版中,您也可以為 BitmapDrawable 物件啟用 mipmap,方法是提供 mipmap 素材資源,並在點陣圖資源檔案中設定 android:mipMap 屬性,或是呼叫 hasMipMap()

    使用者介面

    查看重疊元素

    新的 ViewOverlay 類別在 View 上方提供透明層,您可在其中新增視覺內容,但不會影響版面配置階層。您可以呼叫 getOverlay() 取得任何 ViewViewOverlay。疊加層的大小和位置一律與主機檢視畫面 (建立時所在的檢視區塊) 相同,可讓您新增顯示在主機檢視畫面前方的內容,但無法擴充該主機檢視畫面的邊界。

    如果您想建立動畫 (例如在容器外滑動檢視畫面),或在不影響檢視區塊階層的情況下在畫面上移動項目,使用 ViewOverlay 會格外實用。不過,由於疊加層的可用區域受到主機檢視畫面的限制,因此如要以動畫方式呈現檢視畫面在版面配置中移動的位置,您必須從具有所需版面配置邊界的父項檢視畫面使用重疊。

    為小工具檢視畫面建立疊加層 (例如 Button) 時,您可以呼叫 add(Drawable),將 Drawable 物件新增至疊加層。如果針對版面配置檢視畫面 (例如 RelativeLayout) 呼叫 getOverlay(),傳回的物件為 ViewGroupOverlayViewGroupOverlay 類別是 ViewOverlay 的子類別,還可讓您呼叫 add(View) 來新增 View 物件。

    注意:您新增至疊加層的所有可繪項目和檢視畫面都只有視覺內容。但無法接收焦點或輸入事件。

    舉例來說,以下程式碼的作用是將檢視畫面放置在父項檢視畫面的疊加層中,然後在該檢視畫面上執行翻譯動畫,藉此呈現滑動到右側的動畫:

    Kotlin

    val view: View? = findViewById(R.id.view_to_remove)
    val container: ViewGroup? = view?.parent as ViewGroup
    
    container?.apply {
        overlay.add(view)
        ObjectAnimator.ofFloat(view, "translationX", right.toFloat())
                .start()
    }
    

    Java

    View view = findViewById(R.id.view_to_remove);
    ViewGroup container = (ViewGroup) view.getParent();
    container.getOverlay().add(view);
    ObjectAnimator anim = ObjectAnimator.ofFloat(view, "translationX", container.getRight());
    anim.start();
    

    光學邊界版面配置

    對於包含 nine-patch 背景圖片的檢視畫面,您現在可以根據背景圖片的「光學」邊界 (而非檢視畫面的「裁剪」邊界) 指定這些檢視畫面應與鄰近檢視畫面對齊。

    例如,圖 1 和圖 2 都顯示相同的版面配置,但圖 1 中的版本使用裁剪邊界 (預設行為),而圖 2 則採用光學邊界。由於按鈕和相框模式使用的 nine-patch 圖片及邊緣周圍都有邊框間距,因此使用裁剪範圍時,這些圖片並未對齊彼此,或文字並未對齊。

    注意:圖 1 和圖 2 的螢幕截圖已啟用「Show layout bounds」開發人員設定。紅色線條代表每個檢視畫面的光學邊界,藍色線條表示裁剪邊界,粉紅色表示邊界。

    圖 1. 使用裁剪邊界的版面配置 (預設值)。

    圖 2. 使用光學邊界的版面配置。

    如要根據光學邊界對齊檢視畫面,請將其中一個父項版面配置中的 android:layoutMode 屬性設為 "opticalBounds"。例如:

    <LinearLayout android:layoutMode="opticalBounds" ... >
    

    圖 3. 縮放後的 Holo 按鈕 nine-patch 和光學邊界。

    為了讓這項功能順利運作,套用至檢視畫面背景的 nine-patch 圖片必須在 nine-patch 檔案的底部和右側使用紅色線條指定光學邊界 (如圖 3 所示)。紅線表示應從裁剪邊界中扣除的區域,保留圖片的光學邊界。

    在版面配置中為 ViewGroup 啟用光學邊界後,所有子檢視畫面都會沿用光學邊界版面配置模式,除非您將 android:layoutMode 設為 "clipBounds" 以覆寫該群組。所有版面配置元素也會遵循子項檢視畫面的光學邊界,根據其中的檢視畫面的光學邊界調整自身的邊界。不過,版面配置元素 (ViewGroup 的子類別) 目前不支援套用至本身背景的 nine-patch 圖片的光學邊界。

    如果您為 ViewViewGroup 或其任何子類別建立自訂檢視區塊,該檢視區塊會繼承這些光學邊界行為。

    注意:Holo 主題支援的所有小工具都已更新為光學邊界,包括 ButtonSpinnerEditText 等等。因此,如果應用程式套用 Holo 主題 (Theme.HoloTheme.Holo.Light 等),您可以將 android:layoutMode 屬性設為 "opticalBounds",即可立即受益。

    如要使用「Draw 9-patch」工具為自己的 nine-patch 圖片指定光學邊界,請在點選邊框像素時按住 Control。

    矩形值動畫

    您現在可以使用新的 RectEvaluator,在兩個 Rect 值之間建立動畫。這個新類別是 TypeEvaluator 的實作,可傳遞至 ValueAnimator.setEvaluator()

    視窗附加和焦點事件監聽器

    先前,如要監聽檢視畫面附加/卸離視窗的時間,或焦點發生變更時,您必須覆寫 View 類別,分別實作 onAttachedToWindow()onDetachedFromWindow()onWindowFocusChanged()

    現在,如要接收附加和卸離事件,您可以改為實作 ViewTreeObserver.OnWindowAttachListener,並使用 addOnWindowAttachListener() 在檢視畫面上設定。如要接收焦點事件,您可以實作 ViewTreeObserver.OnWindowFocusChangeListener,並使用 addOnWindowFocusChangeListener() 將其設定在檢視畫面上。

    電視過度掃描支援

    您現在可以為應用程式版面配置啟用過度掃描,以確保應用程式會在所有電視上填滿整個螢幕。過度掃描模式取決於 FLAG_LAYOUT_IN_OVERSCAN 旗標,而您可以使用 Theme_DeviceDefault_NoActionBar_Overscan 等平台主題,或在自訂主題中啟用 windowOverscan 樣式。

    螢幕方向

    <activity> 標記的 screenOrientation 屬性現在支援其他值,以符合使用者自動旋轉的偏好設定:

    "userLandscape"
    "sensorLandscape" 相同,除非使用者停用自動旋轉功能,否則會鎖定在一般橫向螢幕方向,而不會翻轉。
    "userPortrait"
    "sensorPortrait" 相同,除非使用者停用自動旋轉功能,才會鎖定一般直向螢幕方向,而不會翻轉。
    "fullUser"
    "fullSensor" 相同,並允許全部四個方向旋轉,但如果使用者停用自動旋轉功能,就會鎖定在使用者偏好的方向。

    此外,您現在也可以宣告 "locked",將應用程式的方向鎖定為目前的螢幕方向。

    旋轉動畫

    WindowManager 中的新 rotationAnimation 欄位可讓您從系統切換螢幕方向時,選擇要使用的三個動畫之一。三種動畫如下:

    注意:您必須將活動設為使用「全螢幕」模式,才能使用這些動畫,主題設定如 Theme.Holo.NoActionBar.Fullscreen

    以下舉例說明如何啟用「交叉漸變」動畫:

    Kotlin

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
    
        val params: WindowManager.LayoutParams = window.attributes
        params.rotationAnimation = WindowManager.LayoutParams.ROTATION_ANIMATION_CROSSFADE
        window.attributes = params
        ...
    }
    

    Java

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    
        WindowManager.LayoutParams params = getWindow().getAttributes();
        params.rotationAnimation = WindowManager.LayoutParams.ROTATION_ANIMATION_CROSSFADE;
        getWindow().setAttributes(params);
        ...
    }
    

    使用者輸入內容

    全新感應器類型

    新的 TYPE_GAME_ROTATION_VECTOR 感應器可讓你偵測裝置的旋轉情形,不必擔心磁幹擾。與 TYPE_ROTATION_VECTOR 感應器不同,TYPE_GAME_ROTATION_VECTOR 並非以磁北方為根據。

    新的 TYPE_GYROSCOPE_UNCALIBRATEDTYPE_MAGNETIC_FIELD_UNCALIBRATED 感應器提供原始感應器資料,而不會將偏誤估算納入考量。也就是說,現有的 TYPE_GYROSCOPETYPE_MAGNETIC_FIELD 感應器提供感應器資料,可分別將裝置上的陀螺儀和硬式鐵鑽估算偏誤納入考量。而這些感應器的新「未校正」版本則會改為提供原始感應器資料,並分別提供預估偏誤。這些感應器可讓您利用外部資料加強預估偏誤,以提供自訂的感應器資料校正。

    通知監聽器

    Android 4.3 版新增了服務類別 NotificationListenerService,可讓應用程式收到系統發布的新通知資訊。

    如果應用程式目前是透過無障礙服務 API 存取系統通知,請更新應用程式,改為使用這些 API。

    聯絡人供應程式

    「可聯絡」的查詢

    新的聯絡人供應程式查詢 Contactables.CONTENT_URI 可讓您有效率地取得一個 Cursor,其中包含所有符合指定查詢的聯絡人電子郵件地址和電話號碼。

    查詢聯絡人差異

    新增的 API 已新增至聯絡人供應程式,可讓您快速查詢最新的聯絡人資料變更。先前,當聯絡人資料有變動時,您的應用程式會收到相關通知,但您無法確切知道有哪些變更,因此必須擷取所有聯絡人,然後重複查看,才能發現變更內容。

    如要追蹤插入和更新項目的變更,您現在可以在所選項目中加入 CONTACT_LAST_UPDATED_TIMESTAMP 參數,只查詢自上次查詢供應器後變更過的聯絡人。

    新表格 ContactsContract.DeletedContacts 會提供已刪除的聯絡人記錄,用於追蹤已遭刪除的聯絡人 (但每個刪除的聯絡人會在這個表格中保留一段時間)。與 CONTACT_LAST_UPDATED_TIMESTAMP 類似,您可以使用新的選取參數 CONTACT_DELETED_TIMESTAMP,查看自上次查詢供應商後刪除了哪些聯絡人。這個資料表也包含常數 DAYS_KEPT_MILLISECONDS,其中包含將保留記錄的天數 (以毫秒為單位)。

    此外,當使用者透過系統設定選單清除聯絡人儲存空間時,聯絡人提供者現在會廣播 CONTACTS_DATABASE_CREATED 動作,以便有效重新建立聯絡人提供者資料庫。目的在於指示應用程式需要捨棄所有已儲存的聯絡資訊,並透過新的查詢重新載入。

    如需使用這些 API 檢查聯絡人變更的程式碼範例,請參閱 SDK 範例下載中提供的 ApiDemos 範例。

    本地化

    改善對雙向文字的支援

    舊版 Android 支援從右到左 (RTL) 的語言和版面配置,但有時無法妥善處理混合方向文字。因此,Android 4.3 新增了 BidiFormatter API,協助您為與方向相反的內容正確設定文字格式,而且不會對文字的任何部分進行垃圾處理。

    舉例來說,當句子包含字串變數 (例如「您是不是要說 15 Bay Street, Laurel, CA?」) 時,您通常會將經過本地化的字串資源和變數傳遞至 String.format()

    Kotlin

    val suggestion = String.format(resources.getString(R.string.did_you_mean), address)
    

    Java

    Resources res = getResources();
    String suggestion = String.format(res.getString(R.string.did_you_mean), address);
    

    但是,如果語言代碼是希伯來文,則格式化字串會顯示為:

    האם התכוונת ל 15 Bay Street, Laurel, CA?

    答錯了,因為「15」應該是「Bay Street」的左方。解決方法是使用 BidiFormatter 和其 unicodeWrap() 方法。舉例來說,上述程式碼會變成:

    Kotlin

    val bidiFormatter = BidiFormatter.getInstance()
    val suggestion = String.format(
            resources.getString(R.string.did_you_mean),
            bidiFormatter.unicodeWrap(address)
    )
    

    Java

    Resources res = getResources();
    BidiFormatter bidiFormatter = BidiFormatter.getInstance();
    String suggestion = String.format(res.getString(R.string.did_you_mean),
            bidiFormatter.unicodeWrap(address));
    

    根據預設,unicodeWrap() 會使用最高強度的方向性預估經驗法則,如果文字方向的第一個信號無法代表整體內容的正確方向,就可能出現錯誤。如有需要,您可以將其中一個 TextDirectionHeuristic 常數從 TextDirectionHeuristics 傳遞至 unicodeWrap(),以指定不同的經驗法則。

    注意:這些新的 API 也適用於舊版 Android 的 Android 支援資料庫,其中含有 BidiFormatter 類別和相關 API。

    無障礙服務

    處理重要事件

    AccessibilityService 現在可透過 onKeyEvent() 回呼方法接收按鍵輸入事件的回呼。如此一來,您的無障礙服務就能處理按鍵式輸入裝置 (例如鍵盤) 的輸入內容,並將這些事件轉譯為特殊動作,先前只能透過觸控輸入或裝置方向鍵操作。

    選取文字並複製/貼上

    AccessibilityNodeInfo 現在提供 API,讓 AccessibilityService 在節點中選取、剪下、複製及貼上文字。

    如要指定要剪下或複製的文字,您的無障礙服務可以使用新的動作 ACTION_SET_SELECTION,以 ACTION_ARGUMENT_SELECTION_START_INTACTION_ARGUMENT_SELECTION_END_INT 傳遞至選取開始和結束位置。或者,您也可以使用現有動作 ACTION_NEXT_AT_MOVEMENT_GRANULARITY (之前用於移動遊標位置) 操控遊標位置來選取文字,並新增引數 ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN

    接著,您可以使用 ACTION_CUTACTION_COPY 剪下或複製,然後再用 ACTION_PASTE 貼上。

    注意:這些新的 API 也適用於舊版 Android 的 Android 支援資料庫,其中包含 AccessibilityNodeInfoCompat 類別。

    宣告無障礙功能

    從 Android 4.3 開始,無障礙服務必須在中繼資料檔案中宣告無障礙功能,才能使用特定無障礙功能。如未在中繼資料檔案中要求該功能,則該功能為免人工管理。如要宣告服務的無障礙功能,您必須使用與 AccessibilityServiceInfo 類別中各種「功能」常數對應的 XML 屬性。

    舉例來說,如果服務並未要求 flagRequestFilterKeyEvents 功能,就不會收到按鍵事件。

    測試和偵錯

    自動化 UI 測試

    新的 UiAutomation 類別提供 API,可讓您模擬使用者動作,以進行測試自動化。透過使用平台的 AccessibilityService API,UiAutomation API 可讓您檢查畫面內容,並插入任意鍵盤和觸控事件。

    如要取得 UiAutomation 的執行個體,請呼叫 Instrumentation.getUiAutomation()。為了讓這項功能順利運作,您必須在透過 adb shell 執行 InstrumentationTestCase 時,使用 instrument 指令提供 -w 選項。

    使用 UiAutomation 執行個體時,您可以呼叫 executeAndWaitForEvent()、傳遞要執行的 Runnable、作業的逾時期間和 UiAutomation.AccessibilityEventFilter 介面實作,藉此執行任意事件來測試應用程式。在 UiAutomation.AccessibilityEventFilter 實作內,您會收到呼叫,可讓您篩選感興趣的事件,並判斷特定測試案例的成功或失敗。

    如要在測試期間觀察所有事件,請建立 UiAutomation.OnAccessibilityEventListener 的實作並傳遞至 setOnAccessibilityEventListener()。接著,每次事件發生時,事件監聽器介面都會收到對 onAccessibilityEvent() 的呼叫,並接收描述該事件的 AccessibilityEvent 物件。

    UiAutomation API 會以極低的程度公開各種其他作業,以鼓勵開發 UI 測試工具,例如 uiautomator。舉例來說,UiAutomation 也可以:

    • 插入輸入事件
    • 變更螢幕方向
    • 擷取螢幕截圖

    最重要的是,對 UI 測試工具而言,UiAutomation API 會在應用程式邊界上運作,與 Instrumentation 中的工具不同。

    應用程式的 Systrace 事件

    Android 4.3 新增了 Trace 類別和兩種靜態方法:beginSection()endSection(),可讓您定義要納入 Systrace 報表的程式碼區塊。只要在應用程式中建立可追蹤的程式碼區段,Systrace 記錄檔就能提供更詳細的分析,瞭解應用程式中發生速度緩慢情形的哪個部分。

    如要進一步瞭解如何使用 Systrace 工具,請參閱「使用 Systrace 分析顯示與成效」。

    安全性

    應用程式私密金鑰的 Android 金鑰庫

    Android 現在在 KeyStore 服務供應商中提供自訂 Java 安全性提供者 (稱為 Android Key Store),可讓您產生並儲存只有應用程式看得到和使用的私密金鑰。如要載入 Android Key Store,請將 "AndroidKeyStore" 傳遞至 KeyStore.getInstance()

    如要在 Android Key Store 中管理應用程式的私人憑證,請使用 KeyPairGenerator 產生 KeyPairGeneratorSpec 的新金鑰。首先,呼叫 getInstance() 以取得 KeyPairGenerator 的例項。然後呼叫 initialize() 並向其傳遞 KeyPairGeneratorSpec 的執行個體,您可以使用 KeyPairGeneratorSpec.Builder 取得該執行個體。最後,呼叫 generateKeyPair() 取得 KeyPair

    硬體憑證儲存空間

    Android 現在也支援適用於 KeyChain 憑證的硬體支援儲存空間,讓金鑰無法擷取,藉此提供更高的安全性。也就是說,一旦金鑰位於硬體支援的金鑰儲存庫 (安全元件、TPM 或 TrustZone),就能用於加密編譯作業,但無法匯出私密金鑰內容。即使是 OS 核心,也無法存取這個金鑰內容。雖然並非所有 Android 裝置都支援硬體儲存空間,但您可以透過呼叫 KeyChain.IsBoundKeyAlgorithm() 在執行階段檢查是否提供硬體支援的儲存空間。

    資訊清單聲明

    需要宣告的必要功能

    <uses-feature> 元素現在支援下列值,可確保您的應用程式僅安裝在提供應用程式所需功能的裝置上。

    FEATURE_APP_WIDGETS
    宣告您的應用程式提供應用程式小工具,且只能安裝在包含主畫面或類似位置,可讓使用者嵌入應用程式小工具的裝置上。範例:
    <uses-feature android:name="android.software.app_widgets" android:required="true" />
    
    FEATURE_HOME_SCREEN
    宣告您的應用程式為取代主畫面,而且只能安裝在支援第三方主畫面應用程式的裝置上。範例:
    <uses-feature android:name="android.software.home_screen" android:required="true" />
    
    FEATURE_INPUT_METHODS
    宣告應用程式提供自訂輸入法 (使用 InputMethodService 建構的鍵盤),且應僅安裝在支援第三方輸入法的裝置上。範例:
    <uses-feature android:name="android.software.input_methods" android:required="true" />
    
    FEATURE_BLUETOOTH_LE
    宣告您的應用程式使用藍牙低功耗 API,且應只安裝在能夠透過藍牙低功耗與其他裝置通訊的裝置上。範例:
    <uses-feature android:name="android.software.bluetooth_le" android:required="true" />
    

    使用者權限

    <uses-permission> 現在支援下列值,可宣告應用程式存取特定 API 所需的權限。

    BIND_NOTIFICATION_LISTENER_SERVICE
    這是使用新 NotificationListenerService API 的必要步驟。
    SEND_RESPOND_VIA_MESSAGE
    如要接收 ACTION_RESPOND_VIA_MESSAGE 意圖,此為必要項目。

    如要進一步瞭解 Android 4.3 中的所有 API 變更,請參閱 API 差異報告