美文网首页适配
Android 9.0遇到的问题和解决方法

Android 9.0遇到的问题和解决方法

作者: 王占刚 | 来源:发表于2019-06-10 14:37 被阅读79次

    Android 9.0遇到的问题和解决方法

    1. QQ 分享报错,提示找不到org/apache/http/conn/scheme/SchemeRegistry 类。

    Error:

    App的targetSdkVersion设置为28时,在Android 9.0的手机上进行QQ分享报错。提示找不到 org/apache/http/conn/scheme/SchemeRegistry 类。
    

    原因:

    Apache HTTP 客户端弃用(摘自Android 9.0官方变更说明)
    

    https://developer.android.google.cn/about/versions/pie/android-9.0-changes-28#apache-p

    Apache HTTP 客户端弃用
    在 Android 6.0 中,我们取消了对 Apache HTTP 客户端的支持。 从 Android 9 开始,默认情况下该内容库已从 bootclasspath 中移除且不可用于应用。

    解决:

    要继续使用 Apache HTTP 客户端,以 Android 9 及更高版本为目标的应用可以向其 AndroidManifest.xml 添加以下内容:

    <uses-library android:name="org.apache.http.legacy" android:required="false"/>
    

    注:拥有最低 SDK 版本 23 或更低版本的应用需要 android:required="false" 属性,因为在 API 级别低于 24 的设备上,org.apache.http.legacy 库不可用。 (在这些设备上,Apache HTTP 类在 bootclasspath 中提供。)

    作为使用运行时 Apache 库的替代,应用可以在其 APK 中绑定自己的 org.apache.http 库版本。 如果进行此操作,您必须将该库重新打包(使用一个类似 Jar Jar 的实用程序)以避免运行时中提供的类存在类兼容性问题。

    2.非全屏Activity不能设置orientation

    Error:

    java.lang.IllegalStateException: Only fullscreen activities can request orientation
    

    原因:

    这个问题貌似已经被广泛的讨论了,最终我们锁定了April 26的一个commit:

    Prevent non-fullscreen activities from influencing orientation · aosp-mirror/platform_frameworks_base@3979159

    这个改动中抛出异常有关的代码如下:

    if (ActivityInfo.isFixedOrientation(requestedOrientation) 
        && !fullscreen
        && appInfo.targetSdkVersion >= O) {
        throw new IllegalStateException("Only fullscreen activities can request orientation");
    }
    

    基本的意思是说,“fullscreen”为否的activity是不能锁定orientation的,否则抛出异常。下面,我们在看一下“fullscreen”如何定义的。

    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;    
    }
    

    根据上面的定义,如果一个Activity的Style符合下面三个条件之一,认为不是“fullscreen”:

    1.“windowIsTranslucent”为true;
    
    2.“windowIsTranslucent”为false,但“windowSwipeToDismiss”为true;
    
    3.“windowIsFloating“为true;
    

    综上可见,这个改动的目的是想阻止非全屏的Activity锁定屏幕旋转,因为当前Activity是透明的,浮动的或可滑动取消的,是否锁屏应该由全屏的Activity决定,而不是并没有全部占据屏幕的Activity决定。

    解决:

    这个问题貌似在最新的SDK中已经修复,我们在API Level 27的设备上已经无法重现,但我们手头的API Level 26的设备还是能重现。而且根据上面的代码来看,如果想保留当前Activity的style,“isTranslucentOrFloating”的逻辑根本没法绕过,所以想绕开很难,目前能想到的大概两个方向:

    1 推迟SDK升级,等官方修复被大多数设备采用;
    
    2 升级SDK,但重构一下代码,看看已有的非“fullscreen” Activity是不是都是必要的,例如用Fragment实现周围半透明效果,能不能直接把Fragment加入到当前Activity(当然Detach Fragment是有重绘View的开销的)。
    

    3. http请求报错

    Error:

    在Android P 使用HttpUrlConnection进行http请求会出现以下异常:

    java.io.IOException: Cleartext HTTP traffic to **** not permitted
    

    使用OKHttp请求则出现:

    java.net.UnknownServiceException: CLEARTEXT communication ** not permitted by network security policy
    

    原因:

    Google表示,为保证用户数据和设备的安全,针对下一代 Android 系统(Android P) 的应用程序,将要求默认使用加密连接,这意味着 Android P 将禁止 App 使用所有未加密的连接,因此运行 Android P 系统的安卓设备无论是接收或者发送流量,未来都不能明码传输,需要使用下一代(Transport Layer Security)传输层安全协议,而 Android Nougat 和 Oreo 则不受影响。

    在Android P系统的设备上,如果应用使用的是非加密的明文流量的http网络请求,则会导致该应用无法进行网络请求,https则不会受影响,同样地,如果应用嵌套了webview,webview也只能使用https请求。

    解决:

    有人认为 Android P 上所有的 App 都需要使用 TLS 加密会降低上网体验,事实上这是一种误解,至于 App 对于少数旧服务器的连接如果非要使用明码传输,开发者需要更改 App 的网络安全配置以允许此类连接。

    有以下三种解决方案

    • APP改用https请求

    • targetSdkVersion 降到27以下

    • 在 res 下新增一个 xml 目录,然后创建一个名为:network_security_config.xml 文件(名字自定) ,内容如下,大概意思就是允许开启http请求

      <?xml version="1.0" encoding="utf-8"?>
      <network-security-config>
          <base-config cleartextTrafficPermitted="true" />
      </network-security-config>
      
      

      当然也可以针对特定的域名自定义配置
      参考:https://developer.android.com/training/articles/security-config.html

      然后在APP的AndroidManifest.xml文件下的application标签增加以下属性

      <application
      ...
       android:networkSecurityConfig="@xml/network_security_config"
      ...
      />
      

    遇到的更多问题欢迎大家补充……

    相关文章

      网友评论

        本文标题:Android 9.0遇到的问题和解决方法

        本文链接:https://www.haomeiwen.com/subject/kcszxctx.html