以前のリリースと同様に、Android 14 には、アプリに影響する可能性がある動作変更が含まれています。以下の動作変更は、Android 14(API レベル 34)以降をターゲットとするアプリにのみ適用されます。Android 14 以降をターゲットとするアプリの場合は、必要に応じてアプリを修正し、下記の動作に適切に対応する必要があります。
アプリの targetSdkVersion
に関係なく、Android 14 で実行されるすべてのアプリに影響する動作変更のリストも必ずご確認ください。
コア機能
フォアグラウンド サービス タイプは必須
如果您的应用以 Android 14(API 级别 34)或更高版本为目标平台,则必须为应用中的每项前台服务指定至少一个前台服务类型。您应该选择一个能够代表应用用例的前台服务类型。系统需要特定类型的前台服务满足特定用例。
如果应用中的用例与这些类型均不相关,强烈建议您迁移逻辑以使用 WorkManager 或用户发起的数据传输作业。
BluetoothAdapter での BLUETOOTH_CONNECT 権限の適用
Android 14 では、Android 14(API レベル 34)以降をターゲットとするアプリで BluetoothAdapter
getProfileConnectionState()
メソッドを呼び出すときに BLUETOOTH_CONNECT
権限が適用されます。
このメソッドにはすでに BLUETOOTH_CONNECT
権限が必要ですが、適用されていません。次のスニペットに示すように、アプリの AndroidManifest.xml
ファイル内で必ず BLUETOOTH_CONNECT
を宣言し、getProfileConnectionState
を呼び出す前にユーザーが権限を付与したことを確認します。
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
OpenJDK 17 の更新
Android 14 将继续更新 Android 的核心库,以与最新 OpenJDK LTS 版本中的功能保持一致,包括适合应用和平台开发者的库更新和 Java 17 语言支持。
以下变更可能会影响应用兼容性:
- 对正则表达式的更改:现在,为了更严格地遵循 OpenJDK 的语义,不允许无效的组引用。您可能会看到
java.util.regex.Matcher
类抛出IllegalArgumentException
的新情况,因此请务必测试应用中使用正则表达式的情形。如需在测试期间启用或停用此变更,请使用兼容性框架工具切换DISALLOW_INVALID_GROUP_REFERENCE
标志。 - UUID 处理:现在,验证输入参数时,
java.util.UUID.fromString()
方法会执行更严格的检查,因此您可能会在反序列化期间看到IllegalArgumentException
。如需在测试期间启用或停用此变更,请使用兼容性框架工具切换ENABLE_STRICT_VALIDATION
标志。 - ProGuard 问题:有时,在您尝试使用 ProGuard 缩减、混淆和优化应用时,添加
java.lang.ClassValue
类会导致问题。问题源自 Kotlin 库,该库会根据Class.forName("java.lang.ClassValue")
是否会返回类更改运行时行为。如果您的应用是根据没有java.lang.ClassValue
类的旧版运行时开发的,则这些优化可能会将computeValue
方法从派生自java.lang.ClassValue
的类中移除。
JobScheduler がコールバックとネットワークの動作を強化する
自引入以来,JobScheduler 会预期您的应用在几秒内从 onStartJob
或 onStopJob
返回。在 Android 14 之前,如果作业运行时间太长,则会静默停止并失败。如果您的应用以 Android 14(API 级别 34)或更高版本为目标平台且在主线程上超出了授权的时间,应用会触发 ANR,并显示错误消息“对 onStartJob
没有响应”或“对 onStopJob
没有响应”。请考虑迁移到 WorkManager,该版本可支持异步处理,或将所有繁重工作迁移到后台线程。
JobScheduler
还引入了,如果使用 setRequiredNetworkType
或 setRequiredNetwork
约束条件,则需要声明 ACCESS_NETWORK_STATE
权限。如果应用在调度作业时未声明 ACCESS_NETWORK_STATE
权限,并且以 Android 14 或更高版本为目标平台,则会导致 SecurityException
。
Tiles API のリリース
对于以 14 及更高版本为目标平台的应用,TileService#startActivityAndCollapse(Intent)
已废弃,现在会在调用时抛出异常。如果您的应用从功能块启动 activity,请改用 TileService#startActivityAndCollapse(PendingIntent)
。
プライバシー
写真と動画への部分的なアクセス
Android 14 では、Selected Photos Access が導入され、特定のタイプのすべてのメディアへのアクセス権を付与するのではなく、ライブラリ内の特定の画像および動画へのアクセス権をアプリに付与できるようになりました。
この変更は、アプリが Android 14(API レベル 34)以降をターゲットとする場合にのみ有効になります。写真選択ツールをまだ使用していない場合は、アプリに実装して、ストレージの権限をリクエストしなくても、画像や動画を選択する際に一貫性のあるエクスペリエンスを提供することをおすすめします。これにより、ユーザーのプライバシーも強化されます。
ストレージの権限を使用して独自のギャラリー選択ツールを管理しており、実装を完全に制御する必要がある場合は、新しい READ_MEDIA_VISUAL_USER_SELECTED
権限を使用するように実装を調整します。アプリが新しい権限を使用しない場合、システムはアプリを互換モードで実行します。
ユーザー エクスペリエンス
安全な全画面インテント通知
在 Android 11(API 级别 30)中,任何应用都可以在手机处于锁定状态时使用 Notification.Builder.setFullScreenIntent
发送全屏 intent。您可以通过在 AndroidManifest 中声明 USE_FULL_SCREEN_INTENT
权限,在应用安装时自动授予此权限。
全屏 intent 通知适用于需要用户立即注意的极高优先级通知,例如用户来电或用户配置的闹钟设置。对于以 Android 14(API 级别 34)或更高版本为目标平台的应用,获准使用此权限的应用仅限于提供通话和闹钟的应用。对于不适合此资料的任何应用,Google Play 商店会撤消其默认的 USE_FULL_SCREEN_INTENT
权限。这些政策变更的截止日期为 2024 年 5 月 31 日。
在用户更新到 Android 14 之前,在手机上安装的应用仍拥有此权限。用户可以开启和关闭此权限。
您可以使用新 API NotificationManager.canUseFullScreenIntent
检查应用是否具有该权限;如果没有,应用可以使用新 intent ACTION_MANAGE_APP_USE_FULL_SCREEN_INTENT
启动设置页面,在该页面中,用户可以授予权限。
セキュリティ
暗黙的インテントとペンディング インテントの制限
Android 14(API レベル 34)以降をターゲットとするアプリの場合、Android は以下の方法で、アプリが内部アプリ コンポーネントに暗黙的インテントを送信することを制限します。
- 暗黙的インテントは、エクスポートされたコンポーネントにのみ配信されます。アプリは、明示的インテントを使用してエクスポートされていないコンポーネントに配信するか、コンポーネントをエクスポート済みとしてマークする必要があります。
- アプリがコンポーネントまたはパッケージを指定しないインテントで可変ペンディング インテントを作成すると、システムは例外をスローします。
この変更により、アプリの内部コンポーネントによる使用を目的とした暗黙的インテントを、悪意のあるアプリがインターセプトするのを防ぐことができます。
たとえば、アプリのマニフェスト ファイルで宣言できるインテント フィルタは次のようになります。
<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>
アプリが暗黙的インテントを使用してこのアクティビティを起動しようとすると、例外がスローされます。
Kotlin
// Throws an exception when targeting Android 14. context.startActivity(Intent("com.example.action.APP_ACTION"))
Java
// Throws an exception when targeting Android 14. context.startActivity(new Intent("com.example.action.APP_ACTION"));
エクスポートされていないアクティビティをアプリが起動するには、代わりに明示的インテントを使用する必要があります。
Kotlin
// This makes the intent explicit. val explicitIntent = Intent("com.example.action.APP_ACTION") explicitIntent.apply { package = context.packageName } context.startActivity(explicitIntent)
Java
// This makes the intent explicit. Intent explicitIntent = new Intent("com.example.action.APP_ACTION") explicitIntent.setPackage(context.getPackageName()); context.startActivity(explicitIntent);
実行時に登録されるブロードキャスト レシーバでは、エクスポート動作を指定する必要がある
以 Android 14(API 级别 34)或更高版本为目标平台并使用上下文注册的接收器的应用和服务必须指定一个标志,以指明接收器是否应导出到设备上的所有其他应用:分别为 RECEIVER_EXPORTED
或 RECEIVER_NOT_EXPORTED
。此要求有助于利用 Android 13 中引入的这些接收器的功能,保护应用免受安全漏洞的影响。
仅接收系统广播的接收器的例外情况
如果您的应用仅通过 Context#registerReceiver
方法(例如 Context#registerReceiver()
)为系统广播注册接收器,那么在注册接收器时不应指定标志。
動的コードの読み込みの安全性を改善
如果您的应用以 Android 14(API 级别 34)或更高版本为目标平台,并使用动态代码加载 (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);
处理已存在的动态加载文件
为防止系统对现有动态加载的文件抛出异常,我们建议您先删除并重新创建文件,然后再尝试在应用中重新动态加载这些文件。重新创建文件时,请按照上述指南在写入时将文件标记为只读。或者,您可以将现有文件重新标记为只读,但在这种情况下,我们强烈建议您先验证文件的完整性(例如,对照可信值检查文件的签名)以保护应用免遭恶意操作的影响。
バックグラウンドからのアクティビティの起動に関する追加の制限
对于以 Android 14(API 级别 34)或更高版本为目标平台的应用,系统会进一步限制允许应用何时从后台启动 activity:
- 当应用使用
PendingIntent#send()
或类似方法发送PendingIntent
时,如果它想要授予自己的后台 activity 启动待处理 intent 的启动特权,则必须选择启用。如需选择启用,应用应通过setPendingIntentBackgroundActivityStartMode(MODE_BACKGROUND_ACTIVITY_START_ALLOWED)
传递ActivityOptions
软件包。 - 现在,当可见应用使用
bindService()
方法绑定另一个后台应用的服务时,如果可见应用想要授予自己的后台 activity 对绑定服务的启动特权,则必须选择启用。如需选择启用,应用应在调用bindService()
方法时包含BIND_ALLOW_ACTIVITY_STARTS
标志。
这些变更扩展了一组现有限制,以防止恶意应用滥用 API 以在后台启动干扰性活动,从而保护用户。
zip パス トラバーサル
对于以 Android 14(API 级别 34)或更高版本为目标平台的应用,Android 会通过以下方式防止 Zip 路径遍历漏洞:如果 zip 文件条目名称包含“..”或以“/”开头,则 ZipInputStream.getNextEntry()
会抛出 ZipException
。ZipFile(String)
应用可以通过调用 dalvik.system.ZipPathValidator.clearCallback()
选择停用此验证。
MediaProjection のキャプチャ セッションごとにユーザーの同意が必要です
对于以 Android 14(API 级别 34)或更高版本为目标平台的应用,在以下任一情况下,MediaProjection#createVirtualDisplay
会抛出 SecurityException
:
- 您的应用会缓存从
MediaProjectionManager#createScreenCaptureIntent
返回的Intent
,并将其多次传递给MediaProjectionManager#getMediaProjection
。 - 您的应用在同一
MediaProjection
实例上多次调用MediaProjection#createVirtualDisplay
。
您的应用必须在每次捕获会话之前征求用户同意。单次拍摄会话是指对 MediaProjection#createVirtualDisplay
的单次调用,且每个 MediaProjection
实例只能使用一次。
处理配置变更
如果您的应用需要调用 MediaProjection#createVirtualDisplay
来处理配置更改(例如屏幕方向或屏幕尺寸更改),您可以按照以下步骤更新现有 MediaProjection
实例的 VirtualDisplay
:
- 使用新的宽度和高度调用
VirtualDisplay#resize
。 - 为
VirtualDisplay#setSurface
提供具有新宽度和高度的新Surface
。
注册回调
您的应用应注册一个回调,以处理用户不同意继续拍摄会话的情况。为此,请实现 Callback#onStop
并让您的应用发布所有相关资源(例如 VirtualDisplay
和 Surface
)。
如果您的应用未注册此回调,MediaProjection#createVirtualDisplay
会在应用调用此回调时抛出 IllegalStateException
。
非 SDK の制限の更新
Android 14 では、Android デベロッパーの協力と直近の内部テストに基づいて、制限を受ける非 SDK インターフェースのリストが更新されています。Google は、非 SDK インターフェースを制限する前に、可能な限り、その代わりとなる公開インターフェースを利用可能にしています。
Android 14 をターゲットとしないアプリでは、この変更の一部はすぐには影響しない可能性があります。ただし、現時点で(アプリのターゲット API レベルに応じて)一部の非 SDK インターフェースを利用できていても、非 SDK のメソッドまたはフィールドをそのまま使用し続けると、将来的にアプリが機能しなくなるリスクが高くなります。
アプリが非 SDK インターフェースを使用しているかどうか不明な場合は、アプリをテストして確認できます。アプリが非 SDK インターフェースに依存している場合は、SDK の代替インターフェースへの移行を計画してください。ただし Google も、一部のアプリには非 SDK インターフェースを使用する正当なユースケースがあると承知しています。アプリの機能に使用している非 SDK インターフェースの代わりが見つからない場合は、新しい公開 API をリクエストしてください。
如需详细了解此 Android 版本中的变更,请参阅 Android 14 中有关限制非 SDK 接口的更新。如需全面了解有关非 SDK 接口的详细信息,请参阅对非 SDK 接口的限制。