API 級別:17
Android 4.2 (JELLY_BEAN_MR1
) 是 Jelly Bean 版本的更新,可為使用者和應用程式開發人員提供新功能。本文件將介紹
實用的新 API
應用程式開發人員應盡快從 SDK Manager 下載 Android 4.2 系統映像檔和 SDK 平台。如果您沒有搭載 Android 4.2 的裝置可用來測試應用程式,請使用 Android 4.2 系統映像檔,在 Android 模擬器上測試應用程式。接著,針對 Android 4.2 平台建構應用程式,開始使用最新的 API。
為了針對搭載 Android 4.2 的裝置進一步最佳化應用程式,
請將 targetSdkVersion
設為
"17"
,安裝在 Android 4.2 系統映像檔上
,然後使用這項變更發布更新。
您可以在程式碼中加入條件,在執行 minSdkVersion
不支援的 API 前檢查系統 API 級別,藉此使用 Android 4.2 中的 API,同時支援舊版。如要進一步瞭解如何維持回溯相容性,請參閱「建立與先前版本相容的 UI」。
如要進一步瞭解 API 級別的運作方式,請參閱「什麼是 API 級別?」。
重要行為變更
如果您先前曾發布 Android 應用程式,請注意下列事項 可能影響應用程式行為的變更:
- 在預設情況下,我們已不再匯出內容供應器,也就是說,
android:exported
屬性的預設值現在為“false"
。如果有其他應用程式必須 可存取內容供應器,您必須立即明確設定android:exported="true"
。您必須將
android:targetSdkVersion
或android:minSdkVersion
設為 17 以上,這項變更才會生效。否則,即使在 Android 4.2 以上版本上執行,預設值仍為“true"
。 - 如果應用程式要求
ACCESS_COARSE_LOCATION
權限但未要求ACCESS_FINE_LOCATION
權限,使用者位置結果可能會比舊版 Android 版本不準確。為了符合使用者對隱私權的期望,當應用程式要求粗略位置 (而非精確位置) 存取權時,系統不會提供比街區更精確的使用者位置估計值。
- 由
Settings.System
定義的部分裝置設定現在為唯讀。如果應用程式嘗試寫入已移至Settings.Global
的Settings.System
中定義的設定, 在 Android 4.2 以上版本執行時,寫入作業會自動失敗,不顯示任何訊息。即使
android:targetSdkVersion
和android:minSdkVersion
的值低於 17,在 Android 4.2 以上版本中執行時,應用程式也無法修改已移至Settings.Global
的設定。 - 如果您的應用程式使用
WebView
,Android 4.2 會為 安全,以便您可以放心將 JavaScript 繫結至 Android 程式碼。如果您將targetSdkVersion
設為 17 以上,則必須在您要提供給 JavaScript 的任何方法中加入@JavascriptInterface
註解 (方法也必須是公開的)。如未提供 備註,WebView
中的網頁無法透過該方法存取 可在 Android 4.2 以上版本中執行如果將targetSdkVersion
敬上 16 以下,並不需要註解,但我們建議您更新目標版本 並添加備註來加強安全防護進一步瞭解如何將 JavaScript 程式碼繫結至 Android 程式碼。
Daydream
Daydream 是適用於 Android 裝置的全新互動式螢幕保護程式模式。裝置會自動啟動 裝置插入座架,或裝置在接上電源時處於閒置狀態時 充電器 (而非關閉螢幕)。Daydream 一次展示一個夢想, 純粹是視覺、被動式螢幕,會在使用者輕觸時關閉,或具有互動性和回應性 完整的輸入事件套件您的夢想會在應用程式程序中運作,並且具備 Android UI 工具包,包括檢視區塊、版面配置和動畫,因此變得更加靈活, 功能比動態桌布或應用程式小工具更強大
您可以實作 DreamService
的子類別,為 Daydream 建立夢境。DreamService
API 的設計與 Activity
的 API 類似。如要為夢境指定 UI,請在建立視窗後的任何時間 (例如從 onAttachedToWindow()
回呼),將版面配置資源 ID 或 View
傳遞至 setContentView()
。
DreamService
類別提供其他重要生命週期回呼
方法,例如 onDreamingStarted()
、onDreamingStopped()
和 onDetachedFromWindow()
。Service
您無法從應用程式啟動 DreamService
,系統會自動啟動。
如果夢境具有互動功能,您可以從夢境啟動活動,將使用者帶往應用程式的完整 UI,以便進一步瞭解或控制夢境。您可以使用 finish()
結束夢境,讓使用者看到新的活動。
若要允許系統取得您的 day 天 ,請使用 <service>
元素宣告 DreamService
。然後,您必須加入含有 "android.service.dreams.DreamService"
動作的意圖篩選器。例如:
<service android:name=".MyDream" android:exported="true" android:icon="@drawable/dream_icon" android:label="@string/dream_label" > <intent-filter> <action android:name="android.service.dreams.DreamService" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </service>
DreamService
中還有其他實用的方法,請注意:
setInteractive(boolean)
會控制 Dream 是否接收輸入事件,或是在使用者輸入時立即離開。如果夢想 互動,使用者可使用 [Back] (返回) 或 [Home] (主畫面) 按鈕離開夢想,或直接呼叫finish()
就能阻止夢境。- 如要提供全螢幕顯示畫面,您可以呼叫
setFullscreen()
來隱藏狀態列。 - 在 Daydream 啟動前,螢幕會調暗,向使用者發出閒置逾時倒數即將結束的訊號。呼叫
setScreenBright(true)
可改將螢幕設為一般亮度。
詳情請參閱 DreamService
說明文件。
第二螢幕
Android 現在可讓應用程式在連接的其他裝置上顯示獨創內容
透過有線連線或 Wi-Fi 連線至使用者的裝置。
如要為次要螢幕建立獨特內容,請擴充 Presentation
並實作 onCreate()
回呼。在 onCreate()
中,呼叫 setContentView()
指定次要螢幕的 UI。Presentation
類別是 Dialog
類別的擴充功能,可讓應用程式在次要螢幕上顯示獨特的 UI。
如要偵測可顯示 Presentation
的次要螢幕,請按照下列步驟操作:
請使用 DisplayManager
或 MediaRouter
相互整合雖然 DisplayManager
API 可讓您列舉
可能會同時連線的多個螢幕,通常應該改用 MediaRouter
,以便快速存取系統的預設螢幕
簡報
如要取得簡報的預設顯示畫面,請呼叫 MediaRouter.getSelectedRoute()
並傳遞
ROUTE_TYPE_LIVE_VIDEO
。這會傳回 MediaRouter.RouteInfo
物件,說明系統目前為影片播放選取的路徑。如果 MediaRouter.RouteInfo
非空值,請呼叫 getPresentationDisplay()
來取得代表已連結顯示器的 Display
。
接著,您可以將 Display
物件傳遞至 Presentation
類別的建構函式,以便顯示簡報。你分享的螢幕畫面將立即顯示
就會顯示在次要顯示器上
如要在執行階段偵測到新螢幕連線時進行偵測,請建立 MediaRouter.SimpleCallback
的執行個體,並在當中實作 onRoutePresentationDisplayChanged()
回呼方法,系統會在新螢幕連線時呼叫該方法
連接簡報畫面。接著,將 MediaRouter.SimpleCallback
與 ROUTE_TYPE_LIVE_VIDEO
路徑類型一併傳遞至 MediaRouter.addCallback()
,即可註冊 MediaRouter.SimpleCallback
。當您接到:
onRoutePresentationDisplayChanged()
只需按照上述方式呼叫 MediaRouter.getSelectedRoute()
即可。
如要進一步針對次要螢幕最佳化 Presentation
中的 UI,您可以套用不同的主題,方法是在已套用至應用程式或活動的 <style>
中指定 android:presentationTheme
屬性。
請注意,連結至使用者裝置的螢幕通常較大,且可能具有不同的螢幕密度。裝置螢幕特性可能會有所不同
提供專為這類大螢幕最佳化的資源。如果您需要從 Presentation
要求其他資源,請呼叫 getContext()
.getResources()
來取得與螢幕相對應的 Resources
物件。這樣一來,應用程式就能提供最適合次要螢幕螢幕大小和密度的適當資源。
如需更多資訊和部分程式碼範例,請參閱 Presentation
類別說明文件
螢幕鎖定小工具
Android 現已允許使用者在螢幕鎖定畫面上新增應用程式小工具。如要讓您的應用程式小工具在
螢幕鎖定,請將 android:widgetCategory
屬性新增至指定 AppWidgetProviderInfo
的 XML 檔案。這項屬性支援兩個值:home_screen
和 keyguard
。屬性預設為 home_screen
,方便使用者
應用程式小工具。如果您希望應用程式小工具也能同時顯示在鎖定畫面上
畫面中新增 keyguard
值:
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android" ... android:widgetCategory="keyguard|home_screen"> </appwidget-provider>
您也應該在螢幕鎖定畫面上,為應用程式小工具指定初始版面配置,方法是使用
android:initialKeyguardLayout
屬性。這項功能的運作方式與 android:initialLayout
相同,也就是提供可立即顯示的版面配置,直到應用程式小工具初始化並能更新版面配置為止。
如要進一步瞭解如何建構鎖定畫面的應用程式小工具,包括在鎖定畫面上正確調整應用程式小工具的大小,請參閱「應用程式小工具」指南。
多位使用者
Android 現在允許在平板電腦等共用裝置中使用多個使用者空間。裝置上的每位使用者都有自己的帳戶、應用程式、系統設定、檔案和其他使用者相關聯的資料。
應用程式開發人員不必採取其他行動,就能讓應用程式正常運作。 方便多位使用者共用同一個裝置無論裝置上有多少使用者,應用程式為特定使用者儲存的資料,都會與應用程式為其他使用者儲存的資料分開。系統會追蹤哪些使用者資料屬於使用者程序 應用程式正在運作,且僅允許應用程式存取該使用者的資料,而且不允許 存取其他使用者的資料。
在多用戶環境中儲存資料
每當您的應用程式儲存使用者的偏好設定、建立資料庫,或將檔案寫入使用者的 內部或外部儲存空間,只有在該使用者身分執行時,才能存取該資料。
如要確定您的應用程式在多使用者環境中能正常運作,請不要參考 使用硬式編碼路徑,並一律使用內部應用程式目錄或外部儲存空間位置 適當的 API:
- 如要存取內部儲存空間,請使用
getFilesDir()
、getCacheDir()
或openFileOutput()
。 - 如要存取外部儲存空間,請使用
getExternalFilesDir()
或getExternalStoragePublicDirectory()
。
無論您使用哪個 API 為特定使用者儲存資料,在以其他使用者身分執行時,都無法存取該資料。從應用程式的角度來看,每位使用者都是在完全獨立的裝置上執行。
在多使用者環境中識別使用者
如果應用程式想識別不重複的使用者 (例如收集數據分析或建立其他帳戶關聯),請遵循識別不重複安裝事件的最佳做法。只要在應用程式首次啟動時建立新的 UUID
,無論單一裝置上有多少使用者安裝您的應用程式,您都能確保取得用於追蹤每位使用者的專屬 ID。或者,您也可以儲存從伺服器擷取的本機符記,或是使用 Google Cloud Messaging 提供的註冊 ID。
請注意,如果應用程式要求提供任一硬體裝置 ID (例如 Wi-Fi MAC)
地址或 SERIAL
數字) 就會為每個 Pod 提供相同的值
因為這類 ID 與硬體而非使用者相關聯。更不用說這些 ID 會帶來其他問題,詳情請參閱「找出應用程式安裝記錄」網誌文章。
新的全域設定
系統設定已更新,可支援多位使用者,並新增 Settings.Global
。這組設定與 Settings.Secure
設定類似,因為它們都是唯讀,但會全域套用至裝置上的所有使用者空間。
從 Settings.System
或 Settings.Secure
移至此處的現有設定有:如果您的應用程式是
目前正在變更 Settings.System
中定義的設定
(例如 AIRPLANE_MODE_ON
),
在執行 Android 4.2 以上版本的裝置上,如果這些設定
已移至 Settings.Global
。您可以繼續讀取
Settings.Global
,但由於設定不再安全,
在應用程式變更時,嘗試這麼做將會失敗,而且系統會對
在 Android 4.2 以上版本執行應用程式時,系統會記錄應用程式。
支援 RTL 版面配置
Android 現在提供多個 API,可讓您妥善建構使用者介面 轉換版面配置方向,支援使用從右到左 (RTL) UI 和朗讀的語言 例如阿拉伯文和希伯來文
如要開始在應用程式中支援 RTL 版面配置,請在資訊清單檔案中將 android:supportsRtl
屬性設為 <application>
元素,並將其設為 “true"
。啟用這個選項後,系統會啟用各種 RTL API,以便顯示使用 RTL 版面配置的應用程式。舉例來說,動作列會顯示圖示和標題
,以及您使用
架構提供的 View
類別也會復原。
如果需要進一步最佳化使用 RTL 版面配置顯示的應用程式外觀, 最佳化有兩種基本層級:
- 將左側和右側取向的版面配置屬性轉換為開始和結束取向的版面配置屬性。
例如,使用
android:layout_marginStart
取代android:layout_marginLeft
和android:layout_marginEnd
,取代android:layout_marginRight
。RelativeLayout
類別也提供對應的版面配置屬性,用於取代左/右位置,例如android:layout_alignParentStart
可取代android:layout_alignParentLeft
,而android:layout_toStartOf
可取代android:layout_toLeftOf
。 - 如要全面最佳化 RTL 版面配置,您可以提供完全獨立的
使用
ldrtl
資源限定詞的版面配置檔案 (ldrtl
代表 layout-direction-right-to-left}。舉例來說,您可以將預設版面配置檔案儲存在res/layout/
中,並將 RTL 最佳化版面配置儲存在res/layout-ldrtl/
中。ldrtl
限定詞非常適合可繪製資源,因此您可以提供 指向對應閱讀方向的方向圖形。
架構中還提供許多其他用來支援 RTL 版面配置的 API,例如
View
類別,讓您可以實作適用於自訂內容的正確行為
以及在 Configuration
中查詢目前的版面配置方向。
注意:如果您使用 SQlite,且資料表或資料欄的名稱,
「僅限數字」成為
注意:使用 String.format(String, Object...)
可能導致號碼發生錯誤
已轉換成阿拉伯文版本 (如果裝置已設定為阿拉伯文語言代碼)。
您必須使用 String.format(Locale,String,Object...)
,確保系統以 ASCII 格式保留數字。您也可以使用 String.format("%d", int)
,而不要使用
String.valueOf(int)
:
以便設定數字格式
巢狀 Fragment
您現在可以在片段中嵌入片段。在您想將動態且可重複使用的 UI 元件放入本身也是動態且可重複使用的 UI 元件時,這項功能就非常實用。舉例來說,如果您使用 ViewPager
建立可向左向右滑動的片段,且該片段佔用大部分的螢幕空間,現在您可以將片段插入每個片段頁面。
若要為片段建立巢狀結構,只要呼叫 getChildFragmentManager()
上的
您要新增片段的 Fragment
。系統會傳回 FragmentManager
,您也可以像在頂層活動中一樣使用
建立片段交易舉例來說,以下程式碼會從現有的 Fragment
類別中新增片段:
Kotlin
val videoFragment = VideoPlayerFragment() childFragmentManager.beginTransaction().apply { add(R.id.video_fragment, videoFragment) commit() }
Java
Fragment videoFragment = new VideoPlayerFragment(); FragmentTransaction transaction = getChildFragmentManager().beginTransaction(); transaction.add(R.id.video_fragment, videoFragment).commit();
您可以在巢狀片段中呼叫 getParentFragment()
,取得父項片段的參照。
Android 支援資料庫現在也支援巢狀片段,方便您導入巢狀結構片段 Android 1.6 以上版本的片段設計。
注意:如果版面配置包含 <fragment>
,您就無法將版面配置轉譯為片段。只有在動態新增至片段時,系統才支援巢狀片段。
RenderScript
強化了 Renderscript 運算功能,並包含下列功能:
- 指令碼內建函式
您可以使用 Renderscript 內建的指令碼內在值,為您實作常見的作業,例如:
Blends
Blur
Color matrix
3x3 convolve
5x5 convolve
Per-channel lookup table
Converting an Android YUV buffer to RGB
如要使用指令碼內建函式,請呼叫每種方法的靜態
create()
方法 建立指令碼執行個體。接著,您可以呼叫每個指令碼內建項目的可用set()
方法,設定任何必要的輸入內容和選項。最後,請呼叫forEach()
方法來執行指令碼。- 指令碼群組
-
ScriptGroup
可讓您將相關的 Renderscript 鏈結在一起 編寫指令碼,然後按一下呼叫來執行使用
ScriptGroup.Builder
呼叫addKernel()
,將所有指令碼新增至群組。當您 加入所有指令碼,在 呼叫addConnection()
來編寫指令碼。 完成新增連線後,請呼叫create()
建立指令碼群組。在執行指令碼群組前,請先指定輸入內容Allocation
和初始指令碼,以便與setInput(Script.KernelID, Allocation)
方法,並提供輸出內容Allocation
,其中會寫入結果,並將結果寫入最終指令碼 搭配setOutput()
執行最後,呼叫execute()
:執行指令碼群組。 - FilterScript
-
Filterscript 會針對現有的 Renderscript API 定義限制,讓產生的程式碼可在更多種類的處理器 (CPU、GPU 和 DSP) 上執行。如要建立 Filterscript 檔案,請建立
.fs
檔案取代.rs
檔案並指定#pragma rs_fp_relaxed
即可 告知 Renderscript 執行階段,指令碼不需要嚴格的 IEEE 754-2008 浮點精確度。 這種精度允許將非正規數清除至零,以及朝零捨去。此外,Filterscript 不支援指標,因此 Filterscript 指令碼不得使用 32 位元內建類型,且必須使用__attribute__((kernel))
屬性指定自訂根函式,因為root()
函式的預設簽章定義了指標。
注意:雖然 Filterscript 支援平台,但開發人員 SDK 工具版本 21.0.1 將提供支援。
如需 Android 4.2 中所有 API 變更的詳細資訊,請參閱 API 差異比較表。