我正在尝试通过以下方式获取已连接游戏手柄的列表:

InputDevice.getDeviceIds()
        .map { InputDevice.getDevice(it) }
        .filter { it.sources and InputDeviceCompat.SOURCE_GAMEPAD == InputDeviceCompat.SOURCE_GAMEPAD }
        .forEach {
            Log.i("gamepads", "$it")
        }


通常,它只能返回游戏手柄,但是对于我的Nexus TV,此功能块可以找到另外2种设备,两者均为同一类型:

Input Device 4: virtual-search
Descriptor: 38c59f5a8771de8bd485da05030eb001094d7936
Generation: 10
Location: built-in
Keyboard Type: non-alphabetic
Has Vibrator: false
Has mic: false
Sources: 0x701 ( keyboard dpad gamepad )


有趣的事实:虽然这些设备显然是虚拟的,但呼叫InputDevice.isVirtual()都返回false。

因此,最简单的解决方案是根据mLocationInputDevice字段过滤设备。幸运的是,InputDevice具有公共方法可以对其进行检查。不幸的是,此方法InputDevice.isExternal()被标记为隐藏,因此不可用。

还有其他方法可以过滤掉这些虚拟设备,而无需通过反射访问隐藏的方法/字段吗?

最佳答案

看起来可能的解决方案是基于vendorId过滤设备。对于这些virtual-searchInputDevice.getVendorId()返回0,而对于实际的外部设备,其非零。

当然,我禁止自己使用一些带有空供应商ID的无名设备,但这仍然比访问无法保证有效的隐藏方法更好。

09-25 22:55