针对运行Android 14的亚马逊Fire TV设备进行开发
基于Android 14的Fire TV以API级别34为基础。以下各部分说明了在为基于Android 14的Fire TV构建应用时应考虑的一些重要更改。以下部分中朝向标准Android组件的迁移将有助于降低兼容性问题的风险,并简化应用的维护。
- 运行基于Android 14的Fire TV和之前Fire OS版本的设备
- Android更新
- 亚马逊SDK
- 64位兼容性
- 将应用的目标确定为基于Android 14的Fire TV设备
- 测试您的应用
- minSdkVersion和targetSdkVersion的设置
- minSdkVersion对支持的设备有何影响以及向后兼容性
- 支持
- 相关主题
运行基于Android 14的Fire TV和之前Fire OS版本的设备
基于Android 14的Fire TV包含来自Android 12 (API 31)、Android 12L (API 32)、Android 13 (API 33) 和Android 14 (API 34) 的更新。部分较早版本的Fire TV设备仍然搭载较早版本的Fire OS。
有关Fire TV设备和版本的详细列表,请参阅Fire OS版本。
Android更新
请参阅以下主题,了解Android12至14进行的重要更新:
PendingIntent可变性标记
在Android 12发布之前,除非您设置了FLAG_IMMUTABLE
,否则您可以假设PendingIntent
在默认情况下是可变的。从Android 12开始,在使用FLAG_IMMUTABLE
或FLAG_MUTABLE
创建PendingIntent
时,需要明确指定其可变性。
解决方案
在创建PendingIntent
时使用FLAG_IMMUTABLE
,只有在某些功能依赖于修改底层意图时才使用FLAG_MUTABLE
。以下示例说明如何将FLAG_MUTABLE
应用于您需要在行内回复或气泡中使用的PendingIntent
。
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, requestCode, intent, PendingIntent.FLAG_MUTABLE);
val pendingIntent = PendingIntent.getBroadcast(context, requestCode, intent, PendingIntent.FLAG_MUTABLE)
以下是一些可变性标记的示例代码。
您过去使用过的可能如下所示。
PendingIntent pendingIntent =
PendingIntent.getBroadcast(
context,
requestCode,
intent,
/* flags= */ 0);
val pendingIntent =
PendingIntent.getBroadcast(
context,
requestCode,
intent,
/* flags= */ 0)
更新的代码示例可能如下所示。
PendingIntent pendingIntent =
PendingIntent.getBroadcast(
context,
requestCode,
intent,
/* flags= */ PendingIntent.FLAG_MUTABLE);
val pendingIntent =
PendingIntent.getBroadcast(
context,
requestCode,
intent,
/* flags= */ PendingIntent.FLAG_MUTABLE)
有关更多详细信息,请参阅FLAG_IMMUTABLE和PendingIntent(仅提供英文版)。
更安全的组件导出意图
从Android 12开始,如果应用在其活动、服务或广播接收器上使用<intent-filter>
,则必须在清单文件中进行明确的属性声明 (android:exported
),以声明任何应用都可以访问该活动。如果应用没有为android:exported
设置值,则无法将其安装在基于Android 14的Fire TV设备上。为遵守这些新指南,请使用以下属性声明更新应用的AndroidManifest.xml文件。
<activity android:name="ShareActivity" android:exported="false">
如果您将声明设置为true
,则任何应用都可以访问该活动并按其确切的类名启动它。如果将声明设置为false
,则只有同一应用的组件、具有相同用户ID的应用或特权系统组件才能启动活动。
此外,从Android 14开始,任何以API 34为目标的应用还必须为上下文注册的接收器指定RECEIVER_EXPORTED
或RECEIVER_NOT_EXPORTED
标记。如果没有RECEIVER_EXPORTED
或RECEIVER_NOT_EXPORTED
标记,应用将在运行时崩溃。
解决方案
通过更新对Context.registerReceiver
的所有调用以包含这些标记,可以防止运行时崩溃。
有关更多详细信息,请参阅接收隐式意图和运行时注册的广播接收器必须指定导出行为。
targetSdkVersion限制
targetSdkversion
设置为34。有关更多详细信息,请参阅targetSdkVersion的最低API级别。对于targetSdkVersion
介于23到27之间的应用,用户会看到一次性兼容性警告。尽管用户可以关闭警告并且应用可以继续运行,但这会导致用户体验下降。如果您在2022年4月1日之后提交或更新了应用,并且该应用已经在Fire OS 7(或更高版本)上可用,则targetSdkVersion
已经在27以上。
从Android 14开始,用户不能安装targetSdkVersion
低于23的应用。满足此最低目标API级别的要求旨在提高用户的安全性和隐私性。
如需了解更多详细信息,请参阅确保与Android 14的兼容性。
DEX文件 - 升级
如果您在开发Android应用时遇到“Writable dex file is not allowed”(禁止可写dex文件)错误,这可能是由最新版本的Android操作系统的兼容性问题造成。
此错误通常在dex文件(Android应用中编译的代码文件)的权限设置为可写入时发生。在Android 14中,Android引入了更严格的安全措施,防止应用拥有可写的dex文件,因为这会带来潜在的安全风险。
遵循Android的建议。最新版本的Android Studio也将帮助您检测该问题。
错误日志示例
08-21 01:43:58.189 8222 8554 E AndroidRuntime: java.lang.SecurityException: Writable dex file '/data/user/0/com.kptv.ott/cache/1664557424545.jar' is not allowed.
Toast用法
将应用迁移到Android 14时,如果使用Toast,可能会出现以下运行时异常。
Caused by: java.lang.IllegalStateException: Text provided for custom toast, remove previous setView() calls if you want a text toast instead.
在之前的Android版本中,可以在同一Toast上同时设置自定义视图和文本。Android 14强制实行更严格的分离,因此您可以显示基于文本的Toast或自定义视图,但不能同时显示两者。尝试使用这两种方法时会出现IllegalStateException
。
解决方案
使用纯文本Toast来避免Android 14中的IllegalStateException
。
蓝牙权限
更新后的蓝牙权限旨在增强用户隐私,提供更简化的蓝牙连接体验。现在,尝试检索蓝牙名称或建立蓝牙连接时会发生问题,这会导致以下错误日志。
java.lang.SecurityException: Settings key: <bluetooth_name> is only readable to apps with targetSdkVersion lower than or equal to: 31
08-20 11:34:26.175 10079 10152 W cr_media: BLUETOOTH_CONNECT permission is missing.08-20 11:34:26.189 10079 10152 W cr_media: registerBluetoothIntentsIfNeeded: Requires BLUETOOTH permission
解决方案
要解决此问题,请在清单文件中更新应用的蓝牙权限声明,以符合最新的Android指南。如果您的应用以Android 12(API级别31)或更高版本为目标,请声明以下权限。
BLUETOOTH_SCAN
: 如果您的应用会寻找蓝牙设备,例如BLE外围设备,则需要对此进行声明。BLUETOOTH_ADVERTISE
: 如果您的应用使其他蓝牙设备可以发现当前设备,则需要对此进行声明。BLUETOOTH_CONNECT
: 如果您的应用与已配对的蓝牙设备通信,则需要对此进行声明。
有关更多信息,请参阅蓝牙权限。
前台服务
如果尝试在没有必要权限的情况下启动前台服务,该问题显示为java.lang.SecurityException:
java.lang.SecurityException: Permission Denial: startForeground from pid=1824, uid=10479 requires android.permission.FOREGROUND_SERVICE
解决方案
Android 9引入了FOREGROUND_SERVICE
权限。在Android 9或更高版本上运行且使用前台服务的应用必须包含该权限。
如果以Android 14为目标的应用使用前台服务,则它们必须根据前台服务类型声明特定权限。请参阅需要前台服务类型以选择适合您的用例的内容。
要查看跨API级别对前台服务的所有更改,请参阅对前台服务的更改。
更新Exoplayer版本
Exoplayer 2.x版本存在视频流畅性问题,导致用户体验下降。
解决方案
按照AndroidX Media3迁移指南中所述步骤,将应用的ExoPlayer更新为Media3,并强制DefaultRenderersFactory
组件进行MediaCodec
异步排队。
警报安排
SCHEDULE_EXACT_ALARM
权限是Android 12(API级别31)中引入的一项安全敏感权限,允许应用安排准确的警报。此权限在最近的Android版本中已更改。
解决方案
使用和下面所示类似的内容在应用的清单文件中声明权限。
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
<uses-permission android:name="android.permission.USE_EXACT_ALARM" />
但是,在Android 14(API级别34)中,默认情况下不再授予SCHEDULE_EXACT_ALARM
权限,即使您的应用在清单文件中声明了该权限也是如此。这意味着您需要检查在运行时是否授予了权限,如果没有,则向用户申请。
如下所示在您的应用中检查并申请SCHEDULE_EXACT_ALARM
权限。
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
AlarmManager alarmManager = ContextCompat.getSystemService(context, AlarmManager.class);
if (alarmManager != null && !alarmManager.canScheduleExactAlarms()) {
Intent intent = new Intent();
intent.setAction(Settings.ACTION_REQUEST_SCHEDULE_EXACT_ALARM);
context.startActivity(intent);
}
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
val alarmManager = ContextCompat.getSystemService(context, AlarmManager::class.java)
if (alarmManager?.canScheduleExactAlarms() == false) {
Intent().also { intent ->
intent.action = Settings.ACTION_REQUEST_SCHEDULE_EXACT_ALARM
context.startActivity(intent)
}
}
}
评估您的用例并确定是否需要准确的警报。有关更多信息,请参阅可能不需要准确警报的用例。
程序包可见性筛选
Android 11更改了在对其他应用创建意图时程序包的可见性。当应用以Android 11(API级别30)或更高版本为目标并查询有关设备上其他已安装应用的信息时,系统会默认筛选此信息。这会导致意图无提示地失败,不会显示任何错误。
解决方案
某些程序包会自动显示,因此您的应用可能会在查询其他已安装应用时自动检测可见的程序包。要查看其他程序包,请使用<queries>
元素声明您的应用需要提高程序包的可见性。有关更多信息,请参阅Android上的程序包可见性筛选。
亚马逊SDK
如果您依赖亚马逊SDK,则需要更新您的应用AndroidManifest.xml文件并将amazon:enable-feature
元素替换为uses-library
。此更改向后兼容先前的Fire OS版本。
以下示例适用于Amazon Device Messaging (ADM)。
<uses-library
android:name="com.amazon.device.messaging"
android:required="false"/>
有关更多详细信息,请参阅集成您的应用。
64位兼容性
为避免警告您的32位应用与最新的Android版本不兼容,请务必添加对64位的支持。
有关更多详细信息,请参阅支持64位架构。
将应用的目标确定为基于Android 14的Fire TV设备
用户可能会在基于Fire OS 5、Fire OS 6、Fire OS 7、Fire OS 8或基于Android 14的Fire TV上运行您的应用。为了最大限度提高应用与设备上Fire OS版本的兼容性,亚马逊建议根据SDK级别确定目标设备。
在您的代码中,可检查Build.VERSION.SDK_INT
是否大于等于34(Android 14 API级别),以将基于Android 14的Fire TV设备确定为目标。
有关更多详细信息,请参阅支持不同平台版本。
测试您的应用
要测试您的应用,请参阅了解动态应用测试
minSdkVersion和targetSdkVersion的设置
将targetSdkVersion
设置成您确定为目标的最高API级别。对于基于Android 14的Fire TV,亚马逊建议您将targetSdkVersion
设置为34。通过将minSdkVersion
设置为所需的API级别,您仍然可以支持较旧的设备。
下表显示了基于Fire OS版本的API级别。
Fire OS版本 | API级别 |
---|---|
Fire OS 5 | 22 |
Fire OS 7 | 28 |
Fire OS 8 | 30 |
基于Android 14的Fire TV | 34 |
有关更多详细信息,请参阅设备筛选和兼容性。
minSdkVersion对支持的设备有何影响以及向后兼容性
在应用清单(或build.gradle文件)中,minSdkVersion
设置了应用正常运行所需的最低SDK级别。不支持该API级别的设备将不允许用户在该设备上安装应用 — 这是亚马逊应用商店设备筛选和兼容性的工作方式。
Fire OS 5设备基于API级别22 (Lollipop 5.1)。基于Android 14的Fire TV设备以API级别34 (Android 14) 为基础。如果将minSdkVersion
设置为22,即表示您确定应用要求设备至少具有API级别22才能正常运行。
将minSdkVersion
设置为22时,还可在具有更高API级别(例如34)的设备中安装您的应用,因为Android级别向后兼容。API级别34通常包括级别1到34的所有API。每个版本都会在之前的级别上增加一个API级别。
但假设您想利用Android 14中的API(API级别34)。若将minSdkVersion
设置为22,则可以在没有API级别34的Fire OS 5设备中安装您的应用。因此,必须以防御性方式进行编程,检查设备API级别,若设备不支持该API级别,则回退到替代方案。您的代码可能会如下面的代码示例所示。
if (Build.VERSION.SDK_INT >= 34) {
Log.v(TAG, "是,这台设备具备API级别34或更高版本");
} else {
Log.v(TAG, "不是,这台设备不具备API级别34或更高版本");
}
在上一示例中,此代码检查设备的API级别是否大于或等于34,如果是,则运行代码。如果不是,则代码将在else
逻辑上回退。
默认情况下,若未指定targetSdkVersion
,Android将使用与minSdkVersion
相同的值。具体而言,targetSdkVersion
允许您设置应用测试所依据的最新API级别。基于该值,Android将确保此级别设备的性能正常。
例如,若将targetSdkVersion
设置为25或更高版本(Nougat的版本),Android会应用Nougat中包含的运行时权限检查功能。但如果targetSdkVersion
低于25(在Nougat中推出运行时权限检查之前),则Android不会在您的应用中应用此行为。
尽管不建议采取这一做法,但如果需要防止较早版本的应用出现在基于Android 14的Fire TV设备上,可以将maxSdkVersion
设置为Fire OS 8 (30)。
有关更多详细信息,请参阅以下资源:
支持
若应用在基于Android 14的Fire TV上存在问题,请在亚马逊Fire TV和Fire TV Stick论坛中报告该问题。
相关主题
Last updated: 2025年1月28日