Android 12 平台包含可能對應用程式造成影響的行為變更。無論 targetSdkVersion
為何,當應用程式在 Android 12 上執行時,下列行為變更將會套用至所有應用程式。您應測試應用程式,並視需要修改,以便在適當情況下支援新版本功能。
另請務必查看僅對指定 Android 12 為目標版本的應用程式造成影響的行為變更。
使用者體驗
延展過度捲動效果
在搭載 Android 12 以上版本的裝置上,過度捲動事件的視覺行為會有所不同。
在 Android 11 以下版本,過度捲動事件會導致視覺元素發光;在 Android 12 以上版本,視覺元素會在拖曳事件中延展並彈回,並在快速滑動事件中快速滑動並彈回。
詳情請參閱捲動手勢動畫指南。
應用程式啟動畫面
如果您先前已在 Android 11 以下版本中實作了自訂啟動畫面,就必須將應用程式遷移至 SplashScreen
API,以確保其可在 Android 12 以上版本中正確顯示。如果沒有遷移應用程式,使用者啟動應用程式時,會發現啟動效果比較遜色,甚至會出現一些意外情況。
如需操作說明,請參閱「將現有啟動畫面實作遷移至 Android 12」。
此外,從 Android 12 開始,系統會一律為所有應用程式在冷啟動和暖啟動時套用新的 Android 系統預設啟動畫面。根據預設,此系統預設啟動畫面是使用應用程式的啟動器圖示元素和主題的 windowBackground
(如果是單一顏色) 建構而成。
詳情請參閱啟動畫面開發人員指南。
網頁意圖解析
自 Android 12 (API 級別 31) 起,只有在應用程式獲准使用網頁意圖中包含的特定網域時,一般網頁意圖才會解析為應用程式中的活動。如果應用程式未獲准存取網域,系統會改為將網頁意圖解析為使用者的預設瀏覽器應用程式。
應用程式可透過下列任一方式取得這項核准:
使用 Android 應用程式連結驗證網域。
如果應用程式指定 Android 12 以上版本,系統會自動驗證應用程式的 Android 應用程式連結。在應用程式的意圖篩選器中,確認您已加入
BROWSABLE
類別,並支援https
配置。在 Android 12 以上版本中,您可以手動驗證應用程式的 Android 應用程式連結,測試這項更新的邏輯對應用程式的影響。
如果應用程式會叫用網頁意圖,建議加入提示或對話方塊,要求使用者確認動作。
改善手勢操作模式的沉浸模式
Android 12 整合了現有行為,讓使用者在沉浸模式中,更容易執行手勢操作指令。此外,Android 12 也為黏滯沉浸模式提供回溯相容性行為。
Display#getRealSize 和 getRealMetrics:淘汰和限制
Android 裝置有多種板型規格,例如大螢幕、平板電腦和摺疊式裝置。如要為每部裝置適當算繪內容,應用程式必須判斷螢幕或螢幕大小。隨著時間演進,Android 提供不同的 API 來擷取這項資訊。在 Android 11 中,我們推出了 WindowMetrics
API,並淘汰下列方法:
在 Android 12 中,我們仍建議使用 WindowMetrics
,並淘汰下列方法:
為減輕應用程式使用 Display API 擷取應用程式邊界時的行為,Android 12 會限制 API 傳回的值,適用於無法完全調整大小的應用程式。這可能會影響使用 MediaProjection
搭配這項資訊的應用程式。
應用程式應使用 WindowMetrics
API 查詢視窗的界線,並使用 Configuration.densityDpi
查詢目前的密度。
如要與舊版 Android 達成更廣泛的相容性,可以使用 Jetpack WindowManager
程式庫,其中包含支援 Android 4.0 (API 級別 14) 以上版本的 WindowMetrics
類別。
WindowMetrics 的使用範例
首先,請確認應用程式的活動可完全調整大小。
活動應依賴活動內容中的 WindowMetrics
執行任何與 UI 相關的工作,尤其是 WindowManager.getCurrentWindowMetrics()
或 Jetpack 的 WindowMetricsCalculator.computeCurrentWindowMetrics()
。
如果應用程式建立 MediaProjection
,則必須正確調整界線大小,因為投影會擷取投影機應用程式執行的顯示分割區。
如果應用程式可完全調整大小,活動情境會傳回正確的界線,如下所示:
Kotlin
val projectionMetrics: WindowMetrics = activityContext .getSystemService(WindowManager::class.java).maximumWindowMetrics
Java
WindowMetrics projectionMetrics = activityContext .getSystemService(WindowManager.class).getMaximumWindowMetrics();
如果應用程式無法完全調整大小,則必須從 WindowContext
執行個體查詢,並使用 WindowManager.getMaximumWindowMetrics()
或 Jetpack 方法 WindowMetricsCalculator.computeMaximumWindowMetrics()
擷取活動邊界 WindowMetrics
。
Kotlin
val windowContext = context.createWindowContext(mContext.display!!, WindowManager.LayoutParams.TYPE_APPLICATION, null) val projectionMetrics = windowContext.getSystemService(WindowManager::class.java) .maximumWindowMetrics
Java
Context windowContext = context.createWindowContext(mContext.getDisplay(), WindowManager.LayoutParams.TYPE_APPLICATION, null); WindowMetrics projectionMetrics = windowContext.getSystemService(WindowManager.class) .getMaximumWindowMetrics();
多視窗模式下的所有應用程式
Android 12 將多視窗模式設為標準行為。
在大螢幕上 (sw >= 600dp),無論應用程式設定為何,平台都支援所有應用程式採用多視窗模式。如果設為 resizeableActivity="false"
,應用程式會視需要進入相容模式,以符合螢幕尺寸。
在小螢幕上 (sw < 600dp),系統會檢查活動的 minWidth
和 minHeight
,判斷該活動是否能以多視窗模式執行。如果設為 resizeableActivity="false"
,則無論最小寬度和高度為何,該應用程式都無法以多視窗模式執行。
詳情請參閱「多視窗模式支援」。
在大型螢幕上預覽相機畫面
相機應用程式通常會假設裝置方向和相機預覽畫面的顯示比例之間存在固定關係。不過,大螢幕板型規格 (例如折疊式裝置) 和顯示模式 (例如多視窗和多螢幕模式) 挑戰了這項假設。
在 Android 12 上,要求特定螢幕方向且無法調整大小的相機應用程式 (resizeableActivity="false"
) 會自動進入內嵌直向模式,確保相機預覽畫面方向和顯示比例正確。在摺疊式裝置和其他具有相機硬體抽象層 (HAL) 的裝置上,相機輸出內容會額外旋轉,以補償相機感應器方向,並裁剪相機輸出內容,使其符合應用程式相機預覽畫面的顯示比例。無論裝置方向為何,以及裝置處於折疊或展開狀態,裁剪和額外旋轉都能確保相機預覽畫面呈現正確。
前景服務通知的使用者體驗延遲
為簡化短時間執行的前景服務體驗,搭載 Android 12 以上版本的裝置可以延遲 10 秒顯示前景服務通知,少數情況除外。這項變更可讓生命週期較短的工作在通知顯示前完成。
成效
受限制的應用程式待命值區
Android 11 (API 級別 30) 推出了「受限值區」,做為應用程式待命值區。從 Android 12 開始,這個儲存區預設為啟用。受限值區的優先順序是所有值區中最低 (也是限制最嚴格)。優先順序由高至低的值區如下:
- 使用中:應用程式目前正在使用或最近使用過。
- 工作組:應用程式會定期使用。
- 常用:應用程式經常使用,但不是每天都會使用。
- 很少使用:應用程式不常使用。
- 受限制:應用程式會耗用大量系統資源,或可能有不理想的行為。
除了使用模式外,系統也會將應用程式的行為納入考量,判斷是否要將應用程式納入受限制值區。
如果應用程式以合理的方式使用系統資源,就不太可能會指派至受限制值區。此外,如果使用者直接與應用程式互動,系統也會將應用程式設置在限制較少的值區中。
確認應用程式是否位於受限制值區
如要確認系統是否已將應用程式排入受限制值區,請呼叫 getAppStandbyBucket()
。如果這個方法傳回 STANDBY_BUCKET_RESTRICTED
,表示應用程式位於受限制值區。
測試受限制值區的行為
如要測試應用程式在系統將其排入受限制值區時的行為,您可以手動將應用程式移至該值區。如要這麼做,請在終端機視窗中執行下列指令:
adb shell am set-standby-bucket PACKAGE_NAME restricted
前景位置資訊和省電模式
從 Android 12 開始,即使螢幕關閉,只要省電模式處於啟用狀態,系統仍可繼續提供前景位置資訊 (包括來自前景服務的位置資訊)。
先前,省電模式會在螢幕關閉時停止更新位置資訊。 這項變更可延長電池續航力,開發人員也不必要求使用者停用省電模式,確保位置資訊傳送無虞。
如果應用程式透過前景服務要求位置資訊,請按照下列步驟操作:
- 撥打電話
getLocationPowerSaverMode()
查看裝置在省電模式下,定位功能的運作方式。 - 如果傳回
LOCATION_MODE_FOREGROUND_ONLY
,即使省電模式已開啟且螢幕關閉,應用程式仍會在前景或執行前景服務時持續接收位置資訊更新。
安全性和隱私權
大概位置
在搭載 Android 12 以上版本的裝置上,使用者可以要求應用程式僅存取概略位置資訊。
如果應用程式要求 ACCESS_FINE_LOCATION
執行階段權限,您也應要求 ACCESS_COARSE_LOCATION
權限,以處理使用者授予應用程式概略位置存取權的情況。您應在單一執行階段要求中加入這兩項權限。
如圖 1 所示,系統權限對話方塊會包含下列選項:
- 精確:提供精確位置資訊的存取權。
- 概略:僅允許存取大概位置資訊。
麥克風和相機快速停用鈕
如果是搭載 Android 12 以上版本的支援裝置,使用者只要按下一個快速停用鈕,即可啟用或停用裝置上所有應用程式的相機和麥克風存取權。使用者可以透過「快速設定」 (如圖 1 或系統設定中的「隱私」畫面) 切換開關選項。
進一步瞭解這些切換鈕,以及如何確認應用程式遵循CAMERA
和RECORD_AUDIO
權限的最佳做法。
麥克風和攝影機指標
如果是搭載 Android 12 以上版本的裝置,當應用程式存取麥克風或相機,狀態列中會顯示相應圖示。
進一步瞭解這些指標,以及如何檢查應用程式是否遵循 CAMERA
和 RECORD_AUDIO
權限的最佳做法。
權限套件瀏覽權限
在搭載 Android 12 以上版本的裝置上,如果應用程式指定 Android 11 (API 級別 30) 以上版本,並呼叫下列其中一種方法,系統會根據應用程式對其他應用程式的套件顯示設定,篩選結果集:
移除 BouncyCastle 實作項目
Android 12 會移除許多先前已淘汰的加密演算法 BouncyCastle 實作項目,包括所有 AES 演算法。系統會改用這些演算法的 Conscrypt 實作項目。
如果符合下列任一情況,這項變更就會影響您的應用程式:
- 您的應用程式使用 512 位元金鑰大小。Conscrypt 不支援這個金鑰大小。 如有需要,請更新應用程式的密碼編譯邏輯,使用不同大小的金鑰。
您的應用程式搭配
KeyGenerator
使用無效的金鑰大小。 與 BouncyCastle 相比,Conscrypt 實作的KeyGenerator
會對金鑰參數執行額外驗證。舉例來說,Conscrypt 不允許應用程式產生 64 位元的 AES 金鑰,因為 AES 只支援 128、192 和 256 位元的金鑰。BouncyCastle 允許產生大小無效的金鑰,但如果這些金鑰與
Cipher
搭配使用,就會在稍後失敗。 Conscrypt 會提早失敗。您使用 12 位元組以外的大小初始化 Galois/計數器模式 (GCM) 密碼。Conscrypt 實作的
GcmParameterSpec
需要 12 個位元組的初始化作業,這是 NIST 建議的做法。
剪貼簿存取通知
在 Android 12 以上版本中,應用程式首次呼叫 getPrimaryClip()
存取其他應用程式的剪貼簿資料時,系統會顯示訊息泡泡,通知使用者應用程式存取剪貼簿。
祝賀訊息中的文字含有以下格式:
APP pasted from your clipboard.
夾片說明中的文字相關資訊
在 Android 12 以上版本中,getPrimaryClipDescription()
可偵測下列詳細資料:
- 使用
isStyledText()
的樣式化文字。 - 使用
getConfidenceScore()
將文字分類,例如網址。
應用程式無法關閉系統對話方塊
為提升使用者與應用程式和系統互動時的控制權,Android 12 以上版本已淘汰 ACTION_CLOSE_SYSTEM_DIALOGS
Intent 動作。除了少數特殊情況,當應用程式嘗試叫用含有這項動作的 Intent 時,系統會根據應用程式的目標 SDK 版本執行下列其中一項操作:
- 如果應用程式指定 Android 12 以上版本,就會發生
SecurityException
。 如果應用程式指定 Android 11 (API 級別 30) 以下版本,意圖不會執行,且 Logcat 會顯示以下訊息:
E ActivityTaskManager Permission Denial: \ android.intent.action.CLOSE_SYSTEM_DIALOGS broadcast from \ com.package.name requires android.permission.BROADCAST_CLOSE_SYSTEM_DIALOGS, \ dropping broadcast.
例外狀況
在下列情況下,應用程式仍可在 Android 12 以上版本中關閉系統對話方塊:
- 您的應用程式正在執行插樁測試。
應用程式指定 Android 11 以下版本,且顯示的視窗位於通知匣上方。
您的應用程式指定 Android 11 以下版本為目標。此外,使用者已與通知互動 (可能使用通知的動作按鈕),而您的應用程式正在處理服務或廣播接收器,以回應使用者動作。
應用程式指定 Android 11 以下版本,且有作用中的無障礙服務。如果應用程式以 Android 12 為目標,且想關閉通知列,請改用
GLOBAL_ACTION_DISMISS_NOTIFICATION_SHADE
無障礙動作。
系統會封鎖不信任的觸控事件
為維護系統安全和良好使用者體驗,Android 12 會禁止應用程式在疊加層以不安全的方式遮蔽應用程式時,耗用觸控事件。換句話說,系統會封鎖通過特定視窗的觸控事件,但有幾個例外狀況。
受影響的應用程式
這項變更會影響選擇讓觸控事件傳遞至視窗的應用程式,例如使用 FLAG_NOT_TOUCHABLE
標記。相關例子包括但不限於:
- 需要
SYSTEM_ALERT_WINDOW
權限的疊加層,例如使用TYPE_APPLICATION_OVERLAY
的視窗,並使用FLAG_NOT_TOUCHABLE
旗標。 - 使用
FLAG_NOT_TOUCHABLE
旗標的活動視窗。
例外狀況
在下列情況下,系統允許「直通」觸控事件:
- 應用程式內的互動。應用程式會顯示疊加畫面,且只有在使用者與應用程式互動時才會顯示。
信任的視窗。這些視窗包括但不限於:
完全透明的視窗。視窗的
alpha
屬性為 0.0。半透明的系統快訊視窗。當一組系統警示視窗的總不透明度小於或等於系統的觸控遮蔽不透明度上限時,系統會將這組視窗視為半透明。在 Android 12 中,這項最大不透明度預設為 0.8。
偵測何時封鎖不受信任的觸控操作
如果系統封鎖觸控動作,Logcat 會記錄下列訊息:
Untrusted touch due to occlusion by PACKAGE_NAME
測試變更
搭載 Android 12 以上版本的裝置預設會封鎖不受信任的觸控事件。如要允許不受信任的觸控操作,請在終端機視窗中執行下列 ADB 指令:
# A specific app adb shell am compat disable BLOCK_UNTRUSTED_TOUCHES com.example.app # All apps # If you'd still like to see a Logcat message warning when a touch would be # blocked, use 1 instead of 0. adb shell settings put global block_untrusted_touches 0
如要將行為還原為預設值 (封鎖不受信任的觸控),請執行下列指令:
# A specific app adb shell am compat reset BLOCK_UNTRUSTED_TOUCHES com.example.app # All apps adb shell settings put global block_untrusted_touches 2
活動生命週期
按下「返回」鍵時,系統不會再完成根啟動器活動
Android 12 變更了啟動器活動中系統返回鍵的預設處理方式,這些活動位於工作根目錄。在先前的版本中,系統會在按下返回鍵時完成這些活動。在 Android 12 中,系統現在會將活動及其工作移至背景,而不是完成活動。新行為與目前使用主畫面按鈕或手勢離開應用程式時的行為一致。
對大多數應用程式而言,這項變更代表使用者可透過「返回」鍵離開應用程式,並從暖啟動狀態快速繼續使用應用程式,而不必從冷啟動狀態完全重新啟動應用程式。
建議您測試應用程式是否能因應這項異動。如果您的應用程式目前會覆寫 onBackPressed()
來處理返回導覽並完成 Activity
,請更新實作項目,改為呼叫 super.onBackPressed()
,而非完成作業。在適當情況下呼叫 super.onBackPressed()
會將活動及其工作移至背景,並為使用者提供更一致的應用程式間導覽體驗。
另請注意,一般來說,我們建議使用 AndroidX Activity API 提供自訂返回導覽,而不是覆寫 onBackPressed()
。如果沒有任何元件攔截系統返回鍵,AndroidX Activity API 會自動延後至適當的系統行為。
圖形和圖片
改善刷新率切換功能
在 Android 12 中,無論螢幕是否支援流暢切換至新刷新率,都可以使用 setFrameRate()
變更刷新率。流暢切換是指切換時不會出現任何視覺中斷情形,例如黑畫面一兩秒。先前,如果螢幕不支援無縫轉換,在呼叫 setFrameRate()
後,通常會繼續使用相同的更新率。您可以呼叫 getAlternativeRefreshRates()
,預先判斷轉換至新版重新整理功能是否順利。一般來說,回呼 onDisplayChanged()
會在完成重新整理率切換後呼叫,但對於某些外部連線螢幕,則會在非無縫轉換期間呼叫。
以下為實作範例:
Kotlin
// Determine whether the transition will be seamless. // Non-seamless transitions may cause a 1-2 second black screen. val refreshRates = this.display?.mode?.alternativeRefreshRates val willBeSeamless = Arrays.asList<FloatArray>(refreshRates).contains(newRefreshRate) // Set the frame rate even if the transition will not be seamless. surface.setFrameRate(newRefreshRate, FRAME_RATE_COMPATIBILITY_FIXED_SOURCE, CHANGE_FRAME_RATE_ALWAYS)
Java
// Determine whether the transition will be seamless. // Non-seamless transitions may cause a 1-2 second black screen. Display display = context.getDisplay(); // API 30+ Display.Mode mode = display.getMode(); float[] refreshRates = mode.getAlternativeRefreshRates(); boolean willBeSeamless = Arrays.asList(refreshRates).contains(newRefreshRate); // Set the frame rate even if the transition will not be seamless. surface.setFrameRate(newRefreshRate, FRAME_RATE_COMPATIBILITY_FIXED_SOURCE, CHANGE_FRAME_RATE_ALWAYS);
連線能力
Passpoint 更新
Android 12 新增下列 API:
isPasspointTermsAndConditionsSupported()
:「條款及細則」是 Passpoint 功能,可讓網路部署作業以安全的 Passpoint 網路取代使用開放網路的不安全網頁認證入口。如果使用者必須接受條款及細則,系統會顯示通知。如果應用程式建議的 Passpoint 網路設有條款及細則限制,就必須先呼叫這個 API,確認裝置支援這項功能。如果裝置不支援這項功能,就無法連上這個網路,必須建議使用替代或舊版網路。isDecoratedIdentitySupported()
:使用前置字元裝飾驗證網路時,裝飾的身分前置字元可讓網路業者更新網路存取 ID (NAI),透過 AAA 網路內的多個 Proxy 執行明確的路由 (詳情請參閱 RFC 7542)。Android 12 實作這項功能,是為了符合 WBA 針對 PPS-MO 擴充功能的規格。如果應用程式建議的 Passpoint 網路需要裝飾身分,就必須先呼叫這個 API,確認裝置支援這項功能。如果裝置不支援這項功能,系統就不會裝飾身分,且可能無法通過網路驗證。
如要建立 Passpoint 建議,應用程式必須使用 PasspointConfiguration
、Credential
和 HomeSp
類別。這些類別說明 Passpoint 設定檔,該設定檔定義於 Wi-Fi 聯盟 Passpoint 規格中。
詳情請參閱「用於網際網路連線的 Wi-Fi Suggestion API」。
更新非 SDK 介面限制
基於與 Android 開發人員合作及最新的內部測試,Android 12 包含更新後的受限制非 SDK 介面清單。在限制非 SDK 介面之前,我們盡可能確保公開替代方案的可得性。
如果您的應用程式並不是以 Android 12 為目標版本,則此處所述的某些變更可能不會立即對您造成影響。雖然您目前可以使用某些非 SDK 介面 (視應用程式的目標 API 級別而定),但使用任何非 SDK 方法或欄位時,均可能面臨應用程式故障的高度風險。
如果不確定應用程式是否使用非 SDK 介面,可對應用程式進行測試以便確認。如果您的應用程式仰賴非 SDK 介面,則建議您開始規劃遷移至 SDK 替代方案。我們瞭解有些應用程式可使用非 SDK 介面運作。如果您除了為應用程式中的某個功能使用非 SDK 介面外,已別無他法,則應要求新的公用 API。
如要進一步瞭解此 Android 版本中的變更,請參閱「Android 12 的非 SDK 介面限制更新」。如要進一步瞭解非 SDK 介面的一般資訊,請參閱「非 SDK 介面的限制」。