feat: 增加长按功能
This commit is contained in:
@@ -37,6 +37,9 @@ public class InputCommandHandler {
|
|||||||
case "SWIPE":
|
case "SWIPE":
|
||||||
handleSwipe(command);
|
handleSwipe(command);
|
||||||
break;
|
break;
|
||||||
|
case "LONG_PRESS":
|
||||||
|
handleLongPress(command);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
Log.w(TAG, "Unknown action: " + action);
|
Log.w(TAG, "Unknown action: " + action);
|
||||||
}
|
}
|
||||||
@@ -82,6 +85,16 @@ public class InputCommandHandler {
|
|||||||
injectSwipe(x1, y1, x2, y2, duration);
|
injectSwipe(x1, y1, x2, y2, duration);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void handleLongPress(JsonObject command) {
|
||||||
|
float relX = command.get("x").getAsFloat();
|
||||||
|
float relY = command.get("y").getAsFloat();
|
||||||
|
int x = (int) (relX * screenWidth);
|
||||||
|
int y = (int) (relY * screenHeight);
|
||||||
|
|
||||||
|
Log.d(TAG, "Long press at: " + x + ", " + y);
|
||||||
|
injectLongPress(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
private void injectTap(int x, int y) {
|
private void injectTap(int x, int y) {
|
||||||
try {
|
try {
|
||||||
Runtime.getRuntime().exec("input tap " + x + " " + y);
|
Runtime.getRuntime().exec("input tap " + x + " " + y);
|
||||||
@@ -90,6 +103,15 @@ public class InputCommandHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void injectLongPress(int x, int y) {
|
||||||
|
try {
|
||||||
|
// 用起点和终点相同的 swipe 模拟长按,持续 1000ms
|
||||||
|
Runtime.getRuntime().exec("input swipe " + x + " " + y + " " + x + " " + y + " 1000");
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e(TAG, "Error injecting long press event", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void injectSwipe(int x1, int y1, int x2, int y2, long duration) {
|
private void injectSwipe(int x1, int y1, int x2, int y2, long duration) {
|
||||||
try {
|
try {
|
||||||
Runtime.getRuntime().exec("input swipe " + x1 + " " + y1 + " " + x2 + " " + y2 + " " + duration);
|
Runtime.getRuntime().exec("input swipe " + x1 + " " + y1 + " " + x2 + " " + y2 + " " + duration);
|
||||||
|
|||||||
@@ -123,6 +123,11 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
public void onKeyEvent(int keyCode, int action) {
|
public void onKeyEvent(int keyCode, int action) {
|
||||||
sendKeyCommand(keyCode, action);
|
sendKeyCommand(keyCode, action);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onLongPress(float relX, float relY) {
|
||||||
|
sendLongPressCommand(relX, relY);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
updateUI(false);
|
updateUI(false);
|
||||||
@@ -244,8 +249,9 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
@Override
|
@Override
|
||||||
public void onDisconnected() {
|
public void onDisconnected() {
|
||||||
runOnUiThread(() -> {
|
runOnUiThread(() -> {
|
||||||
|
Toast.makeText(MainActivity.this, "网络连接已断开", Toast.LENGTH_SHORT).show();
|
||||||
|
disconnect();
|
||||||
tvStatus.setText("状态: 远端已断开");
|
tvStatus.setText("状态: 远端已断开");
|
||||||
updateUI(false);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -327,6 +333,16 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void sendLongPressCommand(float relX, float relY) {
|
||||||
|
if (webRtcClient != null) {
|
||||||
|
JsonObject cmd = new JsonObject();
|
||||||
|
cmd.addProperty("action", "LONG_PRESS");
|
||||||
|
cmd.addProperty("x", relX);
|
||||||
|
cmd.addProperty("y", relY);
|
||||||
|
webRtcClient.sendControlCommand(cmd.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void disconnect() {
|
private void disconnect() {
|
||||||
if (webRtcClient != null) {
|
if (webRtcClient != null) {
|
||||||
webRtcClient.close();
|
webRtcClient.close();
|
||||||
|
|||||||
@@ -3,9 +3,12 @@ package com.ttstd.controller.view;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
import android.view.GestureDetector;
|
||||||
import android.view.MotionEvent;
|
import android.view.MotionEvent;
|
||||||
import android.view.SurfaceView;
|
import android.view.SurfaceView;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
import com.google.gson.JsonObject;
|
import com.google.gson.JsonObject;
|
||||||
|
|
||||||
@@ -25,11 +28,14 @@ public class RemoteTouchView extends SurfaceView {
|
|||||||
private float lastAbsX;
|
private float lastAbsX;
|
||||||
private float lastAbsY;
|
private float lastAbsY;
|
||||||
private long swipeStartTime;
|
private long swipeStartTime;
|
||||||
|
private boolean isLongPressed = false;
|
||||||
|
private GestureDetector gestureDetector;
|
||||||
|
|
||||||
public interface TouchEventListener {
|
public interface TouchEventListener {
|
||||||
void onTouch(float relX, float relY);
|
void onTouch(float relX, float relY);
|
||||||
void onSwipe(float relX1, float relY1, float relX2, float relY2, long duration);
|
void onSwipe(float relX1, float relY1, float relX2, float relY2, long duration);
|
||||||
void onKeyEvent(int keyCode, int action);
|
void onKeyEvent(int keyCode, int action);
|
||||||
|
void onLongPress(float relX, float relY);
|
||||||
}
|
}
|
||||||
|
|
||||||
public RemoteTouchView(Context context) {
|
public RemoteTouchView(Context context) {
|
||||||
@@ -50,6 +56,20 @@ public class RemoteTouchView extends SurfaceView {
|
|||||||
private void init() {
|
private void init() {
|
||||||
setFocusable(true);
|
setFocusable(true);
|
||||||
setFocusableInTouchMode(true);
|
setFocusableInTouchMode(true);
|
||||||
|
gestureDetector = new GestureDetector(getContext(), new GestureDetector.SimpleOnGestureListener() {
|
||||||
|
@Override
|
||||||
|
public void onLongPress(@NonNull MotionEvent e) {
|
||||||
|
if (listener != null) {
|
||||||
|
isLongPressed = true;
|
||||||
|
float relX = e.getX() / getWidth();
|
||||||
|
float relY = e.getY() / getHeight();
|
||||||
|
relX = Math.max(0, Math.min(1, relX));
|
||||||
|
relY = Math.max(0, Math.min(1, relY));
|
||||||
|
listener.onLongPress(relX, relY);
|
||||||
|
Log.d(TAG, "LongPress at: " + relX + ", " + relY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setTouchEventListener(TouchEventListener listener) {
|
public void setTouchEventListener(TouchEventListener listener) {
|
||||||
@@ -76,6 +96,7 @@ public class RemoteTouchView extends SurfaceView {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onTouchEvent(MotionEvent event) {
|
public boolean onTouchEvent(MotionEvent event) {
|
||||||
|
gestureDetector.onTouchEvent(event);
|
||||||
if (listener == null) return super.onTouchEvent(event);
|
if (listener == null) return super.onTouchEvent(event);
|
||||||
|
|
||||||
float absX = event.getX();
|
float absX = event.getX();
|
||||||
@@ -91,6 +112,7 @@ public class RemoteTouchView extends SurfaceView {
|
|||||||
|
|
||||||
switch (event.getActionMasked()) {
|
switch (event.getActionMasked()) {
|
||||||
case MotionEvent.ACTION_DOWN:
|
case MotionEvent.ACTION_DOWN:
|
||||||
|
isLongPressed = false;
|
||||||
lastTouchX = relX;
|
lastTouchX = relX;
|
||||||
lastTouchY = relY;
|
lastTouchY = relY;
|
||||||
lastAbsX = absX;
|
lastAbsX = absX;
|
||||||
@@ -103,6 +125,9 @@ public class RemoteTouchView extends SurfaceView {
|
|||||||
return true;
|
return true;
|
||||||
|
|
||||||
case MotionEvent.ACTION_UP:
|
case MotionEvent.ACTION_UP:
|
||||||
|
if (isLongPressed) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
long duration = System.currentTimeMillis() - swipeStartTime;
|
long duration = System.currentTimeMillis() - swipeStartTime;
|
||||||
float dx = Math.abs(relX - lastTouchX);
|
float dx = Math.abs(relX - lastTouchX);
|
||||||
float dy = Math.abs(relY - lastTouchY);
|
float dy = Math.abs(relY - lastTouchY);
|
||||||
@@ -140,4 +165,12 @@ public class RemoteTouchView extends SurfaceView {
|
|||||||
cmd.addProperty("duration", duration);
|
cmd.addProperty("duration", duration);
|
||||||
return cmd.toString();
|
return cmd.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String createLongPressCommand(float relX, float relY) {
|
||||||
|
JsonObject cmd = new JsonObject();
|
||||||
|
cmd.addProperty("action", "LONG_PRESS");
|
||||||
|
cmd.addProperty("x", relX);
|
||||||
|
cmd.addProperty("y", relY);
|
||||||
|
return cmd.toString();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -122,12 +122,11 @@ public class WebRtcClient {
|
|||||||
if (newState == PeerConnection.IceConnectionState.CONNECTED) {
|
if (newState == PeerConnection.IceConnectionState.CONNECTED) {
|
||||||
if (connectionListener != null) connectionListener.onConnectionEstablished();
|
if (connectionListener != null) connectionListener.onConnectionEstablished();
|
||||||
} else if (newState == PeerConnection.IceConnectionState.DISCONNECTED) {
|
} else if (newState == PeerConnection.IceConnectionState.DISCONNECTED) {
|
||||||
// DISCONNECTED 可能是暂时的,通常建议观察一段时间或尝试重放信令
|
Log.w(TAG, "ICE Disconnected");
|
||||||
Log.w(TAG, "ICE Disconnected, waiting for recovery...");
|
if (connectionListener != null) connectionListener.onDisconnected();
|
||||||
} else if (newState == PeerConnection.IceConnectionState.FAILED) {
|
} else if (newState == PeerConnection.IceConnectionState.FAILED) {
|
||||||
// FAILED 通常意味着需要重新发起呼叫
|
Log.e(TAG, "ICE Connection Failed");
|
||||||
if (connectionListener != null) connectionListener.onDisconnected();
|
if (connectionListener != null) connectionListener.onDisconnected();
|
||||||
// 这里可以触发重新创建 Offer 的逻辑
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user