您好,登錄后才能下訂單哦!
一、前言
本文主要是從官方文檔中篩選出一些常見的適配項,若有任何紕漏或需要補充的,歡迎大家在評論區指出。
二、版本適配
1. 限制 HTTP 網絡請求
Android 9.0 中限制了 HTTP(明文傳輸)網絡請求,若仍繼續使用HTTP請求,則會在日志中提示以下異常(只是無法正常發出請求,不會導致應用崩潰):
java.net.UnknownServiceException: CLEARTEXT communication to xxx not permitted by network security policy
適配的方法如下:
第一種
在資源目錄中新建一個 xml 文件作為網絡安全配置文件,例如 xml/network_security_config.xml,然后在文件中填寫以下內容:
<?xml version="1.0" encoding="utf-8"?> <network-security-config> <base-config cleartextTrafficPermitted="true" /> </network-security-config>
在AndroidManifest.xml進行配置:
<application ... android:networkSecurityConfig="@xml/network_security_config"> ... </application>
第二種(感謝 AllenChiang 同學的提醒)
Android 6.0 中引入了是否允許網絡使用明文傳輸的配置:
<application android:usesCleartextTraffic=["true" | "false"]>
原來默認為 true,但在 Android 9.0 中默認值改為了 false,因此將配置手動設為 true 即可解決明文傳輸被限制的問題
2. 棄用 Apache HTTP Client
由于官方在 Android 9.0 中移除了所有 Apache HTTP Client 相關的類,因此我們的應用或是一些第三方庫如果使用了這些類,就會拋出找不到類的異常:
java.lang.NoClassDefFoundError: Failed resolution of: Lorg/apache/http/conn/scheme/SchemeRegistry;
若需要繼續使用 Apache HTTP Client ,可通過以下方法進行適配:
在 AndroidManifest.xml 中添加以下內容:
<uses-library android:name="org.apache.http.legacy" android:required="false"/>
或者在應用中直接將 Apache HTTP Client 相關的類打包并進行引用
3. 限制非 SDK 接口的調用
3.1 簡述
一直以來,官方提供的接口分為了 SDK 接口和非 SDK 接口。SDK 接口即官方支持的接口,開發者可以直接調用不會有任何限制。一般而言,SDK 接口都記錄在官方的接口索引中,沒有記錄的就視為非 SDK 接口,例如一些使用了 @hide 標注的方法。
以往開發者對于非 SDK 接口的調用通常是利用反射或者JNI間接調用的方式進行,但這樣的調用方式如果處理不當會比較容易出現一些未知的錯誤。為了提升用戶體驗和降低應用發生崩潰的風險,Android 9.0 對應用能使用的非 SDK 接口實施了限制,具體的限制手段請見下表:
此外,為了開發者能夠順利過渡到 Android 9.0,官方對非 SDK 接口進行了分類,共分為三類,light-greylist(淺灰名單)、dark-greylist(深灰名單)以及blacklist(黑名單):
3.2 如何測試應用是否使用非 SDK 接口
可以通過以下方式進行測試(詳情請至官方文檔):
建議使用第三種方式,該工具的掃描結果會列出應用對于三個限制名單中的接口的調用細節。
4. 前臺服務權限
在 Android 9.0 中,應用在使用前臺服務之前必須先申請 FOREGROUND_SERVICE 權限,否則就會拋出 SecurityException 異常。
此外,由于 FOREGROUND_SERVICE 權限只是普通權限,因此開發者只需在 AndroidManifest.xml 中注冊此權限即可,系統會自動對此權限進行授權:
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
5. 強制執行 FLAG_ACTIVITY_NEW_TASK 要求
在 Android 7.0(API 級別 24)之前,若開發者需要通過非 Activity context 啟動 Activity,就必須設置 Intent 標志 FLAG_ACTIVITY_NEW_TASK,否則會啟動失敗并拋出以下異常
android.util.AndroidRuntimeException: Calling startActivity() from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want?
但這個要求在更新 Android 7.0 以后由于系統問題被臨時取消了,開發者即使不設置標志也可以正常啟動 Activity。而在 Android 9.0 中官方修復了這個問題,這個要求重新開始強制執行,因此開發者在適配 Android 9.0 時需要注意這個問題。
6. 不允許共享 WebView 數據目錄
Android 9.0 中為了改善應用穩定性和數據完整性,應用無法再讓多個進程共用同一 WebView 數據目錄。此類數據目錄一般存儲 Cookie、HTTP 緩存以及其他與網絡瀏覽有關的持久性和臨時性存儲。
如果開發者需要在多進程中使用 WebView,則必須先調用 WebView.setDataDirectorySuffix() 方法為每個進程設置用于存儲 WebView 數據的目錄。若多進程 WebView 之間需要共享數據,開發者需自己通過 IPC 的方式實現。
此外,若開發者只想在一個進程中使用 WebView,并且希望嚴格執行這個規則,可以通過在其他進程中調用 WebView.disableWebView() 方法,這樣其他進程創建 WebView 實例就會拋出異常。
7. 其他 API 方面的修改
7.1 Region.Op 相關
Android 9.0 中如果在使用繪圖裁剪功能時設置了除 Region.Op.INTERSECT 或 Region.Op.DIFFERENCE 以外的類型,就會拋出以下異常:
java.lang.IllegalArgumentException: Invalid Region.Op - only INTERSECT and DIFFERENCE are allowed
具體原因是官方廢棄了那幾個具有 Region.Op 參數的裁剪方法,如 clipRect(@NonNull RectF rect, @NonNull Region.Op op) :
/** * Modify the current clip with the specified rectangle. * * @param rect The rect to intersect with the current clip * @param op How the clip is modified * @return true if the resulting clip is non-empty * * @deprecated Region.Op values other than {@link Region.Op#INTERSECT} and * {@link Region.Op#DIFFERENCE} have the ability to expand the clip. The canvas clipping APIs * are intended to only expand the clip as a result of a restore operation. This enables a view * parent to clip a canvas to clearly define the maximal drawing area of its children. The * recommended alternative calls are {@link #clipRect(RectF)} and {@link #clipOutRect(RectF)}; * * As of API Level API level {@value Build.VERSION_CODES#P} only {@link Region.Op#INTERSECT} and * {@link Region.Op#DIFFERENCE} are valid Region.Op parameters. */ @Deprecated public boolean clipRect(@NonNull RectF rect, @NonNull Region.Op op) { checkValidClipOp(op); return nClipRect(mNativeCanvasWrapper, rect.left, rect.top, rect.right, rect.bottom, op.nativeInt); } private static void checkValidClipOp(@NonNull Region.Op op) { if (sCompatiblityVersion >= Build.VERSION_CODES.P && op != Region.Op.INTERSECT && op != Region.Op.DIFFERENCE) { throw new IllegalArgumentException( "Invalid Region.Op - only INTERSECT and DIFFERENCE are allowed"); } }
對于這個問題,可以通過以下方法進行適配:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { canvas.clipPath(path); } else { canvas.clipPath(path, Region.Op.XOR);// REPLACE、UNION 等類型 }
7.2 Build.SERIAL 被棄用
Android 9.0 之前,開發者可以使用 Build.SERIAL 獲取設備的序列號。現在這個方法被棄用了,Build.SERIAL 將始終設置為 "UNKNOWN" 以保護用戶的隱私。
適配的方法為先請求 READ_PHONE_STATE 權限,然后調用 Build.getSerial() 方法。
以上所述是小編給大家介紹的Android版本適配9.0 Pie詳解整合,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對億速云網站的支持!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。