From 3191bd8863d663f344b964221c055d246f473ac8 Mon Sep 17 00:00:00 2001 From: YeungKhaiChiu <1005935991@qq.com> Date: Sat, 1 Jun 2024 16:47:41 +0800 Subject: [PATCH 1/2] =?UTF-8?q?feat:=20=E5=A2=9E=E5=8A=A0adb=E5=92=8Cuia?= =?UTF-8?q?=E7=9A=84drag=20and=20drop=E6=93=8D=E4=BD=9C=EF=BC=88=E7=9C=9F-?= =?UTF-8?q?=E6=8B=96=E6=8B=BD=E5=85=83=E7=B4=A0=E6=93=8D=E4=BD=9C=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 2 +- .../tests/handlers/AndroidStepHandler.java | 56 +++++++++++++--- .../tests/handlers/AndroidTouchHandler.java | 64 ++++++++++++++++++- 3 files changed, 111 insertions(+), 11 deletions(-) diff --git a/pom.xml b/pom.xml index 24d6a54b..24222dca 100644 --- a/pom.xml +++ b/pom.xml @@ -78,7 +78,7 @@ io.github.soniccloudorg sonic-driver-core - 1.1.29 + 1.1.30 net.coobird diff --git a/src/main/java/org/cloud/sonic/agent/tests/handlers/AndroidStepHandler.java b/src/main/java/org/cloud/sonic/agent/tests/handlers/AndroidStepHandler.java index 33798cb2..9bb5374b 100755 --- a/src/main/java/org/cloud/sonic/agent/tests/handlers/AndroidStepHandler.java +++ b/src/main/java/org/cloud/sonic/agent/tests/handlers/AndroidStepHandler.java @@ -721,8 +721,8 @@ public void swipePoint(HandleContext handleContext, String des1, String xy1, Str double x2 = Double.parseDouble(xy2.substring(0, xy2.indexOf(","))); double y2 = Double.parseDouble(xy2.substring(xy2.indexOf(",") + 1)); int[] point2 = computedPoint(x2, y2); - handleContext.setStepDes("滑动拖拽" + des1 + "到" + des2); - handleContext.setDetail("拖动坐标(" + point1[0] + "," + point1[1] + ")到(" + point2[0] + "," + point2[1] + ")"); + handleContext.setStepDes("从" + des1 + "滑动到" + des2); + handleContext.setDetail("从坐标(" + point1[0] + "," + point1[1] + ")滑动到(" + point2[0] + "," + point2[1] + ")"); try { AndroidTouchHandler.swipe(iDevice, point1[0], point1[1], point2[0], point2[1]); } catch (Exception e) { @@ -738,14 +738,46 @@ public void swipe(HandleContext handleContext, String des, String selector, Stri int y1 = webElement.getRect().getY(); int x2 = webElement2.getRect().getX(); int y2 = webElement2.getRect().getY(); - handleContext.setStepDes("滑动拖拽" + des + "到" + des2); - handleContext.setDetail("拖动坐标(" + x1 + "," + y1 + ")到(" + x2 + "," + y2 + ")"); + handleContext.setStepDes("从" + des + "滑动到" + des2); + handleContext.setDetail("从坐标(" + x1 + "," + y1 + ")滑动到坐标(" + x2 + "," + y2 + ")"); AndroidTouchHandler.swipe(iDevice, x1, y1, x2, y2); } catch (Exception e) { handleContext.setE(e); } } + public void dragByPoint(HandleContext handleContext, String des1, String xy1, String des2, String xy2) { + double x1 = Double.parseDouble(xy1.substring(0, xy1.indexOf(","))); + double y1 = Double.parseDouble(xy1.substring(xy1.indexOf(",") + 1)); + int[] point1 = computedPoint(x1, y1); + double x2 = Double.parseDouble(xy2.substring(0, xy2.indexOf(","))); + double y2 = Double.parseDouble(xy2.substring(xy2.indexOf(",") + 1)); + int[] point2 = computedPoint(x2, y2); + handleContext.setStepDes("拖拽" + des1 + "到" + des2); + handleContext.setDetail("拖拽坐标(" + point1[0] + "," + point1[1] + ")到(" + point2[0] + "," + point2[1] + ")"); + try { + AndroidTouchHandler.drag(iDevice, point1[0], point1[1], point2[0], point2[1]); + } catch (Exception e) { + handleContext.setE(e); + } + } + + public void dragByEle(HandleContext handleContext, String des, String selector, String pathValue, String des2, String selector2, String pathValue2) { + try { + AndroidElement webElement = findEle(selector, pathValue); + AndroidElement webElement2 = findEle(selector2, pathValue2); + int x1 = webElement.getRect().getX(); + int y1 = webElement.getRect().getY(); + int x2 = webElement2.getRect().getX(); + int y2 = webElement2.getRect().getY(); + handleContext.setStepDes("拖拽" + des + "到" + des2); + handleContext.setDetail("拖拽坐标(" + x1 + "," + y1 + ")到(" + x2 + "," + y2 + ")"); + AndroidTouchHandler.drag(iDevice, x1, y1, x2, y2); + } catch (SonicRespException e) { + handleContext.setE(e); + } + } + public void swipeByDefinedDirection(HandleContext handleContext, String slideDirection, int distance) throws Exception { String size = AndroidDeviceBridgeTool.getScreenSize(iDevice); String[] winSize = size.split("x"); @@ -771,7 +803,7 @@ public void swipeByDefinedDirection(HandleContext handleContext, String slideDir } catch (Exception e) { handleContext.setE(e); } - handleContext.setDetail("拖动坐标(" + centerX + "," + centerY + ")到(" + centerX + "," + targetY + ")"); + handleContext.setDetail("从坐标(" + centerX + "," + centerY + ")滑动到坐标(" + centerX + "," + targetY + ")"); } case "down" -> { handleContext.setStepDes("从设备中心位置向下滑动" + distance + "像素"); @@ -785,7 +817,7 @@ public void swipeByDefinedDirection(HandleContext handleContext, String slideDir } catch (Exception e) { handleContext.setE(e); } - handleContext.setDetail("拖动坐标(" + centerX + "," + centerY + ")到(" + centerX + "," + targetY + ")"); + handleContext.setDetail("从坐标(" + centerX + "," + centerY + ")滑动到(" + centerX + "," + targetY + ")"); } case "left" -> { handleContext.setStepDes("从设备中心位置向左滑动" + distance + "像素"); @@ -799,7 +831,7 @@ public void swipeByDefinedDirection(HandleContext handleContext, String slideDir } catch (Exception e) { handleContext.setE(e); } - handleContext.setDetail("拖动坐标(" + centerX + "," + centerY + ")到(" + targetX + "," + centerY + ")"); + handleContext.setDetail("从坐标(" + centerX + "," + centerY + ")滑动到(" + targetX + "," + centerY + ")"); } case "right" -> { handleContext.setStepDes("从设备中心位置向右滑动" + distance + "像素"); @@ -813,7 +845,7 @@ public void swipeByDefinedDirection(HandleContext handleContext, String slideDir } catch (Exception e) { handleContext.setE(e); } - handleContext.setDetail("拖动坐标(" + centerX + "," + centerY + ")到(" + targetX + "," + centerY + ")"); + handleContext.setDetail("从坐标(" + centerX + "," + centerY + ")滑动到(" + targetX + "," + centerY + ")"); } default -> throw new Exception("Sliding in this direction is not supported. Only up/down/left/right are supported!"); @@ -1767,7 +1799,7 @@ public void getPocoElementAttr(HandleContext handleContext, String des, String s } public void obtainPocoElementAttr(HandleContext handleContext, String des, String selector, String pathValue, - String attr, String variable) { + String attr, String variable) { handleContext.setStepDes("获取控件 " + des + " 属性到变量"); handleContext.setDetail("目标属性:" + attr + ",目标变量:" + variable); try { @@ -2463,6 +2495,12 @@ public void runStep(JSONObject stepJSON, HandleContext handleContext) throws Thr case "swipe2" -> swipe(handleContext, eleList.getJSONObject(0).getString("eleName"), eleList.getJSONObject(0).getString("eleType"), eleList.getJSONObject(0).getString("eleValue") , eleList.getJSONObject(1).getString("eleName"), eleList.getJSONObject(1).getString("eleType"), eleList.getJSONObject(1).getString("eleValue")); + case "drag" -> + dragByPoint(handleContext, eleList.getJSONObject(0).getString("eleName"), eleList.getJSONObject(0).getString("eleValue") + , eleList.getJSONObject(1).getString("eleName"), eleList.getJSONObject(1).getString("eleValue")); + case "drag2" -> + dragByEle(handleContext, eleList.getJSONObject(0).getString("eleName"), eleList.getJSONObject(0).getString("eleType"), eleList.getJSONObject(0).getString("eleValue") + , eleList.getJSONObject(1).getString("eleName"), eleList.getJSONObject(1).getString("eleType"), eleList.getJSONObject(1).getString("eleValue")); case "tap" -> tap(handleContext, eleList.getJSONObject(0).getString("eleName"), eleList.getJSONObject(0).getString("eleValue")); case "longPressPoint" -> diff --git a/src/main/java/org/cloud/sonic/agent/tests/handlers/AndroidTouchHandler.java b/src/main/java/org/cloud/sonic/agent/tests/handlers/AndroidTouchHandler.java index c67297c2..a771525c 100755 --- a/src/main/java/org/cloud/sonic/agent/tests/handlers/AndroidTouchHandler.java +++ b/src/main/java/org/cloud/sonic/agent/tests/handlers/AndroidTouchHandler.java @@ -118,7 +118,7 @@ public static void swipe(IDevice iDevice, int x1, int y1, int x2, int y2, int sw int[] re2 = transferWithRotation(iDevice, x2, y2); writeToOutputStream(iDevice, String.format("down %d %d\n", re1[0], re1[1])); try { - Thread.sleep(300); + Thread.sleep(5); // 滑动效果不需要长按300ms } catch (InterruptedException e) { e.printStackTrace(); } @@ -167,6 +167,68 @@ public static void swipe(IDevice iDevice, int x1, int y1, int x2, int y2, int sw } } + public static void drag(IDevice iDevice, int x1, int y1, int x2, int y2) throws SonicRespException { + drag(iDevice, x1, y1, x2, y2, DEFAULT_SWIPE_DURATION); + } + + public static void drag(IDevice iDevice, int x1, int y1, int x2, int y2, int swipeDuration) throws SonicRespException { + switch (getTouchMode(iDevice)) { + case ADB -> + AndroidDeviceBridgeTool.executeCommand(iDevice, String.format("input draganddrop %d %d %d %d %d", x1, y1, x2, y2, swipeDuration)); + case APPIUM_UIAUTOMATOR2_SERVER -> { + AndroidStepHandler curStepHandler = HandlerMap.getAndroidMap().get(iDevice.getSerialNumber()); + if (curStepHandler != null && curStepHandler.getAndroidDriver() != null) { + curStepHandler.getAndroidDriver().drag(x1, y1, x2, y2, swipeDuration, null, null); + } + } + case SONIC_APK -> { + // 原本这段代码是在`swipe(IDevice iDevice, int x1, int y1, int x2, int y2, int swipeDuration)`中的 + // 但是swipe的效果应该是在屏幕滑动,而不是在第一个坐标按下时存在延迟,所以放在drag方法里面更加符合 + int[] re1 = transferWithRotation(iDevice, x1, y1); + int[] re2 = transferWithRotation(iDevice, x2, y2); + writeToOutputStream(iDevice, String.format("down %d %d\n", re1[0], re1[1])); + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + long startTime = System.currentTimeMillis(); + while (true) { + // 当前时间 + long currentTime = System.currentTimeMillis(); + // 计算时间进度 + float timeProgress = (currentTime - startTime) / (float) swipeDuration; + if (timeProgress >= 1.0f) { + // 已经过渡到结束值,停止过渡 + writeToOutputStream(iDevice, String.format("move %d %d\n", re2[0], re2[1])); + break; + } + BiFunction transitionX = (start, end) -> + (int) (start + (end - start) * timeProgress); + BiFunction transitionY = (start, end) -> + (int) (start + (end - start) * timeProgress); + + int currentX = transitionX.apply(re1[0], re2[0]); + int currentY = transitionY.apply(re1[1], re2[1]); + // 使用当前坐标进行操作 + writeToOutputStream(iDevice, String.format("move %d %d\n", currentX, currentY)); + try { + Thread.sleep(5); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + try { + Thread.sleep(200); + } catch (InterruptedException e) { + e.printStackTrace(); + } + writeToOutputStream(iDevice, "up\n"); + } + + } + } + private static int[] transferWithRotation(IDevice iDevice, int x, int y) { Integer directionStatus = AndroidDeviceManagerMap.getRotationMap().get(iDevice.getSerialNumber()); if (directionStatus == null) { From 6eed398567ceb9406be8e4e123c52ad18927ba72 Mon Sep 17 00:00:00 2001 From: YeungHoiChiu <1005935991@qq.com> Date: Mon, 3 Jun 2024 17:51:00 +0800 Subject: [PATCH 2/2] =?UTF-8?q?feat:=20=E5=AE=89=E5=8D=93=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=E8=A7=A6=E6=8E=A7=E6=89=8B=E5=8A=BF=E5=8A=A8=E4=BD=9C?= =?UTF-8?q?=E7=8B=AC=E7=AB=8B=E4=BA=8B=E4=BB=B6=EF=BC=88adb=20motionevent?= =?UTF-8?q?=20down=E6=8C=89=E4=B8=8B=E4=B8=8D=E6=9D=BE=E6=89=8B=E3=80=81up?= =?UTF-8?q?=E6=9D=BE=E6=89=8B=E4=BB=A5=E5=8F=8Amove=E7=A7=BB=E5=8A=A8?= =?UTF-8?q?=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../tests/handlers/AndroidStepHandler.java | 59 +++++++++++++++---- .../tests/handlers/AndroidTouchHandler.java | 17 ++++++ 2 files changed, 63 insertions(+), 13 deletions(-) diff --git a/src/main/java/org/cloud/sonic/agent/tests/handlers/AndroidStepHandler.java b/src/main/java/org/cloud/sonic/agent/tests/handlers/AndroidStepHandler.java index 9bb5374b..17a71eae 100755 --- a/src/main/java/org/cloud/sonic/agent/tests/handlers/AndroidStepHandler.java +++ b/src/main/java/org/cloud/sonic/agent/tests/handlers/AndroidStepHandler.java @@ -70,6 +70,7 @@ import org.springframework.util.CollectionUtils; import javax.imageio.stream.FileImageOutputStream; +import java.awt.desktop.AboutHandler; import java.io.File; import java.util.*; import java.util.concurrent.Future; @@ -427,7 +428,7 @@ public void appAutoGrantPermissions(HandleContext handleContext, String packageN String getDetailCommandResult = AndroidDeviceBridgeTool.executeCommand(iDevice, dumpsysCommandStr); List allPermissionItems = AndroidPermissionExtractor.extractPermissions(getDetailCommandResult, - Arrays.asList("install", "runtime"), true); + Arrays.asList("install", "runtime"), true); allPermissionItems.stream().filter(permissionItem -> !permissionItem.isGranted()) .forEach(permissionItem -> { String curPermission = permissionItem.getPermission(); @@ -778,6 +779,32 @@ public void dragByEle(HandleContext handleContext, String des, String selector, } } + public void motionEventByPoint(HandleContext handleContext, String des, String xy, String motionEventType) throws SonicRespException { + double x = Double.parseDouble(xy.substring(0, xy.indexOf(","))); + double y = Double.parseDouble(xy.substring(xy.indexOf(",") + 1)); + int[] point = computedPoint(x, y); + handleContext.setStepDes("通过坐标" + des + "触发" + motionEventType + "-Motion事件"); + handleContext.setDetail("对坐标" + point[0] + "," + point[1] + String.format("执行Motion事件(%s)", motionEventType)); + try { + AndroidTouchHandler.motionEvent(iDevice, motionEventType, point[0], point[1]); + } catch (SonicRespException e) { + handleContext.setE(e); + } + } + + public void motionEventByEle(HandleContext handleContext, String des, String selector, String pathValue, String motionEventType) throws SonicRespException { + try { + AndroidElement webElement = findEle(selector, pathValue); + int x = webElement.getRect().getX(); + int y = webElement.getRect().getY(); + handleContext.setStepDes("通过" + des + "触发" + motionEventType + "-Motion事件"); + handleContext.setDetail("对坐标" + x + "," + y + String.format("执行Motion事件(%s)", motionEventType)); + AndroidTouchHandler.motionEvent(iDevice, motionEventType, x, y); + } catch (SonicRespException e) { + handleContext.setE(e); + } + } + public void swipeByDefinedDirection(HandleContext handleContext, String slideDirection, int distance) throws Exception { String size = AndroidDeviceBridgeTool.getScreenSize(iDevice); String[] winSize = size.split("x"); @@ -2061,10 +2088,12 @@ public AndroidElement findEle(String selector, String pathValue, Integer retryTi switch (selector) { case "androidIterator" -> we = androidDriver.findElement(pathValue); case "id" -> we = androidDriver.findElement(AndroidSelector.Id, pathValue, retryTime); - case "accessibilityId" -> we = androidDriver.findElement(AndroidSelector.ACCESSIBILITY_ID, pathValue, retryTime); + case "accessibilityId" -> + we = androidDriver.findElement(AndroidSelector.ACCESSIBILITY_ID, pathValue, retryTime); case "xpath" -> we = androidDriver.findElement(AndroidSelector.XPATH, pathValue, retryTime); case "className" -> we = androidDriver.findElement(AndroidSelector.CLASS_NAME, pathValue, retryTime); - case "androidUIAutomator" -> we = androidDriver.findElement(AndroidSelector.UIAUTOMATOR, pathValue, retryTime); + case "androidUIAutomator" -> + we = androidDriver.findElement(AndroidSelector.UIAUTOMATOR, pathValue, retryTime); default -> log.sendStepLog(StepType.ERROR, "查找控件元素失败", "这个控件元素类型: " + selector + " 不存在!!!"); } @@ -2456,10 +2485,9 @@ public void runStep(JSONObject stepJSON, HandleContext handleContext) throws Thr case "getElementAttr" -> getElementAttr(handleContext, eleList.getJSONObject(0).getString("eleName"), eleList.getJSONObject(0).getString("eleType") , eleList.getJSONObject(0).getString("eleValue"), step.getString("text"), step.getString("content")); - case "obtainElementAttr" -> - obtainElementAttr(handleContext, eleList.getJSONObject(0).getString("eleName"), - eleList.getJSONObject(0).getString("eleType"), eleList.getJSONObject(0).getString("eleValue"), - step.getString("text"), step.getString("content")); + case "obtainElementAttr" -> obtainElementAttr(handleContext, eleList.getJSONObject(0).getString("eleName"), + eleList.getJSONObject(0).getString("eleType"), eleList.getJSONObject(0).getString("eleValue"), + step.getString("text"), step.getString("content")); case "logElementAttr" -> logElementAttr(handleContext, eleList.getJSONObject(0).getString("eleName"), eleList.getJSONObject(0).getString("eleType") , eleList.getJSONObject(0).getString("eleValue"), step.getString("text")); @@ -2472,12 +2500,11 @@ public void runStep(JSONObject stepJSON, HandleContext handleContext) throws Thr case "isExistEle" -> isExistEle(handleContext, eleList.getJSONObject(0).getString("eleName"), eleList.getJSONObject(0).getString("eleType") , eleList.getJSONObject(0).getString("eleValue"), step.getBoolean("content")); - case "scrollToEle" -> - scrollToEle(handleContext, eleList.getJSONObject(0).getString("eleName"), - eleList.getJSONObject(0).getString("eleType"), - eleList.getJSONObject(0).getString("eleValue"), - step.getInteger("content"), - step.getString("text")); + case "scrollToEle" -> scrollToEle(handleContext, eleList.getJSONObject(0).getString("eleName"), + eleList.getJSONObject(0).getString("eleType"), + eleList.getJSONObject(0).getString("eleValue"), + step.getInteger("content"), + step.getString("text")); case "isExistEleNum" -> isExistEleNum(handleContext, eleList.getJSONObject(0).getString("eleName"), eleList.getJSONObject(0).getString("eleType"), eleList.getJSONObject(0).getString("eleValue"), @@ -2501,6 +2528,12 @@ public void runStep(JSONObject stepJSON, HandleContext handleContext) throws Thr case "drag2" -> dragByEle(handleContext, eleList.getJSONObject(0).getString("eleName"), eleList.getJSONObject(0).getString("eleType"), eleList.getJSONObject(0).getString("eleValue") , eleList.getJSONObject(1).getString("eleName"), eleList.getJSONObject(1).getString("eleType"), eleList.getJSONObject(1).getString("eleValue")); + case "motionEvent" -> motionEventByEle(handleContext, eleList.getJSONObject(0).getString("eleName"), + eleList.getJSONObject(0).getString("eleType"), eleList.getJSONObject(0).getString("eleValue"), eleList.getJSONObject(0).getString("text")); + case "motionEventByPoint" -> + motionEventByPoint(handleContext, eleList.getJSONObject(0).getString("eleName"), + eleList.getJSONObject(0).getString("eleValue"), + eleList.getJSONObject(0).getString("text")); case "tap" -> tap(handleContext, eleList.getJSONObject(0).getString("eleName"), eleList.getJSONObject(0).getString("eleValue")); case "longPressPoint" -> diff --git a/src/main/java/org/cloud/sonic/agent/tests/handlers/AndroidTouchHandler.java b/src/main/java/org/cloud/sonic/agent/tests/handlers/AndroidTouchHandler.java index a771525c..296d1c77 100755 --- a/src/main/java/org/cloud/sonic/agent/tests/handlers/AndroidTouchHandler.java +++ b/src/main/java/org/cloud/sonic/agent/tests/handlers/AndroidTouchHandler.java @@ -229,6 +229,23 @@ public static void drag(IDevice iDevice, int x1, int y1, int x2, int y2, int swi } } + public static void motionEvent(IDevice iDevice, String motionEventType, int x1, int y1) throws SonicRespException { + switch (getTouchMode(iDevice)) { + case ADB -> + AndroidDeviceBridgeTool.executeCommand(iDevice, String.format("input motionevent %s %d %d", motionEventType, x1, y1)); + case SONIC_APK -> { + int[] re1 = transferWithRotation(iDevice, x1, y1); + writeToOutputStream(iDevice, String.format("%s %d %d\n", motionEventType.toLowerCase(), re1[0], re1[1])); + } + case APPIUM_UIAUTOMATOR2_SERVER -> { + AndroidStepHandler curStepHandler = HandlerMap.getAndroidMap().get(iDevice.getSerialNumber()); + if (curStepHandler != null && curStepHandler.getAndroidDriver() != null) { + curStepHandler.getAndroidDriver().touchAction(motionEventType.toLowerCase(), x1, y1); + } + } + } + } + private static int[] transferWithRotation(IDevice iDevice, int x, int y) { Integer directionStatus = AndroidDeviceManagerMap.getRotationMap().get(iDevice.getSerialNumber()); if (directionStatus == null) {