TOC
前言
Android官方的迁移适配文档有点混乱,这篇文章旨在给开发者在适配中对代码做快速检查。适配变化将分为运行版本影响和Target版本影响,并提供可能影响的功能以便测试参考。转载请注明来源「Bug总柴」
Android Q (API level 29)
在Android Q中变化比较大的是对外置sdcard的访问权限变化,这个变化将会影响大部分需要访问外置存储的应用。
沙箱机制解读
external storage在Android Q开始被设置成像internal storage那种只能访问自己包名下的空间,无法直接访问sdcard其他位置内容。就算声明了READ_EXTERNAL_STORAGE权限,在应用中通过File.listFiles只能看到/storage/emulated/0/Android/data/ , /storage/emulated/0/Android/media/ , /storage/emulated/0/Android/obb/ 三个文件夹。
READ_EXTERNAL_STORAGE和WRITE_EXTERNAL_STORAGE的通用访问外置sdcard的权限被拆分为访问音乐READ_MEDIA_AUDIO、照片READ_MEDIA_IMAGES和视频READ_MEDIA_VIDEO三种权限,而访问应用沙箱的内容无需额外申请权限。
沙箱生效时机
如果target版本小于等于28并且应用是安装在从Android 9升级到Andoid Q的手机上,则会启用兼容模式,仍然可以随意访问external存储的内容。
意味着当target版本大于28,或者应用是在Android Q的手机上新安装都会使沙箱机制生效。这里需要说明,不管是否target到28以上,只要是在Android Q上新安装的应用都会使沙箱机制生效。
对于模拟器里面的Andorid Q Beta 1版本,需要执行adb shell sm set-isolated-storage on开启沙箱机制
影响范围
各种为了实现离线使用功能的离线下载文件
各种缓存文件(例如信息流缓存、广告缓存等)
需要注意某些三方库可能会使用外置sdcard(例如log或者crash统计等)
四、处理办法
对于图片视频音乐和下载文件可以通过MediaStore类访问,或者使用Storage Access Framework
对于之前存储在外置sdcard的其他数据,需要迁移存储到getExternalFilesDir目录中
对于新增的文件尽量保存在getExternalFilesDir和getExternalCacheDir
Api检查
Context.getExternalFilesDir(null) -> /storage/emulated/0/Android/data//files
Context.getExternalFilesDir(Environment.DIRECTORY_PICTURES) -> /storage/emulated/0/Android/data//files/Pictures
Context.externalCacheDir -> /storage/emulated/0/Android/data//cache
Context.obbDir -> /storage/emulated/0/Android/obb/
Environment.getExternalStorageDirectory() -> /storage/emulated/0 (沙箱机制下无法访问)
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES) -> /storage/emulated/0/Pictures (沙箱机制下无法访问)
Android 9 (API level 28)
官方行为变更文档
非SDK接口使用限制
使用 veridex 工具测试apk是否有调用非SDK接口
➜ veridex-mac ./appcompat.sh --dex-file= test.apk
实例结果如下:
6889 hidden API( s) used: 6817 linked against, 72 through reflection
0 in blacklistgetConnectionInfo
3 in dark greylist
47 in light greylist
To run an analysis that can give more reflection accesses,
but could include false positives, pass the --imprecise flag.
其中:
类型
描述
blacklist
不管是否target到28,都会报NoSuchMethodError/NoSuchFieldException
dark greylist
如果target在28一下没问题,但是target到28及以上会报NoSuchMethodError/NoSuchFieldException
light greylist
暂时没有问题,可以使用
处理办法:
去除blacklist以及dark greylist的非android sdk调用的反射调用,有些是android support包内部调用的可以考虑升级support包版本
隐私&权限相关
运行在9.0受到影响
可能受到影响的功能
不能在后台访问麦克风和摄像头
后台录音、后台拍照
加速器陀螺仪等传感器不能在后台持续获取数据
步数计算
通过变化模式 或者单次模式 的传感器收不到事件
显著运动检测、计步器、近程传感器和心率传感器
通话记录权限组别由PHONE
组调整到CALL_LOG
组
需要获通过记录权限的功能
通过android.intent.action.PHONE_STATE
或TelephonyManager.listen
方法获取手机号码需要申请READ_CALL_LOG
权限
例如来电归属地显示或者来电拦截等需要获取通话手机号的功能
wifi扫描频率限制更为严格,getConnectionInfo WifiManager.getScanResults()
以及 WifiManager.startScan()
需要而外权限详见
需要wifi扫描匹配等功能
WifiManager.getConnectionInfo()
要获得SSID和BSSID,要求定位权限并要求设备打开定位功能,NETWORK_STATE_CHANGED_ACTION
不再能获得SSID和BSSID
需要获取wifi信息的功能
WifiManager与WifiP2pManager中getScanResults() getConnectionInfo()
和discoverServices() addServiceRequest()
和NETWORK_STATE_CHANGED_ACTION
不再包含用户定位信息
使用wifi定位功能
TelephonyManager
中getAllCellInfo() listen() getCellLocation() getNeighboringCellInfo() 不返回结果,除非用户打开了定位功能
使用移动信号定位
Target在9.0受到影响
可能受到影响的功能
启动前台服务要去注册android.permission.FOREGROUND_SERVICE
权限
前台服务启动
获取序列号不能通过Build.SERIAL,需要注册android.permission.READ_PHONE_STATE
然后使用Build.getSerial()
获取序列号相关功能
安全相关
运行在9.0受到影响
可能受到影响的功能
SSLSocket
出错不返回NullPointerException
,改成返回IOException
https网络错误处理
加密函数Cipher.getInstance("AES/CBC/PKCS7PADDING", "BC")
Cipher.getInstance("AES/CBC/PKCS7PADDING",Security.getProvider("BC"))
SecureRandom.getInstance("SHA1PRNG", "Crypto");
移除
加密功能
Android secure encrypted files移除
移动app到sdcard功能
Target在9.0受到影响
可能受到影响的功能
DNS客户端需要根据系统使用加密DNS查找与系统相同的主机名,或改由系统解析程序
DNS自解析功能
默认要求使用https,如果需要使用http需要设置cleartextTrafficPermitted="true"
详见
所有http网络请求
webview的数据包括cookies和caches不允许多进程共享
多进程使用webview
不用通过设置全局Unix权限共享数据文件,不用应用的文件共享需要使用ContentProvider
应用间文件共享
国际化相关
运行在9.0受到影响
可能受到影响的功能
java.text.SimpleDateFormat
使用zzzz
格式、java.text.DateFormatSymbols.getZoneStrings()
格式、NumberFormat.getInstance(ULocale, PLURALCURRENCYSTYLE).parse(String)
格式修改
时区、货币显示相关功能
网络相关
Target在9.0受到影响
可能受到影响的功能
NetworkStatsManager
能获取非当前正在使用的流量情况
网络使用统计
ConnectivityManager.getMultipathPreference()
可以获取是否超过了移动流量使用限制
网络使用情况提醒
Apache Http背去除,要使用需要加上<uses-library android:name="org.apache.http.legacy" android:required="false"/>
或者想apache.http相关类包通过jar方式引入
使用旧Apache Http client网络功能
界面相关
运行在9.0受到影响
可能受到影响的功能
通过非activity的context启动activity强制要求intent带上FLAG_ACTIVITY_NEW_TASK
后台启动页面
屏幕旋转方式由原来的“自动旋转”和“纵向”改为“自动旋转”和“固定旋转”
屏幕旋转功能
Target在9.0受到影响
可能受到影响的功能
长或宽为0的view不再可以获取焦点,新开页面不默认获取焦点
交互过程通过特殊焦点实现的功能
webview可以支持带透明度的8位颜色css
webview css 颜色透明度功能
webview中document的root元素滚动位置得到支持
webview 相关
暂停挂起app的通知会在app resumed之后重新通知
通知相关
设备相关
运行在9.0受到影响
可能受到影响的功能
多摄像头支持getCameraIdList()
前后摄像头切换需要选择合适的摄像头
摄像头相关功能
其他
运行在9.0受到影响
可能受到影响的功能
UTF-8解码更加严格按照Unicode标准详见
UTF-8解码相关的功能
实用参考地址
权限组级别
Android 8 (API level 26)
官方行为变更文档
后台限制
隐私&权限相关
运行在8.0受到影响
可能受到影响的功能
ANDROID_ID 从之前的仅与设备相关,改为与应用签名、设备、设备登录用户相关。
使用ANDROID_ID
的功能
获取系统属性net.hostname
将返回null
wifi hostname获取功能
Target在8.0受到影响
可能受到影响的功能
系统属性net.dns*
不再支持
通过系统属性获取dns功能
需要获取DNS信息需要ACCESS_NETWORK_STATE
权限,通过NetworkRequest 或者NetworkCallback 获取
DNS获取功能
获取序列号不能通过Build.SERIAL,需要注册android.permission.READ_PHONE_STATE
然后使用Build.getSerial()
获取序列号相关功能
LauncherApps 获取不同用户的应用信息时,会当做没有任何应用安装,而不是抛出异常
桌面启动器相关功能
相同权限组的其他权限会在真正需要时才被自动授予,之前是整个权限组同时授予
权限授予相关
安全相关
运行在8.0受到影响
可能受到影响的功能
不再支持SSLv3
使用SSLv3的地方
当HTTPS使用错误的TLS协议与服务交互时,不再使用其他TLS协议重试
HTTPS相关
在bionic之外的系统调用将被禁止
bionic系统调用
WebView被运行在多进程空间
WebView间数据共享
APKs安装路径可能会被修改
APKs管理
判断是否能安装应用需使用PackageManager.canRequestPackageInstalls() ,INSTALL_NON_MARKET_APPS
失效
应用安装
8.0系统默认禁止应用安装未知应用
应用安装功能
Thread.UncaughtExceptionHandler
会记录在stacktrace中,但不会杀死应用
线程异常处理
国际化相关
网络相关
运行在8.0受到影响
可能受到影响的功能
无正文的 OPTIONS 请求具有 Content-Length: 0 头部
options请求相关
HttpURLConnection会保证请求最后带上“/”
HttpURLConnection
ProxySelector.setDefault()
设置的代理仅处理scheme/host/port,不会处理请求参数
代理设置相关功能
不再支持空lable的URI
使用URI相关功能
HttpsURLConnection不会执行不安全的TLS/SSL协议版本回退
HttpsURLConnection
隧道Https协议改变,具体见Networking and HTTP(S) connectivity
隧道Https
如果DatagramSocket.connect()
返回错误,DatagramSocket.send() 也会返回错误
socket相关
InetAddress.isReachable()
会在会退到TCP Echo协议之前尝试ICMP协议,若不可达会消耗更多时间
IP地址判断是否可达等网络功能
在支持设备上wifi连接当有强度大且已经保存的网络时可以自动切换
需保证网络切换不会影响应用功能
界面相关
设备相关
Target在8.0受到影响
可能受到影响的功能
音频获取焦点时会自动降低其他音频音量,现在支持暂停而不是降低音量,详见automatic ducking
音频播放相关功能
当来电时,自动静音音频播放
音频播放相关功能
需要使用AudioAttributes 实现音频回放功能,AudioTrack 过期
音频回放功能
音量按键事件会优先给前台activity,如果前台activity不处理会给最近一次播放音频的应用
音量控制
其他