Android 14 应用兼容性适配指导
根据谷歌的时间表,Android 14将于2023年第三季度发布。在第三季度最终发布之前,将有2个开发者预览和4个Beta。Android 14将与34级框架API一起发布。目前应用验证需要设置SDK为UpsideDownCake:我们会在后续的发布中和大家分享更多的14带来的特性解读。请阅读此文
Google 版本发布时间表
Android 14 开发者网站
developer.android.google.cn/about/versi…
下载和安装
developer.android.google.cn/about/versi…
发布时间表
developer.android.com/about/versi…
Android 14 云真机
兼容性调试工具
Android 11开始引入了新的工具,可针对Android新平台中的行为变更进行测试和调试。这些工具是兼容性框架的一部分,该框架使得开发者可通过开发者选项或adb命令单独打开和关闭各项变更。藉此,可在最新android预览版中测试我们的app受到新平台及target api调整的影响,完成app对新平台的兼容适配。
使用开发者选项启用或停用变更
您可以使用开发者选项启用或停用变更。如需找到开发者选项,请按以下步骤操作:
1、如果开发者选项尚未启用,请启用开发者选项。
2、打开设备的“设置”应用,导航到系统 > 开发者选项 > 应用兼容性变更。
3、从列表中选择您的应用。
4、在变更列表中,找到想要开启或关闭的变更,然后点按相应的开关。
使用adb命令打开或关闭变更
请运行以下相应的命令:
adb shell am compat enable (CHANGE_ID|CHANGE_NAME) PACKAGE_NAME
adb shell am compat disable (CHANGE_ID|CHANGE_NAME) PACKAGE_NAME
您需要传递 CHANGE_ID(例如 119147584)或 CHANGE_NAME(例如 CALLBACK_ON_CLEAR_CHANGE)以及应用的 PACKAGE_NAME。
您也可以使用以下命令将变更重置回默认状态,移除您使用 adb 或开发者选项设置的任何替换状态:
adb shell am compat reset (CHANGE_ID|CHANGE_NAME) PACKAGE_NAME
切换变更的启用/停用状态的限制
每当使用开发者选项或adb命令切换应用变更时,应用都会被杀死,以确保覆盖立即生效。
由于切换变更的开启或关闭可能导致应用崩溃或禁用重要的安全变更,为防止恶意使用兼容性框架,在何时切换变更会存在一些限制。是否可以切换变更,取决于变更的类型,应用是否可调试(app:debuggable)以及设备上运行的版本类型。
下表是限制情况:
具体说明及使用方法见:
developer.android.google.cn/guide/app-c…
Android 14 新增变更
Default State | 变更 ID | 内容 | |
---|---|---|---|
ACCESS_SHARED_IDENTITY | Enabled for all apps | 259743961 | Grants access to the launching app’s identity if the app opted-in to sharing its identity by launching this activity with an instance of ActivityOptions on which ActivityOptions.setShareIdentityEnabled(boolean) was invoked with a value of true, or if the launched activity’s uid is the same as the launching app’s. When this change is enabled and one of these requirements is met, the activity can access the launching app’s uid and package name with Activity.getLaunchedFromUid() and Activity.getLaunchedFromPackage(), respectively. |
OVERRIDE_MIN_ASPECT_RATIO_PORTRAIT_ONLY | Enabled for all apps | 203647190 | When OVERRIDE_MIN_ASPECT_RATIO is also enabled, enabling this change for a package limits any other changes that force an activity’s minimum aspect ratio to a certain value—such as OVERRIDE_MIN_ASPECT_RATIO_LARGE and OVERRIDE_MIN_ASPECT_RATIO_MEDIUM—to activities that also have a portrait orientation. |
AUTHORITY_ACCESS_CHECK_CHANGE_ID | Enabled for apps that target Android 14 or higher. | 207133734 | For apps targeting Android 14 and higher, enables checking for authority access for the calling uid on all sync-related APIs. |
DETACH_THROWS_ISE_ONLY | Enabled for apps that target Android 14 or higher. | 207133734 | Flag to gate correct exception thrown by #detachImage. #detachImage is documented as throwing IllegalStateException in the event of an error; a native helper method to this threw RuntimeException if the surface was abandoned while detaching the Image. This previously undocumented exception behavior continues through Android 13 (API level 33). After Android 13 (API level 33), the native helper method only throws IllegalStateExceptions in accordance with the documentation. When this change is enabled, #detachImage only throws an IllegalStateException if it runs into errors while detaching the image. Behavior remains unchanged for apps targeting Android 13 (API level 33) and lower. |
ENFORCE_PACKAGE_VISIBILITY_FILTERING | Enabled for apps that target Android 14 or higher. | 154726397 | For apps targeting Android 14 and higher, requires apps to declare package visibility needs in the manifest in order to access the AccountManager APIs. |
ENFORCE_READ_ONLY_JAVA_DCL | Enabled for apps that target Android 14 or higher. | 218865702 | For apps targeting Android 14 and higher, requires all dynamically-loaded files to be marked as read-only. This prevents files that are dynamically loaded from being unexpectedly overwritten by malicious actors. |
IMPLICIT_INTENTS_ONLY_MATCH_EXPORTED_COMPONENTS | Enabled for apps that target Android 14 or higher. | 229362273 | For apps targeting Android 14 and higher, components must be exported in order to invoke them through implicit intents. If a component is not exported and invoked, it will be removed from the list of receivers. This applies specifically to activities and broadcasts. |
REQUIRE_NETWORK_CONSTRAINT_FOR_NETWORK_JOB_WORK_ITEMS | Enabled for apps that target Android 14 or higher. | 241104082 | For apps targeting Android 14 and higher, requires the hosting job to specify a network constraint if the included JobWorkItem indicates network usage. |
THROW_ON_INVALID_DATA_TRANSFER_IMPLEMENTATION | Enabled for apps that target Android 14 or higher. | 255371817 | For apps targeting Android 14 and higher, the system throws an exception if an app doesn’t properly implement all the necessary data transfer APIs. |
详细了解Android具体变更:
developer.android.google.cn/about/versi…
安全与隐私相关
Android 14 在安全与隐私方面做了很大努力。对三方应用有很大的影响,需要各应用去主动适配;
精准闹铃
从 Android 14 开始,SCHEDULE_EXACT_ALARM 权限不再预先授予,大多数新安装的针对 Android 13 及更高版本的应用程序——该权限默认情况下被拒绝。SCHEDULE_EXACT_ALARM 是Android 12中为应用程序安排精确alrm而引入的权限。
对用户影响
可能受影响的public API接口如下:
1、AlarmManager.setExactAndAllowWhileIdle( int , long , PendingIntent )
2、AlarmManager.setExact( int , long , PendingIntent )
3、AlarmManager.setExact( int , long , String , OnAlarmListener , Handler )
4、AlarmManager.setAlarmClock( AlarmClockInfo , PendingIntent )
目标平台android 13及以上的应用,有调用这些接口,如果没有配置Manifest.permission.SCHEDULE_EXACT_ALARM权限,将会调用失败。
影响范围
1)老版本OTA升级到Android U,先前如果权限预授权,则保留授权
2)目标平台为Android 13及以上
3)AndroidManifest文件中声明了SCHEDULE_EXACT_ALARM权限的应用权限默认关闭
3)非豁免或者预授权的
4)非日程和闹钟应用
开发者适配需知
在应用的清单文件中配置SCHEDULE_EXACT_ALARM权限,应用发送action:android.settings.REQUEST_SCHEDULE_EXACT_ALARM去跳转到设置页面,引导用户去打开。
位置权限新增应用标签描述
权限弹窗新增三方应用的数据共享提示,以此让用户做出更确切的选择目前仅在申请地理位置权限弹窗时显示,显示内容则依赖Play商店上该应用的安全标签,需要应用配置在AndroidManifest的清单文件中,后续OPPO软件商店计划跟进此特性。
对用户的影响
告知安全性。
开发者适配需知
在应用的资源目录/etc/ASL/asl-locations.xml新增配置,例如:
新增照片选择权限READ_MEDIA_VISUAL_USER_SELECTED
当应用请求照片+适配权限时,用户可以选择仅共享特定的照片或视频,目标平台为Android 13以上的应用将遵守此新选项,除非应用程序的targestsdk已升级到U,否则将定期重新提示用户应用尝试选择更多照片。
READ_MEDIA_VISUAL_USER_SELECTED权限是Android U新增的运行时权限,允许应用程序读取用户通过照片选择器选择的外部存储中的图片或视频文件。 应用程序可以检查此权限以验证用户已决定使用照片选择器,而不是通过授予对READ_MEDIA_IMAGES或READ_MEDIA_VIDEO权限,它不会阻止应用程序手动访问标准照片选择器。 此权限应同时请求READ_MEDIA_IMAGES或READ_MEDIA_VIDEO权限,具体取决于需要访问的媒体文件类型
如果应用程序请求READ_MEDIA_IMAGES、READ_MEDIA_VIDEO或者ACCESS_MEDIA_LOCATION,则READ_MEDIA_VISUAL_USER_SELECTED权限将自动添加到应用程序的清单,无论targetSDK 是多少。 如果应用程序不请求此权限,则授予对话框
将为READ_MEDIA_IMAGES、READ_MEDIA_VIDEO的权限请求返回PERMISSION_GRANTED授予状态,但是该应用只能访问由用户选择的媒体文件。 这种错误的授权状态将持续存在,直到应用程序进入后台。
对用户的影响
请求READ_MEDIA_IMAGES或READ_MEDIA_VIDEO权限访问用户的图片或者视频文件,若应用程序的targestsdk小于U,系统将定期重新提示用户应用尝试选择更多照片。
对开发者的影响
目标平台为Android 13以上应用,请求READ_MEDIA_IMAGES或READ_MEDIA_VIDEO权限访问用户的图片或者视频文件。需要应用AndroidManifest配置android.permision.READ_MEDIA_VISUAL_USER_SELECTED权限,请求运行时权限,适配照片选择器。
更安全地导出上下文注册的接收器
为了帮助提高运行时接收器的安全性,Android 13 允许您指定您应用中的特定广播接收器是否应被导出以及是否对设备上的其他应用可见。此变更时 Android 12 更安全的组件输出的延续;
注意:系统广播不受此影响。
对用户的影响
以 Android 14 或更高版本为目标平台的应用,必须为每个广播接收器指定 RECEIVER_EXPORTED 或 RECEIVER_NOT_EXPORTED。否则,当您尝试注册广播接收器时,系统会抛出 SecurityException。
对开发者的影响
以 Android 14 或更高版本为目标平台的应用,在应用的每个广播接收器中,明确指明其他应用是否可以向其发送广播,如以下代码段所示:
// This broadcast receiver should be able to receive broadcasts from other apps.
// This option causes the same behavior as setting the broadcast receiver's
// "exported" attribute to true in your app's manifest.
context.registerReceiver(sharedBroadcastReceiver, intentFilter,
RECEIVER_EXPORTED);
// For app safety reasons, this private broadcast receiver should **NOT**
// be able to receive broadcasts from other apps.
context.registerReceiver(privateBroadcastReceiver, intentFilter,
RECEIVER_NOT_EXPORTED);
新增用户初始化Job权限RUN_USER_INITIATED_JOBS
Android 14 引入了android.permision.RUN_USER_INITIATED_JOBS权限,允许一个应用执行用户初始化Job权限,此权限可以被用手动关闭或者被系统撤销,应用需要targestsdk升级到U后来请求此权限
对用户的影响
略
对开发者的影响
需要应用根据业务情况,申请新权限,执行此类job。详细使用方法样例见:developer.android.com/about/versi…
新增唤醒屏幕权限
Android 14 引入了android.permision.TURN_SCREEN_ON权限,目标平台为Android 14及以上的应用使用唤醒屏幕时,需要在AndroidManifest文件中配置这个权限。另外唤醒屏幕权限有一个对应的appops权限AppOpsManager.OP_TURN_SCREEN_ON,这个权限在Android T上是默认开启,在Android U上对目标平台为Android 14及以上的应用默认关闭。
对用户的影响
目标平台为Android 14及以上的应用唤醒屏幕功能失效;
对开发者的影响
目标平台为Android 14及以上的应用应用调用唤醒屏幕接口失败,功能失效.影响 ACQUIRE_CAUSES_WAKEUP。
PowerManager powerManager = (PowerManager) Context.getSystemService(
Context.POWER_SERVICE);
PowerManager.WakeLock wakeLock = powerManager.newWakeLock(
PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP, "testName");
wakeLock.acquire(3000);
最低可安装的目标API级别
恶意软件通常针对较旧的API级别,以绕过在新Android版本中的安全和隐私保护措施。为了防止这种情况,从Android 14开始,不能安装targetSdkVersion低于23的应用程序。
对用户的影响
部分应用不能安装和备份过来;
注意:升级到Android 14的设备,任何目标SdkVersion低于23的应用程序都将继续安装。
对开发者的影响
应用targetSdkVersion不能小于23,建议升级targetSdkVersion;
更加安全的隐式 Intent
此时Android 13 intent 过滤器会屏蔽不匹配的intent的延续。
Android 13:当您的应用向以 Android 13 或更高版本为目标平台的其他应用的导出组件发送 intent 时,仅当该 intent 与接收应用中的 元素匹配时,系统才会传送该 intent。换言之,系统会屏蔽所有不匹配的 intent。
Android 14:为了防止恶意应用程序拦截intent,针对Android 14的应用程序被限制在内部发送不指定package的Intent。
对用户的影响
应用启动不了页面或服务;
对开发者的影响
实例:
组件声明android:exported(Android 12 特性)
<activity
android:name=".AppActivity"
android:exported="false">
<intent-filter>
<action android:name="com.example.action.APP_ACTION" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
如果应用程序创建了可变的pending intent且未指定component或package、则系统现在会抛出一个异常;
// Throws an exception when targeting Android 14.
// Kotlin Code
context.startActivity(Intent("com.example.action.APP_ACTION"))
//-----------------------------------------------------
// Throws an exception when targeting Android 14.
//JAVA Code
context.startActivity(new Intent("com.example.action.APP_ACTION"));
正确用法
// This makes the intent explicit.
// Kotlin Code
val explicitIntent =
Intent("com.example.action.APP_ACTION")
explicitIntent.apply {
package = context.packageName
}
context.startActivity(explicitIntent)
//-----------------------------------------------------
// This makes the intent explicit.
// JAVA Code
Intent explicitIntent =
new Intent("com.example.action.APP_ACTION")
explicitIntent.setPackage(context.getPackageName());
context.startActivity(explicitIntent);
更安全的动态代码加载
如果您的应用目标平台是Android 14及以上的并使用动态代码加载((Dynamic code loading, DCL),则所有动态加载的文件都必须标记为只读。否则,系统会出现异常。注意:尤其是使用加固和热补丁的应用需要持续关注。
如果必须动态加载代码,请使用以下方法将动态加载的文件(如DEX、JAR或APK文件)设置为只读:
//Kotlin
val jar = File("DYNAMICALLY_LOADED_FILE.jar")
val os = FileOutputStream(jar)
os.use {
// Set the file to read-only first to prevent race conditions
jar.setReadOnly()
// Then write the actual file content
}
val cl = PathClassLoader(jar, parentClassLoader)
//JAVA
File jar = new File("DYNAMICALLY_LOADED_FILE.jar");
try (FileOutputStream os = new FileOutputStream(jar)) {
// Set the file to read-only first to prevent race conditions
jar.setReadOnly();
// Then write the actual file content
} catch (IOException e) { ... }
PathClassLoader cl = new PathClassLoader(jar, parentClassLoader);
详见:developer.android.google.cn/about/versi…
蓝牙权限和API变化
android.permission.BLUETOOTH_CONNECT是Android 12引入的蓝牙连接权限,在Android 14上部分接口新加了此权限。
Apps can kill only their own background processes
应用不应该使用 killBackgroundProcesses() 或其他方式,影响其他应用的进程生命周期。从 Android 14 开始,当应用调用 killBackgroundProcesses(String ackageName) 接口,只能杀死该应用自己的后台进程。
对用户的影响
对于用户来说使用三方软件执行类似"一键加速"功能将会无效,但不会出现异常;
对用户的影响
若传入其他应用的包名,将不会影响该应用的后台进程,即不会kill,Logcat中会出现如下打印:Invalid packageName: com.example.anotherapp
详见:developer.android.com/about/versi…
zip 路径限制
对于以Android 14 为目标平台的应用,Android 通过以下方式防止 Zip 路径漏洞:
1、如果 zip 文件路径中包含“…”或以“/”开头,则ZipFile(String)和ZipInputStream.getNextEntry() 抛出一个ZipException异常;
2、应用程序可以通过调用选择退出此验证dalvik.system.ZipPathValidator.clearCallback()
详见:developer.android.google.cn/about/versi…
更新的非SDK接口限制
Android 14包括了基于Android开发人员的协作以及最新的内部测试的受限制的非SDK接口的更新列表。只要有可能,在限制非SDK接口之前,请确保可以使用公共替代方案。
适配指导
non-SDK接口介绍
developer.android.com/guide/app-c…
测试您的应用是否使用非 SDK 接口
developer.android.com/guide/app-c…
Android 14 限制非SDK
Android 14 中有关限制非 SDK 接口的更新
developer.android.com/about/versi…
系统优化
每一代Android在系统优化上都付出很大的努力,无论在安全、性能、功耗、稳定性和用户体验上都给用户带来很好的体验。
前台服务类型
如果应用程序的目标平台是Android 14及以上,它必须为应用程序中的每个前台服务指定至少一个前台服务类型。系统希望具有特定类型的前台服务以满足特定的用例。
注意:Android 14为健康和远程消息引入了新前台服务类型。系统还为短服务、特殊用例和系统豁免保留了新类型。
详见:developer.android.com/about/versi…
对用户的影响
应用抛出异常。
对开发者的影响
前台服务类型.
l camera
l dataSync
l health
l location
适配方式:注意1、前台服务类型;2、前台服务类型对应权限;
<manifest ...>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK" />
<application ...>
<service
android:name=".MyMediaPlaybackService"
android:foregroundServiceType="mediaPlayback"
android:exported="false">
</service>
</application>
</manifest>
64 bit only
64 位CPU能够为您的用户提供更快、更丰富的体验。添加 64 位的应用版本不仅可以提升性能、为未来创新创造条件,还能针对仅支持 64 位架构的设备做好准备。