前言
本文基于 Android 12 開發(fā)者預覽版 2 中進行介紹新版本中的部分特性讨盒。
時間軸豌习、里程碑和更新:
1. 獲取 Android 12
獲取最新 Android 12 的方式有兩種银萍,一為你已擁有安裝了 Android 11 的 Google Pixel 設備变勇,或者 Android 模擬器。本文介紹的方式為如何通過模擬器設置 Android 12 的 SDK。
在 Android Studio 中飞袋,依次點擊 Tools > SDK Manager。
在 SDK Tools 標簽頁中链患,選擇最新版 Android 模擬器巧鸭,然后點擊 OK。如果尚未安裝最新版本麻捻,則此操作會安裝最新版本纲仍。
-
在 Android Studio 中,依次點擊 Tools > AVD Manager贸毕,然后按照說明創(chuàng)建新的 Android 虛擬設備 (AVD)郑叠。
請務必選擇 Pixel 3、Pixel 3a明棍、Pixel 4乡革、Pixel 4a 或 Pixel 5 設備定義以及 64 位 Android 12 模擬器系統(tǒng)映像。請注意摊腋,Android 12 不支持 32 位 Android 模擬器系統(tǒng)映像沸版。如果您尚未安裝與您的設備定義匹配的 Android 12 系統(tǒng)映像,請點擊 Release Name 旁邊的 Download 下載該映像歌豺。
在 AVD Manager 中返回虛擬設備列表推穷,然后雙擊您的 Android 12 虛擬設備以啟動它。
2. API 變更
Android 12 面向開發(fā)者引入了一些出色的新功能和 API类咧。以下幾部分內容可幫助您了解適用于您的應用的功能并開始使用相關 API馒铃。
2.1 GIF 和 WebP 的原生 ImageDecoder 支持
在 Android 12 中,NDK ImageDecoder
API 已進行了擴展痕惋,可以對 GIF 和 WebP 文件格式的圖片的所有幀和時間數據進行解碼区宇。在 Android 11 中引入該 API 時,該 API 僅從這些格式的動畫中解碼第一張圖片值戳。
使用 ImageDecoder
(而非第三方庫)可進一步縮減 APK 大小议谷,并從未來與安全性和性能相關的更新中受益。
2.2 支持圓角
許多現(xiàn)代設備的屏幕采用圓角設計堕虹,這彰顯了簡潔時尚的風格卧晓,但也為應用開發(fā)者帶來一些額外的問題。要在這些設備上提供出色的用戶體驗赴捞,開發(fā)者需要將這些圓角納入考慮逼裆,調整圓角附近的界面元素,防止出現(xiàn)裁切的情況赦政。
為了解決這個問題胜宇,Android 12 引入了新的 API,便于您查詢圓角及其詳情。RoundedCorner 提供了圓角半徑桐愉、中心點等信息财破。可以通過 Display.getRoundedCorner() 來獲取每個圓角的詳盡信息从诲。
還可以調用 WindowInsets.getRoundedCorner() 來獲取基于應用邊界的圓角位置等信息左痢。如此一來,你就可以根據需要靈活調整界面元素和內容的位置盏求。
2.3 更易用的模糊抖锥、色彩濾鏡等特效
在 Android 12 中,可以更輕松地將常用圖形效果應用于視圖和渲染結構上碎罚“醴希可以使用 RenderEffect 將模糊、色彩濾鏡等特效應用于任何 RenderNode荆烈≌悖可以將這些特效組合為連鎖特效 (即組成內部和外部特效),也可以混用這些特效憔购。還可以通過調用 View.setRenderEffect(RenderEffect) 將特效直接應用于視圖 (View宫峦,因為其基于 RenderNode)。
view.setRenderEffect(RenderEffect.createBlurEffect(radiusX, radiusY, SHADER_TILE_MODE))
有了這個功能玫鸟,在模糊 ImageView 時导绷,就不必進行獲取位圖數據、處理圖像屎飘、創(chuàng)建新 Bitmap妥曲,再將其設置回 ImageView 這些操作了。RenderEffect 利用了現(xiàn)有的渲染流水線钦购,最大限度地減少了額外的計算量檐盟。
還可以使用新的 Window.setBackgroundBlurRadius() API 為窗口背景創(chuàng)建霧面玻璃效果。這個 API 可以設置模糊半徑押桃,以調整霧面密度和范圍葵萎,平臺只會對您的應用窗口邊框內的背景內容應用模糊效果。還可以使用 blurBehindRadius 來模糊窗口后面的所有內容唱凯,從而為浮動窗口營造出深度效果羡忘。
3. 影響應用的行為變更
3.1 針對所有應用的行為變更
以下行為變更將影響在 Android 12 上運行的所有應用,無論采用哪種 targetSdkVersion
都不例外磕昼。
3.1.1 對 MAC 地址的限制
Android 12 進一步限制了所有非系統(tǒng)應用對設備的 MAC 地址的訪問壳坪。
相關 API 會返回空值或占位值,具體取決于應用的 Target SDK 版本:
- 如果應用以 Android 12 為目標平臺掰烟,則該 API 會返回 null。
- 如果應用以 Android 11 或更低版本為目標平臺,則該 API 將返回硬編碼占位值:
02:00:00:00:00:00
開發(fā)者應使用 ConnectivityManager
纫骑,而不是較低級別的 API蝎亚,例如 NetworkInterface
、getifaddrs()
先馆。開發(fā)者在其代碼中調用 NetworkInterface.getHardwareAddress()
時发框,logcat 輸出會顯示:CompatibilityChangeReporter: Compat change id reported: 170188668;
開發(fā)者可以使用名為 RETURN_NULL_HARDWARE_ADDRESS
的兼容性標志切換 NetworkInterface.getHardwareAddress()
的行為:在啟用時返回 null,或在停用時返回 02:00:00:00:00:00
煤墙。
3.1.2 應用覆蓋控制
Android 的系統(tǒng)警告框允許一個應用在其他活動應用之上覆蓋顯示一個圖層梅惯,以幫助應用提醒用戶關注重要操作。不過由于這些窗口會中斷用戶操作仿野,因此應用需要請求權限才能顯示這些內容铣减。在 Android 12 中,可以控制是否允許在自己的內容上顯示這些覆蓋圖層脚作。在聲明新權限后葫哗,你的應用可以調用 Window#setHideOverlayWindows(),以表明在你的應用窗口可見時應隱藏所有 TYPE_APPLICATION_OVERLAY 窗口球涛,比如可以在交易確認流程等敏感界面中如此操作劣针。
3.1.3 應用無法關閉系統(tǒng)對話框
為了加強用戶與應用和系統(tǒng)互動時的控制,從 Android 12 開始亿扁,棄用了 ACTION_CLOSE_SYSTEM_DIALOGS
intent 操作捺典。除了一些特殊情況之外,當應用嘗試調用包含此操作的 intent 時从祝,系統(tǒng)會基于應用的目標 SDK 版本執(zhí)行以下操作之一:
如果應用以 Android 12 為目標平臺襟己,則會發(fā)生 SecurityException。
如果應用以 Android 11(API 級別 30)或更低版本為目標平臺哄褒,則系統(tǒng)不會執(zhí)行 intent稀蟋,并且 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.
3.2 針對以 Android 12 為目標平臺的應用
3.2.1 更安全的導出組件
包含 intent 過濾器的應用組件必須顯式設置 android:exported
屬性,如 Activity呐赡、Service退客、Broadcast Receive。 未設置該屬性的應用無法安裝
在 Android 12 上链嘀。
錯誤信息:
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'
正確示范:
<service android:name="com.example.app.backgroundService"
android:exported="false">
<intent-filter>
<action android:name="com.example.app.START_BACKGROUND" />
</intent-filter>
</service>
3.2.2 待處理 intent 必須聲明可變性
如果你的應用以 Android 12 為目標平臺萌狂,則必須為你的應用創(chuàng)建的每個 PendingIntent
對象指定可變性。這項額外的要求可提高應用的安全性怀泊。
如需聲明特定 PendingIntent
對象是否可變茫藏,請分別使用 PendingIntent.FLAG_MUTABLE
或 PendingIntent.FLAG_IMMUTABLE
標志。如果你的應用試圖在不設置任何可變標志的情況下創(chuàng)建 PendingIntent
對象霹琼,系統(tǒng)會拋出 IllegalArgumentException
务傲,并在 Logcat 中顯示以下消息:
PACKAGE_NAME: Targeting S+ (version 10000 and above) requires that one of \
FLAG_IMMUTABLE or FLAG_MUTABLE be specified when creating a PendingIntent.
Strongly consider using FLAG_IMMUTABLE, only use FLAG_MUTABLE if \
some functionality depends on the PendingIntent being mutable, e.g. if \
it needs to be used with inline replies or bubbles.
盡可能創(chuàng)建不可變的待處理 intent
在大多數情況下凉当,你的應用應創(chuàng)建不可變的 PendingIntent
對象,如以下代碼段所示售葡。如果 PendingIntent
對象不可變看杭,則應用無法修改 intent 來調整調用 intent 的結果。
PendingIntent pendingIntent = PendingIntent.getActivity(
getApplicationContext(),
REQUEST_CODE,
intent,
PendingIntent.FLAG_IMMUTABLE // flags
);
然而挟伙,某些應用需要創(chuàng)建可變的 PendingIntent
對象:
- 通知中的直接回復操作需要變更與回復關聯(lián)的
PendingIntent
對象中的剪輯數據楼雹。通常,您可以通過將FILL_IN_CLIP_DATA
作為標志傳遞給fillIn()
的方法請求此變更尖阔。 - 如果您的應用使用
PendingIntent
將對話放在氣泡中贮缅,則 intent 應該可變,以便系統(tǒng)可以應用正確的標志介却,例如FLAG_ACTIVITY_MULTIPLE_TASK
和FLAG_ACTIVITY_NEW_DOCUMENT
谴供。
如果您的應用創(chuàng)建了可變的 PendingIntent
對象,強烈建議您使用顯式 intent 并填寫 ComponentName
筷笨。如此一來憔鬼,每當另一個應用調用 PendingIntent
并將控制權傳回您的應用時,應用中的相同組件都會啟動胃夏。
3.2.3 前臺服務啟動限制
以 Android 12 為目標平臺的應用在后臺運行時無法再啟動前臺服務轴或,但一些特殊情況除外。如果應用在后臺運行時嘗試啟動前臺服務仰禀,并且前臺服務不符合任何特殊情況照雁,則系統(tǒng)會拋出IllegalStateException
。
4. 關于APP 適配
基于對 Android 12 的調研以及還唄當前的環(huán)境配置答恶,總結出還唄可能面臨的一些適配問題
我司 App 當前環(huán)境配置:
compileSdkVersion = 27
targetSdkVersion = 27
由于當前的目標版本為27饺蚊,小于 Android 12 的目標版本,因此目前只需要關注所有應用的行為變更
悬嗓,如MAC 地址的限制
污呼、禁止使用ACTION_CLOSE_SYSTEM_DIALOGS
的 intent 操作。
如果未來計劃升級目標版本至 31包竹,則需關注以 Android 12 為目標平臺的改動燕酷,如清單文件中申明了intent-filter
的 Activity、Service周瞎,必須設置android:exported
苗缩,我們目前在 APP 啟動頁、短鏈喚起頁等使用了 intent 過濾器声诸;以及在集成推送服務時酱讶,使用到的PendingIntent
也需要適配,詳細可參考官方文檔彼乌。