Developing for Amazon Fire TV Devices Running Android 14
Android 14-based Fire TV is based on API level 34. The following sections explain some of important changes that you should consider when you build apps for Android 14-based Fire TV. The migration to standard Android components in the following sections will help reduce the risk of compatibility issues and provide ease of maintenance for your app.
- Devices that run Android 14-based Fire TV and previous Fire OS versions
- Android updates
- Amazon SDKs
- 64-bit compatibility
- Target your app for Android 14-based Fire TV devices
- Test your app
- What to set for minSdkVersion and targetSdkVersion
- How minSdkVersion affects supported devices and backwards compatibility
- Support
- Related topics
Devices that run Android 14-based Fire TV and previous Fire OS versions
Android 14-based Fire TV incorporates updates from Android 12 (API 31), Android 12L (API 32), Android 13 (API 33), and Android 14 (API 34). Some older Fire TV devices remain on earlier versions of Fire OS.
For a detailed list of Fire TV devices and versions, see Fire OS Versions.
Android updates
See the following topics to learn about important updates through Android 14:
- Android 12 features and APIs
- Android 12L features and APIs
- Android 13 features and APIs
- Android 14 features and APIs
PendingIntent mutability flag
Before the Android 12 release, you could assume PendingIntent
is mutable by default unless you set FLAG_IMMUTABLE
. Starting with Android 12, you are required to explicitly specify the mutability of PendingIntent
when you create it with FLAG_IMMUTABLE
or FLAG_MUTABLE
.
Solution
Use FLAG_IMMUTABLE
when you create a PendingIntent
and only use FLAG_MUTABLE
when some functionality relies on modifying the underlying intent. The following example shows how to apply FLAG_MUTABLE
to a PendingIntent
that you need to use with inline reply or bubbles.
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, requestCode, intent, PendingIntent.FLAG_MUTABLE);
val pendingIntent = PendingIntent.getBroadcast(context, requestCode, intent, PendingIntent.FLAG_MUTABLE)
Here is some sample code for a mutability flag.
Here's what you might have used in the past.
PendingIntent pendingIntent =
PendingIntent.getBroadcast(
context,
requestCode,
intent,
/* flags= */ 0);
val pendingIntent =
PendingIntent.getBroadcast(
context,
requestCode,
intent,
/* flags= */ 0)
Here's what an updated code sample may look like.
PendingIntent pendingIntent =
PendingIntent.getBroadcast(
context,
requestCode,
intent,
/* flags= */ PendingIntent.FLAG_MUTABLE);
val pendingIntent =
PendingIntent.getBroadcast(
context,
requestCode,
intent,
/* flags= */ PendingIntent.FLAG_MUTABLE)
For more details, see FLAG_IMMUTABLE and PendingIntent.
Safer component export intent
Starting with Android 12, if an app uses the <intent-filter>
element on its activities, services, or broadcast receivers, you must have an explicit attribute declaration (android:exported
) on the manifest file to declare that the activity can be accessed by any app. If apps don’t have a value set for android:exported
, they can't be installed on a Android 14-based Fire TV device. To comply with these new guidelines, update your app's AndroidManifest.xml file with the following attribute declaration.
<activity android:name="ShareActivity" android:exported="false">
If you set the declaration to true
, any app can access the activity and launch it by its exact class name. If you set the declaration to false
, only components of the same app, apps with the same user ID, or privileged system components can launch the activity.
Additionally, starting with Android 14, any apps you target to API 34 must also specify the RECEIVER_EXPORTED
or RECEIVER_NOT_EXPORTED
flags for context-registered receivers. Without RECEIVER_EXPORTED
or RECEIVER_NOT_EXPORTED
flags, the apps will crash at runtime.
Solution
You can prevent a crash at runtime by updating all calls to Context.registerReceiver
to include these flags.
For more details, see Receiving an implicit intent and Runtime-registered broadcasts receivers must specify export behavior.
targetSdkVersion constraints
targetSdkversion
to 34. For more details, see Minimum API levels for targetSdkVersion.For apps with targetSdkVersion
between 23 and 27, the user sees a onetime compatibility warning. Although the user can dismiss the warning and the app continues to run, this results in a degraded experience for the user. If you submitted or updated your app after April 1, 2022, and it is already available on Fire OS 7 (or later), the targetSdkVersion
is already be above 27.
Starting with Android 14, users can't install apps that have a targetSdkVersion
lower than 23. The requirement to meet this minimum target API level improves security and privacy for users.
For more details, see Ensure compatibility with Android 14.
DEX files - uplevel
If you encounter the "Writable dex file is not allowed" error while developing your Android app, it's likely due to compatibility issues with the latest version of the Android operating system.
This error typically occurs when the dex files (compiled code files in Android apps) have their permissions set to writable. In Android 14, Android introduced more strict security measures that prevent apps from having writable dex files, since it poses a potential security risk.
Follow Android's recommendations. The latest version of Android Studio will also help you detect this issue.
Error log example
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 usage
When migrating apps to Android 14, the following runtime exception may occur when using Toast.
Caused by: java.lang.IllegalStateException: Text provided for custom toast, remove previous setView() calls if you want a text toast instead.
In previous versions of Android, it was possible to set both a custom view and text on the same Toast. Android 14 enforces a stricter separation, so you can either display a text-based Toast or a custom view, but not both simultaneously. IllegalStateException
appears when attempting to use both methods.
Solution
Use a Text-Only Toast to avoid the IllegalStateException
in Android 14.
Bluetooth permissions
The updated Bluetooth permissions is designed to enhance user privacy and provide a more streamlined Bluetooth connection experience. Now an issue arises when attempting to retrieve the Bluetooth name or establish a Bluetooth connection, which results in the following error logs.
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
Solution
To address this issue, update your app's Bluetooth permission declarations in the manifest file to align with the latest Android guidelines. If your app targets Android 12 (API level 31) or higher, declare the following permissions.
BLUETOOTH_SCAN
: If your app looks for Bluetooth devices, such as BLE peripherals.BLUETOOTH_ADVERTISE
: If your app makes the current device discoverable to other Bluetooth devices.BLUETOOTH_CONNECT
: If your app communicates with already-paired Bluetooth devices.
For more information, see Bluetooth permissions.
Foreground services
The issue manifests as a java.lang.SecurityException when attempting to start a foreground service without the necessary permission:
java.lang.SecurityException: Permission Denial: startForeground from pid=1824, uid=10479 requires android.permission.FOREGROUND_SERVICE
Solution
Android 9 introduced the FOREGROUND_SERVICE
permission. Apps running on Android 9 or above that use foreground services must include that permission.
If apps that target Android 14 use a foreground service, they must declare a specific permission based on the foreground service type. See Foreground service types are required to select what's appropriate for your use case.
To see all the changes to the foreground service across API levels, see Changes to foreground services.
Updating the Exoplayer version
There are video fluidity issues with Exoplayer 2.x versions, resulting in a degraded experience for the user.
Solution
Follow the steps mentioned in the AndroidX Media3 migration guide to update your app’s ExoPlayer to Media3 and force the DefaultRenderersFactory
component to MediaCodec
asynchronous queueing.
Alarm Scheduling
The SCHEDULE_EXACT_ALARM
permission is a security-sensitive permission introduced in Android 12 (API level 31) to allow apps to schedule exact alarms. This permission has changed in recent Android versions.
Solution
Declare the permissions in your app's manifest file with something like this.
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
<uses-permission android:name="android.permission.USE_EXACT_ALARM" />
However, in Android 14 (API level 34), the SCHEDULE_EXACT_ALARM
permission is no longer granted by default, even if your app declares it in the manifest file. This means you need to check if the permission is granted at runtime and request it from the user if it's not.
Check and request the SCHEDULE_EXACT_ALARM
permission in your app using the following.
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)
}
}
}
Evaluate your use cases and determine if exact alarms are needed. For more information, see Use cases that might not require exact alarms.
Package visibility filtering
Android 11 made changes to package visibility when making intents to other apps. When an app targets Android 11 (API level 30) or higher and queries for information about the other installed apps on a device, the system filters this information by default. This causes the intent to fail silently, with no error shown.
Solution
Some packages are visible automatically, so your app can automatically detect visible packages in its queries for other installed apps. To view other packages, declare your app's need for increased package visibility using the <queries>
element. For more information, see Package visibility filtering on Android.
Amazon SDKs
If you depend on Amazon SDKs, you need to update your apps AndroidManifest.xml file and replace the amazon:enable-feature
element with uses-library
. This change is backward compatible with previous Fire OS versions.
The following example is for Amazon Device Messaging (ADM).
<uses-library
android:name="com.amazon.device.messaging"
android:required="false"/>
For more details, see Integrate Your App.
64-bit compatibility
To avoid a warning that your 32-bit app is not compatible with the latest Android version, make sure to add 64-bit support.
For more details, see Support 64-bit architectures.
Target your app for Android 14-based Fire TV devices
Users might run your app on a Fire OS 5, Fire OS 6, Fire OS 7, Fire OS 8, or Android 14-based Fire TV. To maximize your app’s compatibility with the Fire OS version on the device, Amazon recommends that you target the device based on the SDK level.
In your code, you can check whether Build.VERSION.SDK_INT
is greater than or equal to 34 (Android 14 API level) to target Android 14-based Fire TV devices.
For more details, see Supporting Different Platform Versions.
Test your app
In order to test your app, see Understanding Live App Testing
What to set for minSdkVersion and targetSdkVersion
Set targetSdkVersion
to the highest API level that you're targeting. For Android 14-based Fire TV, Amazon recommends that you set targetSdkVersion
for 34. You can still support older devices by setting minSdkVersion
to the API level you want.
The following table shows the API level based on the Fire OS version.
Fire OS Version | API Level |
---|---|
Fire OS 5 | 22 |
Fire OS 7 | 28 |
Fire OS 8 | 30 |
Android 14-based Fire TV | 34 |
For more details, see Device Filtering and Compatibility.
How minSdkVersion affects supported devices and backwards compatibility
In your app manifest (or build.gradle file), minSdkVersion
sets the minimum SDK level that your app needs in order to function properly. Devices that don't support that API level prevent users from installing the app on that device — this is how device filtering and compatibility works with the Appstore.
Fire OS 5 devices are based on API level 22 (Lollipop 5.1). Android 14-based Fire TV devices are based on API level 34 (Android 14). When you set minSdkVersion
to 22, you've decided that your app requires the device to have at least API level 22 for it to function properly.
When you set minSdkVersion
to 22, your app also installs on any devices that have a higher API level (such as 34), because Android levels are backwards-compatible. API level 34 usually includes all the APIs for levels 1 through 34. Each release adds an API level to the previous levels.
However, suppose you want to take advantage of APIs in Android 14 (API level 34). If you set minSdkVersion
to 22, your app installs on Fire OS 5 devices that don't have level 34 APIs. Therefore, you must code in a defensive way to check the device API level and fall back to alternatives if the device doesn't support that API level. Your code might look like the following code example.
if (Build.VERSION.SDK_INT >= 34) {
Log.v(TAG, "Yes, this is an API level 34 or higher device");
} else {
Log.v(TAG, "No, this is not an API level 34 or higher device");
}
In the previous example, the code checks whether the device's API level is greater than or equal to 34, and if so, runs the code. If not, the code falls back on the else
logic.
By default, if targetSdkVersion
is not specified, Android uses the same value as minSdkVersion
. Specifically, targetSdkVersion
lets you set the latest API level that you have tested your app against. Based on this value, Android will ensure proper behavior on devices at this level.
For example, if you set targetSdkVersion
to 25 or higher (Nougat’s release), Android applies the runtime permission checking features included in Nougat. But if targetSdkVersion
is lower than 25 (prior to the runtime permission checking release in Nougat), Android doesn't apply this behavior to your app.
Although not recommended, if you need to prevent older apps from appearing on Android 14-based Fire TV devices, you can set maxSdkVersion
to Fire OS 8 (30).
For more details, see the following resources:
<uses-sdk>
- Supporting Different Platform Versions
- Picking your
compileSdkVersion
,minSdkVersion
, andtargetSdkVersion
Support
If you notice any issues with your app on Android 14-based Fire TV, note the issue in the Amazon Fire TV and Fire TV Stick forums.
Related topics
- Fire OS versions
- Send Recommendations for Android 14
- Identifying Fire TV Devices
- Device Filtering and Compatibility
- Integrate Your App
Last updated: Jan 28, 2025