Android系统级应用如何注入AXIS_RTRIGGER/AXIS_GAS事件?
解决Android系统级应用注入游戏扳机轴(AXIS_RTRIGGER)事件失败的问题
背景
系统级应用持有android.permission.INJECT_EVENTS权限,适配Android 12L及以上版本,采用Kotlin开发,目标是解析硬件按键后通过InputManager向当前界面注入游戏控制器事件。目前左摇杆模拟代码可正常运行,但右扳机(AXIS_RTRIGGER)事件无法被测试应用识别。
问题代码
val eventTime = SystemClock.uptimeMillis() val pointerProperties = MotionEvent.PointerProperties() pointerProperties.id = 1 val pointerCoords = MotionEvent.PointerCoords() pointerCoords.setAxisValue(MotionEvent.AXIS_RTRIGGER, value) val event = MotionEvent.obtain( /* downTime= */ eventTime, /* eventTime= */ eventTime, /* action= */ MotionEvent.ACTION_MOVE, /* pointerCount= */ 1, /* pointerProperties= */ arrayOf(pointerProperties), /* pointerCoords= */ arrayOf(pointerCoords), /* metaState= */ 0, /* buttonstate= */ 0, /* xPrecision= */ 0.1f, /* yPrecision= */0.1f, /* deviceId= */mInputManager.getInputDevice(-1).id, //Using -1 as that's a virtual inputDevice /* edgeFalgs= */0, /* source= */InputDevice.SOURCE_GAMEPAD, /* flags= */0 ) mInputManager.injectInputEvent(event, InputEventInjectionSync.WAIT_FOR_RESULT) event.recycle()
可正常运行的左摇杆参考代码
val eventTime = SystemClock.uptimeMillis() val event = MotionEvent.obtain( /* downTime= */ eventTime, /* eventTime= */ eventTime, /* action= */ MotionEvent.ACTION_MOVE, /* x= */ angle, /* y= */ 0.0f, /* pressure= */ 1.0f, /* size= */ 0f, /* metaState= */ 0, /* xPrecision= */ 0.1f, /* yPrecision= */ 0.1f, /* deviceId= */ mInputManager.getInputDevice(-1).id, /* edgeFlags= */ 0 ) event.source = InputDevice.SOURCE_JOYSTICK mInputManager.injectInputEvent(event, InputEventInjectionSync.NONE) event.recycle()
排查与修复方案
1. 校验轴值范围
MotionEvent.AXIS_RTRIGGER的标准取值范围是0.0f(未按下)到1.0f(完全按下),超出该范围的事件会被系统或测试应用忽略。注入前需确保value被限制在合法区间:
val validValue = value.coerceIn(0.0f, 1.0f)
2. 修正虚拟输入设备获取逻辑
getInputDevice(-1)返回的默认设备可能不支持游戏手柄轴事件。若无法创建自定义虚拟设备,可直接传入设备ID -1(系统会自动映射到合适的虚拟设备),但需确保事件的source与轴类型匹配。
3. 完善MotionEvent构造参数
多指针构造方法需正确设置PointerProperties的必要字段,单指针场景建议使用ID 0,并补充设置工具类型:
val pointerProperties = MotionEvent.PointerProperties().apply { id = 0 toolType = MotionEvent.TOOL_TYPE_UNKNOWN // 游戏控制器无需特定工具类型 }
修正后的完整扳机事件注入代码:
val eventTime = SystemClock.uptimeMillis() val validValue = value.coerceIn(0.0f, 1.0f) val pointerProperties = MotionEvent.PointerProperties().apply { id = 0 toolType = MotionEvent.TOOL_TYPE_UNKNOWN } val pointerCoords = MotionEvent.PointerCoords().apply { setAxisValue(MotionEvent.AXIS_RTRIGGER, validValue) } val event = MotionEvent.obtain( eventTime, eventTime, MotionEvent.ACTION_MOVE, 1, arrayOf(pointerProperties), arrayOf(pointerCoords), 0, 0, 0.1f, 0.1f, -1, // 直接使用-1作为虚拟设备ID 0, InputDevice.SOURCE_GAMEPAD, 0 ) // 强制设置事件源,避免构造时的参数覆盖 event.setSource(InputDevice.SOURCE_GAMEPAD) // 使用WAIT_FOR_RESULT获取注入结果,便于调试 val injectResult = mInputManager.injectInputEvent(event, InputEventInjectionSync.WAIT_FOR_RESULT) // 结果为1表示注入成功,0表示失败 Log.d("TriggerInjection", "Inject result: $injectResult") event.recycle()
4. 发送完整事件序列
仅发送ACTION_MOVE可能无法被测试应用正确识别,需模拟完整的按下-移动-抬起序列:
- 按下:发送
ACTION_DOWN事件,轴值设为初始按压值 - 移动:发送
ACTION_MOVE事件,更新轴值 - 抬起:发送
ACTION_UP事件,轴值设为0.0f
示例代码:
fun sendTriggerEvent(value: Float, action: Int) { val eventTime = SystemClock.uptimeMillis() val validValue = if (action == MotionEvent.ACTION_UP) 0.0f else value.coerceIn(0.0f, 1.0f) val pointerProperties = MotionEvent.PointerProperties().apply { id = 0 toolType = MotionEvent.TOOL_TYPE_UNKNOWN } val pointerCoords = MotionEvent.PointerCoords().apply { setAxisValue(MotionEvent.AXIS_RTRIGGER, validValue) } val event = MotionEvent.obtain( eventTime, eventTime, action, 1, arrayOf(pointerProperties), arrayOf(pointerCoords), 0, 0, 0.1f, 0.1f, -1, 0, InputDevice.SOURCE_GAMEPAD, 0 ) event.setSource(InputDevice.SOURCE_GAMEPAD) mInputManager.injectInputEvent(event, InputEventInjectionSync.WAIT_FOR_RESULT) event.recycle() } // 使用方式 sendTriggerEvent(0.5f, MotionEvent.ACTION_DOWN) // 按下扳机到50% sendTriggerEvent(0.8f, MotionEvent.ACTION_MOVE) // 调整到80% sendTriggerEvent(0.0f, MotionEvent.ACTION_UP) // 松开扳机
5. 验证事件是否被系统接收
若测试应用仍无响应,可使用Android开发者选项中的输入设备测试器验证事件是否被系统正确接收,排除测试应用自身的兼容性问题。
内容的提问来源于stack exchange,提问作者sumofty
相关产品推荐
相关产品推荐

