diff --git a/mini/minicap-shared/aosp/libs/android-31/arm64-v8a/minicap.so b/mini/minicap-shared/aosp/libs/android-31/arm64-v8a/minicap.so new file mode 100644 index 00000000..999bbb4c Binary files /dev/null and b/mini/minicap-shared/aosp/libs/android-31/arm64-v8a/minicap.so differ diff --git a/mini/minicap-shared/aosp/libs/android-31/armeabi-v7a/minicap.so b/mini/minicap-shared/aosp/libs/android-31/armeabi-v7a/minicap.so new file mode 100644 index 00000000..68dc9cad Binary files /dev/null and b/mini/minicap-shared/aosp/libs/android-31/armeabi-v7a/minicap.so differ diff --git a/mini/minicap-shared/aosp/libs/android-31/x86/minicap.so b/mini/minicap-shared/aosp/libs/android-31/x86/minicap.so new file mode 100644 index 00000000..7f85e1a5 Binary files /dev/null and b/mini/minicap-shared/aosp/libs/android-31/x86/minicap.so differ diff --git a/mini/minicap-shared/aosp/libs/android-31/x86_64/minicap.so b/mini/minicap-shared/aosp/libs/android-31/x86_64/minicap.so new file mode 100644 index 00000000..03db4255 Binary files /dev/null and b/mini/minicap-shared/aosp/libs/android-31/x86_64/minicap.so differ diff --git a/pom.xml b/pom.xml index f58642eb..37df2cce 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ com.sonic sonic-agent - 1.0.0 + 1.1.2 jar @@ -66,7 +66,7 @@ io.appium java-client - 7.5.1 + 7.6.0 diff --git a/src/main/java/com/sonic/agent/automation/AndroidStepHandler.java b/src/main/java/com/sonic/agent/automation/AndroidStepHandler.java index 7fab105f..497e3225 100644 --- a/src/main/java/com/sonic/agent/automation/AndroidStepHandler.java +++ b/src/main/java/com/sonic/agent/automation/AndroidStepHandler.java @@ -16,9 +16,7 @@ import com.sonic.agent.interfaces.PlatformType; import com.sonic.agent.tools.PortTool; import com.sonic.agent.tools.UploadTools; -import io.appium.java_client.MobileBy; -import io.appium.java_client.MultiTouchAction; -import io.appium.java_client.TouchAction; +import io.appium.java_client.*; import io.appium.java_client.android.AndroidDriver; import io.appium.java_client.android.AndroidStartScreenRecordingOptions; import io.appium.java_client.android.appmanagement.AndroidInstallApplicationOptions; @@ -48,6 +46,7 @@ import java.time.Duration; import java.util.*; import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import static org.testng.Assert.*; @@ -62,7 +61,7 @@ public class AndroidStepHandler { private AndroidDriver androidDriver; private JSONObject globalParams = new JSONObject(); //包版本 - private String version = ""; +// private String version = ""; //测试起始时间 private long startTime; //测试的包名 @@ -134,6 +133,7 @@ public void startAndroidDriver(String udId) throws InterruptedException { desiredCapabilities.setCapability("skipLogcatCapture", true); try { androidDriver = new AndroidDriver(AppiumServer.service.getUrl(), desiredCapabilities); + androidDriver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS); log.sendStepLog(StepType.PASS, "连接设备驱动成功", ""); } catch (Exception e) { log.sendStepLog(StepType.ERROR, "连接设备驱动失败!", ""); @@ -1378,10 +1378,10 @@ public void runMonkey(HandleDes handleDes, JSONObject content, List } catch (InterruptedException e) { e.printStackTrace(); } - if (version.length() == 0) { - version = AndroidDeviceBridgeTool.getAppOnlyVersion(udId, packageName); - } - log.sendStepLog(StepType.INFO, "", packageName + "包版本:" + version + +// if (version.length() == 0) { +// version = AndroidDeviceBridgeTool.getAppOnlyVersion(udId, packageName); +// } + log.sendStepLog(StepType.INFO, "", "测试目标包:" + packageName + (isOpenPackageListener ? "
应用包名监听器已开启..." : "") + (isOpenH5Listener ? "
H5页面监听器已开启..." : "") + (isOpenActivityListener ? "
黑名单Activity监听器..." : "") + @@ -1406,32 +1406,31 @@ public void publicStep(HandleDes handleDes, String name, JSONArray stepArray) { } public WebElement findEle(String selector, String pathValue) { - WebDriverWait wait = new WebDriverWait(androidDriver, 10);//显式等待 WebElement we = null; switch (selector) { case "id": - we = wait.until(ExpectedConditions.presenceOfElementLocated(MobileBy.id(pathValue))); + we = androidDriver.findElementById(pathValue); break; case "name": - we = wait.until(ExpectedConditions.presenceOfElementLocated(MobileBy.name(pathValue))); + we = androidDriver.findElementByName(pathValue); break; case "xpath": - we = wait.until(ExpectedConditions.presenceOfElementLocated(MobileBy.xpath(pathValue))); + we = androidDriver.findElementByXPath(pathValue); break; case "cssSelector": - we = wait.until(ExpectedConditions.presenceOfElementLocated(MobileBy.cssSelector(pathValue))); + we = androidDriver.findElementByCssSelector(pathValue); break; case "className": - we = wait.until(ExpectedConditions.presenceOfElementLocated(MobileBy.className(pathValue))); + we = androidDriver.findElementByClassName(pathValue); break; case "tagName": - we = wait.until(ExpectedConditions.presenceOfElementLocated(MobileBy.tagName(pathValue))); + we = androidDriver.findElementByTagName(pathValue); break; case "linkText": - we = wait.until(ExpectedConditions.presenceOfElementLocated(MobileBy.linkText(pathValue))); + we = androidDriver.findElementByLinkText(pathValue); break; case "partialLinkText": - we = wait.until(ExpectedConditions.presenceOfElementLocated(MobileBy.partialLinkText(pathValue))); + we = androidDriver.findElementByPartialLinkText(pathValue); break; default: log.sendStepLog(StepType.ERROR, "查找控件元素失败", "这个控件元素类型: " + selector + " 不存在!!!"); diff --git a/src/main/java/com/sonic/agent/automation/RemoteDebugDriver.java b/src/main/java/com/sonic/agent/automation/RemoteDebugDriver.java index a6813b59..9024f7b7 100644 --- a/src/main/java/com/sonic/agent/automation/RemoteDebugDriver.java +++ b/src/main/java/com/sonic/agent/automation/RemoteDebugDriver.java @@ -2,11 +2,14 @@ import com.google.common.collect.ImmutableMap; import com.sonic.agent.tools.PortTool; +import com.sonic.agent.websockets.WebViewWSServer; import org.mitre.dsmiley.httpproxy.ProxyServlet; import org.openqa.selenium.WebDriver; import org.openqa.selenium.chrome.ChromeDriver; import org.openqa.selenium.chrome.ChromeOptions; import org.openqa.selenium.remote.DesiredCapabilities; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.web.servlet.ServletRegistrationBean; import org.springframework.context.annotation.Bean; @@ -24,6 +27,7 @@ */ @Configuration public class RemoteDebugDriver { + private static final Logger logger = LoggerFactory.getLogger(RemoteDebugDriver.class); private static String chromePath; public static int port = 0; public static WebDriver webDriver; @@ -54,19 +58,26 @@ public ServletRegistrationBean proxyServletRegistration() { @Bean @DependsOn(value = "setChromePath") public static void startChromeDriver() { - DesiredCapabilities desiredCapabilities = new DesiredCapabilities(); - ChromeOptions chromeOptions = new ChromeOptions(); - System.setProperty("webdriver.chrome.driver", chromePath); - if (port == 0) { - int debugPort = PortTool.getPort(); - port = debugPort; - chromeOptions.addArguments("--remote-debugging-port=" + debugPort); - } else { - chromeOptions.addArguments("--remote-debugging-port=" + port); + try { + DesiredCapabilities desiredCapabilities = new DesiredCapabilities(); + ChromeOptions chromeOptions = new ChromeOptions(); + System.setProperty("webdriver.chrome.driver", chromePath); + if (port == 0) { + int debugPort = PortTool.getPort(); + port = debugPort; + chromeOptions.addArguments("--remote-debugging-port=" + debugPort); + } else { + chromeOptions.addArguments("--remote-debugging-port=" + port); + } + chromeOptions.addArguments("--headless"); + chromeOptions.addArguments("--no-sandbox"); + chromeOptions.addArguments("--disable-gpu"); + chromeOptions.addArguments("--disable-dev-shm-usage"); + desiredCapabilities.setCapability(ChromeOptions.CAPABILITY, chromeOptions); + webDriver = new ChromeDriver(desiredCapabilities); + } catch (Exception e) { + logger.info("chromeDriver启动失败!"); } - chromeOptions.addArguments("--headless"); - desiredCapabilities.setCapability(ChromeOptions.CAPABILITY, chromeOptions); - webDriver = new ChromeDriver(desiredCapabilities); } public static void close() { diff --git a/src/main/java/com/sonic/agent/bridge/android/AndroidDeviceBridgeTool.java b/src/main/java/com/sonic/agent/bridge/android/AndroidDeviceBridgeTool.java index b0834b50..3bcc0fb9 100644 --- a/src/main/java/com/sonic/agent/bridge/android/AndroidDeviceBridgeTool.java +++ b/src/main/java/com/sonic/agent/bridge/android/AndroidDeviceBridgeTool.java @@ -1,17 +1,17 @@ package com.sonic.agent.bridge.android; +import com.alibaba.fastjson.JSONObject; import com.android.ddmlib.*; -import com.sonic.agent.exception.SonicException; import com.sonic.agent.tools.DownImageTool; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.annotation.DependsOn; import org.springframework.stereotype.Component; +import javax.websocket.Session; import java.io.File; import java.io.IOException; import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; /** * @author ZhouYiXun @@ -216,19 +216,19 @@ public static void removeForward(IDevice iDevice, int port, String serviceName) * @des 推送文件 * @date 2021/8/16 19:59 */ - public static void pushLocalFile(IDevice iDevice, String localPath, String remotePath) { - AndroidDeviceThreadPool.cachedThreadPool.execute(() -> { - //使用iDevice的pushFile方法好像有bug,暂时用命令行去推送 - ProcessBuilder pb = new ProcessBuilder(new String[]{getADBPathFromSystemEnv(), "-s", iDevice.getSerialNumber(), "push", localPath, remotePath}); - pb.redirectErrorStream(true); - try { - pb.start(); - } catch (IOException e) { - logger.error(e.getMessage()); - return; - } - }); - } +// public static void pushLocalFile(IDevice iDevice, String localPath, String remotePath) { +// AndroidDeviceThreadPool.cachedThreadPool.execute(() -> { +// //使用iDevice的pushFile方法好像有bug,暂时用命令行去推送 +// ProcessBuilder pb = new ProcessBuilder(new String[]{getADBPathFromSystemEnv(), "-s", iDevice.getSerialNumber(), "push", localPath, remotePath}); +// pb.redirectErrorStream(true); +// try { +// pb.start(); +// } catch (IOException e) { +// logger.error(e.getMessage()); +// return; +// } +// }); +// } /** * @param iDevice @@ -329,39 +329,35 @@ public static String matchMiniTouchFile(String sdk) { } public static void pushYadb(IDevice iDevice) { - String yadbFile = executeCommand(iDevice, " ls /data/local/tmp | grep yadb"); - if (yadbFile != null && yadbFile.contains("yadb")) { - return; - } else { - File yadbLocalFile = new File("plugins" + File.separator + "yadb"); - pushLocalFile(iDevice, yadbLocalFile.getPath(), "/data/local/tmp/yadb"); - boolean yadbFileExist = false; - //轮训目录,直到推送文件结束 - while (!yadbFileExist) { - String yadbDeviceFile = executeCommand(iDevice, " ls /data/local/tmp | grep yadb"); - if (yadbDeviceFile != null && yadbDeviceFile.contains("yadb")) { - yadbFileExist = true; - } - } - executeCommand(iDevice, "chmod 777 /data/local/tmp/yadb"); + executeCommand(iDevice, "rm -rf /data/local/tmp/yadb"); + File yadbLocalFile = new File("plugins" + File.separator + "yadb"); + try { + iDevice.pushFile(yadbLocalFile.getAbsolutePath(), "/data/local/tmp/yadb"); + } catch (IOException e) { + e.printStackTrace(); + } catch (AdbCommandRejectedException e) { + e.printStackTrace(); + } catch (TimeoutException e) { + e.printStackTrace(); + } catch (SyncException e) { + e.printStackTrace(); } + executeCommand(iDevice, "chmod 777 /data/local/tmp/yadb"); } public static void pushToCamera(IDevice iDevice, String url) { try { File image = DownImageTool.download(url); - pushLocalFile(iDevice, image.getPath(), "/sdcard/DCIM/Camera/" + image.getName()); - boolean fileExist = false; - //轮训目录,直到推送文件结束 - while (!fileExist) { - String files = executeCommand(iDevice, " ls /sdcard/DCIM/Camera | grep " + image.getName()); - if (files != null && files.contains(image.getName())) { - fileExist = true; - } - } + iDevice.pushFile(image.getAbsolutePath(), "/sdcard/DCIM/Camera/" + image.getName()); executeCommand(iDevice, "am broadcast -a android.intent.action.MEDIA_SCANNER_SCAN_FILE -d file:///sdcard/DCIM/Camera/" + image.getName()); } catch (IOException e) { e.printStackTrace(); + } catch (AdbCommandRejectedException e) { + e.printStackTrace(); + } catch (SyncException e) { + e.printStackTrace(); + } catch (TimeoutException e) { + e.printStackTrace(); } } @@ -373,7 +369,7 @@ public static void pushToCamera(IDevice iDevice, String url) { * @des 开启miniCap服务 * @date 2021/8/16 20:04 */ - public static void startMiniCapServer(IDevice iDevice, int quality, int screen) throws SonicException { + public static void startMiniCapServer(IDevice iDevice, int quality, int screen, Session session) throws AdbCommandRejectedException, IOException, SyncException, TimeoutException { //先删除原有路径下的文件,防止上次出错后停止,再次打开会报错的情况 executeCommand(iDevice, "rm -rf /data/local/tmp/minicap*"); //获取cpu信息 @@ -385,32 +381,28 @@ public static void startMiniCapServer(IDevice iDevice, int quality, int screen) File miniCapFile = new File("mini" + File.separator + cpuAbi + File.separator + miniCapFileName); File miniCapSoFile = new File("mini/minicap-shared/aosp/libs/android-" + androidSdkVersion + File.separator + cpuAbi + File.separator + "minicap.so"); - pushLocalFile(iDevice, miniCapFile.getPath(), "/data/local/tmp/" + miniCapFileName); - pushLocalFile(iDevice, miniCapSoFile.getPath(), "/data/local/tmp/minicap.so"); - boolean miniCapFileExist = false; - //轮训目录,直到推送文件结束 - while (!miniCapFileExist) { - String miniCapBin = executeCommand(iDevice, " ls /data/local/tmp | grep " + miniCapFileName); - String miniCapSo = executeCommand(iDevice, " ls /data/local/tmp | grep minicap.so"); - if (miniCapBin != null && miniCapBin.contains(miniCapFileName) && miniCapSo != null && miniCapSo.contains("minicap.so")) { - miniCapFileExist = true; - } - } + iDevice.pushFile(miniCapFile.getAbsolutePath(), "/data/local/tmp/" + miniCapFileName); + iDevice.pushFile(miniCapSoFile.getAbsolutePath(), "/data/local/tmp/minicap.so"); //给文件权限 executeCommand(iDevice, "chmod 777 /data/local/tmp/" + miniCapFileName); String size = getScreenSize(iDevice); - AtomicBoolean isSupport = new AtomicBoolean(true); + String vSize = Integer.parseInt(size.substring(0, size.indexOf("x"))) / 2 + "x" + Integer.parseInt(size.substring(size.indexOf("x") + 1)) / 2; try { //开始启动 - iDevice.executeShellCommand(String.format("LD_LIBRARY_PATH=/data/local/tmp /data/local/tmp/%s -Q " + quality + " -P %s@%s/%d", miniCapFileName, size, size, screen), new IShellOutputReceiver() { + iDevice.executeShellCommand(String.format("LD_LIBRARY_PATH=/data/local/tmp /data/local/tmp/%s -Q " + quality + " -P %s@%s/%d", + miniCapFileName, size, vSize, screen), new IShellOutputReceiver() { @Override public void addOutput(byte[] bytes, int i, int i1) { String res = new String(bytes, i, i1); logger.info(res); if (res.contains("Vector<> have different types")) { - isSupport.set(false); logger.info(iDevice.getSerialNumber() + "设备不兼容投屏!"); - return; + if (session != null) { + JSONObject support = new JSONObject(); + support.put("msg", "support"); + support.put("text", "该设备不兼容MiniCap投屏!"); + sendText(session, support.toJSONString()); + } } } @@ -428,8 +420,15 @@ public boolean isCancelled() { , iDevice.getSerialNumber()); logger.error(e.getMessage()); } - if (!isSupport.get()) { - throw new SonicException("该设备不兼容投屏!"); + } + + private static void sendText(Session session, String message) { + synchronized (session) { + try { + session.getBasicRemote().sendText(message); + } catch (IllegalStateException | IOException e) { + logger.error("socket发送失败!连接已关闭!"); + } } } @@ -440,7 +439,7 @@ public boolean isCancelled() { * @des 开启miniTouch服务 * @date 2021/8/16 20:26 */ - public static void miniTouchStart(IDevice iDevice) { + public static void miniTouchStart(IDevice iDevice) throws AdbCommandRejectedException, IOException, SyncException, TimeoutException { //先删除原有路径下的文件,防止上次出错后停止,再次打开会报错的情况 executeCommand(iDevice, "rm -rf /data/local/tmp/minitouch*"); //获取cpu信息 @@ -449,15 +448,7 @@ public static void miniTouchStart(IDevice iDevice) { String androidSdkVersion = getProperties(iDevice, "ro.build.version.sdk"); String miniTouchFileName = matchMiniTouchFile(androidSdkVersion); File miniTouchFile = new File("mini" + File.separator + cpuAbi + File.separator + miniTouchFileName); - pushLocalFile(iDevice, miniTouchFile.getAbsolutePath(), "/data/local/tmp/" + miniTouchFileName); - boolean miniTouchFileExist = false; - //轮训目录,直到推送文件结束 - while (!miniTouchFileExist) { - String miniTouchBin = executeCommand(iDevice, " ls /data/local/tmp | grep " + miniTouchFileName); - if (miniTouchBin != null && miniTouchBin.contains(miniTouchFileName)) { - miniTouchFileExist = true; - } - } + iDevice.pushFile(miniTouchFile.getAbsolutePath(), "/data/local/tmp/" + miniTouchFileName); //给文件权限 executeCommand(iDevice, "chmod 777 /data/local/tmp/" + miniTouchFileName); try { @@ -493,15 +484,15 @@ public boolean isCancelled() { * @des 获取app版本信息 * @date 2021/8/16 15:29 */ - public static String getAppOnlyVersion(String udId, String packageName) { - IDevice iDevice = getIDeviceByUdId(udId); - //实质是获取安卓开发在gradle定义的versionName来定义版本号 - String version = executeCommand(iDevice, String.format("pm dump %s | grep 'versionName'", packageName)); - version = version.substring(version.indexOf("=") + 1, version.length() - 1); - if (version.length() > 50) { - version = version.substring(0, version.indexOf(" ") + 1); - } - //因为不同设备获取的信息不一样,所以需要去掉\r、\n - return version.replace("\r", "").replace("\n", ""); - } +// public static String getAppOnlyVersion(String udId, String packageName) { +// IDevice iDevice = getIDeviceByUdId(udId); +// //实质是获取安卓开发在gradle定义的versionName来定义版本号 +// String version = executeCommand(iDevice, String.format("pm dump %s | grep 'versionName'", packageName)); +// version = version.substring(version.indexOf("=") + 1, version.length() - 1); +// if (version.length() > 50) { +// version = version.substring(0, version.indexOf(" ") + 1); +// } +// //因为不同设备获取的信息不一样,所以需要去掉\r、\n +// return version.replace("\r", "").replace("\n", ""); +// } } diff --git a/src/main/java/com/sonic/agent/exception/SonicException.java b/src/main/java/com/sonic/agent/exception/SonicException.java deleted file mode 100644 index f4497fa2..00000000 --- a/src/main/java/com/sonic/agent/exception/SonicException.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.sonic.agent.exception; - -/** - * @author ZhouYiXun - * @des - * @date 2021/10/10 11:57 - */ -public class SonicException extends Exception { - public SonicException(String message) { - super(message); - } -} diff --git a/src/main/java/com/sonic/agent/tools/MiniCapTool.java b/src/main/java/com/sonic/agent/tools/MiniCapTool.java index e7a8447f..350b391a 100644 --- a/src/main/java/com/sonic/agent/tools/MiniCapTool.java +++ b/src/main/java/com/sonic/agent/tools/MiniCapTool.java @@ -1,10 +1,12 @@ package com.sonic.agent.tools; import com.alibaba.fastjson.JSONObject; +import com.android.ddmlib.AdbCommandRejectedException; import com.android.ddmlib.IDevice; +import com.android.ddmlib.SyncException; +import com.android.ddmlib.TimeoutException; import com.sonic.agent.bridge.android.AndroidDeviceBridgeTool; import com.sonic.agent.bridge.android.AndroidDeviceThreadPool; -import com.sonic.agent.exception.SonicException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -34,13 +36,13 @@ public Future start(String udId, AtomicReference banner, AtomicRefe int qua = 0; switch (pic) { case "low": - qua = 5; + qua = 10; break; case "middle": - qua = 10; + qua = 30; break; case "high": - qua = 50; + qua = 60; break; } int s; @@ -69,12 +71,15 @@ public Future start(String udId, AtomicReference banner, AtomicRefe Future miniCapPro = AndroidDeviceThreadPool.cachedThreadPool.submit(() -> { try { - AndroidDeviceBridgeTool.startMiniCapServer(iDevice, finalQua, finalC); - } catch (SonicException e) { - JSONObject support = new JSONObject(); - support.put("msg", "support"); - support.put("text", e.getMessage()); - sendText(session, support.toJSONString()); + AndroidDeviceBridgeTool.startMiniCapServer(iDevice, finalQua, finalC, session); + } catch (AdbCommandRejectedException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } catch (SyncException e) { + e.printStackTrace(); + } catch (TimeoutException e) { + e.printStackTrace(); } }); try { @@ -91,21 +96,15 @@ public Future start(String udId, AtomicReference banner, AtomicRefe try { capSocket = new Socket("localhost", finalMiniCapPort); inputStream = capSocket.getInputStream(); - int len = 4096; while (!finalMiniCapPro.isDone()) { - byte[] buffer = new byte[len]; - int realLen = 0; - try { - realLen = inputStream.read(buffer); - } catch (IOException e) { - e.printStackTrace(); - } - if (buffer.length != realLen && realLen >= 0) { - buffer = subByteArray(buffer, 0, realLen); - } - if (realLen >= 0) { - dataQueue.offer(buffer); + byte[] buffer; + int len = 0; + while (len == 0) { + len = inputStream.available(); } + buffer = new byte[len]; + inputStream.read(buffer); + dataQueue.add(buffer); } } catch (IOException e) { e.printStackTrace(); @@ -136,7 +135,7 @@ public Future start(String udId, AtomicReference banner, AtomicRefe AndroidDeviceThreadPool.cachedThreadPool.execute(() -> { int readBannerBytes = 0; - int bannerLength = 24; + int bannerLength = 2; int readFrameBytes = 0; int frameBodyLength = 0; byte[] frameBody = new byte[0]; diff --git a/src/main/java/com/sonic/agent/tools/ScrcpyTool.java b/src/main/java/com/sonic/agent/tools/ScrcpyTool.java new file mode 100644 index 00000000..eb3402d7 --- /dev/null +++ b/src/main/java/com/sonic/agent/tools/ScrcpyTool.java @@ -0,0 +1,26 @@ +package com.sonic.agent.tools; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.Socket; + +public class ScrcpyTool { + public static void main(String[] args) throws IOException { + Socket capSocket; + OutputStream outputStream; + InputStream inputStream; + capSocket = new Socket("localhost", 8666); + outputStream = capSocket.getOutputStream(); + inputStream = capSocket.getInputStream(); + outputStream.write(0); + while (capSocket.isConnected()) { + System.out.println(inputStream.read()); + } + System.out.println(1); + } + + public void startScrcpyServer() { + + } +} diff --git a/src/main/java/com/sonic/agent/websockets/AndroidWSServer.java b/src/main/java/com/sonic/agent/websockets/AndroidWSServer.java index 57c8f525..ef40a048 100644 --- a/src/main/java/com/sonic/agent/websockets/AndroidWSServer.java +++ b/src/main/java/com/sonic/agent/websockets/AndroidWSServer.java @@ -3,7 +3,10 @@ import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; +import com.android.ddmlib.AdbCommandRejectedException; import com.android.ddmlib.IDevice; +import com.android.ddmlib.SyncException; +import com.android.ddmlib.TimeoutException; import com.sonic.agent.automation.AndroidStepHandler; import com.sonic.agent.automation.HandleDes; import com.sonic.agent.automation.RemoteDebugDriver; @@ -114,7 +117,19 @@ public void onOpen(Session session, @PathParam("key") String secretKey, @PathPar if (devicePlatformVersion < 9) { int finalMiniTouchPort = PortTool.getPort(); - Future miniTouchPro = AndroidDeviceThreadPool.cachedThreadPool.submit(() -> AndroidDeviceBridgeTool.miniTouchStart(iDevice)); + Future miniTouchPro = AndroidDeviceThreadPool.cachedThreadPool.submit(() -> { + try { + AndroidDeviceBridgeTool.miniTouchStart(iDevice); + } catch (AdbCommandRejectedException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } catch (SyncException e) { + e.printStackTrace(); + } catch (TimeoutException e) { + e.printStackTrace(); + } + }); AndroidDeviceThreadPool.cachedThreadPool.execute(() -> { try { Thread.sleep(3000); @@ -185,8 +200,12 @@ public void onMessage(String message, Session session) throws InterruptedExcepti case "forwardView": { JSONObject forwardView = new JSONObject(); IDevice iDevice = udIdMap.get(session); - List webViewList = Arrays.asList(AndroidDeviceBridgeTool - .executeCommand(iDevice, "cat /proc/net/unix | grep webview").split("\n")); + List wList = Arrays.asList("webview", "WebView"); + List webViewList = new ArrayList<>(); + for (String w : wList) { + webViewList.addAll(Arrays.asList(AndroidDeviceBridgeTool + .executeCommand(iDevice, "cat /proc/net/unix | grep " + w).split("\n"))); + } Set webSet = new HashSet<>(); for (String w : webViewList) { if (w.contains("@") && w.indexOf("@") + 1 < w.length()) { @@ -213,11 +232,15 @@ public void onMessage(String message, Session session) throws InterruptedExcepti has.add(j); JSONObject r = new JSONObject(); r.put("port", port); - ResponseEntity infoEntity = - restTemplate.exchange("http://localhost:" + port + "/json/version", HttpMethod.GET, new HttpEntity(headers), LinkedHashMap.class); - if (infoEntity.getStatusCode() == HttpStatus.OK) { - r.put("version", infoEntity.getBody().get("Browser")); - r.put("package", infoEntity.getBody().get("Android-Package")); + try { + ResponseEntity infoEntity = + restTemplate.exchange("http://localhost:" + port + "/json/version", HttpMethod.GET, new HttpEntity(headers), LinkedHashMap.class); + if (infoEntity.getStatusCode() == HttpStatus.OK) { + r.put("version", infoEntity.getBody().get("Browser")); + r.put("package", infoEntity.getBody().get("Android-Package")); + } + } catch (Exception e) { + continue; } ResponseEntity responseEntity = restTemplate.exchange("http://localhost:" + port + "/json/list", HttpMethod.GET, new HttpEntity(headers), JSONArray.class); @@ -338,7 +361,7 @@ public void onMessage(String message, Session session) throws InterruptedExcepti int y1 = Integer.parseInt(xy1.substring(xy1.indexOf(",") + 1)); int x2 = Integer.parseInt(xy2.substring(0, xy2.indexOf(","))); int y2 = Integer.parseInt(xy2.substring(xy2.indexOf(",") + 1)); - AndroidDeviceBridgeTool.executeCommand(udIdMap.get(session), "input swipe " + x1 + " " + y1 + " " + x2 + " " + y2 + " 300"); + AndroidDeviceBridgeTool.executeCommand(udIdMap.get(session), "input swipe " + x1 + " " + y1 + " " + x2 + " " + y2 + " 200"); } } catch (Exception e) { e.printStackTrace(); diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml index ccade71d..84033be8 100644 --- a/src/main/resources/application-dev.yml +++ b/src/main/resources/application-dev.yml @@ -7,8 +7,8 @@ spring: rabbitmq: host: localhost port: 5672 - username: guest - password: guest + username: sonic + password: sonic virtual-host: sonic listener: simple: @@ -26,9 +26,9 @@ logging: sonic: chrome: - path: C:\\Program Files (x86)\\Google\\Chrome\\Application\\chromedriver.exe + path: C:\Program Files\Google\Chrome\Application\chromedriver.exe folder: url: http://localhost:8094/api/folder agent: host: 127.0.0.1 - key: 1 + key: 29002272-4659-4808-a804-08ce3388b136 diff --git a/src/main/resources/application-prod.yml b/src/main/resources/application-prod.yml new file mode 100644 index 00000000..0f14f387 --- /dev/null +++ b/src/main/resources/application-prod.yml @@ -0,0 +1,44 @@ +server: + #Agent服务的端口,可以自行更改 + port: 7777 + +spring: + application: + name: apex-agent + rabbitmq: + #rabbitMQ的host地址(如果用体验版的mq,这个host改为部署体验版机器的ip) + host: localhost + #如果用体验版的mq,这里是5673 + port: 5673 + #MQ的用户名 + username: guest + #MQ的密码 + password: guest + #MQ的vHost + virtual-host: / + listener: + simple: + acknowledge-mode: manual + publisher-confirm-type: correlated + publisher-returns: true + +logging: + file: + name: logs/${spring.application.name}.log + logback: + rollingpolicy: + clean-history-on-start: true + max-history: 3 + +sonic: + chrome: + # Agent机器上的chrome浏览器的driver路径,可以去http://npm.taobao.org/mirrors/chromedriver/下载 + path: C:\Program Files\Google\Chrome\Application\chromedriver.exe + folder: + # 如果跨网段,这个host和port改成后端的host和port + url: http://localhost:8094/api/folder + agent: + # 替换为部署Agent机器的ipv4 + host: 127.0.0.1 + # 替换为前端新增Agent生成的key + key: 29002272-4659-4808-a804-08ce3388b136