和先前版本一樣,Android 12 也包含可能會影響應用程式的行為變更。以下行為變更僅適用於指定 Android 12 以上版本的應用程式。如果您的應用程式指定 Android 12 為目標版本,建議您視情況修改應用程式,以便支援這些行為。
另外,請務必查看影響所有在 Android 12 上執行的應用程式的行為變更清單。
使用者體驗
自訂通知
Android 12 變更了完全自訂通知的外觀和行為。在過去,自訂通知可以使用整個通知區域,並自行提供版面配置和樣式。這會導致反模式,可能會讓使用者感到困惑,或在不同裝置上造成版面配置相容性問題。
如果是指定 Android 12 為目標版本的應用程式,附帶自訂內容檢視畫面的通知將不再使用整個通知區域,系統會改為套用標準範本。這個範本可確保自訂通知與所有狀態的其他通知具有相同的裝飾,例如通知的圖示和展開預設用途 (處於收合狀態),以及通知的圖示、應用程式名稱,以及收合預設用途 (在展開狀態中)。這個行為與 Notification.DecoratedCustomViewStyle
的行為幾乎相同。
因此,Android 12 可讓使用者透過熟悉且熟悉的通知展開功能,所有通知看起來一致且易於瀏覽。
下圖顯示標準範本中的自訂通知:
以下範例說明自訂通知在收合和展開狀態下的顯示方式:
Android 12 的變更會影響定義 Notification.Style
自訂子類別,或使用 Notification.Builder
方法 setCustomContentView(RemoteViews)
、setCustomBigContentView(RemoteViews)
和 setCustomHeadsUpContentView(RemoteViews)
的應用程式。
如果您的應用程式使用完全自訂通知,建議您盡快使用新範本進行測試。
啟用自訂通知變更:
- 將應用程式的
targetSdkVersion
變更為S
,即可啟用新行為。 - 重新編譯。
- 在搭載 Android 12 的裝置或模擬器上安裝應用程式。
- 將應用程式的
測試所有使用自訂檢視畫面的通知,確保這些通知的外觀與您要在通知欄中都能如預期般呈現。測試時,請將以下考量因素納入考量,並進行必要調整:
自訂資料檢視的維度已有異動。一般來說,自訂通知的高度會少於之前。在收合狀態下,自訂內容的高度上限已從 106dp 降至 48dp。此外,橫向空間也較少。
指定 Android 12 為目標的應用程式可展開所有通知。一般來說,這表示如果您使用
setCustomContentView
,也應使用setBigCustomContentView
,確保收合和展開狀態一致。為確保「抬頭」狀態符合您的預期,請務必將通知管道的優先順序設為「高」(畫面上會彈出)。
Android 應用程式連結驗證方式異動
針對指定 Android 12 以上版本為目標版本的應用程式,系統會對 Android 應用程式連結的驗證方式做出幾項變更。這些變更可提供更穩定的應用程式連結體驗,讓應用程式開發人員和使用者手上有更多掌控權。
如果您使用 Android 應用程式連結驗證功能,在應用程式中開啟網頁連結,在新增意圖篩選器以便進行 Android 應用程式連結驗證時,請確認使用的格式是否正確。請特別注意,確認這些意圖篩選器包含 BROWSABLE
類別,並支援 https
配置。
您也可以手動驗證應用程式的連結,以測試宣告的可靠性。
改善子母畫面行為
Android 12 針對子母畫面 (PiP) 模式改善行為,並建議針對手勢導覽和元素式導覽的轉場動畫提供外觀改善建議。
詳情請參閱「子母畫面改善功能」。
吐司重新設計
在 Android 12 中,浮動式訊息檢視畫面已經重新設計。浮動式訊息現在最多只能顯示兩行文字,並會在文字旁顯示應用程式圖示。
詳情請參閱「浮動式訊息總覽」。
安全性和隱私權
大概位置
在搭載 Android 12 以上版本的裝置上,使用者可以要求應用程式的概略位置精確度。
WebView 中的新式 SameSite Cookie
Android 的 WebView 元件是以 Chromium 為基礎,這是 Google Chrome 瀏覽器的開放原始碼專案。Chromium 推出了調整第三方 Cookie 的處理方式,以提升安全性和隱私權,並讓使用者能進一步掌握相關資訊。自 Android 12 起,當應用程式指定 Android 12 (API 級別 31) 以上版本時,這些變更也會納入 WebView
。
Cookie 的 SameSite
屬性可控制與任何要求一起傳送,或僅與同網站要求一併傳送。下列隱私權保護變更可改善第三方 Cookie 的預設處理方式,並協助防範不慎的跨網站分享行為:
- 沒有
SameSite
屬性的 Cookie 會視為SameSite=Lax
。 - 含有
SameSite=None
的 Cookie 也必須指定Secure
屬性,表示 Cookie 需要安全的環境,且應透過 HTTPS 傳送。 - 系統會將網站的 HTTP 和 HTTPS 版本連結視為跨網站要求,因此除非 Cookie 正確標示為
SameSite=None; Secure
,否則系統不會傳送 Cookie。
對開發人員而言,一般的指引是在重要的使用者流程中找出跨網站 Cookie 依附元件,確認 SameSite
屬性已視需要明確設定適當的值。您必須明確指定哪些 Cookie,能跨網站運作,或從 HTTP 移至 HTTPS 的同網站瀏覽作業。
如需網頁開發人員針對這些變更的完整指南,請參閱「SameSite Cookie 說明」和「Schemeful SameSite」。
在應用程式中測試 SameSite 行為
如果您的應用程式使用 WebView,或管理使用 Cookie 的網站或服務,建議您在 Android 12 WebView 上測試流程。 如果發現問題,您可能需要更新 Cookie,才能支援新的 SameSite 行為。
請留意登入和嵌入內容的問題,以及登入流程、購買和其他驗證流程 (當使用者從不安全的頁面開始並轉換至安全頁面)。
如要使用 WebView 測試應用程式,您必須為要測試的應用程式啟用新的 SameSite 行為,方法是完成下列任一步驟:
在 WebView 開發人員工具中切換 UI 標記 webview-enable-modern-cookie-same-site,即可在測試裝置上手動啟用 SameSite 行為。
這個方法可讓您在任何搭載 Android 5.0 (API 級別 21) 以上版本的裝置 (包括 Android 12 及 WebView 89.0.4385.0 以上版本) 上進行測試。
請在
targetSdkVersion
前編譯應用程式,以針對 Android 12 (API 級別 31) 為目標。如果您採用這種做法,則必須使用搭載 Android 12 的裝置。
如要瞭解如何在 Android 上為 WebView 進行遠端偵錯,請參閱「開始使用 Android 裝置的遠端偵錯功能」。
其他資源
如要進一步瞭解 SameSite 現代行為,以及推出至 Chrome 和 WebView 的作業,請造訪 Chromium SameSite 更新頁面。如果您在 WebView 或 Chromium 中發現錯誤,可以透過公開的 Chromium 問題追蹤器回報。
動作感應器有速率限制
為保護可能的私密使用者資訊,如果應用程式指定 Android 12 以上版本,系統會對特定動作感應器和位置感應器提供的資料重新整理頻率設下限制。
進一步瞭解感應器速率限制。
應用程式休眠
Android 12 以 Android 11 (API 級別 30) 中引入的權限自動重設行為擴充。如果應用程式指定的是 Android 12,而使用者已連續數月未與應用程式互動,系統會自動重設所有已授予的權限,並將應用程式設為「休眠」狀態。
詳情請參閱應用程式休眠指南。
資料存取稽核中的歸因聲明
Android 11 (API 級別 30) 推出的資料存取稽核 API 可讓您根據應用程式的用途建立歸因標記。這些標記可協助您輕鬆判斷應用程式的哪些部分會執行特定類型的資料存取。
如果應用程式指定 Android 12 以上版本,則必須在應用程式的資訊清單檔案中宣告這些歸因標記。
ADB 備份限制
為保護私人應用程式資料,Android 12 會變更 adb backup
指令的預設行為。針對指定 Android 12 (API 級別 31) 以上版本為目標版本的應用程式,當使用者執行 adb backup
指令時,系統會從從裝置匯出的任何其他系統資料中排除應用程式資料。
如果您的測試或開發工作流程需要使用 adb backup
的應用程式資料,您現在可以在應用程式的資訊清單檔案中將 android:debuggable
設為 true
,選擇匯出應用程式的資料。
更安全的元件匯出功能
如果應用程式指定 Android 12 以上版本,且包含使用意圖篩選器的活動、服務或廣播接收器,您必須為這些應用程式元件明確宣告 android:exported
屬性。
如果應用程式元件包含 LAUNCHER
類別,請將 android:exported
設為 true
。在大多數其他情況下,請將 android:exported
設為 false
。
以下程式碼片段示範了包含 android:exported
屬性設為 false
的意圖篩選器的服務範例:
<service android:name="com.example.app.backgroundService" android:exported="false"> <intent-filter> <action android:name="com.example.app.START_BACKGROUND" /> </intent-filter> </service>
Android Studio 中的訊息
如果應用程式的活動、服務或廣播接收器使用意圖篩選器,但未宣告 android:exported
,系統會根據您使用的 Android Studio 版本顯示下列警告訊息:
Android Studio 2020.3.1 Canary 11 以上版本
系統會顯示下列訊息:
資訊清單檔案中會顯示下列 Lint 警告:
When using intent filters, please specify android:exported as well
嘗試編譯應用程式時,系統會顯示下列建構錯誤訊息:
Manifest merger failed : Apps targeting Android 12 and higher are required \ to specify an explicit value for android:exported when the corresponding \ component has an intent filter defined.
舊版 Android Studio
如果您嘗試安裝應用程式,Logcat 會顯示以下錯誤訊息:
Installation did not succeed.
The application could not be installed: INSTALL_FAILED_VERIFICATION_FAILURE
List of apks:
[0] '.../build/outputs/apk/debug/app-debug.apk'
Installation failed due to: 'null'
待處理意圖的可變動性
如果應用程式指定 Android 12 為目標版本,您必須指定應用程式建立的每個 PendingIntent
物件可變動性。這項額外要求可以提升應用程式的安全性。
測試待處理的意圖可變動性變更
如要判斷應用程式是否缺少可變動性宣告,請在 Android Studio 中尋找以下 Lint 警告:
Warning: Missing PendingIntent mutability flag [UnspecifiedImmutableFlag]
不安全的意圖啟動
為了提昇平台安全性,Android 12 以上版本提供偵錯功能,可偵測不安全的意圖啟動作業。當系統偵測到這類不安全的啟動作業時,就會發生 StrictMode 違規情形。
成效
前景服務啟動限制
以 Android 12 以上版本為目標的應用程式無法在背景執行時啟動前景服務,但少數特殊情況除外。如果應用程式嘗試在背景執行時啟動前景服務,就會發生例外狀況 (少數特殊情況除外)。
在應用程式於背景執行的情況下,建議您使用 WorkManager 安排及啟動加急作業。如要完成使用者要求且具時效性的動作,請在精確鬧鐘中啟動前景服務。
精確鬧鐘權限
為了鼓勵應用程式節省系統資源,如果應用程式指定 Android 12 以上版本為目標,並設定精確鬧鐘,則需要存取系統設定中「特殊應用程式存取權」畫面中的「鬧鐘與提醒」功能。
如要取得這項特殊應用程式存取權,請在資訊清單中要求 SCHEDULE_EXACT_ALARM
權限。
精確鬧鐘只應用於面向使用者的功能。進一步瞭解設定精確鬧鐘的使用限制。
停用行為變更
準備讓應用程式指定 Android 12 時,您可以暫時停用可進行偵錯的建構變化版本中的行為變更,以便進行測試。如要這樣做,請完成下列任一步驟:
- 在「開發人員選項」設定畫面中,選取「應用程式相容性變更」。在顯示的畫面中,輕觸應用程式名稱,然後關閉「REQUIRE_EXACT_ALARM_PERMISSION」。
在開發機器的終端機視窗中執行下列指令:
adb shell am compat disable REQUIRE_EXACT_ALARM_PERMISSION PACKAGE_NAME
通知彈跳床限制
當使用者與通知互動時,部分應用程式會啟動應用程式元件,藉此回應輕觸通知,最終使用者最終查看並進行互動的活動。這個應用程式元件稱為通知彈跳床。
為改善應用程式效能和使用者體驗,目標 Android 12 以上版本的應用程式無法透過服務或用來做為通知彈跳床的廣播接收器啟動活動。換句話說,使用者輕觸通知或通知中的動作按鈕後,您的應用程式就無法在服務或廣播接收器中呼叫 startActivity()
。
如果應用程式嘗試透過用來做為通知彈跳床的服務或廣播接收器啟動活動,系統會防止活動啟動,並在 Logcat 中顯示下列訊息:
Indirect notification activity start (trampoline) from PACKAGE_NAME, \
this should be avoided for performance reasons.
找出哪些應用程式元件是通知彈跳床
測試應用程式時,輕觸通知後,您可以找出在應用程式中擔任通知彈跳床的服務或廣播接收器。方法是查看下列終端機指令的輸出內容:
adb shell dumpsys activity service \ com.android.systemui/.dump.SystemUIAuxiliaryDumpService
輸出內容的部分內容包含「NotifInteractionLog」文字。本節提供必要資訊,協助您辨識因輕觸通知而啟動的元件。
請更新應用程式
如果您的應用程式是透過做為通知彈跳床的服務或廣播接收器啟動活動,請完成下列遷移步驟:
- 建立
PendingIntent
物件,並與使用者輕觸通知後看到的活動建立關聯。 - 使用您在上一個步驟中建立的
PendingIntent
物件,建立通知。
如要識別活動來源,以便執行記錄等作業,請在發布通知時使用額外項目。如需集中式記錄,請使用 ActivityLifecycleCallbacks
或 Jetpack 生命週期觀察器。
切換行為
測試可進行偵錯的應用程式版本時,您可以使用 NOTIFICATION_TRAMPOLINE_BLOCK
應用程式相容性標記啟用或停用這項限制。
備份與還原
在 Android 12 (API 級別 31) 上執行並指定此版本的應用程式,其備份與還原功能的運作方式會有所變更。Android 備份和還原有兩種形式:
- 雲端備份:使用者資料會儲存在使用者的 Google 雲端硬碟中,以便日後在該裝置或新裝置上還原。
- 裝置對裝置 (D2D) 轉移:使用者資料會從舊裝置直接傳送至新裝置,例如透過傳輸線。
如要進一步瞭解如何備份及還原資料,請參閱「使用自動備份功能備份使用者資料」和「使用 Android 備份服務備份鍵/值組合」。
D2D 傳輸功能變更
針對 Android 12 以上版本執行及指定 Android 12 以上版本的應用程式:
使用 XML 設定機制指定包含及排除規則不會影響 D2D 傳輸,但仍會影響雲端式備份和還原功能 (例如 Google 雲端硬碟備份)。如要指定 D2D 傳輸規則,您必須使用下一節說明的新設定。
在部分裝置製造商的裝置上,指定
android:allowBackup="false"
會停用將資料備份至 Google 雲端硬碟的功能,但不會停用應用程式的 D2D 傳輸功能。
新的包含和排除格式
在 Android 12 以上版本中運作且指定 Android 12 或以上版本的應用程式會針對 XML 設定使用不同的格式。這個格式會要求您分別為雲端備份和 D2D 轉移作業指定包含和排除規則,因此可明確區分 Google 雲端硬碟備份和 D2D 轉移作業的差異。
或者,您也可以使用此設定指定備份規則,在搭載 Android 12 以上版本的裝置上,系統會忽略先前使用的設定。搭載 Android 11 以下版本的裝置仍需要舊版設定。
XML 格式變更
以下是 Android 11 以下版本備份與還原設定的格式:
<full-backup-content> <include domain=["file" | "database" | "sharedpref" | "external" | "root"] path="string" requireFlags=["clientSideEncryption" | "deviceToDeviceTransfer"] /> <exclude domain=["file" | "database" | "sharedpref" | "external" | "root"] path="string" /> </full-backup-content>
下方將以粗體顯示格式的變更。
<data-extraction-rules> <cloud-backup [disableIfNoEncryptionCapabilities="true|false"]> ... <include domain=["file" | "database" | "sharedpref" | "external" | "root"] path="string"/> ... <exclude domain=["file" | "database" | "sharedpref" | "external" | "root"] path="string"/> ... </cloud-backup> <device-transfer> ... <include domain=["file" | "database" | "sharedpref" | "external" | "root"] path="string"/> ... <exclude domain=["file" | "database" | "sharedpref" | "external" | "root"] path="string"/> ... </device-transfer> </data-extraction-rules>
如需更多資訊,請參閱使用自動備份功能備份使用者資料的指南中相應章節。
應用程式的資訊清單標記
在資訊清單檔案中使用 android:dataExtractionRules
屬性,將應用程式指向新的 XML 設定。指向新的 XML 設定時,在搭載 Android 12 以上版本的裝置上,系統會忽略指向舊設定的 android:fullBackupContent
屬性。以下程式碼範例顯示新的資訊清單檔案項目:
<application ... <!-- The below attribute is ignored. --> android:fullBackupContent="old_config.xml" <!-- You can point to your new configuration using the new dataExtractionRules attribute . --> android:dataExtractionRules="new_config.xml" ...> </application>
連線能力
藍牙權限
Android 12 導入了 BLUETOOTH_SCAN
、BLUETOOTH_ADVERTISE
和 BLUETOOTH_CONNECT
權限。有了這些權限,以 Android 12 為目標版本的應用程式就能更輕鬆地與藍牙裝置互動,尤其是不需要存取裝置位置資訊的應用程式。
如要讓裝置針對 Android 12 以上版本做好準備,請更新應用程式的邏輯。請勿宣告舊版藍牙權限,不如宣告較現代化的藍牙權限組合。
同時進行點對點 + 網際網路連線
針對指定 Android 12 (API 級別 31) 以上版本的應用程式,如果裝置支援並行點對點和網際網路連線,就能同時維持同時與對等裝置和主要網際網路連線的 Wi-Fi 連線,從而提供更順暢的使用者體驗。指定 Android 11 (API 級別 30) 以下版本的應用程式仍會遇到舊版行為,也就是主要 Wi-Fi 網路在連線至對等裝置之前中斷連線。
相容性
WifiManager.getConnectionInfo()
只能針對單一網路傳回 WifiInfo
。因此,在 Android 12 以上版本中,API 的行為已發生以下變更:
- 如果只有一個 Wi-Fi 網路可用,系統會傳回該網路的
WifiInfo
。 - 如果有可用的 Wi-Fi 網路多於一個,且呼叫應用程式觸發對等端對連線,系統會傳回對應至對等端裝置的
WifiInfo
。 - 如果有可用的 Wi-Fi 網路不只一個,且呼叫應用程式未觸發對等端連線,系統會傳回主要網際網路提供連線的
WifiInfo
。
為了在支援雙重 Wi-Fi 網路的裝置上提供更好的使用者體驗,我們建議所有應用程式 (尤其是會觸發點對點連線的應用程式) 都不要再呼叫 WifiManager.getConnectionInfo()
,而是改用 NetworkCallback.onCapabilitiesChanged()
來取得與用於註冊 NetworkCallback
的 NetworkRequest
相符的所有 WifiInfo
物件。getConnectionInfo()
已於 Android 12 淘汰。
以下程式碼範例說明如何在 NetworkCallback
中取得 WifiInfo
:
Kotlin
val networkCallback = object : ConnectivityManager.NetworkCallback() { ... override fun onCapabilitiesChanged( network : Network, networkCapabilities : NetworkCapabilities) { val transportInfo = networkCapabilities.getTransportInfo() if (transportInfo !is WifiInfo) return val wifiInfo : WifiInfo = transportInfo ... } }
Java
final NetworkCallback networkCallback = new NetworkCallback() { ... @Override public void onCapabilitiesChanged( Network network, NetworkCapabilities networkCapabilities) { final TransportInfo transportInfo = networkCapabilities.getTransportInfo(); if (!(transportInfo instanceof WifiInfo)) return; final WifiInfo wifiInfo = (WifiInfo) transportInfo; ... } ... };
mDNSResponseer 原生 API
Android 12 會在應用程式可使用 mDNSResponseer 原生 API 與 mDNSResponseer Daemon 互動時,調整時機。之前,當應用程式在網路上註冊服務並呼叫 getSystemService()
方法時,系統的 NSD 服務會啟動 mDNSResponseer Daemon,即使應用程式尚未呼叫任何 NsdManager
方法也一樣。隨後,守護程式會將裝置訂閱至所有節點多點廣播群組,導致系統更頻繁地喚醒並使用額外電力。為盡量減少電池用量,在 Android 12 以上版本中,系統現在只會在 NSD 事件需要時啟動 mDNSResponseer Daemon,並在之後停止 mDNSResponseer Daemon。
由於這項變更會影響 mDNSResponder 守護程式可用的時間,因此假設在呼叫 getSystemService()
方法後,mDNSResponder 守護程式會啟動的應用程式,可能會收到系統傳送的訊息,指出 mDNSResponder 守護程式無法使用。若是使用 NsdManager
且未使用 mDNSResponseer 原生 API 的應用程式,則不受這項變更影響。
供應商程式庫
供應商提供的原生共用程式庫
根據預設,如果應用程式指定 Android 12 (API 級別 31) 以上版本為目標,無法存取由晶片供應商或裝置製造商提供的非 NDK 原生共享程式庫。只有使用 <uses-native-library>
標記明確要求時,才能存取這些程式庫。
如果應用程式指定 Android 11 (API 級別 30) 以下版本,則不需要 <uses-native-library>
標記。在這種情況下,任何原生共享程式庫均可存取,無論其是否為 NDK 程式庫。
更新非 SDK 限制
基於與 Android 開發人員合作及最新的內部測試,Android 12 包含更新後的受限制非 SDK 介面清單。在限制非 SDK 介面之前,我們盡可能確保公開替代方案的可得性。
如果您的應用程式並未以 Android 12 為目標版本,則此處所述的某些變更可能不會立即對您造成影響。雖然您目前可以使用某些非 SDK 介面 (視應用程式的目標 API 級別而定),但使用任何非 SDK 方法或欄位時,均可能面臨應用程式故障的高度風險。
如果不確定應用程式是否使用非 SDK 介面,您可以測試應用程式來確認。如果您的應用程式仰賴非 SDK 介面,則建議您開始規劃遷移至 SDK 替代方案。不過,我們瞭解有些應用程式可使用非 SDK 介面運作。如果您除了為應用程式中的某個功能使用非 SDK 介面外,已別無他法,則應要求新的公用 API。
如要進一步瞭解此 Android 版本中的變更,請參閱「Android 12 的非 SDK 介面限制更新內容」。如要進一步瞭解非 SDK 介面的一般資訊,請參閱非 SDK 介面的限制。