功能优化

This commit is contained in:
lihongwei 2025-06-27 13:48:31 +08:00
parent d021cdc9a9
commit 452f1d6377
5 changed files with 214 additions and 27 deletions

View File

@ -1,5 +1,6 @@
package com.auto.clicker.autoclicker.data;
import android.util.Log;
import android.view.WindowManager;
import android.widget.TextView;
@ -31,6 +32,7 @@ public class PointEvent extends Event {
}
public void setX(int x) {
Log.d("PointEvent", "setX called on id=" + id + " with x=" + x);
this.x = x;
}

View File

@ -12,12 +12,13 @@ import android.view.accessibility.AccessibilityEvent;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import com.auto.clicker.autoclicker.data.Event;
import com.auto.clicker.autoclicker.data.EventWrapper;
import com.auto.clicker.autoclicker.data.PointEvent;
import com.auto.clicker.autoclicker.data.SlideEvent;
import com.auto.clicker.autoclicker.util.EventViewBinder;
import com.auto.clicker.autoclicker.util.ScreenUtils;
import com.auto.clicker.autoclicker.view.FloatingViewManager;
import java.util.ArrayList;
import java.util.Comparator;
@ -36,6 +37,9 @@ public class AutoClickService extends AccessibilityService {
private List<EventWrapper> runtimeEvents = new ArrayList<>();
private FloatingViewManager floatingViewManager;
private int touchPointSize;
private final Handler handler = new Handler(Looper.getMainLooper());
private boolean isRunning = false;
@ -52,6 +56,15 @@ public class AutoClickService extends AccessibilityService {
int screenWidth = screenSize.x;
int screenHeight = screenSize.y;
logDebug("屏幕尺寸: " + screenWidth + "x" + screenHeight);
ForegroundService service = ForegroundService.getInstance();
if (service != null) {
floatingViewManager = service.getFloatingViewManager();
}
if (floatingViewManager != null) {
touchPointSize = floatingViewManager.getTouchPointSize();
}
}
public static AutoClickService getInstance() {
@ -118,6 +131,9 @@ public class AutoClickService extends AccessibilityService {
isRunning = true;
currentEventIndex = 0;
EventViewBinder.setAllTouchPointsDraggable(false);
logDebug("开始执行事件队列 - 共 " + runtimeEvents.size() + " 个事件");
executeEventsByType();
}
@ -127,6 +143,9 @@ public class AutoClickService extends AccessibilityService {
if (isRunning) {
isRunning = false;
handler.removeCallbacksAndMessages(null);
EventViewBinder.setAllTouchPointsDraggable(true);
logDebug("停止执行事件");
}
}
@ -162,13 +181,20 @@ public class AutoClickService extends AccessibilityService {
}
private void performSingleClick(PointEvent pointEvent) {
int x = pointEvent.getX();
int y = pointEvent.getY();
int viewLeftX = pointEvent.getX();
int viewTopY = pointEvent.getY();
logDebug("执行点击: (" + x + ", " + y + ")");
final int CORRECTION_X = 54;
final int CORRECTION_Y = 165;
int correctedViewLeftX = viewLeftX + CORRECTION_X;
int correctedViewTopY = viewTopY + CORRECTION_Y;
int finalClickX = correctedViewLeftX + touchPointSize / 2;
int finalClickY = correctedViewTopY + touchPointSize / 2;
Path path = new Path();
path.moveTo(x, y);
path.moveTo(finalClickX, finalClickY); // 使用最终计算出的点击中心坐标
GestureDescription.StrokeDescription stroke =
new GestureDescription.StrokeDescription(path, 0, clickDuration);
GestureDescription gesture =
@ -200,16 +226,34 @@ public class AutoClickService extends AccessibilityService {
private void performSlide(SlideEvent slideEvent) {
PointEvent start = slideEvent.getStartPoint();
PointEvent end = slideEvent.getEndPoint();
int startX = start.getX();
int startY = start.getY();
int endX = end.getX();
int endY = end.getY();
logDebug("执行滑动: 从 (" + startX + ", " + startY + ") 到 (" + endX + ", " + endY + ")");
int viewStartX = start.getX();
int viewStartY = start.getY();
int viewEndX = end.getX();
int viewEndY = end.getY();
logDebug("--- performSlide start ---");
logDebug("原始 SlideEvent 起点: (" + viewStartX + ", " + viewStartY + ")");
logDebug("原始 SlideEvent 终点: (" + viewEndX + ", " + viewEndY + ")");
final int CORRECTION_X = 54;
final int CORRECTION_Y = 165;
int finalStartX = viewStartX + CORRECTION_X + touchPointSize / 2;
int finalStartY = viewStartY + CORRECTION_Y + touchPointSize / 2;
int finalEndX = viewEndX + CORRECTION_X + touchPointSize / 2;
int finalEndY = viewEndY + CORRECTION_Y + touchPointSize / 2;
logDebug("滑动起点(视图坐标): (" + viewStartX + ", " + viewStartY + ")");
logDebug("滑动终点(视图坐标): (" + viewEndX + ", " + viewEndY + ")");
logDebug("滑动起点(修正后): (" + finalStartX + ", " + finalStartY + ")");
logDebug("滑动终点(修正后): (" + finalEndX + ", " + finalEndY + ")");
Path path = new Path();
path.moveTo(startX, startY);
path.lineTo(endX, endY);
// 这里必须使用修正后的坐标才能确保手势在正确的位置执行
path.moveTo(finalStartX, finalStartY);
path.lineTo(finalEndX, finalEndY);
GestureDescription.StrokeDescription stroke =
new GestureDescription.StrokeDescription(path, 0, slideDuration);
GestureDescription gesture =
@ -225,6 +269,10 @@ public class AutoClickService extends AccessibilityService {
handler.postDelayed(() -> executeEventsByType(), clickInterval);
flashTouchFeedback(feedbackIndex);
}
logDebug("--- onCompleted: 下一个事件将是 index " + currentEventIndex + " ---");
// 再次打印确认 slideEvent.getStartPoint() getEndPoint() 是否被意外修改
logDebug("onCompleted 后SlideEvent 起点: (" + slideEvent.getStartPoint().getX() + ", " + slideEvent.getStartPoint().getY() + ")");
logDebug("onCompleted 后SlideEvent 终点: (" + slideEvent.getEndPoint().getX() + ", " + slideEvent.getEndPoint().getY() + ")");
}
@Override
@ -234,8 +282,13 @@ public class AutoClickService extends AccessibilityService {
currentEventIndex++;
handler.postDelayed(() -> executeEventsByType(), clickInterval + 300);
}
logDebug("--- onCancelled: 下一个事件将是 index " + currentEventIndex + " ---");
// 再次打印确认 slideEvent.getStartPoint() getEndPoint() 是否被意外修改
logDebug("onCancelled 后SlideEvent 起点: (" + slideEvent.getStartPoint().getX() + ", " + slideEvent.getStartPoint().getY() + ")");
logDebug("onCancelled 后SlideEvent 终点: (" + slideEvent.getEndPoint().getX() + ", " + slideEvent.getEndPoint().getY() + ")");
}
}, null);
logDebug("--- performSlide end ---");
}
private void flashTouchFeedback(int index) {
@ -257,6 +310,9 @@ public class AutoClickService extends AccessibilityService {
super.onDestroy();
instance = null;
stopClicking();
EventViewBinder.setAllTouchPointsDraggable(true);
Intent intent = new Intent("com.auto.clicker.autoclicker.SERVICE_DESTROYED");
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
logDebug("无障碍服务已销毁");

View File

@ -7,6 +7,8 @@ import android.os.Build;
import android.util.Log;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
import android.widget.TextView;
@ -15,12 +17,19 @@ import com.auto.clicker.autoclicker.data.PointEvent;
import com.auto.clicker.autoclicker.data.SlideEvent;
import com.auto.clicker.autoclicker.view.ConnectingLineView;
import java.util.HashMap;
import java.util.Map;
public class EventViewBinder {
// 存储每个视图及其对应的 OnTouchListener 实例用于启用/禁用拖动
private static final Map<View, View.OnTouchListener> activeDragListeners = new HashMap<>();
public interface OnPositionChangedCallback {
void onPositionChanged(int x, int y);
}
// --- bindPoint 方法 ---
public static void bindPoint(Context context, WindowManager windowManager,
PointEvent pointEvent, int touchPointSize,
int screenWidth, int screenHeight,
@ -38,17 +47,22 @@ public class EventViewBinder {
pointView.setTextSize(TypedValue.COMPLEX_UNIT_SP, initialTextSize);
DraggableHelper.makeDraggable(pointView, params, windowManager,
screenWidth, screenHeight,
// 创建并保存 OnTouchListener
View.OnTouchListener touchListener = createTouchListener(
pointView, params, windowManager, screenWidth, screenHeight,
(x, y) -> {
pointEvent.setX(x);
pointEvent.setY(y);
if (callback != null) callback.onPositionChanged(x, y);
});
pointView.setOnTouchListener(touchListener);
activeDragListeners.put(pointView, touchListener); // 保存监听器到 Map
windowManager.addView(pointView, params);
}
// --- bindSlide 方法 ---
public static void bindSlide(Context context, WindowManager windowManager,
SlideEvent slideEvent, int touchPointSize,
int screenWidth, int screenHeight,
@ -81,25 +95,29 @@ public class EventViewBinder {
slideEvent.setLineView(lineView);
slideEvent.setLineParams(lineParams);
// 拖动起点
DraggableHelper.makeDraggable(startView, startParams, windowManager,
screenWidth, screenHeight,
// 拖动起点 - 创建并保存监听器
View.OnTouchListener startTouchListener = createTouchListener(
startView, startParams, windowManager, screenWidth, screenHeight,
(x, y) -> {
start.setX(x);
start.setY(y);
updateLinePosition(slideEvent, touchPointSize);
if (callback != null) callback.onPositionChanged(x, y);
});
startView.setOnTouchListener(startTouchListener);
activeDragListeners.put(startView, startTouchListener); // 保存监听器
// 拖动终点
DraggableHelper.makeDraggable(endView, endParams, windowManager,
screenWidth, screenHeight,
// 拖动终点 - 创建并保存监听器
View.OnTouchListener endTouchListener = createTouchListener(
endView, endParams, windowManager, screenWidth, screenHeight,
(x, y) -> {
end.setX(x);
end.setY(y);
updateLinePosition(slideEvent, touchPointSize);
if (callback != null) callback.onPositionChanged(x, y);
});
endView.setOnTouchListener(endTouchListener);
activeDragListeners.put(endView, endTouchListener); // 保存监听器
windowManager.addView(lineView, lineParams);
windowManager.addView(startView, startParams);
@ -108,12 +126,95 @@ public class EventViewBinder {
updateLinePosition(slideEvent, touchPointSize);
}
// --- DraggableHelper 移动过来的 OnTouchListener 创建逻辑 ---
// 这个方法创建并返回一个 View.OnTouchListener 实例
private static View.OnTouchListener createTouchListener(
View view, WindowManager.LayoutParams params, WindowManager windowManager,
int screenWidth, int screenHeight, DraggableHelper.DragCallback callback) { // 仍然使用 DraggableHelper.DragCallback 接口
return new View.OnTouchListener() {
private float lastX, lastY;
private float paramX, paramY;
private boolean isDragging = false; // 标记是否正在拖动
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
lastX = event.getRawX();
lastY = event.getRawY();
paramX = params.x;
paramY = params.y;
isDragging = false; // 重置拖动状态
return true;
case MotionEvent.ACTION_MOVE:
isDragging = true; // 正在拖动
float dx = event.getRawX() - lastX;
float dy = event.getRawY() - lastY;
int newX = (int) (paramX + dx);
int newY = (int) (paramY + dy);
newX = Math.max(0, Math.min(newX, screenWidth - view.getWidth()));
newY = Math.max(0, Math.min(newY, screenHeight - view.getHeight()));
params.x = newX;
params.y = newY;
windowManager.updateViewLayout(view, params);
if (callback != null) {
callback.onPositionChanged(newX, newY);
}
return true;
case MotionEvent.ACTION_UP:
if (!isDragging) { // 如果没有拖动才视为点击
v.performClick();
}
return true;
}
return false;
}
};
}
// --- 新增方法统一控制所有触摸点的拖动状态 ---
public static void setAllTouchPointsDraggable(boolean draggable) {
for (Map.Entry<View, View.OnTouchListener> entry : activeDragListeners.entrySet()) {
View view = entry.getKey();
View.OnTouchListener listener = entry.getValue();
if (draggable) {
// 启用拖动重新设置保存的监听器
view.setOnTouchListener(listener);
} else {
// 禁用拖动将监听器设置为 null阻止触摸事件
view.setOnTouchListener(null);
}
}
}
// --- 新增方法移除不再需要的视图及其监听器 ---
public static void removeBoundView(WindowManager windowManager, View view) {
if (view != null) {
try {
windowManager.removeView(view);
activeDragListeners.remove(view); // Map 中移除
Log.d("EventViewBinder", "移除视图并清理监听器: " + view.getTag());
} catch (IllegalArgumentException e) {
Log.e("EventViewBinder", "尝试移除不存在的视图: " + e.getMessage());
}
}
}
// --- 辅助方法 (保持不变) ---
public static TextView createTouchPointView(Context context, String label) {
TextView touchPointView = new TextView(context);
touchPointView.setBackgroundResource(R.drawable.ring_has_bg);
touchPointView.setGravity(Gravity.CENTER);
touchPointView.setText(label);
touchPointView.setTextColor(Color.WHITE);
touchPointView.setTag(label); // 添加一个Tag方便日志识别
return touchPointView;
}
@ -144,7 +245,7 @@ public class EventViewBinder {
overlayType,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL |
WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE,
WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE, // 线条通常不可触摸
PixelFormat.TRANSLUCENT
);
params.gravity = Gravity.TOP | Gravity.START;
@ -168,4 +269,3 @@ public class EventViewBinder {
lineView.setPoints(startCenterX, startCenterY, endCenterX, endCenterY);
}
}

View File

@ -86,6 +86,8 @@ public class FloatingViewManager {
private static final int DEFAULT_TOUCH_POINT_SIZE = 100;
private static final int DEFAULT_CONTROL_BAR_WIDTH_DP = 38;
private ImageView playButton;
public FloatingViewManager(Context context) {
this.context = context;
this.windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
@ -223,7 +225,7 @@ public class FloatingViewManager {
}
private void setupControlButtons(LinearLayout controlBar,int mode) {
ImageView playButton = controlBar.findViewById(R.id.play_button);
playButton = controlBar.findViewById(R.id.play_button);
ImageView addButton = controlBar.findViewById(R.id.add_button);
ImageView removeButton = controlBar.findViewById(R.id.remove_button);
ImageView slideButton = controlBar.findViewById(R.id.slide_button);
@ -239,6 +241,10 @@ public class FloatingViewManager {
addPointEvent();
}
AutoClickService service = AutoClickService.getInstance();
boolean serviceIsRunning = (service != null && service.isClicking());
updatePlayButtonImage(serviceIsRunning);
playButton.setOnClickListener(v -> toggleMultipleClicking());
addButton.setOnClickListener(v -> addPointEvent());
removeButton.setOnClickListener(v -> removeLastEvent());
@ -286,6 +292,8 @@ public class FloatingViewManager {
isMultipleRunning = !isMultipleRunning;
Log.d(TAG, "多点点击服务状态: " + service.isClicking());
updatePlayButtonImage(isMultipleRunning);
}
private void addPointEvent() {
@ -906,4 +914,16 @@ public class FloatingViewManager {
public int getControlBarWidth() {
return controlBarWidth;
}
private void updatePlayButtonImage(boolean isRunning) {
if (playButton == null) {
return;
}
if (isRunning) {
playButton.setImageResource(R.drawable.pause);
} else {
playButton.setImageResource(R.drawable.play);
}
}
}

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="14dp"
android:height="14dp"
android:viewportWidth="14"
android:viewportHeight="14">
<path
android:pathData="M2,0L12,0A2,2 0,0 1,14 2L14,12A2,2 0,0 1,12 14L2,14A2,2 0,0 1,0 12L0,2A2,2 0,0 1,2 0z"
android:fillColor="#E83434"/>
</vector>