Android 9.0 适配指南

Android 9.0 适配指南_第1张图片

8月份开始在Google Play上发布的应用必须支持64位架构。可以看到适配工作真的不能像以前一样随心所欲了。

Android适配系列:

  • Android 6.0 的动态权限管理

  • Android 7.0脱坑指南

  • Android 8.0适配指北

2.准备工作

进入正题,首先将我们项目中的targetSdkVersion改为 28。接下来运行你的项目,看有没中枪。

3.网络1.Http请求失败

在9.0中默认情况下启用网络传输层安全协议 (TLS),默认情况下已停用明文支持。也就是不允许使用http请求,要求使用https。

比如我使用的是okhttp,会报错:

java.net.UnknownServiceException: CLEARTEXT communication toxxxx notpermitted bynetwork security policy

解决方法是需要我们添加网络安全配置。首先在 res 目录下新建xml文件夹,添加network_security_config.xml文件:

AndroidManifest.xml中的application添加:

...

以上这是一种简单粗暴的配置方法,要么支持http,要么不支持http。为了安全灵活,我们可以指定支持的http域名:

secure.example.com 

cdn.example1.com 

当然不止这些配置,还有抓包配置、设置自定义CA以及各种场景下灵活的配置,详细的方法可以查看官方文档。

2.Apache HTTP 客户端弃用

在 Android 6.0 时,就已经取消了对 Apache HTTP 客户端的支持。从 Android 9.0 开始,默认情况下该库已从 bootclasspath 中移除。但是耐不住有些SDK中还在使用,比如我见到的友盟QQ分享报错问题。

所以要想继续使用Apache HTTP,需要在应用的 AndroidManifest.xml 文件中添加:

4.前台服务

可以试着搜索一下你的代码,看是否有调用startForegroundService 方法来启动一个前台服务。

startForegroundService 主要来源估计都是 8.0适配时候加上的:

Intent intentService = newIntent( this, MyService. class);

if(android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {

startForegroundService(intentService);

} else{

startService(intentService);

}

9.0 要求创建一个前台服务需要请求 FOREGROUND_SERVICE 权限,否则系统会引发 SecurityException。

java.lang.RuntimeException: Unable to startservice com.weilu.test.MyService@ 81795be withIntent { cmp=com.weilu.test/.MyService }:

java.lang.SecurityException: Permission Denial: startForeground frompid= 28631, uid= 10626requires android.permission.FOREGROUND_SERVICE

atandroid.app.ActivityThread.handleServiceArgs(ActivityThread.java: 3723)

atandroid.app.ActivityThread.access$ 1700(ActivityThread.java: 201)

atandroid.app.ActivityThread$H.handleMessage(ActivityThread.java: 1705)

atandroid.os.Handler.dispatchMessage(Handler.java: 106)

atandroid.os.Looper.loop(Looper.java: 207)

atandroid.app.ActivityThread.main(ActivityThread.java: 6820)

atjava.lang.reflect.Method.invoke( NativeMethod)

atcom.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java: 547)

atcom.android.internal.os.ZygoteInit.main(ZygoteInit.java: 876)

解决方法就是AndroidManifest.xml中添加FOREGROUND_SERVICE权限:

5.启动Activity

在9.0 中,不能直接非 Activity 环境中(比如Service,Application)启动 Activity,否则会崩溃报错:

java.lang.RuntimeException: Unable to createservice com.weilu.test.MyService: android.util.AndroidRuntimeException: CallingstartActivity fromoutside ofan Activity contextrequires the FLAG_ACTIVITY_NEW_TASK flag. Isthis really what you want?

atandroid.app.ActivityThread.handleCreateService(ActivityThread.java: 3578)

atandroid.app.ActivityThread.access$ 1400(ActivityThread.java: 201)

atandroid.app.ActivityThread$H.handleMessage(ActivityThread.java: 1690)

atandroid.os.Handler.dispatchMessage(Handler.java: 106)

atandroid.os.Looper.loop(Looper.java: 207)

atandroid.app.ActivityThread.main(ActivityThread.java: 6820)

atjava.lang.reflect.Method.invoke( NativeMethod)

atcom.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java: 547)

atcom.android.internal.os.ZygoteInit.main(ZygoteInit.java: 876)

这类问题一般会在点击推送消息跳转页面这类场景,解决方法就是 Intent 中添加标志FLAG_ACTIVITY_NEW_TASK,

Intent intent = newIntent( this, TestActivity. class);

intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

startActivity(intent);

6.异形屏适配

这类异形屏叫法很多,刘海屏、水滴屏、挖孔屏、美人尖。。。

  1. 其实如果你的页面不需要全屏显示,那么不需要额外的适配工作。

  2. 如果页面是全屏显示(比如启动页)。为了防止你的内容被遮挡,大部分场景下都是可以使用获取状态栏高度来处理遮挡的适配问题。因为状态栏的高度都是大于等于刘海的高度。

当然,如果你想利用起来刘海区域,就需要获取刘海位置等信息进行适配。在Android 9.0中官方提供了DisplayCutout 类,可以确定刘海区域的位置,国内的部分厂商在8.0就有了自己的适配方案。

具体的我就不过多介绍了,推荐大家看以下文章:

  • Android P 刘海屏适配全攻略

  • Android刘海屏、水滴屏全面屏适配方案

7.权限

首先是权限组的变更:

Android 9.0 适配指南_第2张图片

Android 9.0 适配指南_第3张图片

上图可以看到,在9.0 中新增权限组CALL_LOG 并将 READ_CALL_LOG、WRITE_CALL_LOG 和 PROCESS_OUTGOING_CALLS 权限从PHONE中移入该组。

1.限制访问通话记录

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

2.限制访问电话号码

  • 要通过 PHONE_STATE Intent 操作读取电话号码,同时需要 READ_CALL_LOG 权限和 READ_PHONE_STATE 权限。

  • 要从 PhoneStateListener的onCallStateChanged 中读取电话号码,只需要 READ_CALL_LOG 权限。不需要 READ_PHONE_STATE 权限。

8.其他

  • 在 Android 9 中,调用Build.SERIAL 会始终返回 UNKNOWN 以保护用户的隐私。如果你的应用需要访问设备的硬件序列号,那么需要先请求 READ_PHONE_STATE 权限,然后调用 Build.getSerial。

  • 注意非 SDK 接口的限制。主要是一些热修复、插件化框架涉及比较多,注意及时升级新版本。

  • 多进程使用WebView注意无法共用同一数据目录。详细点击查看

总的来说,9.0的适配工作需要改动和注意的点相比较以前版本的适配来说并不多,从本篇的篇幅就可以看出来,详细的变化可以参看文末的链接。后面如果遇到什么坑,我也会及时补充进来。感谢你的阅读!!

参考

  • Android 9.0 行为变更

  • targetSdkVersion升级28

你可能感兴趣的:(Android问题)