PlayerDeviceUtils.java
Overview
`PlayerDeviceUtils` is a utility class designed to provide device-specific playback behavior information within the media playback system. Its primary purpose is to detect whether the current Android device is a television or a Fire TV device, and based on this detection, decide if the media player should run as a single instance or multiple instances.
This decision is essential due to hardware and platform-specific constraints:
TV devices and Amazon Fire TVs generally benefit from a single ExoPlayer instance to handle both content and ads playback.
Certain devices like the Xiaomi Mi Box have known limitations in resource handling when multiple ExoPlayer instances are created, which can cause playback failures.
By encapsulating this logic, `PlayerDeviceUtils` ensures stable and optimized playback experiences tailored for different hardware environments.
Class: PlayerDeviceUtils
public class PlayerDeviceUtils {
// ...
}
Description
A final utility class with static methods to:
Detect whether the device is a TV or Fire TV.
Determine if the application should use a single ExoPlayer instance for video and ad playback.
This class caches the detected device type to avoid redundant system calls.
Constants
Constant Name | Description |
|---|---|
`TAG` | Logging tag (class simple name). |
`XIAOMI_MANUFACTURER` | The string `"Xiaomi"` to identify Xiaomi devices. |
`MI_BOX_DEVICE` | The device model string `"once"` identifying Mi Box. |
`AMAZON_FEATURE_FIRE_TV` | System feature string `"amazon.hardware.fire_tv"` to detect Fire TV devices. |
`sIsTVDevice` | Cached `Boolean` indicating if device is a TV (nullable initially). |
Methods
1. public static boolean isTVDevice(final Context context)
**Purpose:** Detects if the current device is a television or Amazon Fire TV.
**Parameters:**
context(Context): Android context to access system services and package manager.
**Returns:**
boolean:trueif the device is detected as a TV or Fire TV,falseotherwise.
**Behavior:**
Checks if cached
sIsTVDeviceis set; if not, proceeds to detect.Uses
UiModeManagerto check if current UI mode type isUI_MODE_TYPE_TELEVISION.If not a TV by UI mode, checks if the device has the Fire TV system feature.
Caches and returns the result.
**Example Usage:**
if (PlayerDeviceUtils.isTVDevice(context)) {
// Adjust UI or playback for TV
}
2. public static boolean useSinglePlayer()
**Purpose:** Determines if the playback system should use a single ExoPlayer instance to handle both content and ads, instead of using separate players.
**Parameters:**
None.
**Returns:**
boolean:trueif a single player should be used,falsefor dual players.
**Logic:**
Returns
trueif the device is a TV device (sIsTVDevice == true).Returns
trueif the device manufacturer is Xiaomi and the device model is"once"(Xiaomi Mi Box).Otherwise, returns
false.
**Important Note:**
This method relies on
sIsTVDevicebeing initialized (typically after callingisTVDevice()).Using a single player on these devices avoids known issues with resource limitations or player stuck states when multiple player instances are created.
**Example Usage:**
if (PlayerDeviceUtils.useSinglePlayer()) {
// Initialize a single ExoPlayer instance for both content and ads
} else {
// Use separate player instances for content and ads
}
Implementation Details
Caching:
The detection of whether the device is a TV is cached in the static variablesIsTVDeviceto minimize performance overhead on repeated calls.Device Identification:
Uses Android system services (UiModeManager) and package features (PackageManager.hasSystemFeature) to robustly detect TV devices.Manufacturer and Device Model Check:
Uses Google ExoPlayer utility classUtilto access device manufacturer and model strings for Xiaomi Mi Box detection. This is a known problematic device for multiple player instances.Static Utility Design:
All methods and variables are static, so no instantiation ofPlayerDeviceUtilsis needed. This aligns with its role as a helper class.
Interaction with Other System Components
Media Playback Initialization:
The result fromisTVDevice()anduseSinglePlayer()directly influences how the media player instances are initialized in playback components such asDoubleViewTubiPlayerActivityor other player controllers.Ad Playback Strategy:
WhenuseSinglePlayer()returnstrue, the system uses a single ExoPlayer instance for both main content and ads, which affects ad insertion logic and buffering strategies.Device-Specific Compatibility Handling:
This class abstracts device-related decisions away from core playback logic, allowing centralized updates if new devices or conditions need to be supported.Dependency on Android Framework and ExoPlayer Util:
Uses Android services and ExoPlayer’sUtilfor device info, so it depends on those libraries being available.
Usage Example
public void initializePlayer(Context context) {
if (PlayerDeviceUtils.isTVDevice(context)) {
Log.d("PlayerInit", "Device is TV, using single player");
}
if (PlayerDeviceUtils.useSinglePlayer()) {
// Setup single ExoPlayer for content and ads
} else {
// Setup dual ExoPlayer instances
}
}
Mermaid Flowchart: PlayerDeviceUtils Function Relationships
flowchart TD
A[isTVDevice(context)] --> B{Check sIsTVDevice cache}
B -->|null| C[Query UiModeManager for TV mode]
B -->|cached value| D[Return cached sIsTVDevice]
C --> E{Is UI Mode TV?}
E -->|Yes| F[Set sIsTVDevice = true]
E -->|No| G[Check Fire TV feature]
G --> H{Has Fire TV feature?}
H -->|Yes| F
H -->|No| I[Set sIsTVDevice = false]
F --> D
I --> D
J[useSinglePlayer()] --> K{Is sIsTVDevice true?}
K -->|Yes| L[Return true]
K -->|No| M{Is Xiaomi Mi Box?}
M -->|Yes| L
M -->|No| N[Return false]
Summary
PlayerDeviceUtilsis a focused utility class that detects if a device is a TV or Fire TV and decides whether to use a single ExoPlayer instance for media playback.It handles device detection efficiently with caching and uses Android framework services and ExoPlayer utilities.
Key use cases include adapting playback strategies to device capabilities, improving stability and performance on TVs and specific devices like Xiaomi Mi Box.
This class is integral to ensuring the media playback system adapts correctly to diverse hardware environments.