前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Android 9.0适配及部分新特性介绍

Android 9.0适配及部分新特性介绍

作者头像
用户2802329
发布2018-12-10 11:59:00
3.2K0
发布2018-12-10 11:59:00
举报
文章被收录于专栏:Android先生Android先生

1、Android 9.0应用迁移

1.1 概述

在最开始针对速贷进行Android9.0版本的适配时,我使用的是真机是vivo X21A,将targetSdkVersion升到28,运行发现网络请求全报400 Bad Request,查阅了网上针对android9.0网络请求问题的解决方案以及其他的一些迁移到Android9.0需注意的点(下文会讲到),做了些适配和调整,发现仍有问题,通过抓包也并没有发现问题的原因所在。随后试了下模拟器以及借来的google pixel(9.0)真机运行了下,能正常使用,并没有发现什么问题,于是猜想是机子本身系统的问题。

  • 11.01更新:莫名又正常运行了。
1.2 Android9的迁移和适配

在模拟器上的适配我这边做的不多,官网有比较详细的介绍: 将应用迁移到 Android 9

1.2.1 针对Android 9设备上运行的所有应用都有影响的关键变化有(列举了常用的,具体看官方文档):
  • * 对非 SDK 接口的限制:现已禁止访问特定的非 SDK 接口,无论是直接访问,还是通过 JNI 或反射进行间接访问。尝试访问受限制的接口时,会生成 NoSuchFieldException 和 NoSuchMethodException 之类的错误。
  • 移除加密提供程序:从 Android 9 开始,Crypto JCA 提供程序已被移除。调用 SecureRandom.getInstance("SHA1PRNG", "Crypto") 将会引发 NoSuchProviderException。
  • 更严格的 UTF-8 解码器:在 Android 9 中,针对 Java 语言的 UTF-8 解码器比以往更严格,并且遵循 Unicode 标准。
  • 强制执行 FLAG_ACTIVITY_NEW_TASK :在 Android 9 中,您不能从非 Activity 环境中启动 Activity,除非您传递 Intent 标志 FLAG_ACTIVITY_NEW_TASK。 如果您尝试在不传递此标志的情况下启动 Activity,则该 Activity 不会启动,系统会在日志中输出一则消息。
1.2.2 targetSdkVersion 设置为 28 时影响应用的关键变化(列举了常用的,具体看官方文档):
  • * 默认情况下启用网络传输层安全协议 (TLS):如果应用以 Android 9 或更高版本为目标平台,则默认情况下 isCleartextTrafficPermitted() 函数返回 false。 如果您的应用需要为特定域名启用明文,您必须在应用的网络安全性配置中针对这些域名将 cleartextTrafficPermitted 显式设置为 true。
  • * 前台服务:针对 Android 9 或更高版本并使用前台服务的应用必须请求 FOREGROUND_SERVICE 权限。 这是普通权限,因此,系统会自动为请求权限的应用授予此权限。
  • 按进程分设基于网络的数据目录:为改善 Android 9 中的应用稳定性和数据完整性,应用无法再让多个进程共用同一 WebView 数据目录。 此类数据目录一般存储 Cookie、HTTP 缓存以及其他与网络浏览有关的持久性和临时性存储。
  • 构建序列号弃用:在 Android 9 中,Build.SERIAL 始终设置为 "UNKNOWN" 以保护用户的隐私。 如果您的应用需要访问设备的硬件序列号,您应改为请求 READ_PHONE_STATE 权限,然后调用 getSerial()。

其中星号*标注的是我在项目中添加的修改部分。

1.3、适配详解(重要部分)
1.3.1、non-sdk 接口限制

non-sdk即非 SDK 接口,它们是不属于官方 Android SDK 的 Java 字段和函数,它们属于实现详情,不提倡被调用或者被禁止调用的,需要通过反射等其他手段来实现;而SDK接口是官方提供的,公开的标准接口,可以被我们调用。

我们可以通过查看日志消息来得知调用的非SDK接口属于灰名单还是黑名单:

也可以使用命令扫描整个app里面存在的非 SDK 接口:

代码语言:javascript
复制
1appcompat.sh --dex-file=apk路径

如:

/Users/Clem/常用工具/runtime-master-appcompat/veridex-mac/appcompat.sh --dex-file=/Users/Clem/常用工具/runtime-master-appcompat/app-jianrongsudai-debug.apk 结果如图:

  • 白名单:即SDK
  • 浅灰名单(72个):仍可以访问的非 SDK 函数/字段
  • 深灰名单(7个):对于目标 SDK 低于 API 级别 28 的应用,允许使用深灰名单接口; 对于目标 SDK 为 API 28 或更高级别的应用:行为与黑名单相同
  • 黑名单(0个):受限,无论目标 SDK 如何,平台将表现为似乎接口并不存在

列入浅灰名单的非 SDK 接口包含可以在 Android 9 中继续工作的函数和字段,但不能保证在未来版本的平台中能够继续访问,主要需要关注深灰名单和黑名单,需要找到可以替代的SDK接口进行适配。网上有人发现了绕过API检查的方法,也有专门的库允许在Android P上使用反射而没有任何限制,如FreeReflection:

代码语言:javascript
复制
1//允许在Android P上使用反射而不受任何限制
2implementation 'me.weishu:free_reflection:1.2.0'
3
4//在App.java中加入即可:
5Reflection.unseal(this);
1.3.2、http网络请求的问题

在我们项目中,使用OKHttp请求会出现如下异常:

代码语言:javascript
复制
1java.net.UnknownServiceException: CLEARTEXT communication ** not permitted by network security policy

也就是说,当API级别为28及以上时,应用使用的如果是非加密的明文流量的http网络请求,则会导致该应用无法进行网络请求,https则不会受影响,网上提供了三种方案:

  • APP改用https请求
  • targetSdkVersion 降到27及以下
  • 在 res 下新增一个 xml 目录,然后创建一个名为:network_security_config.xml 文件(名字可自定),大概意思就是允许开启http请求,内容如下:
代码语言:javascript
复制
1<?xml version="1.0" encoding="utf-8"?>
2<network-security-config>
3    <base-config cleartextTrafficPermitted="true" />
4</network-security-config>

然后在APP的AndroidManifest.xml文件下的application标签增加以下属性即可完成:

代码语言:javascript
复制
1<application
2...
3 android:networkSecurityConfig="@xml/network_security_config"
4...
5/>
1.4、后续问题

在完成上述的适配修改后,交给测试测了以后发现了如下问题:

  • 1、绑定公积金,选择城市时,页面会崩溃
  • 2、环境切换功能,点击测试入口时,页面会崩溃
  • 3、需支持支付宝h5支付
  • 4、偶现人脸识别不成功,反复进入活体认证页面

针对问题一和二:我测试了下Android9.0的模拟器以及google pixel(9.0)真机,发现并没有这些问题,而在vivo X21A真机上面,当页面崩溃时也没有任何明确的错误日志,只看到如图的信息:

通过打断点调试发现在vivo X21A真机上,无法使用Spinner和RadioButton控件(目前看到的就这两个),一旦使用就会造成崩溃,这个比较头疼,猜测是系统问题。

  • 11.07更新:使用新机子华为 Mate 20发现并没有这个问题。

针对问题三:测试了一下只有targetSdkVersion 设置为 28时才会出现该问题,与设备的系统版本无关,上蚂蚁金服平台查了下最新文档发现,App支付功能近期有了更新和升级,具体来说就是:打包方式更换为 AAR,替代之前的 JAR 打包,SDK 支付接口部分不变(亲测有效)。下载官方demo可以发现附带的更新日志文档中也有记录这些,如图:

针对问题四,由于是偶现,且也没有任何明确的报错日志,需要多个真机进行多次测试。

2、新特性介绍(功能及API)

2.1、显示屏缺口支持:layoutInDisplayCutoutMode

Android P的真机设备或模拟器上都可以模拟屏幕缺口,提供了三种样式。

  • 11.07更新:使用新机子华为 Mate 20发现开发者选项中没有提供模拟屏幕缺口,且该机也自带有凹口位置,状态栏也一直处于刘海区域。下面提到的模式针对该机效果都不变。

API 28也提供了新的类: DisplayCutout 类,该类主要用于获取凹口位置和安全区域的位置等。 主要接口如下:

方法

接口说明

getBoundingRects()

返回Rects的列表,每个Rects都是显示屏上非功能区域的边界矩形

getSafeInsetLeft ()

返回安全区域距离屏幕左边的距离,单位是px。

getSafeInsetRight ()

返回安全区域距离屏幕右边的距离,单位是px。

getSafeInsetTop ()

返回安全区域距离屏幕顶部的距离,单位是px。

getSafeInsetBottom()

返回安全区域距离屏幕底部的距离,单位是px。

此外,API 28中还提供了新的布局参数属性 layoutInDisplayCutoutMode ,包含了三种不同模式:

模式

模式说明

LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT

只有当DisplayCutout完全包含在系统栏中时,才允许窗口延伸到DisplayCutout区域。 否则,窗口布局不与DisplayCutout区域重叠。

LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER

该窗口决不允许与DisplayCutout区域重叠。

LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES

该窗口始终允许延伸到屏幕短边上的DisplayCutout区域。

注:在Android P之前,各大手机厂商针对刘海适配方案都不太一样。

2.2、适用于可绘制对象和位图: ImageDecoder

可以将PNG, JPEG, WEBP, GIF, or HEIF 格式的图片的转换成Drawable 或者Bitmap 对象的类,可不再使用BitmapFactoryBitmapFactory.Options API。

代码语言:javascript
复制
 1ImageDecoder.OnHeaderDecodedListener listener = new ImageDecoder.OnHeaderDecodedListener() {
 2                @Override
 3                public void onHeaderDecoded(ImageDecoder decoder, ImageDecoder.ImageInfo info, ImageDecoder.Source source) {
 4                //将解码的图像缩放到精确尺寸
 5                    decoder.setTargetSampleSize(2);
 6                }
 7            };
 8            ImageDecoder.Source source = ImageDecoder.createSource(getResources(), R.mipmap.ic_launcher);
 9            //转换成Drawable对象
10            Drawable drawable = ImageDecoder.decodeDrawable(source, listener);
11            //转换成Bitmap对象
12            //Bitmap bitmap = ImageDecoder.decodeBitmap(source);
2.3、动画:AnimatedImageDrawable

Android 9 引入了 AnimatedImageDrawable 类,用于绘制和显示 GIF 和 WebP 动画图像。 AnimatedImageDrawable 的工作方式与 AnimatedVectorDrawable 的相似之处在于,都是渲染线程驱动 AnimatedImageDrawable 的动画。 渲染线程还使用工作线程进行解码,因此,解码不会干扰渲染线程的其他操作。 这种实现机制允许您的应用在显示动画图像时,无需管理其更新,也不会干扰应用界面线程上的其他事件。

代码语言:javascript
复制
1private void decodeImage() throws IOException {
2    Drawable decodedAnimation = ImageDecoder.decodeDrawable(
3        ImageDecoder.createSource(getResources(), R.drawable.my_drawable));
4
5    if (decodedAnimation instanceof AnimatedImageDrawable) {
6        // 如果属于动画,则优先开启动画,展示第一帧
7        ((AnimatedImageDrawable) decodedAnimation).start();
8    }
9}
2.4、Magnifier(放大镜)

Android P引入了Magnifier来提升用户选择文字的体验,它通过放大镜将文字放大从而来帮助用户准确定位想要选择的文字:

代码语言:javascript
复制
 1@RequiresApi(api = 28)
 2        @Override
 3        public boolean onTouch(View v, MotionEvent event) {
 4            Magnifier magnifier = new Magnifier(v);
 5            switch (event.getActionMasked()) {
 6                case MotionEvent.ACTION_DOWN:
 7                    magnifier.show(event.getX(), event.getY());
 8                    break;
 9                case MotionEvent.ACTION_MOVE:
10                    magnifier.show(event.getX(), event.getY());
11                    break;
12                case MotionEvent.ACTION_UP:
13                    magnifier.dismiss();
14                    break;
15                default:
16                    break;
17            }
18            return true;
19        }
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2018-11-09,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 IT先森养成记 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1、Android 9.0应用迁移
    • 1.1 概述
      • 1.2 Android9的迁移和适配
        • 1.3、适配详解(重要部分)
          • 1.4、后续问题
          • 2、新特性介绍(功能及API)
            • 2.1、显示屏缺口支持:layoutInDisplayCutoutMode
              • 2.2、适用于可绘制对象和位图: ImageDecoder
                • 2.3、动画:AnimatedImageDrawable
                  • 2.4、Magnifier(放大镜)
                  相关产品与服务
                  人脸识别
                  腾讯云神图·人脸识别(Face Recognition)基于腾讯优图强大的面部分析技术,提供包括人脸检测与分析、比对、搜索、验证、五官定位、活体检测等多种功能,为开发者和企业提供高性能高可用的人脸识别服务。 可应用于在线娱乐、在线身份认证等多种应用场景,充分满足各行业客户的人脸属性识别及用户身份确认等需求。
                  领券
                  问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档