如何检查Android TV上的应用是否正在运行?

29

有没有办法检查应用程序是否在Android电视或Android手机上运行?

我知道如何检查正在运行的版本,但是如果应用程序在Android电视与手机上运行,我想启动特定的服务。希望能将两者放在同一个库下。

4个回答

46

来自Android文档中的处理电视硬件

public static final String TAG = "DeviceTypeRuntimeCheck";

    UiModeManager uiModeManager = (UiModeManager) getSystemService(UI_MODE_SERVICE);
    if (uiModeManager.getCurrentModeType() == Configuration.UI_MODE_TYPE_TELEVISION) {
        Log.d(TAG, "Running on a TV Device");
    } else {
        Log.d(TAG, "Running on a non-TV Device");
}

3
这正是 Google 提到的。 - Roc Boronat
无法解析符号getCurrentModeType。我遇到了这个错误。谢谢 - MindRoasterMir
这两个语句末尾缺少分号。谢谢。 - MindRoasterMir
这是来自Android培训文档的建议方式,应该被接受为正确答案。 - ninjachippie
有些电视设备无法访问UI_MODE_SERVICE(它返回null),所以像@Beloo建议的那样,检查系统功能如FEATURE_TELEVISION或FEATURE_LEANBACK也是一个不错的替代方案。 - undefined

23
private boolean isDirectToTV() {
  return(getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEVISION)
      || getPackageManager().hasSystemFeature(PackageManager.FEATURE_LEANBACK));
}

如果设备在广告中宣传自己具有android.hardware.type.televisionandroid.software.leanback系统功能,则会返回true。Android TV和Fire TV可以正确处理此功能;我还没有在其他环境中尝试过。


+1 这种方法让你可以轻松地在相应的平台上插入功能,我刚刚在 AndroidTV 上使用它来制作“正在播放”卡片。 - sschrass
FEATURE_TELEVISION在API 21及以上版本中已被弃用。谢谢。 - MindRoasterMir
1
如果您的minSdkVersion为21或更高版本,则可以跳过FEATURE_TELEVISION/android.hardware.type.television部分,直接使用FEATURE_LEANBACK/android.software.leanback - CommonsWare

6

3
安卓团队建议使用以下方式检查安卓电视:https://developer.android.com/training/tv/start/hardware.html。 - leafartist
由于某种原因,Android团队的建议对我不起作用。如Robert建议的那样,测试缺少触摸屏是成功的。 - Casey Perkins

4

总结之前的答案:

  • 如果uiModeManager.currentModeType == UI_MODE_TYPE_TELEVISION,那肯定是电视
  • 我们不能依靠currentModeType来判断它是否是电视,因为一些电视设备实际上会返回UI_MODE_TYPE_NORMAL
  • 因此,我们应该检查FEATURE_TELEVISION来判断早期的设备,检查FEATURE_LEANBACK来判断lollipop设备。
  • 如果你想支持不仅是电视,还有带有屏幕的静止设备,你可以添加额外的检查来预测它
  • 你必须小心,以免在手机上显示电视界面

这是我们实际使用的Kotlin代码:

enum class UiModeType {
    NORMAL,
    DESK,
    CAR,
    TV,
    APPLIANCE,
    WATCH,
    VR
}

private val modeType: Int
    get() = uiModeManager.currentModeType

fun getUiModeType(): UiModeType = when {
    modeType == UI_MODE_TYPE_APPLIANCE -> UiModeType.APPLIANCE
    modeType == UI_MODE_TYPE_CAR -> UiModeType.CAR
    modeType == UI_MODE_TYPE_DESK -> UiModeType.DESK
    modeType == UI_MODE_TYPE_TELEVISION -> UiModeType.TV

    sdkInt >= Build.VERSION_CODES.KITKAT_WATCH &&
        modeType == UI_MODE_TYPE_WATCH -> UiModeType.WATCH

    sdkInt >= Build.VERSION_CODES.O &&
        modeType == UI_MODE_TYPE_VR_HEADSET -> UiModeType.VR

    isLikelyTelevision() -> UiModeType.TV

    modeType == UI_MODE_TYPE_NORMAL -> UiModeType.NORMAL
    else -> UiModeType.NORMAL
}

private fun isLikelyTelevision(): Boolean = with(packageManager) {
    return@with when {
        sdkInt >= Build.VERSION_CODES.LOLLIPOP &&
            hasSystemFeature(PackageManager.FEATURE_LEANBACK) -> true
        sdkInt < Build.VERSION_CODES.LOLLIPOP &&
            @Suppress("DEPRECATION")
            hasSystemFeature(PackageManager.FEATURE_TELEVISION) -> true
        isBatteryAbsent() &&
            hasSystemFeature(PackageManager.FEATURE_USB_HOST) &&
            hasSystemFeature(PackageManager.FEATURE_ETHERNET) &&
            !hasSystemFeature(PackageManager.FEATURE_TOUCHSCREEN)
}

@SuppressLint("NewApi")
private fun isBatteryAbsent(): Boolean {
    return if (sdkInt >= Build.VERSION_CODES.LOLLIPOP) {
        batteryManager?.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY) == 0
    } else {
        false
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接