diff --git a/WebRTCControlled/app/src/main/java/com/ttstd/controlled/input/AccessibilityInputUtils.java b/WebRTCControlled/app/src/main/java/com/ttstd/controlled/input/AccessibilityInputUtils.java index c108df0..29ca8ec 100644 --- a/WebRTCControlled/app/src/main/java/com/ttstd/controlled/input/AccessibilityInputUtils.java +++ b/WebRTCControlled/app/src/main/java/com/ttstd/controlled/input/AccessibilityInputUtils.java @@ -53,7 +53,7 @@ public class AccessibilityInputUtils implements InputExecutor { } @Override - public void injectKeyEvent(int keyCode) { + public void injectKeyEvent(int keyCode, int keyAction) { KeyboardAccessibilityService svc = getService(); if (svc == null) { Log.w(TAG, "Accessibility service not running, cannot inject key"); diff --git a/WebRTCControlled/app/src/main/java/com/ttstd/controlled/input/InputCommandHandler.java b/WebRTCControlled/app/src/main/java/com/ttstd/controlled/input/InputCommandHandler.java index b1c9fab..4016da2 100644 --- a/WebRTCControlled/app/src/main/java/com/ttstd/controlled/input/InputCommandHandler.java +++ b/WebRTCControlled/app/src/main/java/com/ttstd/controlled/input/InputCommandHandler.java @@ -133,8 +133,13 @@ public class InputCommandHandler { private void handleKey(ControlMessage command) { int keyCode = command.getKeyCode(); - Log.d(TAG, "Key press: " + keyCode); - inputExecutor.injectKeyEvent(keyCode); + if (keyCode == 0) { + Log.w(TAG, "Ignoring KEY command with keyCode=0"); + return; + } + int keyAction = command.getKeyAction(); + Log.d(TAG, "Key press: keyCode=" + keyCode + ", keyAction=" + keyAction); + inputExecutor.injectKeyEvent(keyCode, keyAction); } private void handleSwipe(ControlMessage command) { diff --git a/WebRTCControlled/app/src/main/java/com/ttstd/controlled/input/InputExecutor.java b/WebRTCControlled/app/src/main/java/com/ttstd/controlled/input/InputExecutor.java index af26acb..603cb5a 100644 --- a/WebRTCControlled/app/src/main/java/com/ttstd/controlled/input/InputExecutor.java +++ b/WebRTCControlled/app/src/main/java/com/ttstd/controlled/input/InputExecutor.java @@ -7,7 +7,12 @@ public interface InputExecutor { void injectTap(int x, int y); void injectLongPress(int x, int y); void injectSwipe(int x1, int y1, int x2, int y2, long duration); - void injectKeyEvent(int keyCode); + /** + * 注入按键事件。 + * @param keyCode Android KeyEvent 键值(如 KeyEvent.KEYCODE_A)。 + * @param keyAction 动作:0=ACTION_DOWN,1=ACTION_UP;传 -1 表示“按下并立即抬起”的一次性点击(兼容旧行为)。 + */ + void injectKeyEvent(int keyCode, int keyAction); void injectMotionEvent(int action, int x, int y); /** diff --git a/WebRTCControlled/app/src/main/java/com/ttstd/controlled/input/RootShellInputUtils.java b/WebRTCControlled/app/src/main/java/com/ttstd/controlled/input/RootShellInputUtils.java index 1da7f8e..c7d9c86 100644 --- a/WebRTCControlled/app/src/main/java/com/ttstd/controlled/input/RootShellInputUtils.java +++ b/WebRTCControlled/app/src/main/java/com/ttstd/controlled/input/RootShellInputUtils.java @@ -31,7 +31,7 @@ public class RootShellInputUtils implements InputExecutor { } @Override - public void injectKeyEvent(int keyCode) { + public void injectKeyEvent(int keyCode, int keyAction) { executeRootCommand(String.format(Locale.US, "input keyevent %d", keyCode)); } diff --git a/WebRTCControlled/app/src/main/java/com/ttstd/controlled/input/ShellInputUtils.java b/WebRTCControlled/app/src/main/java/com/ttstd/controlled/input/ShellInputUtils.java index cbe1bca..85f8244 100644 --- a/WebRTCControlled/app/src/main/java/com/ttstd/controlled/input/ShellInputUtils.java +++ b/WebRTCControlled/app/src/main/java/com/ttstd/controlled/input/ShellInputUtils.java @@ -25,7 +25,7 @@ public class ShellInputUtils implements InputExecutor { } @Override - public void injectKeyEvent(int keyCode) { + public void injectKeyEvent(int keyCode, int keyAction) { executeShellCommand(String.format(Locale.US, "input keyevent %d", keyCode)); } diff --git a/WebRTCControlled/app/src/main/java/com/ttstd/controlled/input/SystemInputUtils.java b/WebRTCControlled/app/src/main/java/com/ttstd/controlled/input/SystemInputUtils.java index d91d878..e24ea6a 100644 --- a/WebRTCControlled/app/src/main/java/com/ttstd/controlled/input/SystemInputUtils.java +++ b/WebRTCControlled/app/src/main/java/com/ttstd/controlled/input/SystemInputUtils.java @@ -2,6 +2,7 @@ package com.ttstd.controlled.input; import android.os.SystemClock; import android.util.Log; +import android.util.SparseLongArray; import android.view.InputDevice; import android.view.InputEvent; import android.view.KeyEvent; @@ -21,6 +22,7 @@ public class SystemInputUtils implements InputExecutor { private static final int INJECT_INPUT_EVENT_MODE_ASYNC = 0; private static final int INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH = 2; private long mDownTime; + private final SparseLongArray mKeyDownTimes = new SparseLongArray(); public SystemInputUtils() { try { @@ -69,10 +71,28 @@ public class SystemInputUtils implements InputExecutor { } @Override - public void injectKeyEvent(int keyCode) { + public void injectKeyEvent(int keyCode, int keyAction) { + if (mInputManager == null || mInjectInputEventMethod == null) { + return; + } long now = SystemClock.uptimeMillis(); - injectKeyEvent(now, now, KeyEvent.ACTION_DOWN, keyCode); - injectKeyEvent(now, SystemClock.uptimeMillis(), KeyEvent.ACTION_UP, keyCode); + if (keyAction < 0) { + // 向后兼容:未指定动作时执行“按下并立即抬起”的一次性点击 + injectKeyEvent(now, now, KeyEvent.ACTION_DOWN, keyCode); + injectKeyEvent(now, now, KeyEvent.ACTION_UP, keyCode); + return; + } + int action = (keyAction == 0) ? KeyEvent.ACTION_DOWN : KeyEvent.ACTION_UP; + long downTime; + if (action == KeyEvent.ACTION_DOWN) { + downTime = now; + mKeyDownTimes.put(keyCode, downTime); + } else { + // 抬起时复用按下时刻,保证同一次按键周期内 downTime 一致(用于长按/组合键识别) + downTime = mKeyDownTimes.get(keyCode, now); + mKeyDownTimes.delete(keyCode); + } + injectKeyEvent(downTime, now, action, keyCode); } @Override diff --git a/WebRTCControllerWeb/src/App.vue b/WebRTCControllerWeb/src/App.vue index 409f8f7..8ae9b12 100644 --- a/WebRTCControllerWeb/src/App.vue +++ b/WebRTCControllerWeb/src/App.vue @@ -27,10 +27,7 @@ async function onLogout() {