Android 12 保姆級適配指南

And人 wedding.png

背景

郵件內(nèi)容.png

近期,Google Play向所有的應(yīng)用開發(fā)者發(fā)送了一封郵件,郵件中明確了應(yīng)用將目標(biāo)API級別更新為Android 12的最后期限。

這表示,Android 12的適配工作不得不提上日程了。

本著將改動最小化的原則,建議在開始適配之前,可以將此次需要適配的一系列行為變更,按照對自身項目的影響程度,先進行優(yōu)先級劃分,并依據(jù)此優(yōu)先級去分批、逐步完成適配工作。

該如何進行劃分呢?可能具體到每個人的項目情況都有所不同,這里提供一下筆者項目的適配任務(wù)優(yōu)先級劃分標(biāo)準(zhǔn),供其他開發(fā)者參考:

P0:功能異常
指明確影響到了App功能的正常使用,甚至導(dǎo)致App無法正常啟動或者崩潰率直線上升的行為變更。

P1:體驗下降
指雖不影響功能正常使用,但可能導(dǎo)致獲取數(shù)據(jù)的準(zhǔn)確度下降,進而影響運營判斷;或者需要增加操作步驟,進而影響用戶體驗的行為變更。

P2:可選優(yōu)化
指對App本身沒有什么實質(zhì)影響,但做好適配后可以增強App健壯性,或者可以提高用戶體驗的行為變更。

接下來,我們就以上面劃分好的優(yōu)先級標(biāo)準(zhǔn),來開始對Android 12的適配工作。

影響所有App的行為變更

P0:功能異常

應(yīng)用啟動畫面

造成影響

簡單講,就是從Android 12開始,所有的App在每次啟動時(特指冷啟動與溫啟動),系統(tǒng)都會為我們加上一個默認(rèn)的啟動畫面,如下所示:

應(yīng)用啟動畫面.gif

該啟動畫面主要由以下4個元素組成,分別為:


啟動畫面構(gòu)成元素.png

(1) 應(yīng)用圖標(biāo):可以是靜態(tài)或動畫形式。默認(rèn)情況下,使用Launcher圖標(biāo)。

(2) 圖標(biāo)背景:可選,在圖標(biāo)與窗口背景之間需要更高的對比度時很有用。

(3) 前景遮罩:可選,前景的 ? 將被遮蓋。

(4) 窗口背景:不透明的單色,默認(rèn)是所設(shè)置主題的windowBackground。

雖然這個啟動畫面允許我們一定程度的自定義,但總體都無法跳脫出以上4個元素,且無法去除。如果不做任何處理,加上我們原有的閃屏頁和廣告頁,視覺上會有多個啟動畫面

適配方案

方案1(懶人專用):設(shè)置除窗口背景之外的元素都為透明

處理后的效果就是,在啟動時會先顯示由所設(shè)置主題的windowBackground指定的純色背景,即與大多數(shù)開發(fā)者之前為了解決啟動黑屏/白屏問題所采用的方法一致。

應(yīng)用啟動畫面-純色背景.gif

方案2(常規(guī)做法):改用SplashScreen API定制系統(tǒng)啟動畫面

缺點就是可定制程度低,可能無法滿足產(chǎn)品的需求;

如果總體的效果可以接受,那么接下來要處理的就是對原有閃屏頁的取舍,以及與原有廣告頁的畫面銜接了。

但如開頭所言,我們的目標(biāo)是將改動最小化,那么,原有閃屏頁該干嘛還是讓它干嘛,初始化也好,路由也罷,邏輯不變,要求只是不再顯示而已。

具體做法如下:

  1. 添加 SplashScreen compat 庫
添加SplashScreen庫.png
  1. 在閃屏頁調(diào)用 SplashScreen#setKeepOnScreenCondition{ true } 使得默認(rèn)的啟動畫面持續(xù)覆蓋原有的閃屏頁,直到廣告頁開始顯現(xiàn)時,才調(diào)用SplashScreen#setKeepOnScreenCondition{ false } 讓頁面重新顯示,以此實現(xiàn)平穩(wěn)過渡
SplashScreen#setKeepOnScreenCondition.png
應(yīng)用啟動畫面-持續(xù)覆蓋原有的閃屏頁.gif

麥克風(fēng)和攝像頭切換開關(guān)

造成影響

簡單講,就是從Android 12開始,用戶可以通過狀態(tài)欄下拉菜單中兩個新增的切換開關(guān)選項,一鍵啟用/停用攝像頭和麥克風(fēng)使用權(quán)限。

麥克風(fēng)和攝像頭切換開關(guān).png

請注意,這里的「使用權(quán)限」針對的是設(shè)備上的所有App,是全局的,不要和Android 6.0的「運行時權(quán)限」混淆。

而兩者在具體表現(xiàn)上也有所不同,在實際操作中:

  • 當(dāng)關(guān)閉攝像頭使用權(quán)限后,畫面錄制將繼續(xù)進行,但只會收到空白畫面

  • 當(dāng)關(guān)閉麥克風(fēng)使用權(quán)限后,聲音錄制將繼續(xù)進行,但只會收到無聲視頻

適配方案

盡管官網(wǎng)上提供了檢查設(shè)備是否支持麥克風(fēng)和攝像頭切換開關(guān)的API,也就是檢查狀態(tài)欄下拉菜單是否有這兩個開關(guān)選項,然而這對于我們實際的適配工作幾乎沒有什么卵用:

檢查設(shè)備是否支持麥克風(fēng)和攝像頭切換開關(guān)的API.png

SensorPrivacyManager類倒是有提供檢查指定切換開關(guān)是否開啟的API,但由于是系統(tǒng)權(quán)限,因此即使是通過反射形式也無法調(diào)用:

檢查指定切換開關(guān)是否開啟的API.png

所幸的是,如果用戶主動關(guān)閉了攝像頭或麥克風(fēng)的使用權(quán)限,那么當(dāng)下次App再需要啟動攝像頭或麥克風(fēng)時,系統(tǒng)就會提醒用戶,相關(guān)硬件的使用權(quán)限已關(guān)閉,并申請重新開啟:

麥克風(fēng)切換開關(guān)-重新開啟.gif

因此,對于此行為變更的適配,我們要做的,就是驗證在用戶主動關(guān)閉了攝像頭或麥克風(fēng)使用權(quán)限后,App的相關(guān)功能是否受影響,至于監(jiān)聽/提示/重新開啟的工作則交給系統(tǒng)幫我們完成即可。

影響目標(biāo)API級別為Android 12的App的行為變更

P0:功能異常

更安全的組件導(dǎo)出

造成影響

簡單講,就是以Android 12為目標(biāo)平臺的App,如果其包含的四大組件中使用到了Intent過濾器(intent-filter),則必須顯式聲明 android:exported 屬性,否則App將無法在Android 12及更高系統(tǒng)版本的設(shè)備上安裝

無法在Android 12及更高系統(tǒng)版本的設(shè)備上安裝.png

適配方案

這里要區(qū)分兩種情況:

  • 如果是自身項目使用到了,則按要求顯式聲明即可;

  • 如果是依賴的第三方庫使用到了,那就比較麻煩了。且不說等待第三方庫更新的過程很被動,如果該庫還已停止維護了,那就芭比Q了。

但眾所周知,Android Studio Project在打包時是會合并多個Module的AndroidManifest.xml文件的,基于這種情況,我們就可以通過編寫Gradle腳本,在打包過程中檢索合并后的AndroidManifest.xml文件中,所有使用到了Intent過濾器但沒有聲明exported屬性的組件,動態(tài)地為其加上exported屬性。

具體的Gradle腳本已經(jīng)有人寫過了,這里就不再貼出了:
http://events.jianshu.io/p/1913b48f2dad

待處理 intent 可變

造成影響

簡單講,就是以Android 12為目標(biāo)平臺的App,在構(gòu)建PendingIntent時,需要指定Flag為FLAG_IMMUTABLE(建議)或FLAG_MUTABLE二者之一,否則App將崩潰并出現(xiàn)以下警告。

待處理 intent 可變性崩潰警告.png

適配方案

指定Flag為FLAG_IMMUTABLE(建議)或FLAG_MUTABLE二者之一.png

但同樣可能出現(xiàn)第三方庫的代碼未正確指定Flag的問題,目前除了等待第三方庫更新之外似乎也沒有更好的措施。

前臺服務(wù)啟動限制

造成影響

簡單講,就是以Android 12為目標(biāo)平臺的App,如果嘗試在后臺運行時啟動前臺服務(wù)(startForegroundService),則會引發(fā)ForegroundServiceStartNotAllowedException異常(某些場景除外):

ForegroundServiceStartNotAllowedException異常.png

適配方案

分兩步走:

  • 檢查App是否有在后臺啟動前臺服務(wù)的行為

可在Terminal終端執(zhí)行以下adb命令,該命令會監(jiān)控你的App是否有在后臺啟動前臺服務(wù)的行為,一旦有此行為,就會在通知欄推送一條提醒,定位到觸發(fā)此行為的代碼處:

adb shell device_config put activity_manager \ default_fgs_starts_restriction_notification_enabled true

檢查您的應(yīng)用程序是否執(zhí)行后臺啟動.gif
  • 考慮改用WorkManager的加急工作來執(zhí)行后臺任務(wù)

精確的鬧鐘權(quán)限

造成影響

簡單講,就是以Android 12為目標(biāo)平臺的App,如果使用到了AlarmManager來設(shè)置定時任務(wù),并且設(shè)置的是精準(zhǔn)的鬧鐘(使用了setAlarmClock()、setExact()、setExactAndAllowWhileIdle()這幾種方法),則需要確保SCHEDULE_EXACT_ALARM權(quán)限聲明且打開,否則App將崩潰并出現(xiàn)以下警告:

SCHEDULE_EXACT_ALARM權(quán)限聲明未打開.png

適配方案

分三步走:

  • 在AndroidManifest.xml清單文件中聲明 SCHEDULE_EXACT_ALARM 權(quán)限

<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />

  • 判斷是否具有設(shè)置精確鬧鐘的權(quán)限
判斷是否具有設(shè)置精確鬧鐘的權(quán)限.png
  • 打開鬧鐘和提醒權(quán)限授權(quán)頁面,進行授權(quán)
打開鬧鐘和提醒權(quán)限授權(quán)頁面.png
進行授權(quán).png

通知 trampoline 限制

造成影響

簡單講,就是我們之前在配置通知(Notification)的點按行為時,可能會通過PendingIntent來啟動一個Service或BrocastReceiver。而以Android 12為目標(biāo)平臺的App,如果嘗試在Service或BrocastReceiver中內(nèi)調(diào)用 startActivity(),系統(tǒng)會阻止該Activity啟動,并在 Logcat 中顯示以下消息:

嘗試在Service或BrocastReceiver中內(nèi)調(diào)用 startActivity().png

適配方案

分兩步走:

  • 排查哪個Service或BrocastReceiver有此行為

可在Terminal終端執(zhí)行以下adb命令,該命令會在你點按通知后,識別哪個Service或BrocastReceiver調(diào)用了startActivity(),并輸出相關(guān)信息到Logcat,可以通過關(guān)鍵字“NotifInteractionLog”進行過濾:

adb shell dumpsys activity service \ com.android.systemui/.dump.SystemUIAuxiliaryDumpService

通過關(guān)鍵字“NotifInteractionLog”進行過濾.png
  • 考慮在配置通知(Notification)的點按行為時選擇直接啟動Activity

P1:體驗下降

大致位置

造成影響

做過定位功能的Android開發(fā)者都知道,Android提供了兩種不同精確度的位置權(quán)限,分別是:

  • ACCESS_COARSE_LOCATION(大致位置)

    提供設(shè)備位置的估算值,將范圍限定在大約 1.6 公里(1 英里)內(nèi)

  • ACCESS_FINE_LOCATION(確切位置)

    通常將范圍限定在大約 50 米(160 英尺)內(nèi),有時精確到幾米(10 英尺)范圍以內(nèi)

而在以Android 12為目標(biāo)平臺的App上,當(dāng)App嘗試請求ACCESS_FINE_LOCATION權(quán)限時,系統(tǒng)權(quán)限對話框會提供兩個選項,即允許App獲取確切位置,還是僅允許獲取大致位置。

允許App獲取確切位置,還是僅允許獲取大致位置.png

也即是說,給了用戶拒絕提供確切位置的權(quán)力,一旦用戶拒絕,這種情況下App就只能獲取到大致位置了。

適配方案

雖然用戶可能拒絕提供確切位置,但我們依舊可以再次請求升級到確切位置:

再次請求升級到確切位置.png

當(dāng)然,在再次請求前提供一個適當(dāng)?shù)慕忉屨f明是一個比較好的做法,App本身也要做好只能獲取到大致位置時的業(yè)務(wù)降級處理。

應(yīng)用休眠

造成影響

簡單講,就是以Android 12為目標(biāo)平臺的App,如果用戶有長達幾個月的時間沒有打開過你的App,那么你之前申請的所有運行時權(quán)限都會被重置為未授權(quán)狀態(tài),即使再次打開也無法恢復(fù),需要重新申請。

適配方案

基本上,只要你的App之前已經(jīng)做好運行時權(quán)限的的判斷和申請,那對你的App就幾乎沒什么影響。如果還是想穩(wěn)妥的測試一下,可以用Terminal終端執(zhí)行adb命令,手動觸發(fā)應(yīng)用休眠:

https://developer.android.com/topic/performance/app-hibernation#manually-invoke

應(yīng)用休眠運行時權(quán)限重置.gif

自定義通知

造成影響

簡單講,就是如果之前App中的通知(Notification)中使用到了自定義內(nèi)容視圖,并且該視圖是填滿整個通知區(qū)域的。那么當(dāng)App以Android 12為目標(biāo)平臺后,視圖將不再能填充整個區(qū)域,而是會被縮小到某個固定范圍:

縮小到某個固定范圍.png

另外,所有通知現(xiàn)在都變成了可展開的,如果你之前設(shè)置自定義內(nèi)容視圖時使用的是 setCustomContentView方法,那你現(xiàn)在則還需要另外再使用setBigCustomContentView方法來設(shè)置展開狀態(tài)的樣式,以確保通知在收起狀態(tài)和展開狀態(tài)的樣式能統(tǒng)一。

適配方案

確認(rèn)被縮減顯示范圍后的自定義內(nèi)容視圖樣式是否能接受,若不能接受,則根據(jù)實際需要調(diào)整即可。

演示Demo

這邊提供了一個Demo,可以幫助我們在實際操作中,快速理解以上行為變更的具體表現(xiàn),并且由于是輕量級的Demo,所以也方便我們進行改動,快速驗證適配方案的效果:

https://github.com/madchan/SupportAndroid12

Demo.png

「椎鋒陷陳」微信技術(shù)號現(xiàn)已開通,為了獲得第一手的技術(shù)文章推送,歡迎搜索關(guān)注!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,572評論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,071評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,409評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,569評論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 71,360評論 6 404
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 54,895評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,979評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,123評論 0 286
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,643評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 40,559評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,742評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,250評論 5 356
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 43,981評論 3 346
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,363評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,622評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,354評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 47,707評論 2 370

推薦閱讀更多精彩內(nèi)容