Android P 9.0特性及适配

一、前言

Android P 在Google IO2018就正式发版了,随着用户设备升级和项目升级,Android P的使用者越来越多。

Android P (9.0,API级别 28),引入了许多新特性和新功能。本文重点介绍面向开发者的新功能。

主要内容有以下几项:

  • 刘海屏适配
  • 利用Wi-Fi RTT进行室内定位
  • 通知栏功能增强
  • 限制访问通话记录和电话号码
  • 对使用非 SDK 接口的限制和适配策略
  • 多摄像头支持和摄像头更新
  • 非Activity-Context启动Activity
  • Apache HTTP 客户端弃用,影响采用非标准 ClassLoader 的应用
  • 前台服务
  • 限制隐式广播

关于具体的API变更的,可以戳官网说明 ->  Android P API差异报告

二、特性及适配

1、刘海屏适配

Android 9 支持最新的全面屏,其中包含为摄像头和扬声器预留空间的屏幕缺口。 通过 DisplayCutout 类可确定非功能区域的位置和形状,这些区域不应显示内容。 要确定这些屏幕缺口区域是否存在及其位置,使用 getDisplayCutout()函数。

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 为设备屏幕缺口周围的内容进行布局。 可以将此属性设为下列值之一:

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,会延伸过去;若cutout在长边,一定不会延伸过去。
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在长边有cutout的情况,会排出在外。


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

2、利用Wi-Fi RTT进行室内定位

Android 9增加了对IEEE 802.11mc Wi-Fi协议(也称为Wi-Fi往返时间(RTT))的平台支持,从而让您的应用可以利用室内定位功能,简单理解就是一种利用室内无线电波(WIFI)、磁场、声音信号或移动设备收集的其他感觉信息来定位建筑物内物体或人的技术。 

在运行 Android 9 且具有硬件支持的设备上,应用可以使用 RTT API 来测量与附近支持 RTT 的 Wi-Fi 接入点 (AP) 的距离。 设备必须已启用位置服务并开启 Wi-Fi 扫描(在 Settings > Location 下),同时您的应用必须具有 ACCESS_FINE_LOCATION 权限。设备无需连接到接入点即可使用 RTT。 

3、通知栏功能增强

Android 8.0 引入了通知渠道,允许您为要显示的每种通知类型创建可由用户自定义的渠道。 Android 9 通过下列变更简化通知渠道设置:

  • 屏蔽渠道组:现在,用户可以针对某个应用在通知设置中屏蔽整个渠道组。 您可以使用 isBlocked() 函数确定何时屏蔽一个渠道组,从而不会向该组中的渠道发送任何通知。
    此外,您的应用可以使用全新的 getNotificationChannelGroup() 函数查询当前渠道组设置。

  • 全新的广播 Intent 类型:现在,当通知渠道和渠道组的屏蔽状态发生变更时,Android 系统将发送广播 Intent。 拥有已屏蔽的渠道或渠道组的应用可以侦听这些 Intent 并做出相应的回应。 有关这些 Intent 操作和 extra 的更多信息,请参阅 NotificationManager 参考中更新的常量列表。 有关响应广播 Intent 的信息,请参阅广播。

  • NotificationManager.Policy 有 3 种新的“请勿打扰”优先级类别:

  • PRIORITY_CATEGORY_ALARMS优先处理警报。

  • PRIORITY_CATEGORY_MEDIA 优先处理媒体源的声音,如媒体和语音导航。

  • PRIORITY_CATEGORY_SYSTEM 优先处理系统声音。

  • NotificationManager.Policy 还有 7 种新的“请勿打扰”常量,可以用来抑制视觉中断:

  • SUPPRESSED_EFFECT_FULL_SCREEN_INTENT 防止通知启动全屏 Activity。

  • SUPPRESSED_EFFECT_LIGHTS 屏蔽通知灯。

  • SUPPRESSED_EFFECT_PEEK 防止通知短暂进入视图(“滑出”)。

  • SUPPRESSED_EFFECT_STATUS_BAR 防止通知显示在支持状态栏的设备的状态栏中。

  • SUPPRESSED_EFFECT_BADGE 在支持标志的设备上屏蔽标志。 如需了解详细信息,请参阅修改通知标志。

  • SUPPRESSED_EFFECT_AMBIENT 在支持微光显示的设备上屏蔽通知。

  • SUPPRESSED_EFFECT_NOTIFICATION_LIST 防止通知显示在支持列表视图(如通知栏或锁屏)的设备的列表视图中。

4、限制访问通话记录

Android 9 引入 CALL_LOG 权限组并将 READ_CALL_LOGWRITE_CALL_LOG  PROCESS_OUTGOING_CALLS 权限移入该组。 在之前的 Android 版本中,这些权限位于 PHONE 权限组。

如果应用需要访问通话记录或者需要处理去电,则您必须向 CALL_LOG 权限组明确请求这些权限。 否则会发生 SecurityException。

5、限制访问电话号码

在未首先获得 READ_CALL_LOG 权限的情况下,除了应用的用例需要的其他权限之外,运行于 Android 9 上的应用无法读取电话号码或手机状态。

与来电和去电关联的电话号码可在手机状态广播(比如来电和去电的手机状态广播)中看到,并可通过 PhoneStateListener 类访问。 但是,如果没有 READ_CALL_LOG 权限,则 PHONE_STATE_CHANGED 广播和 PhoneStateListener提供的电话号码字段为空</mark>。

要从手机状态中读取电话号码,请根据您的用例更新应用以请求必要的权限:

  • 要通过 PHONE_STATE Intent 操作读取电话号码,同时需要 READ_CALL_LOG 权限和 READ_PHONE_STATE 权限
  • 要从 onCallStateChanged() 中读取电话号码,只需要 READ_CALL_LOG 权限。 不需要 READ_PHONE_STATE 权限

6、对使用非 SDK 接口的限制和适配策略

为帮助确保应用稳定性和兼容性,此平台对某些非 SDK 函数和字段的使用进行了限制;无论您是直接访问这些函数和字段,还是通过反射或 JNI 访问,这些限制均适用。 在 Android 9 中,您的应用可以继续访问这些受限的接口;该平台通过 toast 和日志条目提醒您注意这些接口。 如果您的应用显示这样的 toast,则必须寻求受限接口之外的其他实现策略。 如果您认为没有可行的替代策略,您可以提交错误以请求重新考虑此限制。

对于非SDK 接口

  • 浅灰名单:仍可以访问的非 SDK 函数/字段。
  • 深灰名单:
    对于目标 SDK 低于 API 级别 28 的应用,允许使用深灰名单接口。
    对于目标 SDK 为 API 28 或更高级别的应用:行为与黑名单相同。
  • 黑名单:受限,无论目标 SDK 如何
    平台将提示接口并不存在。
    例如,无论应用何时尝试使用接口,平台都会引发 NoSuchMethodError/NoSuchFieldException,即使应用想要了解某个特殊类别的字段/函数名单,平台也不会包含接口。

检测是否使用了非SDK接口

  1. 下载工具,阅读README.txt
  2. 打包一个应用 APK,建议使用 release 包,排除一些未使用到的单元测试类或者其他因素的影响,取消混淆,将 APK 放到工具目录下;
  1. 执行命令 ./appcompat.sh --dex-file=test.apk,在终端上会输出三个名单每个 API 的详细调用处

非 SDK API 的处理

适配的原则是优先黑名单和深灰名单,浅灰名单在官方未有替代 API 之前可以暂时不适配,在 Android P 上运行也不会有任何问题。

  1. 向google申请
    在之前 DP 版本时开发者如果遇到了不得不使用的黑名单或者深灰名单 API,需要向 google 官方及时提出反馈 (反馈url)申请将其移动到浅灰名单中,但是目前正式版本已经发布,未得知该申请通道是否仍有效。
  2. 针对第三方库调用到了非 SDK API 接口,解决办法当然是直接查询相关资料或者联系库提供方,确认是否有适配 Android P 新版本的 SDK。还有需要提到的一点,就算更换适配完成的第三方 SDK 后,仍然可能会在同一地方扫描出非 SDK API 的调用,这是因为适配工程师只是在调用处加了一个 try-catch 保护逻辑,虽然这样也勉强叫做适配完成,但是还是强烈建议大家使用如下的适配方式:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
// Android P or above
} else {
// below Android P
}

严格按照上面的适配方案,扫描工具就不会再扫描出此处的非 SDK API 调用,我们也无需每次都去确认所有非 SDK API 调用处都加了保护逻辑。
当然如果第三方库没有适配也没有近期适配的意向,目前有两种方法:第一种是屏蔽入口;第二种是反编译 SDK,在关键地方加上适配代码;

7、多摄像头支持和摄像头更新

在运行 Android 9 的设备上,您可以通过两个或更多物理摄像头来同时访问多个视频流。 在配备双前置摄像头或双后置摄像头的设备上,您可以创建只配备单摄像头的设备所不可能实现的创新功能,例如无缝缩放、背景虚化和立体成像。 通过该 API,您还可以调用逻辑或融合的摄像头视频流,该视频流可在两个或更多摄像头之间自动切换。

摄像头方面的其他改进还包括附加会话参数和 Surface 共享,前者有助于降低首次拍照期间的延迟,而后者则让摄像头客户端能够处理各种用例,而无需停止并启动摄像头视频流。 我们还针对基于显示屏的 flash 支持和 OIS 时间戳访问新增了一些 API,用以实现应用级的图像稳定化和特效。

在 Android 9 中,多摄像头 API支持单色摄像头,适用于具有 FULL 或 LIMITED 功能的设备。 单色输出通过 YUV_420_888 格式实现,Y 为灰度,U (Cb) 为 128,V (Cr) 为 128。

在受支持的设备上,Android 9 还支持外置 USB/UVC 摄像头。

8、限制非Activity场景启动Activity

 从Android 9.0开始,只有当Intent flag中指定了FLAG_ACTIVITY_NEW_TASK,才允许在非Activity场景启动Activity。如果不在Intent添加FLAG_ACTIVITY_NEW_TASK,将无法通过非Activity的Context启动一个Activity,并且会抛异常。

9、http网络请求的问题

当API级别为28及以上时,应用使用的如果是非加密的明文流量的http网络请求,则会导致该应用无法进行网络请求,https则不会受影响。

有三种解决方法:

1)APP改用https请求

2)targetSdkVersion 降到27及以下

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

<?xml version="1.0" encoding="utf-8"?>

<network-security-config>
    <base-config cleartextTrafficPermitted="true" />
</network-security-config>

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

<application
       android:name=".App"
       android:icon="@mipmap/ic_launcher"
       android:label="@string/app_name"
       android:networkSecurityConfig="@xml/network_security_config"
       android:roundIcon="@mipmap/ic_launcher_round"
       android:theme="@style/AppTheme"></application>
/>

10、前台服务

针对 Android 9 或更高版本并使用前台服务的应用必须请求 FOREGROUND_SERVICE 权限。 这是普通权限,因此,系统会自动为请求权限的应用授予此权限。

如果针对 Android 9 或更高版本的应用尝试创建一个前台服务且未请求 FOREGROUND_SERVICE,则系统会引发 SecurityException。

11、限制静态广播的接收

升级安卓9.0之后,隐式广播将会被全面禁止,在AndroidManifest中注册的Receiver将不能够生效。

现在需要在应用中进行动态注册。

 

其他更多特性,可戳 -> Android 9 功能和 API

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

KWMax

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值