Android Pie(9.0) 新特性和適配策略

Android Pie(9.0) New Features

內(nèi)容:

  • 劉海屏適配
  • 通知功能的變更
  • 隱私權(quán)變更
  • 對(duì)使用非 SDK 接口的限制 和 適配策略
  • 非Activity-Context啟動(dòng)Activity
  • Apache HTTP 客戶端棄用,影響采用非標(biāo)準(zhǔn) ClassLoader 的應(yīng)用
  • 前臺(tái)服務(wù)

API 變更

Display Cutout Support

Android 9 支持最新的全面屏,其中包含為攝像頭和揚(yáng)聲器預(yù)留空間的屏幕缺口。 通過 DisplayCutout 類可確定非功能區(qū)域的位置和形狀,這些區(qū)域不應(yīng)顯示內(nèi)容。 要確定這些屏幕缺口區(qū)域是否存在及其位置,使用 getDisplayCutout()函數(shù)。

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
    View decorView = getWindow().getDecorView();
    WindowInsets rootWindowInsets = decorView.getRootWindowInsets();
    if (rootWindowInsets != null) {
        DisplayCutout cutout = rootWindowInsets.getDisplayCutout();
        List<Rect> boundingRects = cutout.getBoundingRects();
        if (boundingRects != null && boundingRects.size() > 0) {
            String msg;
            for (Rect rect : boundingRects) {
                msg = s+"left-" + rect.left;
                Log.d(TAG, msg);
            }
         }
    }
}

用新的窗口布局屬性 layoutInDisplayCutoutMode 為設(shè)備屏幕缺口周圍的內(nèi)容進(jìn)行布局。 可以將此屬性設(shè)為下列值之一:

LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT

The window is allowed to extend into the DisplayCutout area, only if the DisplayCutout is fully contained within a system bar. Otherwise, the window is laid out such that it does not overlap with the DisplayCutout area.

LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES

The window is always allowed to extend into the DisplayCutout areas on the short edges of the screen. The window will never extend into a DisplayCutout area on the long edges of the screen.屏幕短邊有cutout,會(huì)延伸過去;若cutout在長(zhǎng)邊,一定不會(huì)延伸過去。

In this mode, the window extends under cutouts on the short edge of the display in both portrait and landscape, regardless of whether the window is hiding the system bars

On the other hand, should the cutout be on the long edge of the display, a letterbox will be applied such that the window does not extend into the cutout on either long edge在長(zhǎng)邊有cutout的情況,會(huì)排出在外。

LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER

The window is never allowed to overlap with the DisplayCutout area.

This should be used with windows that transiently set View.SYSTEM_UI_FLAG_FULLSCREEN or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION to avoid a relayout of the window when the respective flag is set or cleared.

WindowManager.LayoutParams lp = getWindow().getAttributes();
lp.layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT;
getWindow().setAttributes(lp);

Channel settings, broadcasts, and Do Not Disturb

Android 8.0 引入了通知渠道,允許您為要顯示的每種通知類型創(chuàng)建可由用戶自定義的渠道。 Android 9 通過下列變更簡(jiǎn)化通知渠道設(shè)置:

  • 屏蔽渠道組:現(xiàn)在,用戶可以針對(duì)某個(gè)應(yīng)用在通知設(shè)置中屏蔽整個(gè)渠道組。 您可以使用 isBlocked() 函數(shù)確定何時(shí)屏蔽一個(gè)渠道組,從而不會(huì)向該組中的渠道發(fā)送任何通知。
    此外,您的應(yīng)用可以使用全新的 getNotificationChannelGroup() 函數(shù)查詢當(dāng)前渠道組設(shè)置。

  • 全新的廣播 Intent 類型:現(xiàn)在,當(dāng)通知渠道和渠道組的屏蔽狀態(tài)發(fā)生變更時(shí),Android 系統(tǒng)將發(fā)送廣播 Intent。 擁有已屏蔽的渠道或渠道組的應(yīng)用可以偵聽這些 Intent 并做出相應(yīng)的回應(yīng)。 有關(guān)這些 Intent 操作和 extra 的更多信息,請(qǐng)參閱 NotificationManager 參考中更新的常量列表。 有關(guān)響應(yīng)廣播 Intent 的信息,請(qǐng)參閱廣播。

  • NotificationManager.Policy 有 3 種新的“請(qǐng)勿打擾”優(yōu)先級(jí)類別:

  • PRIORITY_CATEGORY_ALARMS優(yōu)先處理警報(bào)。

  • PRIORITY_CATEGORY_MEDIA 優(yōu)先處理媒體源的聲音,如媒體和語音導(dǎo)航。

  • PRIORITY_CATEGORY_SYSTEM 優(yōu)先處理系統(tǒng)聲音。

  • NotificationManager.Policy 還有 7 種新的“請(qǐng)勿打擾”常量,可以用來抑制視覺中斷:

  • SUPPRESSED_EFFECT_FULL_SCREEN_INTENT 防止通知啟動(dòng)全屏 Activity。

  • SUPPRESSED_EFFECT_LIGHTS 屏蔽通知燈。

  • SUPPRESSED_EFFECT_PEEK 防止通知短暫進(jìn)入視圖(“滑出”)。

  • SUPPRESSED_EFFECT_STATUS_BAR 防止通知顯示在支持狀態(tài)欄的設(shè)備的狀態(tài)欄中。

  • SUPPRESSED_EFFECT_BADGE 在支持標(biāo)志的設(shè)備上屏蔽標(biāo)志。 如需了解詳細(xì)信息,請(qǐng)參閱修改通知標(biāo)志。

  • SUPPRESSED_EFFECT_AMBIENT 在支持微光顯示的設(shè)備上屏蔽通知。

  • SUPPRESSED_EFFECT_NOTIFICATION_LIST 防止通知顯示在支持列表視圖(如通知欄或鎖屏)的設(shè)備的列表視圖中。

隱私權(quán)變更-現(xiàn)在收的原來越緊,安卓也越來越規(guī)范

為了增強(qiáng)用戶隱私,Android 9 引入了若干行為變更,如限制后臺(tái)應(yīng)用訪問設(shè)備傳感器、限制通過 Wi-Fi 掃描檢索到的信息,以及與通話、手機(jī)狀態(tài)和 Wi-Fi 掃描相關(guān)的新權(quán)限規(guī)則和權(quán)限組。

無論采用哪一種目標(biāo) SDK 版本,這些變更都會(huì)影響運(yùn)行于 Android 9 上的所有應(yīng)用。

后臺(tái)對(duì)傳感器的訪問受限

Android 9 限制后臺(tái)應(yīng)用訪問用戶輸入和傳感器數(shù)據(jù)的能力。 如果您的應(yīng)用在運(yùn)行 Android 9 設(shè)備的后臺(tái)運(yùn)行,系統(tǒng)將對(duì)您的應(yīng)用采取以下限制:

您的應(yīng)用不能訪問麥克風(fēng)或攝像頭。
使用連續(xù)報(bào)告模式的傳感器(例如加速度計(jì)和陀螺儀)不會(huì)接收事件。
使用變化或一次性報(bào)告模式的傳感器不會(huì)接收事件。
如果您的應(yīng)用需要在運(yùn)行 Android 9 的設(shè)備上檢測(cè)傳感器事件,請(qǐng)使用前臺(tái)服務(wù)。

限制訪問通話記錄

Android 9 引入 CALL_LOG 權(quán)限組并將 READ_CALL_LOGWRITE_CALL_LOGPROCESS_OUTGOING_CALLS 權(quán)限移入該組。 在之前的 Android 版本中,這些權(quán)限位于 PHONE 權(quán)限組。

如果應(yīng)用需要訪問通話記錄或者需要處理去電,則您必須向 CALL_LOG 權(quán)限組明確請(qǐng)求這些權(quán)限。 否則會(huì)發(fā)生 <mark>SecurityException</mark>。

限制訪問電話號(hào)碼

在未首先獲得 READ_CALL_LOG 權(quán)限的情況下,除了應(yīng)用的用例需要的其他權(quán)限之外,運(yùn)行于 Android 9 上的應(yīng)用無法讀取電話號(hào)碼或手機(jī)狀態(tài)。

與來電和去電關(guān)聯(lián)的電話號(hào)碼可在手機(jī)狀態(tài)廣播(比如來電和去電的手機(jī)狀態(tài)廣播)中看到,并可通過 PhoneStateListener 類訪問。 但是,如果沒有 READ_CALL_LOG 權(quán)限,則 PHONE_STATE_CHANGED 廣播和 PhoneStateListener <mark>提供的電話號(hào)碼字段為空</mark>。

要從手機(jī)狀態(tài)中讀取電話號(hào)碼,請(qǐng)根據(jù)您的用例更新應(yīng)用以請(qǐng)求必要的權(quán)限:

  • 要通過 PHONE_STATE Intent 操作讀取電話號(hào)碼,同時(shí)需要 READ_CALL_LOG 權(quán)限READ_PHONE_STATE 權(quán)限。
  • 要從 onCallStateChanged() 中讀取電話號(hào)碼,只需要 READ_CALL_LOG 權(quán)限。 不需要 READ_PHONE_STATE 權(quán)限。

電話信息現(xiàn)在依賴設(shè)備位置設(shè)置

如果用戶在運(yùn)行 Android 9 的設(shè)備上<mark>停用設(shè)備定位</mark>,則以下函數(shù)不提供結(jié)果:

  • TelephonyManager.getAllCellInfo()
  • TelephonyManager.listen()
  • TelephonyManager.getCellLocation()
  • TelephonyManager.getNeighboringCellInfo()

Build.SERIAL 始終設(shè)置為 "UNKNOWN" 以保護(hù)用戶的隱私。

如果您的應(yīng)用需要訪問設(shè)備的硬件序列號(hào),您應(yīng)改為請(qǐng)求 READ_PHONE_STATE權(quán)限,然后調(diào)用 getSerial()。

多進(jìn)程 webview 信息訪問限制

在 Android P 中為了提升系統(tǒng)的安全性,用戶無法在多進(jìn)程的 webview 中共享數(shù)據(jù)目錄,該目錄下存儲(chǔ)的是一些 cookies、Http 緩存和其他一些永久、臨時(shí)的緩存。當(dāng)下不少應(yīng)用會(huì)把 webview 放在另一個(gè)進(jìn)程中打開以避免內(nèi)存泄漏,但是他們 cookies 的設(shè)置往往還是在主進(jìn)程中,所以開發(fā)者需要仔細(xì)排查自己的應(yīng)用是否有這么使用,webview 相關(guān)運(yùn)行是否正常等。

對(duì)使用非 SDK 接口的限制

為幫助確保應(yīng)用穩(wěn)定性和兼容性,此平臺(tái)對(duì)某些非 SDK 函數(shù)和字段的使用進(jìn)行了限制;無論您是直接訪問這些函數(shù)和字段,還是通過反射或 JNI 訪問,這些限制均適用。 在 Android 9 中,您的應(yīng)用可以繼續(xù)訪問這些受限的接口;<mark>該平臺(tái)通過 toast日志條目提醒您注意這些接口</mark>。 如果您的應(yīng)用顯示這樣的 toast,則必須尋求受限接口之外的其他實(shí)現(xiàn)策略。 如果您認(rèn)為沒有可行的替代策略,您可以提交錯(cuò)誤以請(qǐng)求重新考慮此限制。

SDK 接口的鏈接

對(duì)于非SDK 接口

  • 淺灰名單:仍可以訪問的非 SDK 函數(shù)/字段。
  • 深灰名單:
    對(duì)于目標(biāo) SDK 低于 API 級(jí)別 28 的應(yīng)用,允許使用深灰名單接口。
    對(duì)于目標(biāo) SDK 為 API 28 或更高級(jí)別的應(yīng)用:行為與黑名單相同。
  • 黑名單:受限,無論目標(biāo) SDK 如何
    平臺(tái)將提示接口并不存在。
    例如,無論應(yīng)用何時(shí)嘗試使用接口,<mark>平臺(tái)都會(huì)引發(fā) NoSuchMethodError/NoSuchFieldException,</mark>即使應(yīng)用想要了解某個(gè)特殊類別的字段/函數(shù)名單,平臺(tái)也不會(huì)包含接口。

檢測(cè)是否使用了非SDK接口

  1. 下載工具,閱讀README.txt
  2. 打包一個(gè)應(yīng)用 APK,建議使用 release 包,排除一些未使用到的單元測(cè)試類或者其他因素的影響,取消混淆,將 APK 放到工具目錄下;
  1. 執(zhí)行命令 ./appcompat.sh --dex-file=test.apk,在終端上會(huì)輸出三個(gè)名單每個(gè) API 的詳細(xì)調(diào)用處

非 SDK API 的處理

適配的原則是優(yōu)先黑名單和深灰名單,淺灰名單在官方未有替代 API 之前可以暫時(shí)不適配,在 Android P 上運(yùn)行也不會(huì)有任何問題。

  1. 向google申請(qǐng)
    在之前 DP 版本時(shí)開發(fā)者如果遇到了不得不使用的黑名單或者深灰名單 API,需要向 google 官方及時(shí)提出反饋 (反饋url)申請(qǐng)將其移動(dòng)到淺灰名單中,但是目前正式版本已經(jīng)發(fā)布,未得知該申請(qǐng)通道是否仍有效。
  2. 針對(duì)第三方庫調(diào)用到了非 SDK API 接口,解決辦法當(dāng)然是直接查詢相關(guān)資料或者聯(lián)系庫提供方,確認(rèn)是否有適配 Android P 新版本的 SDK。還有需要提到的一點(diǎn),就算更換適配完成的第三方 SDK 后,仍然可能會(huì)在同一地方掃描出非 SDK API 的調(diào)用,這是因?yàn)檫m配工程師只是在調(diào)用處加了一個(gè) try-catch 保護(hù)邏輯,雖然這樣也勉強(qiáng)叫做適配完成,但是還是強(qiáng)烈建議大家使用如下的適配方式:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
// Android P or above
} else {
// below Android P
}

嚴(yán)格按照上面的適配方案,掃描工具就不會(huì)再掃描出此處的非 SDK API 調(diào)用,我們也無需每次都去確認(rèn)所有非 SDK API 調(diào)用處都加了保護(hù)邏輯。
當(dāng)然如果第三方庫沒有適配也沒有近期適配的意向,目前有兩種方法:第一種是屏蔽入口;第二種是反編譯 SDK,在關(guān)鍵地方加上適配代碼;

非Activity-Context啟動(dòng)Activity,現(xiàn)在強(qiáng)制執(zhí)行 FLAG_ACTIVITY_NEW_TASK 要求

Apache HTTP 客戶端棄用,影響采用非標(biāo)準(zhǔn) ClassLoader 的應(yīng)用

將 compileSdkVersion 升級(jí)到 28 之后,如果在項(xiàng)目中用到了 Apache HTTP client 的相關(guān)類,<mark>就會(huì)拋出找不到這些類的錯(cuò)誤</mark>。這是因?yàn)楣俜揭呀?jīng)<mark>在 Android P 的啟動(dòng)類加載器中將其移除</mark>,如果仍然需要使用 Apache HTTP client.

  1. 在 Manifest 文件中加入:
<uses-library android:name="org.apache.http.legacy" android:required="false"/>
  1. 或者也可以直接將 Apache HTTP client 的相關(guān)類打包進(jìn) APK 中。
  2. 如果它們委托給 系統(tǒng) ClassLoader,則應(yīng)用在 Android 9 或更高版本上將失敗并顯示 NoClassDefFoundError,因?yàn)?系統(tǒng) ClassLoader 不再識(shí)別這些類。 為防止將來出現(xiàn)類似問題,一般情況下,應(yīng)用應(yīng)通過 應(yīng)用 ClassLoader加載類,而不是直接訪問系統(tǒng) ClassLoader

前臺(tái)服務(wù)

針對(duì) Android 9 或更高版本并使用前臺(tái)服務(wù)的應(yīng)用<mark>必須請(qǐng)求</mark> FOREGROUND_SERVICE 權(quán)限。 這是普通權(quán)限,因此,系統(tǒng)會(huì)自動(dòng)為請(qǐng)求權(quán)限的應(yīng)用授予此權(quán)限。

如果針對(duì) Android 9 或更高版本的應(yīng)用嘗試創(chuàng)建一個(gè)前臺(tái)服務(wù)且未請(qǐng)求 FOREGROUND_SERVICE,則系統(tǒng)會(huì)引發(fā) SecurityException。


新開了個(gè)個(gè)人公眾號(hào),求關(guān)注, 希望有懂運(yùn)營的朋友給點(diǎn)建議


image
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,323評(píng)論 25 708
  • 用兩張圖告訴你,為什么你的 App 會(huì)卡頓? - Android - 掘金 Cover 有什么料? 從這篇文章中你...
    hw1212閱讀 14,099評(píng)論 2 59
  • 1、通過CocoaPods安裝項(xiàng)目名稱項(xiàng)目信息 AFNetworking網(wǎng)絡(luò)請(qǐng)求組件 FMDB本地?cái)?shù)據(jù)庫組件 SD...
    陽明AI閱讀 16,228評(píng)論 3 119
  • 親子日記211篇,6月5日,星期二,天氣:多云 今天周二,像往常一樣早起做飯,日子在忙碌中重復(fù)著,但每天的心境不同...
    楊梓萌媽媽閱讀 526評(píng)論 0 2
  • 體驗(yàn)時(shí)間:2017·12·10 體驗(yàn)者:楊蕊瑜 影城名稱:濰坊萬達(dá)影城CBD店 導(dǎo)語:坐落在濰坊的Day dre...
    楊顏寧33閱讀 911評(píng)論 0 0

友情鏈接更多精彩內(nèi)容