行為變更:所有應用程式

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 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),系統會檢查活動的 minWidthminHeight,判斷該活動是否能以多視窗模式執行。如果設為 resizeableActivity="false",則無論最小寬度和高度為何,該應用程式都無法以多視窗模式執行。

詳情請參閱「多視窗模式支援」。

在大型螢幕上預覽相機畫面

相機應用程式通常會假設裝置方向和相機預覽畫面的顯示比例之間有固定的關係。但大螢幕板型規格 (例如折疊式裝置) 和多視窗模式和多螢幕等顯示模式,會難以判斷這樣的假設。

在 Android 12 中,如果相機應用程式會要求特定螢幕方向,且無法調整大小 (resizeableActivity="false"),系統會自動進入插邊直向模式,確保相機預覽畫面的方向和長寬比正確無誤。在折疊式及其他附有相機硬體抽象層 (HAL) 的裝置上,系統會為相機輸出內容套用額外的旋轉機制,藉此因應相機感應器方向,並裁剪相機輸出內容,以符合應用程式相機預覽畫面的顯示比例。無論裝置螢幕方向以及裝置的折疊或展開狀態為何,裁剪和額外旋轉可確保相機預覽畫面正確呈現。

前景服務通知的使用者體驗延遲

為了針對短期執行的前景服務提供簡便的體驗,搭載 Android 12 或以上版本的裝置可能會延遲 10 秒顯示前景服務通知,但有幾項例外。這項變更能讓短期工作有機會在通知顯示前完成。

效能

受限制的應用程式待命值區

Android 11 (API 級別 30) 推出了受限制值區做為應用程式待命值區。從 Android 12 開始,這個值區將預設為啟用。 受限制值區的優先順序是所有值區的最低優先順序且設有最高的限制。按照優先順序由高到低的順序分類為:

  1. 使用中:應用程式目前正在使用或最近剛使用過。
  2. 工作組:應用程式會定期使用。
  3. 常用:應用程式經常使用,但不是每天都會使用。
  4. 罕見:應用程式不常使用。
  5. 受限制:應用程式會耗用大量系統資源,或可能有不理想的行為。

除了使用模式外,系統也會將應用程式的行為納入考量,判斷是否要將應用程式納入受限制值區。

如果應用程式以合理的方式使用系統資源,就不太可能會指派至受限制值區。此外,如果使用者直接與應用程式互動,系統也會將應用程式設置在限制較少的值區中。

檢查應用程式是否位於受限制值區

如要確認系統是否已將應用程式排入受限制值區,請呼叫 getAppStandbyBucket()。如果這個方法的傳回值為 STANDBY_BUCKET_RESTRICTED,表示您的應用程式位於受限制值區。

測試受限制值區的行為

如要測試應用程式在系統排入受限制值區時的行為,您可以手動將應用程式移至該值區。方法是在終端機視窗中執行下列指令:

adb shell am set-standby-bucket PACKAGE_NAME restricted

安全性和隱私權

大概位置

對話方塊有兩組上下排的選項
圖 1. 系統權限對話方塊,可讓使用者授予大概位置資訊。

在搭載 Android 12 以上版本的裝置上,使用者可以要求應用程式只能存取大概位置資訊。

如果應用程式要求 ACCESS_FINE_LOCATION 執行階段權限,您也應要求 ACCESS_COARSE_LOCATION 權限,以處理使用者授予應用程式的概略位置存取權的情況。您應在單一執行階段要求中納入這兩項權限。

系統權限對話方塊包含以下使用者選項,如圖 1 所示:

  • 精確:讓使用者存取精確位置資訊,
  • 概略:只提供大概位置資訊的存取權。

麥克風和相機快速停用鈕

在搭載 Android 12 以上版本的裝置上,使用者只要按下一個切換鈕,即可啟用或停用裝置上所有應用程式的相機和麥克風存取權。使用者可以透過快速設定 (如圖 1 或系統設定中的「隱私權」畫面) 存取可切換的選項。

進一步瞭解這些切換鈕,以及如何檢查應用程式是否遵循 CAMERARECORD_AUDIO 權限的最佳做法。

麥克風和相機指示燈

若是搭載 Android 12 或以上版本的裝置,當應用程式存取麥克風或相機時,在狀態列中會顯示相關圖示。

進一步瞭解這些指標,以及如何檢查應用程式是否遵循 CAMERARECORD_AUDIO 權限的最佳做法。

快速設定圖塊會標上「相機存取權」和「麥克風存取權」
圖 2. 「快速設定」中的麥克風和相機快速停用鈕。
右上角的圓角矩形,內含相機和麥克風圖示
圖 3. 麥克風和相機圖示,顯示近期的資料存取權。

權限套件瀏覽權限

在搭載 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() 可偵測下列詳細資料:

應用程式無法關閉系統對話方塊

為了改善使用者與應用程式和系統互動時的控制項,ACTION_CLOSE_SYSTEM_DIALOGS 意圖動作已於 Android 12 淘汰。除了少數特殊情況,當應用程式嘗試叫用包含這項動作的意圖時,系統會根據應用程式的目標 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 標記)。以下包括但不限於:

例外狀況

在下列情況下,可以使用「直通」觸控:

  • 應用程式內互動。應用程式會顯示重疊,而且只有在使用者與應用程式互動時才會顯示重疊。
  • 信任的視窗:這些期間包括但不限於:

  • 隱形視窗。視窗的根檢視畫面為 GONEINVISIBLE

  • 完全透明的視窗。視窗的 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 中,系統現在會將活動和任務移至背景,而非完成活動。使用主畫面按鈕或手勢離開應用程式時,新行為與目前行為相符。

對大多數應用程式來說,這項變更表示使用 Back 功能離開應用程式的使用者,能夠更快速地從暖機狀態恢復應用程式,而不必從冷狀態完全重新啟動應用程式。

建議您採用這項變更來測試應用程式。如果應用程式目前覆寫 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 網路,必須先呼叫這個 API,確認裝置支援該項功能。如果裝置不支援這項功能,就無法連線至這個網路,且必須建議採用替代網路或舊版網路。
  • isDecoratedIdentitySupported():向具有前置字串裝飾的網路進行驗證時,經過裝飾的身分前置字串可讓網路運算子更新網路存取 ID (NAI),以透過 AAA 網路內的多個 Proxy 執行明確轉送 (詳情請參閱 RFC 7542)。

    為符合 PPS-MO 擴充功能的 WBA 規格,Android 12 會實作這項功能。如果應用程式建議採用已裝飾的身分的 Passpoint 網路,必須先呼叫這個 API,以確保裝置支援這項功能。如果裝置不支援這項功能,就無法裝飾身分,且網路驗證可能會失敗。

如要建立 Passpoint 建議,應用程式必須使用 PasspointConfigurationCredentialHomeSp 類別。這些類別說明的是 Passpoint 設定檔,詳情請參閱 Wi-Fi Alliance Passpoint 規格

詳情請參閱「用於網際網路連線的 Wi-Fi 建議 API」。

更新非 SDK 介面限制

基於與 Android 開發人員合作及最新的內部測試,Android 12 包含更新後的受限制非 SDK 介面清單。在限制非 SDK 介面之前,我們盡可能確保公開替代方案的可得性。

如果您的應用程式並不是以 Android 12 為目標版本,則此處所述的某些變更可能不會立即對您造成影響。不過,雖然您目前可以使用某些非 SDK 介面 (視應用程式的目標 API 級別而定),但使用任何非 SDK 方法或欄位時,都會面臨應用程式中斷的高風險。

如果不確定應用程式是否使用非 SDK 介面,可對應用程式進行測試以便確認。如果您的應用程式仰賴非 SDK 介面,則建議您開始規劃遷移至 SDK 替代方案。我們瞭解有些應用程式可使用非 SDK 介面運作。如果您除了為應用程式中的某個功能使用非 SDK 介面外,已別無他法,則應要求新的公用 API

如要進一步瞭解此 Android 版本中的變更,請參閱 Android 12 的非 SDK 介面限制更新內容。如要進一步瞭解非 SDK 介面的一般資訊,請參閱非 SDK 介面的限制