Android 9.0遇到的問(wèn)題和解決方法
1. QQ 分享報(bào)錯(cuò)铐尚,提示找不到org/apache/http/conn/scheme/SchemeRegistry 類(lèi)圣蝎。
Error:
App的targetSdkVersion設(shè)置為28時(shí)帆调,在Android 9.0的手機(jī)上進(jìn)行QQ分享報(bào)錯(cuò)柜蜈。提示找不到 org/apache/http/conn/scheme/SchemeRegistry 類(lèi)。
原因:
Apache HTTP 客戶(hù)端棄用(摘自Android 9.0官方變更說(shuō)明)
https://developer.android.google.cn/about/versions/pie/android-9.0-changes-28#apache-p
Apache HTTP 客戶(hù)端棄用
在 Android 6.0 中城须,我們?nèi)∠藢?duì) Apache HTTP 客戶(hù)端的支持碘菜。 從 Android 9 開(kāi)始凹蜈,默認(rèn)情況下該內(nèi)容庫(kù)已從 bootclasspath 中移除且不可用于應(yīng)用限寞。
解決:
要繼續(xù)使用 Apache HTTP 客戶(hù)端,以 Android 9 及更高版本為目標(biāo)的應(yīng)用可以向其 AndroidManifest.xml 添加以下內(nèi)容:
<uses-library android:name="org.apache.http.legacy" android:required="false"/>
注:擁有最低 SDK 版本 23 或更低版本的應(yīng)用需要 android:required="false" 屬性仰坦,因?yàn)樵?API 級(jí)別低于 24 的設(shè)備上履植,org.apache.http.legacy 庫(kù)不可用。 (在這些設(shè)備上悄晃,Apache HTTP 類(lèi)在 bootclasspath 中提供玫霎。)
作為使用運(yùn)行時(shí) Apache 庫(kù)的替代,應(yīng)用可以在其 APK 中綁定自己的 org.apache.http 庫(kù)版本妈橄。 如果進(jìn)行此操作庶近,您必須將該庫(kù)重新打包(使用一個(gè)類(lèi)似 Jar Jar 的實(shí)用程序)以避免運(yùn)行時(shí)中提供的類(lèi)存在類(lèi)兼容性問(wèn)題。
2.非全屏Activity不能設(shè)置orientation
Error:
java.lang.IllegalStateException: Only fullscreen activities can request orientation
原因:
這個(gè)問(wèn)題貌似已經(jīng)被廣泛的討論了眷蚓,最終我們鎖定了April 26的一個(gè)commit:
這個(gè)改動(dòng)中拋出異常有關(guān)的代碼如下:
if (ActivityInfo.isFixedOrientation(requestedOrientation)
&& !fullscreen
&& appInfo.targetSdkVersion >= O) {
throw new IllegalStateException("Only fullscreen activities can request orientation");
}
基本的意思是說(shuō)鼻种,“fullscreen”為否的activity是不能鎖定orientation的,否則拋出異常沙热。下面普舆,我們?cè)诳匆幌隆癴ullscreen”如何定義的。
public static boolean isTranslucentOrFloating(TypedArray attributes) {
final boolean isTranslucent = attributes.getBoolean(com.android.internal.R.styleable.Window_windowIsTranslucent, false);
final boolean isSwipeToDismiss = !attributes.hasValue( com.android.internal.R.styleable.Window_windowIsTranslucent)
&& attributes.getBoolean( com.android.internal.R.styleable.Window_windowSwipeToDismiss, false);
final boolean isFloating = attributes.getBoolean(com.android.internal.R.styleable.Window_windowIsFloating, false);
return isFloating || isTranslucent || isSwipeToDismiss;
}
根據(jù)上面的定義校读,如果一個(gè)Activity的Style符合下面三個(gè)條件之一,認(rèn)為不是“fullscreen”:
1.“windowIsTranslucent”為true祖能;
2.“windowIsTranslucent”為false歉秫,但“windowSwipeToDismiss”為true;
3.“windowIsFloating“為true养铸;
綜上可見(jiàn)雁芙,這個(gè)改動(dòng)的目的是想阻止非全屏的Activity鎖定屏幕旋轉(zhuǎn),因?yàn)楫?dāng)前Activity是透明的钞螟,浮動(dòng)的或可滑動(dòng)取消的兔甘,是否鎖屏應(yīng)該由全屏的Activity決定,而不是并沒(méi)有全部占據(jù)屏幕的Activity決定鳞滨。
解決:
這個(gè)問(wèn)題貌似在最新的SDK中已經(jīng)修復(fù)洞焙,我們?cè)贏PI Level 27的設(shè)備上已經(jīng)無(wú)法重現(xiàn),但我們手頭的API Level 26的設(shè)備還是能重現(xiàn)拯啦。而且根據(jù)上面的代碼來(lái)看澡匪,如果想保留當(dāng)前Activity的style,“isTranslucentOrFloating”的邏輯根本沒(méi)法繞過(guò)褒链,所以想繞開(kāi)很難唁情,目前能想到的大概兩個(gè)方向:
1 推遲SDK升級(jí),等官方修復(fù)被大多數(shù)設(shè)備采用甫匹;
2 升級(jí)SDK甸鸟,但重構(gòu)一下代碼惦费,看看已有的非“fullscreen” Activity是不是都是必要的,例如用Fragment實(shí)現(xiàn)周?chē)胪该餍Ч谰拢懿荒苤苯影袴ragment加入到當(dāng)前Activity(當(dāng)然Detach Fragment是有重繪View的開(kāi)銷(xiāo)的)薪贫。
3. http請(qǐng)求報(bào)錯(cuò)
Error:
在Android P 使用HttpUrlConnection進(jìn)行http請(qǐng)求會(huì)出現(xiàn)以下異常:
java.io.IOException: Cleartext HTTP traffic to **** not permitted
使用OKHttp請(qǐng)求則出現(xiàn):
java.net.UnknownServiceException: CLEARTEXT communication ** not permitted by network security policy
原因:
Google表示,為保證用戶(hù)數(shù)據(jù)和設(shè)備的安全篮绰,針對(duì)下一代 Android 系統(tǒng)(Android P) 的應(yīng)用程序后雷,將要求默認(rèn)使用加密連接,這意味著 Android P 將禁止 App 使用所有未加密的連接吠各,因此運(yùn)行 Android P 系統(tǒng)的安卓設(shè)備無(wú)論是接收或者發(fā)送流量臀突,未來(lái)都不能明碼傳輸,需要使用下一代(Transport Layer Security)傳輸層安全協(xié)議贾漏,而 Android Nougat 和 Oreo 則不受影響候学。
在Android P系統(tǒng)的設(shè)備上,如果應(yīng)用使用的是非加密的明文流量的http網(wǎng)絡(luò)請(qǐng)求纵散,則會(huì)導(dǎo)致該應(yīng)用無(wú)法進(jìn)行網(wǎng)絡(luò)請(qǐng)求梳码,https則不會(huì)受影響,同樣地伍掀,如果應(yīng)用嵌套了webview掰茶,webview也只能使用https請(qǐng)求。
解決:
有人認(rèn)為 Android P 上所有的 App 都需要使用 TLS 加密會(huì)降低上網(wǎng)體驗(yàn)蜜笤,事實(shí)上這是一種誤解濒蒋,至于 App 對(duì)于少數(shù)舊服務(wù)器的連接如果非要使用明碼傳輸,開(kāi)發(fā)者需要更改 App 的網(wǎng)絡(luò)安全配置以允許此類(lèi)連接把兔。
有以下三種解決方案
APP改用https請(qǐng)求
targetSdkVersion 降到27以下
-
在 res 下新增一個(gè) xml 目錄沪伙,然后創(chuàng)建一個(gè)名為:network_security_config.xml 文件(名字自定) ,內(nèi)容如下县好,大概意思就是允許開(kāi)啟http請(qǐng)求
<?xml version="1.0" encoding="utf-8"?> <network-security-config> <base-config cleartextTrafficPermitted="true" /> </network-security-config>
當(dāng)然也可以針對(duì)特定的域名自定義配置
參考:https://developer.android.com/training/articles/security-config.html然后在APP的AndroidManifest.xml文件下的application標(biāo)簽增加以下屬性
<application ... android:networkSecurityConfig="@xml/network_security_config" ... />