官方明确指出:目标是在限制使用非 SDK 接口之前确保有可用的公开替代方案。
反射或JNI必须要有替代方案!
如果您不打算以 Android Q 为目标平台,那么其中一些变更可能不会立即对您产生影响。虽然您目前可以使用灰名单中的一些非 SDK 接口(取决于您应用的目标 API 级别),但如果您使用任何非 SDK 方法或字段,则应用无法运行的风险终归较高。
要了解详情,请参阅非 SDK 接口在 Android Q 中的受限情况出现变化以及针对非 SDK 接口的限制。
从 Android Q 开始,增加 手势导航 功能。
若启用手势导航,则会影响设备上的所有应用,无论应用是否以 Android Q 为目标平台,都是如此。
例如,如果用户从屏幕边缘向内滑动,系统会将该手势解读为“返回”导航,除非应用针对屏幕的相应部分明确替换该手势。
导航栏区域,系统手势区域,可能需要将这些重叠区域排除出去。
为了确保App与手势导航兼容,您需要将应用内容扩展到屏幕边缘,并适当地处理存在冲突的手势。有关信息,请参阅手势导航文档。
从 Android Q 开始,共享对象不得包含文本重定位被强制执行
从 Android Q 开始,多个路径不再采用常规文件形式,而是采用符号链接形式。如果应用一直以来依赖的都是采用常规文件形式的路径,则可能会出现故障:
这些变更也会影响文件的 64 位版本,对于这些版本,会将 lib/ 替换为 lib64/。
为了确保兼容性,新符号链接会基于旧路径提供,例如 /system/lib/libc.so 现在是指向 /apex/com.android.runtime/lib/bionic/libc.so 的符号链接,等等。因此,dlopen(“/system/lib/libc.so”) 会继续工作,但当应用尝试通过读取 /proc/self/maps 或类似项来检测已加载的库时,将会发现不同之处。这并不常见,但我们发现一些应用会将这种做法作为对抗黑客攻击的一项举措。如果是这样,则应该将新的 /apex/… 路径添加为 Bionic 文件的有效路径。
从 Android Q 开始,系统二进制文件和库会映射到只执行(不可读取)内存,作为应对代码重用攻击的安全强化技术。有意或意外读入已标记为只执行的内存段会抛出 SIGSEGV,无论此读入行为是来自错误、漏洞还是有意的内存自省都不例外。
您可以通过检查 /data/tombstones/ 中的相关 tombstone 文件来确定崩溃是否由变更改所导致。与只执行相关的崩溃包含以下中止消息:
Cause: execute-only (no-read) memory access error; likely due to data in .text.
要解决此问题,开发者可以通过调用 mprotect() 将只执行内存段标记为**“读取+执行”**,例如用于执行内存检查。不过,我们强烈建议您事后将其重新设为只执行,因为这样可以更好地保护您的应用和用户。
对 ptrace 的调用不会受到影响,因此 ptrace 调试也不会受到影响。
以 Android Q 为targetApi的不受信任的应用,无法再针对应用主目录中的文件调用 exec()。这种从可写应用的主目录执行文件的行为违反了 W^X。
应用应该仅加载嵌入到应用的 APK 文件中的二进制代码。
也就是说下载到应用目录的文件,无法被exec()。
此外,以 Android Q 为目标平台的应用无法针对已执行 dlopen() 的文件中的可执行代码进行内存中修改
。这包括含有文本重定位的所有共享对象 (.so) 文件。
在 Android Q 中,以下与 WLAN 直连相关的广播不再具有粘性(sticky)。
Android Q 扩大了支持范围,现在可以使用 WLAN 感知数据路径轻松创建 TCP/UDP 套接字。
服务器可以执行以下任一操作:
在 Android Q(Go 版本)设备上运行的应用无法获得 SYSTEM_ALERT_WINDOW 权限
。
这是因为绘制叠加层窗口会使用过多的内存
,这对低内存 Android 设备的性能十分有害。
如果在搭载 Android 9 或更低版本的 Go 版设备上运行的应用获得了 SYSTEM_ALERT_WINDOW 权限,则即使设备升级到 Android Q 也会保留此权限
。不过,尚不具有此权限的应用在设备升级后便无法获得此权限了。
如果 Go 设备上的应用发送具有 ACTION_MANAGE_OVERLAY_PERMISSION 操作的 intent,则系统会自动拒绝此请求
,并将用户转到设置
屏幕,上面会显示不允许授予此权限,原因是它会减慢设备的运行速度。如果 Go 设备上的应用调用 Settings.canDrawOverlays(),则此方法始终返回 false。同样,这些限制不适用
于在设备升级到 Android Q 之前便已收到 SYSTEM_ALERT_WINDOW 权限的应用
。
在 Android Q 中,当用户首次运行以 Android 6.0(API 级别 23)以下的版本为目标平台的任何应用时,Android 平台会向用户发出警告
。如果此应用要求用户授予权限,则系统会先向用户提供调整应用权限的机会,然后才会允许此应用首次运行。
由于 Google Play 的目标 API 方面的要求,用户只有在运行最近未更新的应用时才会看到这些警告。对于通过其他商店分发的应用,我们也将于 2019 年引入类似的目标 API 方面的要求。要详细了解这些要求,请参阅在 2019 年扩展目标 API 级别方面的要求。
以下 SHA-2 CBC 加密套件已从平台中移除:
这些加密套件不如使用 GCM 的类似加密套件安全,并且大多数服务器要么同时支持这些加密套件的 GCM 变体和 CBC 变体,要么二者均不支持。
注意:应用和库应该让其所需的加密套件集与 getSupportedCipherSuites() 中返回的值相交,以便提前防范加密套件日后遭到移除。
Android Q 引入了与应用使用情况相关的以下行为变更:
UsageStats 应用使用情况的改进
按应用开启灰度模式
按应用开启干扰模式
暂停和播放
android.preference 库现已弃用。开发者应该改为使用 AndroidX preference 库,这是Android Jetpack 的一部分。如需获取其他有助于迁移和开发的资源,请查看经过更新的设置指南以及我们的公开示例应用和参考文档。
Android Q 对 java.util.zip 软件包(用于处理 ZIP 文件)中的类做出了以下变更。这些变更会让库的行为在 Android 和使用 java.util.zip 的其他平台之间更加一致。
在以前的版本中,如果在调用 end() 之后调用 Inflater 类中的某些方法,这些方法会抛出 IllegalStateException。在 Android Q 中,这些方法会抛出 NullPointerException。
如果所提供的 ZIP 文件不包含任何文件,则 ZipFile 的构造函数(采用的参数类型为 File、int 和 Charset)不再抛出 ZipException。
如果 ZipOutputStream 中的 finish() 方法尝试为不包含任何文件的 ZIP 文件写入输出流,此方法不再抛出 ZipException。
很多使用摄像头的应用都会假定如果设备采用纵向配置,则物理设备也会处于纵向,正如摄像头方向中所述。在过去可以做出这样的假定,但在推出新型设备(例如可折叠设备)后,这发生了变化。针对这些设备做出这样的假定可能导致相机取景器的显示产生错误的旋转和/或缩放。
以 API 级别 24 或更高级别为目标平台的应用应该明确设置 android:resizeableActivity,并提供必要的功能来处理多窗口操作。
从 Android Q 开始,只有在发生重大充电事件之后拔下设备电源插头,SystemHealthManager 才会重置其电池用量统计信息。
一般来说,重大充电事件指的是设备电池已充满,或者设备电量从几乎耗尽变为即将充满。
在 Android Q 之前,无论何时拔下设备电源插头,无论电池电量有多微小的变化,电池用量统计信息都会重置。