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,同時支援舊版,只要在程式碼中新增條件,即可在執行 minSdkVersion 不支援的 API 之前檢查系統 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,讓使用者在受限制的個人資料環境中執行時,控管應用程式可用的內容類型。

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

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

  • TYPE_BOOLEAN:適用於 true 或 false 的限制。
  • TYPE_CHOICE:適用於包含多個互斥選項 (圓形按鈕選項) 的限制。
  • TYPE_MULTI_SELECT:此限制提供多個無法互斥 (核取方塊選項) 的限制。

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

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

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

支援受限設定檔的帳戶

新增至主要使用者的帳戶都可以透過受限的設定檔存取,但根據預設,您無法透過 AccountManager API 存取這些帳戶。如果您在受限的設定檔中嘗試使用 AccountManager 新增帳戶,就會收到失敗結果。由於這些限制,您有以下三個選項:

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

    如要透過受限的設定檔存取帳戶,您必須在 <application> 標記中加入 android:restrictedAccountType 屬性:

    <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 現在支援藍牙低功耗 (LE) 技術,在 android.bluetooth 中提供新的 API。使用新的 API,您可以建構能夠與藍牙低功耗週邊裝置 (例如心率監測器和計步器) 通訊的 Android 應用程式。

    藍牙 LE 是一項硬體功能,不適用於部分 Android 裝置,因此您必須在資訊清單檔案中為 "android.hardware.bluetooth_le" 宣告 <uses-feature> 元素:

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

    如果您已熟悉 Android 的傳統藍牙 API,請注意使用藍牙 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,來宣告處理這些訊息的功能。

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

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

    多媒體

    MediaExtractor 和 MediaCodec 強化項目

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

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

    媒體數位版權管理

    新的 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 檔案。您也可以將 MediaMuxerMediaExtractor 搭配使用,執行媒體編輯,無需編碼或解碼。

    RemoteControlClient 的播放進度和拖曳

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

    首先,您必須將 FLAG_KEY_MEDIA_POSITION_UPDATE 旗標傳遞至 setTransportControlsFlags(),藉此啟用該旗標。

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

    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 物件新增至疊加層。如果您為版面配置檢視畫面呼叫 getOverlay() (例如 RelativeLayout),傳回的物件會是 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 的螢幕截圖已啟用「顯示版面配置邊界」開發人員設定。每個檢視畫面的紅色線條代表光學邊界,藍線表示裁剪邊界,而粉紅色則代表邊界。

    圖 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",就能立即受益。

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

    矩形值的動畫

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

    視窗連接和焦點事件監聽器

    之前,如果想監聽檢視畫面附加/卸離視窗或焦點變更時,需要覆寫 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」

    新的聯絡人供應程式查詢 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?

    答錯了,因為「Bay Street」應該要有「15 個」。解決方案是使用 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 支援資料庫 (包含 BidiFormatter 類別和相關 API),提供舊版 Android 使用。

    無障礙服務

    處理重要事件

    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 貼上。

    注意:透過 Android 支援資料庫AccessibilityNodeInfoCompat 類別,這些新 API 也適用於舊版 Android。

    宣告無障礙功能

    從 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 中的 API 不同。

    應用程式的 Systrace 事件

    Android 4.3 新增了 Trace 類別,其中包含兩個靜態方法 (beginSection()endSection()),可讓您定義要納入 Systrace 報表的程式碼區塊。透過在應用程式中建立可追蹤程式碼的區段,Systrace 記錄可以提供更詳細的分析,協助您瞭解應用程式效能降低的時間點。

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

    安全性

    用於應用程式私密金鑰的 Android 金鑰存放區

    Android 現在會在 KeyStore 設施 (稱為「Android Key Store」) 中提供自訂 Java 安全性提供者,讓您產生及儲存僅供您的應用程式查看與使用的私密金鑰。如要載入 Android Key Store,請將 "AndroidKeyStore" 傳遞至 KeyStore.getInstance()

    如要在 Android Key Store 中管理應用程式的私人憑證,請使用 KeyPairGeneratorSpec 產生包含 KeyPairGenerator 的新金鑰。首先,呼叫 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 差異報表