Android P版本應用相容性適配技術指導
ndroid P版本中伴隨很多機制和新增特性的改變,對自研以及第三方應用帶來了很多相容性問題。
本文件第1章主要介紹谷歌P版本開發環境搭建以及除錯;第2章節主要是對P版本相容性現狀一些摸底測試情況以及問題分類;第3章節主要是P版本一些特性介紹以及應用適配P版本的一些開發指導。
1. Android P背景
1.1 Android P版本里程碑
Preview 1 (initial release, alpha)
Preview 2 (incremental update, beta)
Preview 3 (final APIs and official SDK, Play publishing, beta)
Preview 4 (release candidate for testing)
Preview 5 (release candidate for final testing)
Final release to AOSP and ecosystem
1.2 刷機指導
1.2.1 版本下載
1.2.2 刷機
刷手機的方法(刷機前需要退出之前登入的谷歌賬號):
(1)下載對應裝置的壓縮包並解壓;
(2)手機連上USB後,執行adb reboot bootloader命令;
(3)等手機出現小機器人以後,並且顯示‘unlock’字樣時,執行壓縮包中的bat指令碼。
如果是“lock”字樣:
(1)連續點選設定-版本號3次,開啟開發人員選項;
(2)在開發人員選項中開啟OEM unlock;
(3)連線手機到電腦,執行adb reboot bootloader命令到小機器人介面;
(4)執行fastboot oem unlock,這樣手機就解鎖了,再使用上面的刷機方法即可。
1.3 P版本開發環境搭建
1.4 華為終端開放實驗室Android P 版本相容性測試
開發者如果沒有Pixcel真機並且不喜歡谷歌模擬器除錯,也可以選擇華為終端開放實驗室提供的遠端真機來進行P版本測試和除錯。請參考連結:華為終端開放實驗室Android P 版本相容性測試上線。
2. 第三方應用相容性測試情況
基於谷歌的DP1版本進行了國內Top1000相容性摸底測試,測試物件:華為應用市場中各領域中熱門的應用。詳細情況可以參考連結:P版本國內首份千款主流應用Android P版本相容性測試報告發布。
3. 相容性分析
3.1 Restrictions on non-SDK interfaces
3.1.1 背景介紹
(1)non-SDK interfaces的定義
以@hide標記的類/方法/屬性
(2)應用濫用non-SDK interfaces的危害
這些non-SDK介面在大版本之間的變化可能很頻繁,帶來相容性問題。
(3)影響範圍:
三方應用都會受到該特性影響。
(4)解決辦法
(5)名單分類
①Light grey list: targetSDK>=P時,警告;
②Dark grey list: targetSDK<P時,警告;>=p時,不允許呼叫;
③Black list:三方應用不允許呼叫;
注:在發貨版本上不會有警告。
(6)non-SDK interfaces名單列表
觸發警告的non-SDK介面會被上報至谷歌,以便進一步分析判斷,調整介面名單的內容。4月份前都有調整的機會,6月份定稿。谷歌將於近日給出初始的介面名單,且有申訴渠道,有可能由此將特定non-SDK介面加入gray list,DP1的時候,谷歌釋出black list,OEM進行評估,同時谷歌測試top1000;
3.1.2 相容性影響
三方應用的熱補丁、加殼方案、呼叫non-SDK介面的所有三方應用可能會受到影響;在Developer Preview的後續版本中,訪問non-SDK介面的各種方法都會產生錯誤或其他不良結果。下表提供了有關訪問方式及其各自結果的詳細資訊。
需要三方應用排查non-SDK介面的呼叫,並提前整改,否則可能現在或者是將來會出現相容性問題。
3.1.3 適配指導
(1)通過日誌,找出應用呼叫的所有non-SDK介面名單,關鍵日誌:
AccessinghiddenfieldLandroid/os/Message;->flags: I(lightgreylist, JNI)AccessinghiddenmethodLandroid/app/ActivityThread;->currentActivityThread()Landroid/app/ActivityThread;(darkgreylist, reflection)
(2)對於已經被禁止呼叫的介面需要整改,尋找替換該non-SDK介面的方案;
(3)如果必須要呼叫的non-SDK介面可以向谷歌申訴把介面加入到灰名單:https://b.corp.google.com/hotlists/825416;
3.2 Battery Improvements
3.2.1 背景介紹
谷歌在P版本之前沒有一個完整的功耗解決方案,OEM廠商分別開發各自的功耗方案,管控手段都包括了清理應用,功耗得到優化,但是同時也影響了三方應用的一些功能正常使用,谷歌為了解決這個問題在P版本提出了自己的功耗解決方案,該方案主要包含:
(1)AAB(Auto Awesome Battery):
①通過ML演算法將應用進行分類,不同型別的應用功耗管控策略不一樣
②Firebase Cloud Messaging (FCM):管控三方訊息接收的頻率
③谷歌提供了統一的應用的管控方法:Forced App Standby (FAS),谷歌不會通過清理應用來優化功耗
(2)Extreme Battery Saver(EBS)谷歌超級省電模式;
(3)Smart screen brightness:螢幕亮度調節優化演算法。
3.2.2 相容性影響
谷歌功耗方案對三方應用各種管控,存在導致應用後臺功能無法正常使用的可能,特別是:IM、郵箱、鬧鐘、音樂(直播)、地圖導航、運動健康、下載、日曆等應用影響比較大。目前通過谷歌提供的除錯命令驗證:所有的應用都有可能會被分到管控的型別,對三方的後臺功能是有影響的。
3.2.3 適配指導
如何判斷是不是谷歌AAB方案導致的問題?谷歌提供了除錯命令,可以獲取應用所處的管控分類,並且可以讓某個應用進入指定的分類進行管控,測試驗證對應管控策略下的應用行為。
(1)Unplug (or adb shell dumpsys battery unplug )
(2)adb shell am get-standby-bucket <package name> ; //獲取某個指定應用分類資料(5-50)
5 EXEMPT/WHITELISTED
10 ACTIVE
20 WORKING_SET
30 FREQUENT
40 RARE
50 NEVER
(3) adb shell am set-standby-bucket <package name> <bucket>//強制把某個應用設定到指定的類別
(4)Programmatic: UsageStatsManager::getAppStandbyBucket()
3.3 挖孔屏適配
3.3.1 背景介紹
(1)谷歌P版本提供了統一的挖孔屏方案和三方適配挖孔屏方案:
①對於有狀態列的頁面,不會受到挖孔屏特性的影響;
②全屏顯示的頁面,系統挖孔屏方案會對應用介面做下移避開挖孔區顯示;
③已經適配的P的應用的全屏頁面可以通過谷歌提供的適配方案使用挖孔區,真正做到全屏顯示。
(2)P版本三方適配挖孔屏方案:
①新增挖孔屏挖孔尺寸和位置介面
class WindowInsets { DisplayCutout getDisplayCutout(); } class DisplayCutout { int getSafeInsetLeft(); int getSafeInsetTop(); int getSafeInsetRight(); int getSafeInsetBottom(); Region getBounds(); }
②新窗口布局模式,允許應用程式請求是否在挖孔區域佈局:
class WindowManager.LayoutParams { int layoutInDisplayCutoutMode; final int LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT; final int LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS; final int LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER; }
layoutInDisplayCutoutMode值說明:
a)LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT:預設情況下,全屏視窗不會使用到挖孔區域,非全屏視窗可正常使用挖孔區域。
b)LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS:視窗宣告使用挖孔區域
c)LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER:視窗宣告不使用挖孔區域
3.3.2 相容性影響
(1)系統下移方案導致佈局問題(截斷、錯亂,按鈕熱區錯位);
小說頁碼被截斷問題
(2)狀態列高度寫死問題;
狀態列背景高度寫死問題
(3)沉浸式佈局遮擋問題;
搜尋框被遮擋問題
視訊內容被遮擋問題
3.3.3 適配指導
(1)在非挖孔屏P版本手機可以開啟模擬挖孔屏除錯的功能:
①在開發人員選項螢幕中,向下滾動到繪圖部分,然後點選“模擬具有凹口的顯示屏”設定項;
②選擇挖孔尺寸資訊;
(2)在挖孔屏除錯開啟之後,瀏覽應用的所有頁面,測試所有遮擋問題,或者是下移導致的問題,對有問題的頁面進行佈局適配,適配方案:
①可以通過谷歌提供的適配方案,使用挖孔區全屏顯示解決:
WindowManager.LayoutParams lp = getWindow().getAttributes(); lp.layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS; getWindow().setAttributes(lp);
②佈局調整,建議佈局調整策略:
應用頁面背景可以充滿整個螢幕顯示,控制元件和文字等關鍵資訊佈局在狀態列以外的區域顯示,保證關鍵資訊不會出現遮擋(谷歌要求:狀態列高度和挖孔高度要保持一致),需要用到的介面:
a)獲取挖孔尺寸資訊介面,具體可以參考:3.3.1章節;
b)獲取系統狀態列高度介面:
public static int getStatusBarHeight(Context context) { int result = 0; int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android"); if (resourceId > 0) { result = context.getResources().getDimensionPixelSize(resourceId); } return result; }
(3)P版本適配工作:谷歌提供的適配方案要求應用必須要適配到P版本才能使用,所以如果應用需要適配挖孔屏,還需要驗證應用適配到P版本的其他相容性問題並解決,可參考:https://developer.android.com/preview/migration.html。
3.4 藍芽後臺掃描管控
3.4.1 背景介紹
(1)特性介紹
減少功耗,減少後臺佔用CPU,提供更加智慧的掃描策略來降低功耗,對後臺應用、滅屏場景下的掃描作限制,提供更加低功耗的掃描間隔和視窗。
(2)影響APP範圍:沒有設定過濾條件的所有應用
private void startScan(List<ScanFilter> filters, ScanSettings settings, final ScanCallback callback, List<List<ResultStorageDescriptor>> resultStorages)
第一個引數(ScanFilter):篩選條件,可以通過設定過濾器的mDeviceName、mDeviceAddress、mServiceUuid等作為過濾條件進行過濾。也就是如果第一個引數傳入的是null,該應用會受該特性影響。
(3)管控措施:
後臺:降低掃描的空佔比;
滅屏:禁止藍芽掃描。
3.4.2 相容性影響
影響應用後臺藍芽掃描功能。
3.4.3 適配指導
發起藍芽掃描的時候新增過濾條件。
3.5 Camera、sensor和麥克風後臺管控
3.5.1 背景介紹
增加Camera、sensor和麥克風的background限制,對所有SDK都生效;限制sensor event向後臺應用或服務的傳輸,對前臺應用無影響;主要是考慮隱私原因,功耗不是主要動機;對應用來說是很大的變化。
3.5.2 相容性影響
(1)影響範圍:應用處於idle和gone的狀態就會被管控,切換到後臺一分鐘應用就會進入idle狀態,但是有前臺服務的不會進入idle狀態;
(2)影響三方功能:後臺錄音,拍照、攝像、定位和計步。
3.5.3 適配指導
(1)問題定位,確認是不是該特性管控導致的:
①檢視應用狀態:adb shell dumpsys activity p com.sina.weibo ,然後搜尋UID states檢視UID的狀態
②檢視應用有沒有註冊監聽sensor情況:adb shell dumpsys sensorservice
(2)適配方案:需要後臺訪問麥克風、sensor和camera的時候增加前臺服務。
如果滿足以下任意條件,應用將被視為處於前臺:
①具有可見 Activity(不管該 Activity 已啟動還是已暫停)。
②具有前臺服務。
③另一個前臺應用已關聯到該應用(不管是通過繫結到其中一個服務,還是通過使用其中一個內容提供程式)。 例如,如果另一個應用繫結到該應用的服務,那麼該應用處於前臺:
a)IME
b)桌布服務
c)通知偵聽器
d)語音或文字服務
3.6 更嚴格的Seccomp filter
3.6.1 背景介紹
大量的系統呼叫暴露在使用者空間,但其實在程式的整個生命週期內並沒有使用,增加了系統安全的攻擊面。而隨著系統呼叫的改變和成熟,可以產生出一組儘量少的系統呼叫暴露在使用者空間。Seccomp-bpf就是在應用程式的使用中,限制只能呼叫有限指定的系統呼叫。Seccomp過濾器提給了一種手段,為一個程序呼叫系統呼叫時指定了過濾器,而這個過濾器則是BPF。
3.6.2 相容性影響
谷哥對zygote程序設定了seccomp filter,使的app程序僅能夠通過bionic庫呼叫系統呼叫。其他系統呼叫將會被系統攔截,可能會導致一些應用閃退相容性問題,如果應用呼叫了不允許的系統呼叫,會接收到SIGKILL訊號;P版本比O版本限制更嚴格,在P版本同樣存在相容性問題的風險。
3.6.3 適配指導
app程序通過bionic庫呼叫systemcalls:
3.7 FLAG_ACTIVITY_NEW_TASK被強制要求
在P版本,如果不在Intent新增FLAG_ACTIVITY_NEW_TASK,將無法通過非Activity的Context啟動一個Activity,並且會拋異常。
比如在Service中啟動Activity,如果Intent不新增FLAG_ACTIVITY_NEW_TASK,就會拋異常:
@Override public void onCreate() { Log.v(TAG, "ServiceDemo onCreate"); super.onCreate(); Intent intent = new Intent(this, Main2Activity.class); // intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(intent); }
3.8 應用禁止訪問xt_qtaguid目錄的檔案
對應用程式不再允許直接讀取/ proc / net / xt_qtaguid資料夾中的檔案。原因是為了確保和執行Android P的裝置保持一致,這些裝置根本沒有這些檔案。
依賴這些檔案的公共API,TrafficStats和NetworkStatsManager繼續按預期工作。但是,不支援的cutils函式(如qtaguid_tagSocket())可能無法按預期方式工作,或者根本無法在不同的裝置上工作。
3.9 Crypto provider在P版本去掉了
從P版本開始,Crypto JCA provider被去掉了,呼叫SecureRandom.getInstance(“SHA1PRNG”, “Crypto”) 將會報NoSuchProviderException。
3.10 前臺服務許可權
應用如果想使用前臺服務需要申請FOREGROUND_SERVICE許可權,這個許可權是普通許可權,如果不申請許可權就直接啟動前臺服務會拋SecurityException。
3.11 去除通過Build.serial獲取裝置識別碼
應用需要驗證手機序列號必須要申請READ_PHONE_STATE許可權,然後通過P版本新增的介面Build.getSerial() 來獲取:
(1)通過Build.SERIAL獲取不到真實資料:Build.serial:unknown
(2)通過Build.getSerial()才能獲取真實的資料,需要使用者授權READ_PHONE_STATE許可權
該特性隻影響已經適配P的應用,也就是targetSDK Version>=P。
3.12 不允許共享WebView資料目錄
應用程式不能再跨程序共享單個WebView資料目錄。如果您的應用有多個使用WebView,CookieManager或android.webkit包中的其他API的程序,則當第二個程序呼叫WebView方法時,您的應用將崩潰。
該特性隻影響已經適配P的應用,也就是targetSDK Version>=P。
3.13 Notifications
3.13.1 背景介紹
(1)增強的訊息體驗:
從Android 7.0開始,你可以增加一個action以對訊息或從通知直接進入文字的行為作出反應。Android P有如下增強:
①支援影象: Android P現在可在訊息中展示影象,通過在訊息中setData()即可實現此功能;
②為了便捷性而做出的簡化支援: 新的Notification.Person類用於識別對話中的人物,包含他們的頭像和URI. 很多其他的API,例如addMessage(),
在利用Person類而不是CharSequence;
③儲存回覆為草稿:當用戶不小心關閉訊息通知時,你的app可以獲取由系統發出的EXTRAREMOTEINPUT_DRAFT。你可以使用這個extra值來在app中進行預填充,從而使使用者可以更快地完成回覆
④識別是否對話為群聊:你可以使用setGroupConversation()來識別一個對話是否為群聊
⑤為Intent設定語義動作:setSemanticAction()方法可以讓開發者給一個行為增加語義,如標記為讀,刪除,回覆等等
⑥智慧回覆:Android P支援相同的建議性回覆。使用RemoteIntent.setChoices()來提供一組標準回覆給使用者
(2)Channel設定,廣播和免打擾
Android O引入了通知Channel的概念,從而可以讓開發者為每類通知建立自定義的channel. Android P通過如下變化簡化了通知channel設定:
①限制channel組:使用者現在可以通過對一個app的通知設定來限制整個channel的通知組。你可以使用isBlocked()方法來判斷一個通知組是否被限制,從而,不再發送通知到那個組的channel中。此外,你可通過getNotificationChannelGroup()方法獲取當前channel組的設定
②新的廣播Intent型別:當通知channel以及channel組的阻塞狀態發生變化時,Android系統會發送廣播。被阻塞通知channel的app可以監聽這些intent並作出相應的反應。
③新的不打擾類別: NotificationManager.Policy有兩個策略常量: PRIORITY_CATEGORYALARMS(鬧鈴優先)和PRIORITY_CATEGORY_MEDIA_SYSTEM_OTHER(媒體,系統和遊戲聲音優先)
3.13.2 適配指導
(1)使用Person(P版本新增)顯示發訊息使用者頭像:
顯示效果:
3.13.3 相容性影響
新特性,對三方相容性無影響,可以增強IM應用的通知體驗。
4. 參考文獻
(1)Google P版本的P-preview SDK已經發布, P-preview的SDK下載地址:https://developer.android.com/preview/overview.html
(2)Google P版本的P-preview source code地址: https://android.googlesource.com/platform/frameworks/base/+/android-p-preview-1
(3)Google P版本的P-preview source code下載方法: https://source.android.com/source/downloading.html
(4)目前Pixel、Pixel XL、Pixel 2和Pixcel 2 XL可以升級P-preview版本,下載地址如下: https://developer.android.com/preview/download.html
(5)Google P版本版本計劃:https://developer.android.com/preview/migration.html
(6) Google P版本新特性和主要行為變更:https://developer.android.com/preview/features.html
https://developer.android.com/preview/behavior-changes.html