Android 8.0系统API问题适配和学习

android 8.0在系统性能和安全性上做了一些优化,而这些API上的改动,对我们软件也带来一部分影响,下面简要说明一些我的软件测试和适配

一、Android 8.0遇到的问题

1. 线程中断:

  • 描述:软件中一个长期挂载执行的命令轮询线程,中断了,
  • 原因:Android 8.0判断软件未活跃状态,是否软件持有的所有Wake Lock,恰巧线程中调用的Lock.wait,同步锁,被系统唤醒后,线程结束
  • 处理:增加运行标签,重新启动线程机制,增加sleep机制

2. invalid pthread_t 0x2243df2546 passed to libc

  • 描述: 在JNI运行中报错,invalid pthread_t passed to libc,查看代码发现,在调用pthread_join()方法时报错
  • 原因:
    • 检测到线程队列指针为空的情况下还去调用分离线程会出现异常,在pthread_join中会调用__pthread_internal_find,https://github.com/aosp-mirror/platform_bionic/blob/master/libc/bionic/pthread_join.cpp
    • 在__pthread_internal_find方法时https://github.com/aosp-mirror/platform_bionic/blob/master/libc/bionic/pthread_internal.cpp
      Android 8.0系统API问题适配和学习_第1张图片
      image
  • 处理:经检测发现,由于c++代码中不严谨的写法导致了该问题,未启动线程(未传入线程指针)前,调用了pthread_join的方法,在以前的版本中,软件没有崩溃,所以没有检测到,修改后无问题

二、改动:(这一切都是基于targetApi=26)

  1. 在新版的gradle要求中,软件在2018年底google市场强制要求,软件targetApi=26,一些简单的代码改动,如依赖包写法等,不提

  2. 后台执行限制:这一点很重要,android 8.0为了提高电池续航能力,增加机制如下

    • 当应用没有任何活跃的组件而进入到缓存状态时,系统将会释放所有应用所持有的Wake Lock

    • 后台应用访问后台服务自由度降低

    • 应用不能用manifests注册隐式广播

    • 部分注意点:

      • targetApi=26的应用,在没有创建后台服务的权限时调用startService()会抛出异常IllegalStateException
      • 新方法Context.startForegroundService()会开启一个前台服务。后台应用也可以调用这个方法,但是在服务创建之后5秒钟之内必须调用startForeground()
  3. 位置更新频率限制:受影响API:

    • Fused Location Provider (FLP)
    • Geofencing
    • GNSS Measurements
    • Location Manager
    • Wi-Fi Manager
  4. 安全性

    • 不再支持SSLv3
    • 当对一个服务器建立HTTPS连接时,如果服务器没有正确实现TSL协议版本,HttpsURLConnection不再回退到之前版本再次尝试
    • 安卓8.0对所有应用程序都使用了SECCOMP过滤器,限制了可以使用的syscall为bionic暴露的syscall。尽管由于后向兼容的原因,还有其他可以使用的syscall,但安卓强烈反对开发者使用这些syscall
    • Webview对象运行在多进程模式。为了提供更好的安全性,网页内容会在一个应用进程外的独立进程处理
    • APK不一定在以“-1”或者“-2”结尾的文件夹中。应用应该使用sourceDir获得路径,不应该直接使用文件夹的格式
  5. 隐私性

    • 对于升级到8.0之前安装的应用,ANDROID_ID会保持不变。如果卸载后重新安装的话,ANDROID_ID将会改变。如果想保存卸载之前的ANDROID_ID的值,可以使用Key/Value Backup将老值和新值关联起来。
    • 对于安装在8.0系统的应用来说,ANDROID_ID根据应用签名和用户的不同而不同。ANDROID_ID唯一决定于应用签名、用户和设备三者的组合。
    • 只要应用签名不变,卸载再安装应用不会改变ANDROID_ID
    • 有Google Play服务的设备可以使用Advertising ID,其他设备应该继续使用ANDROID_ID
    • 访问net.hostname会返回null
  6. 内容改变通知

    • 安卓8.0改变了ContentResolver.notifyChange(Uri, ContentObserver)和registerContentObserver(Uri, boolean, ContentObserver)的行为。这些接口要求Uri中的authority背后真实定义了一个有效的ContentProvider。
  7. 权限

    • 应用将只被授予其申请的权限。但是,如果应用之后再申请同一权限组中的其他权限时,将自动被授予
        例如,应用在Manifest里同时注册了READ_EXTERNAL_STORAGE和WRITE_EXTERNAL_STORAG两个权限。在targetApi=25或之前的版本中,当应用请求READ_EXTERNAL_STORAGE权限并且用户授权了之后,
                    系统会自动授予WRITE_EXTERNAL_STORAG权限,因为READ_EXTERNAL_STORAGE和WRITE_EXTERNAL_STORAG同属STORAGE权限组其都在manifest里注册了。但在安卓8.0系统中,只有READ_EXTERNAL_STORAGE会被授权,但是当应用再次申请WRITE_EXTERNAL_STORAG权限时,系统会不提示用户直接授权。
  1. 类加载

    • 系统会检查类加载器返回的类描述符是否匹配期望的类描述符,如果描述符不匹配,系统会抛出NoClassDefFoundError错误,并且会在异常中记录详细信息。
    • 系统还会检查描述符是否有效。这个检查会捕获由于JNI调用间接加载类的方法(如GetFieldID())中无效的描述符引起的错误。例如,签名中java/lang/String的字段是无法找到,因为这不是一个有效的签名。正确的签名应该为Ljava/lang/String;。
    • DexFile API已经被废弃了,强烈建议开发者使用包括PathClassLoader和BaseDexClassLoader在内的系统类加载器。

你可能感兴趣的:(Android 8.0系统API问题适配和学习)