diff --git a/pom.xml b/pom.xml
index ce841fde..21f338b9 100644
--- a/pom.xml
+++ b/pom.xml
@@ -4,9 +4,9 @@
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0
- com.sonic
+ org.cloud.sonic
sonic-agent
- v1.3.0-beta1.1
+ v1.3.0-release
jar
diff --git a/src/main/java/com/sonic/agent/AgentApplication.java b/src/main/java/org/cloud/sonic/agent/AgentApplication.java
similarity index 91%
rename from src/main/java/com/sonic/agent/AgentApplication.java
rename to src/main/java/org/cloud/sonic/agent/AgentApplication.java
index 51f9adbe..06b34b00 100644
--- a/src/main/java/com/sonic/agent/AgentApplication.java
+++ b/src/main/java/org/cloud/sonic/agent/AgentApplication.java
@@ -1,33 +1,33 @@
-package com.sonic.agent;
-
-import com.sonic.agent.tools.SpringTool;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.boot.SpringApplication;
-import org.springframework.boot.autoconfigure.SpringBootApplication;
-import org.springframework.boot.web.embedded.tomcat.TomcatConnectorCustomizer;
-import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Import;
-
-/**
- * @author ZhouYiXun
- * @des Agent端启动类
- * @date 2021/08/16 19:26
- */
-@Import(SpringTool.class)
-@SpringBootApplication
-public class AgentApplication {
- @Value("${sonic.agent.port}")
- private int port;
-
- public static void main(String[] args) {
- SpringApplication.run(AgentApplication.class, args);
- }
-
- @Bean
- public TomcatServletWebServerFactory servletContainer() {
- TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory(port);
- factory.addConnectorCustomizers((TomcatConnectorCustomizer) connector -> connector.setProperty("relaxedQueryChars", "|{}[]\\"));
- return factory;
- }
-}
+package org.cloud.sonic.agent;
+
+import org.cloud.sonic.agent.tools.SpringTool;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.web.embedded.tomcat.TomcatConnectorCustomizer;
+import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Import;
+
+/**
+ * @author ZhouYiXun
+ * @des Agent端启动类
+ * @date 2021/08/16 19:26
+ */
+@Import(SpringTool.class)
+@SpringBootApplication
+public class AgentApplication {
+ @Value("${sonic.agent.port}")
+ private int port;
+
+ public static void main(String[] args) {
+ SpringApplication.run(AgentApplication.class, args);
+ }
+
+ @Bean
+ public TomcatServletWebServerFactory servletContainer() {
+ TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory(port);
+ factory.addConnectorCustomizers((TomcatConnectorCustomizer) connector -> connector.setProperty("relaxedQueryChars", "|{}[]\\"));
+ return factory;
+ }
+}
diff --git a/src/main/java/com/sonic/agent/automation/AndroidStepHandler.java b/src/main/java/org/cloud/sonic/agent/automation/AndroidStepHandler.java
similarity index 96%
rename from src/main/java/com/sonic/agent/automation/AndroidStepHandler.java
rename to src/main/java/org/cloud/sonic/agent/automation/AndroidStepHandler.java
index e8422c84..0f9393bb 100644
--- a/src/main/java/com/sonic/agent/automation/AndroidStepHandler.java
+++ b/src/main/java/org/cloud/sonic/agent/automation/AndroidStepHandler.java
@@ -1,1559 +1,1553 @@
-package com.sonic.agent.automation;
-
-import com.alibaba.fastjson.JSON;
-import com.alibaba.fastjson.JSONArray;
-import com.alibaba.fastjson.JSONObject;
-import com.android.ddmlib.IDevice;
-import com.sonic.agent.bridge.android.AndroidDeviceBridgeTool;
-import com.sonic.agent.bridge.android.AndroidDeviceThreadPool;
-import com.sonic.agent.interfaces.ErrorType;
-import com.sonic.agent.interfaces.ResultDetailStatus;
-import com.sonic.agent.interfaces.StepType;
-import com.sonic.agent.maps.AndroidPasswordMap;
-import com.sonic.agent.tools.*;
-import com.sonic.agent.interfaces.PlatformType;
-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;
-import io.appium.java_client.android.appmanagement.AndroidTerminateApplicationOptions;
-import io.appium.java_client.android.nativekey.AndroidKey;
-import io.appium.java_client.android.nativekey.KeyEvent;
-import io.appium.java_client.appmanagement.BaseTerminateApplicationOptions;
-import io.appium.java_client.remote.AndroidMobileCapabilityType;
-import io.appium.java_client.remote.AutomationName;
-import io.appium.java_client.remote.MobileCapabilityType;
-import io.appium.java_client.touch.WaitOptions;
-import io.appium.java_client.touch.offset.PointOption;
-import org.jsoup.Jsoup;
-import org.jsoup.nodes.Attribute;
-import org.jsoup.nodes.Document;
-import org.openqa.selenium.*;
-import org.openqa.selenium.chrome.ChromeOptions;
-import org.openqa.selenium.remote.DesiredCapabilities;
-import org.openqa.selenium.support.ui.ExpectedConditions;
-import org.openqa.selenium.support.ui.WebDriverWait;
-import org.springframework.core.env.Environment;
-import org.springframework.core.io.FileSystemResource;
-import org.springframework.http.ResponseEntity;
-import org.springframework.util.Base64Utils;
-import org.springframework.util.FileCopyUtils;
-import org.springframework.util.LinkedMultiValueMap;
-import org.springframework.util.MultiValueMap;
-import org.springframework.web.client.RestTemplate;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-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.*;
-
-/**
- * @author ZhouYiXun
- * @des 安卓自动化处理类
- * @date 2021/8/16 20:10
- */
-public class AndroidStepHandler {
- public LogTool log = new LogTool();
- private RestTemplate restTemplate = SpringTool.getBean(RestTemplate.class);
- private Environment environment = SpringTool.getBean(Environment.class);
- private String baseUrl = "http://" + environment.getProperty("sonic.server.host")
- + ":" + environment.getProperty("sonic.server.folder-port") + "/api/folder";
- private AndroidDriver androidDriver;
- private JSONObject globalParams = new JSONObject();
- //包版本
-// private String version = "";
- //测试起始时间
- private long startTime;
- //测试的包名
- private String testPackage = "";
- private String udId = "";
- //测试状态
- private int status = 1;
-
- public void setTestMode(int caseId, int resultId, String udId, String type, String sessionId) {
- log.caseId = caseId;
- log.resultId = resultId;
- log.udId = udId;
- log.type = type;
- log.sessionId = sessionId;
- }
-
- public void setGlobalParams(JSONObject jsonObject) {
- globalParams = jsonObject;
- }
-
- /**
- * @return
- * @author ZhouYiXun
- * @des new时开始计时
- * @date 2021/8/16 20:01
- */
- public AndroidStepHandler() {
- startTime = Calendar.getInstance().getTimeInMillis();
- }
-
- /**
- * @param udId
- * @return void
- * @author ZhouYiXun
- * @des 启动安卓驱动,连接设备
- * @date 2021/8/16 20:01
- */
- public void startAndroidDriver(String udId) throws InterruptedException {
- this.udId = udId;
- DesiredCapabilities desiredCapabilities = new DesiredCapabilities();
- //微信webView配置
- ChromeOptions chromeOptions = new ChromeOptions();
- chromeOptions.setExperimentalOption("androidProcess", "com.tencent.mm:tools");
- desiredCapabilities.setCapability(ChromeOptions.CAPABILITY, chromeOptions);
- //webView通用配置,自动下载匹配的driver
- desiredCapabilities.setCapability(AndroidMobileCapabilityType.RECREATE_CHROME_DRIVER_SESSIONS, true);
- desiredCapabilities.setCapability(AndroidMobileCapabilityType.CHROMEDRIVER_EXECUTABLE_DIR, "webview");
- desiredCapabilities.setCapability(AndroidMobileCapabilityType.CHROMEDRIVER_CHROME_MAPPING_FILE, "webview/version.json");
- //平台
- desiredCapabilities.setCapability(AndroidMobileCapabilityType.PLATFORM_NAME, Platform.ANDROID);
- //选用的自动化框架
- desiredCapabilities.setCapability(MobileCapabilityType.AUTOMATION_NAME, AutomationName.ANDROID_UIAUTOMATOR2);
- //关闭运行时阻塞其他Accessibility服务,开启的话其他不能使用了
- desiredCapabilities.setCapability("disableSuppressAccessibilityService", true);
- //adb指令超时时间
- desiredCapabilities.setCapability(AndroidMobileCapabilityType.ADB_EXEC_TIMEOUT, 7200000);
- //UIA2安装超时时间
- desiredCapabilities.setCapability("uiautomator2ServerInstallTimeout", 600000);
-
- //io.appium.uiautomator2.server io.appium.uiautomator2.server.test //io.appium.settings
-// desiredCapabilities.setCapability("skipServerInstallation",true);
-// desiredCapabilities.setCapability("disableWindowAnimation",true);
-// desiredCapabilities.setCapability("skipDeviceInitialization",true);
- //等待新命令超时时间
- desiredCapabilities.setCapability(MobileCapabilityType.NEW_COMMAND_TIMEOUT, 7200);
- //不重置应用
- desiredCapabilities.setCapability(MobileCapabilityType.NO_RESET, true);
- //单独唤起应用的话,这个需要设置空字符串
- desiredCapabilities.setCapability(MobileCapabilityType.BROWSER_NAME, "");
- //指定设备序列号
- desiredCapabilities.setCapability(MobileCapabilityType.UDID, udId);
- //随机systemPort
- desiredCapabilities.setCapability(AndroidMobileCapabilityType.SYSTEM_PORT, PortTool.getPort());
- 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, "连接设备驱动失败!", "");
- //测试标记为失败
- setResultDetailStatus(ResultDetailStatus.FAIL);
- throw e;
- }
- Capabilities capabilities = androidDriver.getCapabilities();
- Thread.sleep(100);
- log.androidInfo("Android", capabilities.getCapability("platformVersion").toString(),
- udId, capabilities.getCapability("deviceManufacturer").toString(),
- capabilities.getCapability("deviceModel").toString(),
- capabilities.getCapability("deviceApiLevel").toString(),
- capabilities.getCapability("deviceScreenSize").toString());
- }
-
- /**
- * @return void
- * @author ZhouYiXun
- * @des 关闭driver
- * @date 2021/8/16 20:21
- */
- public void closeAndroidDriver() {
- try {
- if (androidDriver != null) {
- //终止测试包
- if (!testPackage.equals("")) {
- try {
- androidDriver.terminateApp(testPackage, new AndroidTerminateApplicationOptions().withTimeout(Duration.ofMillis(1000)));
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- androidDriver.quit();
- log.sendStepLog(StepType.PASS, "退出连接设备", "");
- }
- } catch (Exception e) {
- log.sendStepLog(StepType.WARN, "测试终止异常!请检查设备连接状态", "");
- //测试异常
- setResultDetailStatus(ResultDetailStatus.WARN);
- e.printStackTrace();
- }
- }
-
- public void waitDevice(int waitCount) {
- log.sendStepLog(StepType.INFO, "设备非空闲状态!第" + waitCount + "次等待连接...", "");
- }
-
- public void waitDeviceTimeOut() {
- log.sendStepLog(StepType.ERROR, "等待设备超时!测试跳过!", "");
- //测试标记为异常
- setResultDetailStatus(ResultDetailStatus.WARN);
- }
-
- public AndroidDriver getAndroidDriver() {
- return androidDriver;
- }
-
- /**
- * @param status
- * @return void
- * @author ZhouYiXun
- * @des 设置测试状态
- * @date 2021/8/16 23:46
- */
- public void setResultDetailStatus(int status) {
- if (status > this.status) {
- this.status = status;
- }
- }
-
- public void sendStatus() {
- log.sendStatusLog(status);
- }
-
- //判断有无出错
- public int getStatus() {
- return status;
- }
-
- //调试每次重设状态
- public void resetResultDetailStatus() {
- status = 1;
- }
-
- /**
- * @return boolean
- * @author ZhouYiXun
- * @des 检测是否低电量
- * @date 2021/8/16 23:16
- */
- public boolean getBattery() {
- double battery = androidDriver.getBatteryInfo().getLevel();
- if (battery <= 0.1) {
- log.sendStepLog(StepType.ERROR, "设备电量过低!", "跳过本次测试...");
- return true;
- } else {
- return false;
- }
- }
-
- /**
- * @return void
- * @author ZhouYiXun
- * @des 获取性能信息(Appium自带的cpu和network方法貌似有bug, 后续再优化)
- * @date 2021/8/16 23:16
- */
- public void getPerform() {
- if (!testPackage.equals("")) {
- List performanceData = Arrays.asList("memoryinfo", "batteryinfo");
- for (String performName : performanceData) {
- List> re = androidDriver.getPerformanceData(testPackage, performName, 1);
- List mem;
- if (performName.equals("memoryinfo")) {
- mem = Arrays.asList(0, 1, 2, 5, 6, 7);
- } else {
- mem = Collections.singletonList(0);
- }
- JSONObject perform = new JSONObject();
- for (Integer memNum : mem) {
- perform.put(re.get(0).get(memNum).toString(), re.get(1).get(memNum));
- }
- log.sendPerLog(testPackage, performName.equals("memoryinfo") ? 1 : 2, perform);
- }
- }
- }
-
- //配合前端渲染,需要每个节点加上id
- private int xpathId = 1;
-
- /**
- * @return com.alibaba.fastjson.JSONArray
- * @author ZhouYiXun
- * @des 获取页面xpath信息
- * @date 2021/8/16 23:16
- */
- public JSONArray getResource() {
- androidDriver.context("NATIVE_APP");
- JSONArray elementList = new JSONArray();
- Document doc = Jsoup.parse(androidDriver.getPageSource());
- String xpath = "/hierarchy";
- elementList.addAll(getChildren(doc.body().children().get(0).children(), xpath));
- xpathId = 1;
- return elementList;
- }
-
- /**
- * @param elements
- * @param xpath 父级节点xpath
- * @return com.alibaba.fastjson.JSONArray
- * @author ZhouYiXun
- * @des 获取子节点信息
- * @date 2021/8/16 23:36
- */
- public JSONArray getChildren(org.jsoup.select.Elements elements, String xpath) {
- JSONArray elementList = new JSONArray();
- for (int i = 0; i < elements.size(); i++) {
- JSONObject ele = new JSONObject();
- //tag次数
- int tagCount = 0;
- //兄弟节点index
- int siblingIndex = 0;
- String indexXpath;
- for (int j = 0; j < elements.size(); j++) {
- if (elements.get(j).attr("class").equals(elements.get(i).attr("class"))) {
- tagCount++;
- }
- //当i==j时候,兄弟节点index等于tag出现次数,因为xpath多个tag的时候,[]里面下标是从1开始
- if (i == j) {
- siblingIndex = tagCount;
- }
- }
- //如果tag出现次数等于1,xpath结尾不添加[]
- if (tagCount == 1) {
- indexXpath = xpath + "/" + elements.get(i).attr("class");
- } else {
- indexXpath = xpath + "/" + elements.get(i).attr("class") + "[" + siblingIndex + "]";
- }
- ele.put("id", xpathId);
- xpathId++;
- ele.put("label", "<" + elements.get(i).attr("class") + ">");
- JSONObject detail = new JSONObject();
- detail.put("xpath", indexXpath);
- for (Attribute attr : elements.get(i).attributes()) {
- //把bounds字段拆出来解析,方便前端进行截取
- if (attr.getKey().equals("bounds")) {
- String bounds = attr.getValue().replace("][", ":");
- String pointStart = bounds.substring(1, bounds.indexOf(":"));
- String pointEnd = bounds.substring(bounds.indexOf(":") + 1, bounds.indexOf("]"));
- detail.put("bStart", pointStart);
- detail.put("bEnd", pointEnd);
- }
- detail.put(attr.getKey(), attr.getValue());
- }
- ele.put("detail", detail);
- if (elements.get(i).children().size() > 0) {
- ele.put("children", getChildren(elements.get(i).children(), indexXpath));
- }
- elementList.add(ele);
- }
- return elementList;
- }
-
- /**
- * @return void
- * @author ZhouYiXun
- * @des 开始录像
- * @date 2021/8/16 23:56
- */
- public void startRecord() {
- try {
- AndroidStartScreenRecordingOptions recordOption = new AndroidStartScreenRecordingOptions();
- //限制30分钟,appium支持的最长时间
- recordOption.withTimeLimit(Duration.ofMinutes(30));
- //开启bugReport,开启后录像会有相关附加信息
- recordOption.enableBugReport();
- //是否强制终止上次录像并开始新的录像
- recordOption.enableForcedRestart();
- //限制码率,防止录像过大
- recordOption.withBitRate(3000000);
- androidDriver.startRecordingScreen(recordOption);
- } catch (Exception e) {
- log.sendRecordLog(false, "", "");
- }
- }
-
- /**
- * @return void
- * @author ZhouYiXun
- * @des 停止录像
- * @date 2021/8/16 23:56
- */
- public void stopRecord() {
- File recordDir = new File("test-output/record");
- if (!recordDir.exists()) {
- recordDir.mkdirs();
- }
- long timeMillis = Calendar.getInstance().getTimeInMillis();
- String fileName = timeMillis + "_" + udId.substring(0, 4) + ".mp4";
- File uploadFile = new File(recordDir + File.separator + fileName);
- try {
- //加锁防止内存泄漏
- synchronized (AndroidStepHandler.class) {
- FileOutputStream fileOutputStream = new FileOutputStream(uploadFile);
- byte[] bytes = Base64Utils.decodeFromString((androidDriver.stopRecordingScreen()));
- fileOutputStream.write(bytes);
- fileOutputStream.close();
- }
- log.sendRecordLog(true, fileName, UploadTools.uploadPatchRecord(uploadFile));
- } catch (Exception e) {
- log.sendRecordLog(false, fileName, "");
- }
- }
-
-// public void settingSonicPlugins(IDevice iDevice) {
-// try {
-// androidDriver.activateApp("com.sonic.plugins");
-// try {
-// Thread.sleep(1000);
-// } catch (Exception e) {
-// }
-// log.sendStepLog(StepType.INFO, "已安装Sonic插件!", "");
-// } catch (Exception e) {
-// log.sendStepLog(StepType.ERROR, "未安装Sonic插件!", "");
-// throw e;
-// }
-// try {
-// if (!androidDriver.currentActivity().equals("com.sonic.plugins.MainActivity")) {
-// try {
-// AndroidDeviceBridgeTool.executeCommand(iDevice, "input keyevent 4");
-// Thread.sleep(1000);
-// } catch (Exception e) {
-// }
-// }
-// findEle("xpath", "//android.widget.TextView[@text='服务状态:已开启']");
-// } catch (Exception e) {
-// log.sendStepLog(StepType.ERROR, "未开启Sonic插件服务!请到辅助功能或无障碍开启", "");
-// throw e;
-// }
-// try {
-// findEle("id", "com.sonic.plugins:id/password_edit").clear();
-// if (AndroidPasswordMap.getMap().get(log.udId) != null
-// && (AndroidPasswordMap.getMap().get(log.udId) != null)
-// && (!AndroidPasswordMap.getMap().get(log.udId).equals(""))) {
-// findEle("id", "com.sonic.plugins:id/password_edit").sendKeys(AndroidPasswordMap.getMap().get(log.udId));
-// } else {
-// findEle("id", "com.sonic.plugins:id/password_edit").sendKeys("sonic123456");
-// }
-// findEle("id", "com.sonic.plugins:id/save").click();
-// } catch (Exception e) {
-// log.sendStepLog(StepType.ERROR, "配置Sonic插件服务失败!", "");
-// throw e;
-// }
-// }
-
- public void install(HandleDes handleDes, String path) {
- handleDes.setStepDes("安装应用");
- handleDes.setDetail("App安装路径: " + path);
-// IDevice iDevice = AndroidDeviceBridgeTool.getIDeviceByUdId(log.udId);
-// String manufacturer = iDevice.getProperty(IDevice.PROP_DEVICE_MANUFACTURER);
- try {
- androidDriver.unlockDevice();
- if (androidDriver.getConnection().isAirplaneModeEnabled()) {
- androidDriver.toggleAirplaneMode();
- }
- if (!androidDriver.getConnection().isWiFiEnabled()) {
- androidDriver.toggleWifi();
- }
- } catch (Exception e) {
- log.sendStepLog(StepType.WARN, "安装前准备跳过...", "");
- }
- log.sendStepLog(StepType.INFO, "", "开始安装App,请稍后...");
-// if (manufacturer.equals("OPPO") || manufacturer.equals("vivo") || manufacturer.equals("Meizu")) {
-// settingSonicPlugins(iDevice);
-// AndroidDeviceBridgeTool.executeCommand(iDevice, "input keyevent 3");
-// }
-// //单独适配一下oppo
-// if (manufacturer.equals("OPPO")) {
-// try {
-// androidDriver.installApp(path, new AndroidInstallApplicationOptions()
-// .withAllowTestPackagesEnabled().withReplaceEnabled()
-// .withGrantPermissionsEnabled().withTimeout(Duration.ofMillis(60000)));
-// } catch (Exception e) {
-// }
-// //单独再适配colorOs
-// if (androidDriver.currentActivity().equals(".verification.login.AccountActivity")) {
-// try {
-// if (AndroidPasswordMap.getMap().get(log.udId) != null
-// && (AndroidPasswordMap.getMap().get(log.udId) != null)
-// && (!AndroidPasswordMap.getMap().get(log.udId).equals(""))) {
-// findEle("id", "com.coloros.safecenter:id/et_login_passwd_edit"
-// ).sendKeys(AndroidPasswordMap.getMap().get(log.udId));
-// } else {
-// findEle("id", "com.coloros.safecenter:id/et_login_passwd_edit"
-// ).sendKeys("sonic123456");
-// }
-// findEle("id", "android:id/button1").click();
-// } catch (Exception e) {
-// }
-// }
-// AtomicInteger tryTime = new AtomicInteger(0);
-// AndroidDeviceThreadPool.cachedThreadPool.execute(() -> {
-// while (tryTime.get() < 20) {
-// tryTime.getAndIncrement();
-// //部分oppo有继续安装
-// try {
-// WebElement getContinueButton = findEle("id", "com.android.packageinstaller:id/virus_scan_panel");
-// Thread.sleep(2000);
-// AndroidDeviceBridgeTool.executeCommand(iDevice,
-// String.format("input tap %d %d", (getContinueButton.getRect().width) / 2
-// , getContinueButton.getRect().y + getContinueButton.getRect().height));
-// Thread.sleep(2000);
-// } catch (Exception e) {
-// e.printStackTrace();
-// }
-// //低版本oppo安装按钮在右边
-// try {
-// findEle("id", "com.android.packageinstaller:id/install_confirm_panel");
-// WebElement getInstallButton = findEle("id", "com.android.packageinstaller:id/bottom_button_layout");
-// Thread.sleep(2000);
-// AndroidDeviceBridgeTool.executeCommand(iDevice, String.format("input tap %d %d"
-// , ((getInstallButton.getRect().width) / 4) * 3
-// , getInstallButton.getRect().y + (getInstallButton.getRect().height) / 2));
-// Thread.sleep(2000);
-// } catch (Exception e) {
-// e.printStackTrace();
-// }
-// //部分oppo无法点击
-// try {
-// findEle("xpath", "//*[@text='应用权限']");
-// WebElement getInstallButton = findEle("id", "com.android.packageinstaller:id/install_confirm_panel");
-// Thread.sleep(2000);
-// AndroidDeviceBridgeTool.executeCommand(iDevice, String.format("input tap %d %d"
-// , (getInstallButton.getRect().width) / 2, getInstallButton.getRect().y + getInstallButton.getRect().height));
-// Thread.sleep(2000);
-// } catch (Exception e) {
-// e.printStackTrace();
-// }
-// if (!androidDriver.getCurrentPackage().equals("com.android.packageinstaller")) {
-// break;
-// }
-// }
-// });
-// while (androidDriver.getCurrentPackage().equals("com.android.packageinstaller") && tryTime.get() < 20) {
-// try {
-// findEle("xpath", "//*[@text='完成']").click();
-// } catch (Exception e) {
-// }
-// }
-// } else {
- try {
- androidDriver.installApp(path, new AndroidInstallApplicationOptions()
- .withAllowTestPackagesEnabled().withReplaceEnabled()
- .withGrantPermissionsEnabled().withTimeout(Duration.ofMillis(60000)));
- } catch (Exception e) {
- handleDes.setE(e);
- return;
- }
-// }
- }
-
- public void uninstall(HandleDes handleDes, String appPackage) {
- handleDes.setStepDes("卸载应用");
- handleDes.setDetail("App包名: " + appPackage);
- try {
- androidDriver.removeApp(appPackage);
- } catch (Exception e) {
- handleDes.setE(e);
- }
- }
-
- /**
- * @param packageName
- * @return void
- * @author ZhouYiXun
- * @des 终止app
- * @date 2021/8/16 23:46
- */
- public void terminate(HandleDes handleDes, String packageName) {
- handleDes.setStepDes("终止应用");
- handleDes.setDetail("应用包名: " + packageName);
- try {
- androidDriver.terminateApp(packageName, new AndroidTerminateApplicationOptions().withTimeout(Duration.ofMillis(1000)));
- } catch (Exception e) {
- handleDes.setE(e);
- }
- }
-
- public void runBackground(HandleDes handleDes, long time) {
- handleDes.setStepDes("后台运行应用");
- handleDes.setDetail("后台运行App " + time + " ms");
- try {
- androidDriver.runAppInBackground(Duration.ofMillis(time));
- } catch (Exception e) {
- handleDes.setE(e);
- }
- }
-
- public void openApp(HandleDes handleDes, String appPackage) {
- handleDes.setStepDes("打开应用");
- handleDes.setDetail("App包名: " + appPackage);
- try {
- testPackage = appPackage;
- androidDriver.activateApp(appPackage);
- } catch (Exception e) {
- handleDes.setE(e);
- }
- }
-
- public void rotateDevice(HandleDes handleDes, String text) {
- try {
- String s = "";
- switch (text) {
- case "screenSub":
- s = "sub";
- handleDes.setStepDes("左转屏幕");
- break;
- case "screenAdd":
- s = "add";
- handleDes.setStepDes("右转屏幕");
- break;
- case "screenAbort":
- s = "abort";
- handleDes.setStepDes("关闭自动旋转");
- break;
- }
- AndroidDeviceBridgeTool.screen(AndroidDeviceBridgeTool.getIDeviceByUdId(udId), s);
- } catch (Exception e) {
- handleDes.setE(e);
- }
- }
-
- public void lock(HandleDes handleDes) {
- handleDes.setStepDes("锁定屏幕");
- try {
- androidDriver.lockDevice();
- } catch (Exception e) {
- handleDes.setE(e);
- }
- }
-
- public void unLock(HandleDes handleDes) {
- handleDes.setStepDes("解锁屏幕");
- try {
- androidDriver.unlockDevice();
- } catch (Exception e) {
- handleDes.setE(e);
- }
- }
-
- public void airPlaneMode(HandleDes handleDes) {
- handleDes.setStepDes("切换飞行模式");
- try {
- androidDriver.toggleAirplaneMode();
- } catch (Exception e) {
- handleDes.setE(e);
- }
- }
-
- public void wifiMode(HandleDes handleDes) {
- handleDes.setStepDes("打开WIFI网络");
- try {
- if (!androidDriver.getConnection().isWiFiEnabled()) {
- androidDriver.toggleWifi();
- }
- } catch (Exception e) {
- handleDes.setE(e);
- }
- }
-
- public void locationMode(HandleDes handleDes) {
- handleDes.setStepDes("切换位置服务");
- try {
- androidDriver.toggleLocationServices();
- } catch (Exception e) {
- handleDes.setE(e);
- }
- }
-
- public void asserts(HandleDes handleDes, String actual, String expect, String type) {
- handleDes.setDetail("真实值: " + actual + " 期望值: " + expect);
- try {
- switch (type) {
- case "assertEquals":
- handleDes.setStepDes("断言验证(相等)");
- assertEquals(actual, expect);
- break;
- case "assertTrue":
- handleDes.setStepDes("断言验证(包含)");
- assertTrue(actual.contains(expect));
- break;
- case "assertNotTrue":
- handleDes.setStepDes("断言验证(不包含)");
- assertFalse(actual.contains(expect));
- break;
- }
- } catch (AssertionError e) {
- handleDes.setE(e);
- }
- }
-
- public String getText(HandleDes handleDes, String des, String selector, String pathValue) {
- String s = "";
- handleDes.setStepDes("获取" + des + "文本");
- handleDes.setDetail("获取" + selector + ":" + pathValue + "文本");
- try {
- s = findEle(selector, pathValue).getText();
- log.sendStepLog(StepType.INFO, "", "文本获取结果: " + s);
- } catch (Exception e) {
- handleDes.setE(e);
- }
- return s;
- }
-
- public void hideKey(HandleDes handleDes) {
- handleDes.setStepDes("隐藏键盘");
- handleDes.setDetail("隐藏弹出键盘");
- try {
- androidDriver.hideKeyboard();
- } catch (Exception e) {
- handleDes.setE(e);
- }
- }
-
- public void toWebView(HandleDes handleDes, String webViewName) {
- handleDes.setStepDes("切换到" + webViewName);
- try {
- androidDriver.context(webViewName);
- } catch (Exception e) {
- handleDes.setE(e);
- }
- }
-
- public void click(HandleDes handleDes, String des, String selector, String pathValue) {
- handleDes.setStepDes("点击" + des);
- handleDes.setDetail("点击" + selector + ": " + pathValue);
- try {
- findEle(selector, pathValue).click();
- } catch (Exception e) {
- handleDes.setE(e);
- }
- }
-
- public void sendKeys(HandleDes handleDes, String des, String selector, String pathValue, String keys) {
- if (keys.contains("{{random}}")) {
- String random = (int) (Math.random() * 10 + Math.random() * 10 * 2) + 5 + "";
- keys = keys.replace("{{random}}", random);
- }
- if (keys.contains("{{timestamp}}")) {
- String timeMillis = Calendar.getInstance().getTimeInMillis() + "";
- keys = keys.replace("{{timestamp}}", timeMillis);
- }
- keys = replaceTrans(keys);
- handleDes.setStepDes("对" + des + "输入内容");
- handleDes.setDetail("对" + selector + ": " + pathValue + " 输入: " + keys);
- try {
- findEle(selector, pathValue).sendKeys(keys);
- } catch (Exception e) {
- handleDes.setE(e);
- }
- }
-
- public void getTextAndAssert(HandleDes handleDes, String des, String selector, String pathValue, String expect) {
- handleDes.setStepDes("获取" + des + "文本");
- handleDes.setDetail("获取" + selector + ":" + pathValue + "文本");
- try {
- String s = findEle(selector, pathValue).getText();
- log.sendStepLog(StepType.INFO, "", "文本获取结果: " + s);
- try {
- expect = replaceTrans(expect);
- assertEquals(s, expect);
- log.sendStepLog(StepType.INFO, "验证文本", "真实值: " + s + " 期望值: " + expect);
- } catch (AssertionError e) {
- log.sendStepLog(StepType.ERROR, "验证" + des + "文本失败!", "");
- handleDes.setE(e);
- }
- } catch (Exception e) {
- handleDes.setE(e);
- }
- }
-
- public void longPressPoint(HandleDes handleDes, String des, String xy, int time) {
- int x = Integer.parseInt(xy.substring(0, xy.indexOf(",")));
- int y = Integer.parseInt(xy.substring(xy.indexOf(",") + 1));
- handleDes.setStepDes("长按" + des);
- handleDes.setDetail("长按坐标" + time + "毫秒 (" + x + "," + y + ")");
- try {
- TouchAction ta = new TouchAction(androidDriver);
- ta.longPress(PointOption.point(x, y)).waitAction(WaitOptions.waitOptions(Duration.ofMillis(time))).release().perform();
- } catch (Exception e) {
- handleDes.setE(e);
- }
- }
-
- public void keyCode(HandleDes handleDes, String key) {
- handleDes.setStepDes("按系统按键" + key + "键");
- try {
- androidDriver.pressKey(new KeyEvent().withKey(AndroidKey.valueOf(key)));
- } catch (Exception e) {
- handleDes.setE(e);
- }
- }
-
- public void multiAction(HandleDes handleDes, String des1, String xy1, String des2, String xy2, String des3, String xy3, String des4, String xy4) {
- int x1 = Integer.parseInt(xy1.substring(0, xy1.indexOf(",")));
- 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));
- int x3 = Integer.parseInt(xy3.substring(0, xy3.indexOf(",")));
- int y3 = Integer.parseInt(xy3.substring(xy3.indexOf(",") + 1));
- int x4 = Integer.parseInt(xy4.substring(0, xy4.indexOf(",")));
- int y4 = Integer.parseInt(xy4.substring(xy4.indexOf(",") + 1));
- String detail = "坐标" + des1 + "( " + x1 + ", " + y1 + " )移动到坐标" + des2 + "( " + x2 + ", " + y2 + " ),同时坐标" + des3 + "( " + x3 + ", " + y3 + " )移动到坐标" + des4 + "( " + x4 + ", " + y4 + " )";
- handleDes.setStepDes("双指操作");
- handleDes.setDetail(detail);
- try {
- TouchAction hand1 = new TouchAction(androidDriver);
- TouchAction hand2 = new TouchAction(androidDriver);
- MultiTouchAction multiTouchAction = new MultiTouchAction(androidDriver);
- hand1.press(PointOption.point(x1, y1)).moveTo(PointOption.point(x2, y2)).release();
- hand2.press(PointOption.point(x3, y3)).moveTo(PointOption.point(x4, y4)).release();
- multiTouchAction.add(hand1);
- multiTouchAction.add(hand2);
- multiTouchAction.perform();
- } catch (Exception e) {
- handleDes.setE(e);
- }
- }
-
- public void tap(HandleDes handleDes, String des, String xy) {
- int x = Integer.parseInt(xy.substring(0, xy.indexOf(",")));
- int y = Integer.parseInt(xy.substring(xy.indexOf(",") + 1));
- handleDes.setStepDes("点击" + des);
- handleDes.setDetail("点击坐标(" + x + "," + y + ")");
- try {
- TouchAction ta = new TouchAction(androidDriver);
- ta.tap(PointOption.point(x, y)).perform();
- } catch (Exception e) {
- handleDes.setE(e);
- }
- }
-
- public void swipe(HandleDes handleDes, String des1, String xy1, String des2, String xy2) {
- int x1 = Integer.parseInt(xy1.substring(0, xy1.indexOf(",")));
- 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));
- handleDes.setStepDes("滑动拖拽" + des1 + "到" + des2);
- handleDes.setDetail("拖动坐标(" + x1 + "," + y1 + ")到(" + x2 + "," + y2 + ")");
- try {
- TouchAction ta = new TouchAction(androidDriver);
- ta.press(PointOption.point(x1, y1)).waitAction(WaitOptions.waitOptions(Duration.ofMillis(300))).moveTo(PointOption.point(x2, y2)).release().perform();
- } catch (Exception e) {
- handleDes.setE(e);
- }
- }
-
- public void longPress(HandleDes handleDes, String des, String selector, String pathValue, int time) {
- handleDes.setStepDes("长按" + des);
- handleDes.setDetail("长按控件元素" + time + "毫秒 ");
- try {
- TouchAction ta = new TouchAction(androidDriver);
- WebElement webElement = findEle(selector, pathValue);
- int x = webElement.getLocation().getX();
- int y = webElement.getLocation().getY();
- Duration duration = Duration.ofMillis(time);
- ta.longPress(PointOption.point(x, y)).waitAction(WaitOptions.waitOptions(duration)).release().perform();
- } catch (Exception e) {
- handleDes.setE(e);
- }
- }
-
- public void clear(HandleDes handleDes, String des, String selector, String pathValue) {
- handleDes.setStepDes("清空" + des);
- handleDes.setDetail("清空" + selector + ": " + pathValue);
- try {
- findEle(selector, pathValue).clear();
- } catch (Exception e) {
- handleDes.setE(e);
- }
- }
-
- public void getTitle(HandleDes handleDes, String expect) {
- String title = androidDriver.getTitle();
- handleDes.setStepDes("验证网页标题");
- handleDes.setDetail("标题:" + title + ",期望值:" + expect);
- try {
- assertEquals(title, expect);
- } catch (AssertionError e) {
- handleDes.setE(e);
- }
- }
-
- public void clickByImg(HandleDes handleDes, String des, String pathValue) throws Exception {
- handleDes.setStepDes("点击图片" + des);
- handleDes.setDetail(pathValue);
- File file = null;
- if (pathValue.startsWith("http")) {
- try {
- file = DownImageTool.download(pathValue);
- } catch (Exception e) {
- handleDes.setE(e);
- return;
- }
- }
- File localCap = getScreenToLocal();
- FindResult findResult;
- FileSystemResource resource1 = new FileSystemResource(file);
- FileSystemResource resource2 = new FileSystemResource(localCap);
- MultiValueMap param = new LinkedMultiValueMap<>();
- param.add("file1", resource1);
- param.add("file2", resource2);
- param.add("type", "finder");
- try {
- ResponseEntity responseEntity =
- restTemplate.postForEntity(baseUrl + "/upload/cv", param, JSONObject.class);
- if (responseEntity.getBody().getInteger("code") == 2000) {
- findResult = responseEntity.getBody().getJSONObject("data").toJavaObject(FindResult.class);
- if (findResult != null) {
- try {
- log.sendStepLog(StepType.INFO, "图片定位到坐标:(" + findResult.getX() + "," + findResult.getY() + ") 耗时:" + findResult.getTime() + " ms",
- findResult.getUrl());
- TouchAction ta = new TouchAction(androidDriver);
- ta.tap(PointOption.point(findResult.getX(), findResult.getY())).perform();
- } catch (Exception e) {
- log.sendStepLog(StepType.ERROR, "点击" + des + "失败!", "");
- handleDes.setE(e);
- }
- }
- } else if (responseEntity.getBody().getInteger("code") == 4003) {
- handleDes.setE(new Exception("图像匹配失败!"));
- } else {
- handleDes.setE(new Exception("点击失败!cv服务出错!"));
- }
- } catch (Exception e) {
- handleDes.setE(new Exception("点击失败!cv服务访问出错!"));
- } finally {
- file.delete();
- localCap.delete();
- }
- }
-
- public void readText(HandleDes handleDes, String language, String text) throws Exception {
-// TextReader textReader = new TextReader();
-// String result = textReader.getTessResult(getScreenToLocal(), language);
-// log.sendStepLog(StepType.INFO, "",
-// "图像文字识别结果:
" + result);
-// String filter = result.replaceAll(" ", "");
- handleDes.setStepDes("图像文字识别");
- handleDes.setDetail("(该功能暂时关闭)期望包含文本:" + text);
-// if (!filter.contains(text)) {
-// handleDes.setE(new Exception("图像文字识别不通过!"));
-// }
- }
-
- public void toHandle(HandleDes handleDes, String titleName) throws Exception {
- handleDes.setStepDes("切换Handle");
- Thread.sleep(1000);
- Set handle = androidDriver.getWindowHandles();//获取handles
- String ha;
- for (int i = 1; i <= handle.size(); i++) {
- ha = (String) handle.toArray()[handle.size() - i];//查找handle
- try {
- androidDriver.switchTo().window(ha);//切换到最后一个handle
- } catch (Exception e) {
- }
- if (androidDriver.getTitle().equals(titleName)) {
- handleDes.setDetail("切换到Handle:" + ha);
- log.sendStepLog(StepType.INFO, "页面标题:" + androidDriver.getTitle(), "");
- break;
- }
- }
- }
-
- public File getScreenToLocal() {
- File file = ((TakesScreenshot) androidDriver).getScreenshotAs(OutputType.FILE);
- File resultFile = new File("test-output/" + log.udId + Calendar.getInstance().getTimeInMillis() + ".jpg");
- try {
- FileCopyUtils.copy(file, resultFile);
- } catch (IOException e) {
- e.printStackTrace();
- }
- return resultFile;
- }
-
- public String replaceTrans(String text) {
- if (text.contains("{{") && text.contains("}}")) {
- String tail = text.substring(text.indexOf("{{") + 2);
- if (tail.contains("}}")) {
- String child = tail.substring(tail.indexOf("}}") + 2);
- String middle = tail.substring(0, tail.indexOf("}}"));
- text = text.substring(0, text.indexOf("}}") + 2);
- if (globalParams.getString(middle) != null) {
- text = text.replace("{{" + middle + "}}", globalParams.getString(middle));
- }
- text = text + replaceTrans(child);
- }
- }
- return text;
- }
-
- public void checkImage(HandleDes handleDes, String des, String pathValue, double matchThreshold) throws Exception {
- log.sendStepLog(StepType.INFO, "开始检测" + des + "兼容", "检测与当前设备截图相似度,期望相似度为" + matchThreshold + "%");
- File file = null;
- if (pathValue.startsWith("http")) {
- file = DownImageTool.download(pathValue);
- }
- File localCap = getScreenToLocal();
- FileSystemResource resource1 = new FileSystemResource(file);
- FileSystemResource resource2 = new FileSystemResource(localCap);
- MultiValueMap param = new LinkedMultiValueMap<>();
- param.add("file1", resource1);
- param.add("file2", resource2);
- param.add("type", "checker");
- try {
- ResponseEntity responseEntity =
- restTemplate.postForEntity(baseUrl + "/upload/cv", param, JSONObject.class);
- if (responseEntity.getBody().getInteger("code") == 2000) {
- double score = responseEntity.getBody().getDouble("data");
- handleDes.setStepDes("检测" + des + "图片相似度");
- handleDes.setDetail("相似度为" + score * 100 + "%");
- if (score == 0) {
- handleDes.setE(new Exception("图片相似度检测不通过!比对图片分辨率不一致!"));
- } else if (score < (matchThreshold / 100)) {
- handleDes.setE(new Exception("图片相似度检测不通过!expect " + matchThreshold + " but " + score * 100));
- }
- } else {
- handleDes.setE(new Exception("图片相似度检测出错!cv服务出错!"));
- }
- } catch (Exception e) {
- e.printStackTrace();
- handleDes.setE(new Exception("图片相似度检测出错!cv服务访问出错!"));
- } finally {
- file.delete();
- localCap.delete();
- }
- }
-
- public void exceptionLog(Throwable e) {
- log.sendStepLog(StepType.WARN, "", "异常信息: " + e.fillInStackTrace().toString());
- }
-
- public void errorScreen() {
- try {
- androidDriver.context("NATIVE_APP");//先切换回app
- log.sendStepLog(StepType.WARN, "获取异常截图", UploadTools
- .upload(((TakesScreenshot) androidDriver).getScreenshotAs(OutputType.FILE), "imageFiles"));
- } catch (Exception e) {
- log.sendStepLog(StepType.ERROR, "捕获截图失败", "");
- }
- }
-
- public String stepScreen(HandleDes handleDes) {
- handleDes.setStepDes("获取截图");
- String url = "";
- try {
- androidDriver.context("NATIVE_APP");//先切换回app
- url = UploadTools.upload(((TakesScreenshot) androidDriver)
- .getScreenshotAs(OutputType.FILE), "imageFiles");
- handleDes.setDetail(url);
- } catch (Exception e) {
- handleDes.setE(e);
- }
- return url;
- }
-
- public Set getWebView() {
- Set contextNames = androidDriver.getContextHandles();
- return contextNames;
- }
-
- public String getCurrentActivity() {
- return androidDriver.currentActivity();
- }
-
- public void pause(HandleDes handleDes, int time) {
- handleDes.setStepDes("强制等待");
- handleDes.setDetail("等待" + time + " ms");
- try {
- Thread.sleep(time);
- } catch (InterruptedException e) {
- handleDes.setE(e);
- }
- }
-
- public void runMonkey(HandleDes handleDes, JSONObject content, List text) {
- handleDes.setStepDes("运行随机事件测试完毕");
- String packageName = content.getString("packageName");
- int pctNum = content.getInteger("pctNum");
- if (!androidDriver.isAppInstalled(packageName)) {
- log.sendStepLog(StepType.ERROR, "应用未安装!", "设备未安装 " + packageName);
- handleDes.setE(new Exception("未安装应用"));
- return;
- }
- IDevice iDevice = AndroidDeviceBridgeTool.getIDeviceByUdId(udId);
- JSONArray options = content.getJSONArray("options");
- int width = androidDriver.manage().window().getSize().width;
- int height = androidDriver.manage().window().getSize().height;
- int sleepTime = 50;
- int systemEvent = 0;
- int tapEvent = 0;
- int longPressEvent = 0;
- int swipeEvent = 0;
- int zoomEvent = 0;
- int navEvent = 0;
- boolean isOpenH5Listener = false;
- boolean isOpenPackageListener = false;
- boolean isOpenActivityListener = false;
- boolean isOpenNetworkListener = false;
- if (!options.isEmpty()) {
- for (int i = options.size() - 1; i >= 0; i--) {
- JSONObject jsonOption = (JSONObject) options.get(i);
- if (jsonOption.getString("name").equals("sleepTime")) {
- sleepTime = jsonOption.getInteger("value");
- }
- if (jsonOption.getString("name").equals("systemEvent")) {
- systemEvent = jsonOption.getInteger("value");
- }
- if (jsonOption.getString("name").equals("tapEvent")) {
- tapEvent = jsonOption.getInteger("value");
- }
- if (jsonOption.getString("name").equals("longPressEvent")) {
- longPressEvent = jsonOption.getInteger("value");
- }
- if (jsonOption.getString("name").equals("swipeEvent")) {
- swipeEvent = jsonOption.getInteger("value");
- }
- if (jsonOption.getString("name").equals("zoomEvent")) {
- zoomEvent = jsonOption.getInteger("value");
- }
- if (jsonOption.getString("name").equals("navEvent")) {
- navEvent = jsonOption.getInteger("value");
- }
- if (jsonOption.getString("name").equals("isOpenH5Listener")) {
- isOpenH5Listener = jsonOption.getBoolean("value");
- }
- if (jsonOption.getString("name").equals("isOpenPackageListener")) {
- isOpenPackageListener = jsonOption.getBoolean("value");
- }
- if (jsonOption.getString("name").equals("isOpenActivityListener")) {
- isOpenActivityListener = jsonOption.getBoolean("value");
- }
- if (jsonOption.getString("name").equals("isOpenNetworkListener")) {
- isOpenNetworkListener = jsonOption.getBoolean("value");
- }
- options.remove(options.get(i));
- }
- }
- int finalSleepTime = sleepTime;
- int finalTapEvent = tapEvent;
- int finalLongPressEvent = longPressEvent;
- int finalSwipeEvent = swipeEvent;
- int finalZoomEvent = zoomEvent;
- int finalSystemEvent = systemEvent;
- int finalNavEvent = navEvent;
- Future> randomThread = AndroidDeviceThreadPool.cachedThreadPool.submit(() -> {
- log.sendStepLog(StepType.INFO, "", "随机事件数:" + pctNum +
- "
目标应用:" + packageName
- + "
用户操作时延:" + finalSleepTime + " ms"
- + "
轻触事件权重:" + finalTapEvent
- + "
长按事件权重:" + finalLongPressEvent
- + "
滑动事件权重:" + finalSwipeEvent
- + "
多点触控事件权重:" + finalZoomEvent
- + "
物理按键事件权重:" + finalSystemEvent
- + "
系统事件权重:" + finalNavEvent
- );
- openApp(new HandleDes(), packageName);
- TouchAction ta = new TouchAction(androidDriver);
- TouchAction ta2 = new TouchAction(androidDriver);
- MultiTouchAction multiTouchAction = new MultiTouchAction(androidDriver);
- int totalCount = finalSystemEvent + finalTapEvent + finalLongPressEvent + finalSwipeEvent + finalZoomEvent + finalNavEvent;
- for (int i = 0; i < pctNum; i++) {
- try {
- int random = new Random().nextInt(totalCount);
- if (random >= 0 && random < finalSystemEvent) {
- int key = new Random().nextInt(9);
- String keyType = "";
- switch (key) {
- case 0:
- keyType = "HOME";
- break;
- case 1:
- keyType = "BACK";
- break;
- case 2:
- keyType = "MENU";
- break;
- case 3:
- keyType = "APP_SWITCH";
- break;
- case 4:
- keyType = "BRIGHTNESS_DOWN";
- break;
- case 5:
- keyType = "BRIGHTNESS_UP";
- break;
- case 6:
- keyType = "VOLUME_UP";
- break;
- case 7:
- keyType = "VOLUME_DOWN";
- break;
- case 8:
- keyType = "VOLUME_MUTE";
- break;
- }
- androidDriver.pressKey(new KeyEvent(AndroidKey.valueOf(keyType)));
- }
- if (random >= finalSystemEvent && random < (finalSystemEvent + finalTapEvent)) {
- int x = new Random().nextInt(width - 60) + 60;
- int y = new Random().nextInt(height - 60) + 60;
- ta.tap(PointOption.point(x, y)).perform();
- }
- if (random >= (finalSystemEvent + finalTapEvent) && random < (finalSystemEvent + finalTapEvent + finalLongPressEvent)) {
- int x = new Random().nextInt(width - 60) + 60;
- int y = new Random().nextInt(height - 60) + 60;
- ta.longPress(PointOption.point(x, y)).waitAction(WaitOptions.waitOptions(Duration.ofSeconds(new Random().nextInt(3) + 1))).release().perform();
- }
- if (random >= (finalSystemEvent + finalTapEvent + finalLongPressEvent) && random < (finalSystemEvent + finalTapEvent + finalLongPressEvent + finalSwipeEvent)) {
- int x1 = new Random().nextInt(width - 60) + 60;
- int y1 = new Random().nextInt(height - 80) + 80;
- int x2 = new Random().nextInt(width - 60) + 60;
- int y2 = new Random().nextInt(height - 80) + 80;
- ta.press(PointOption.point(x1, y1)).waitAction(WaitOptions.waitOptions(Duration.ofMillis(200))).moveTo(PointOption.point(x2, y2)).release().perform();
- }
- if (random >= (finalSystemEvent + finalTapEvent + finalLongPressEvent + finalSwipeEvent) && random < (finalSystemEvent + finalTapEvent + finalLongPressEvent + finalSwipeEvent + finalZoomEvent)) {
- int x1 = new Random().nextInt(width - 80);
- int y1 = new Random().nextInt(height - 80);
- int x2 = new Random().nextInt(width - 100);
- int y2 = new Random().nextInt(height - 80);
- int x3 = new Random().nextInt(width - 100);
- int y3 = new Random().nextInt(height - 80);
- int x4 = new Random().nextInt(width - 100);
- int y4 = new Random().nextInt(height - 80);
- ta.press(PointOption.point(x1, y1)).waitAction(WaitOptions.waitOptions(Duration.ofMillis(200))).moveTo(PointOption.point(x2, y2)).release();
- ta2.press(PointOption.point(x3, y3)).waitAction(WaitOptions.waitOptions(Duration.ofMillis(200))).moveTo(PointOption.point(x4, y4)).release();
- multiTouchAction.add(ta);
- multiTouchAction.add(ta2);
- multiTouchAction.perform();
- }
- if (random >= (finalSystemEvent + finalTapEvent + finalLongPressEvent + finalSwipeEvent + finalZoomEvent) && random < (finalSystemEvent + finalTapEvent + finalLongPressEvent + finalSwipeEvent + finalZoomEvent + finalNavEvent)) {
- androidDriver.toggleWifi();
- }
- Thread.sleep(finalSleepTime);
- } catch (Throwable e) {
- e.printStackTrace();
- }
- }
- }
- );
- Boolean finalIsOpenH5Listener = isOpenH5Listener;
- Future> H5Listener = AndroidDeviceThreadPool.cachedThreadPool.submit(() -> {
- if (finalIsOpenH5Listener) {
- int h5Time = 0;
- while (!randomThread.isDone()) {
- try {
- Thread.sleep(8000);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- try {
- if (androidDriver.findElementsByClassName("android.webkit.WebView").size() > 0) {
- h5Time++;
- AndroidDeviceBridgeTool.executeCommand(iDevice, "input keyevent 4");
- } else {
- h5Time = 0;
- }
- if (h5Time >= 12) {
- androidDriver.terminateApp(packageName, new AndroidTerminateApplicationOptions().withTimeout(Duration.ofMillis(1000)));
- h5Time = 0;
- }
- } catch (Throwable e) {
- e.printStackTrace();
- }
- }
- }
- }
- );
- boolean finalIsOpenPackageListener = isOpenPackageListener;
- Future> packageListener = AndroidDeviceThreadPool.cachedThreadPool.submit(() -> {
- if (finalIsOpenPackageListener) {
- while (!randomThread.isDone()) {
- int waitTime = 0;
- while (waitTime <= 10 && (!randomThread.isDone())) {
- try {
- Thread.sleep(5000);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- if (!androidDriver.getCurrentPackage().equals(packageName)) {
- androidDriver.activateApp(packageName);
- }
- waitTime++;
- }
- androidDriver.activateApp(packageName);
- }
- }
- }
- );
- boolean finalIsOpenActivityListener = isOpenActivityListener;
- Future> activityListener = AndroidDeviceThreadPool.cachedThreadPool.submit(() -> {
- if (finalIsOpenActivityListener) {
- if (text.isEmpty()) {
- return;
- }
- Set blackList = new HashSet<>();
- for (JSONObject activities : text) {
- blackList.add(activities.getString("name"));
- }
- while (!randomThread.isDone()) {
- try {
- Thread.sleep(8000);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- if (blackList.contains(getCurrentActivity())) {
- AndroidDeviceBridgeTool.executeCommand(iDevice, "input keyevent 4");
- } else continue;
- try {
- Thread.sleep(8000);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- if (blackList.contains(getCurrentActivity())) {
- androidDriver.terminateApp(packageName, new AndroidTerminateApplicationOptions().withTimeout(Duration.ofMillis(1000)));
- }
- }
- }
- }
- );
- boolean finalIsOpenNetworkListener = isOpenNetworkListener;
- Future> networkListener = AndroidDeviceThreadPool.cachedThreadPool.submit(() -> {
- if (finalIsOpenNetworkListener) {
- while (!randomThread.isDone()) {
- try {
- Thread.sleep(8000);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- if (androidDriver.getConnection().isAirplaneModeEnabled()) {
- androidDriver.toggleAirplaneMode();
- }
- try {
- Thread.sleep(8000);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- if (!androidDriver.getConnection().isWiFiEnabled()) {
- androidDriver.toggleWifi();
- }
- }
- }
- }
- );
- try {
- Thread.sleep(500);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
-// if (version.length() == 0) {
-// version = AndroidDeviceBridgeTool.getAppOnlyVersion(udId, packageName);
-// }
- log.sendStepLog(StepType.INFO, "", "测试目标包:" + packageName +
- (isOpenPackageListener ? "
应用包名监听器已开启..." : "") +
- (isOpenH5Listener ? "
H5页面监听器已开启..." : "") +
- (isOpenActivityListener ? "
黑名单Activity监听器..." : "") +
- (isOpenNetworkListener ? "
网络状态监听器已开启..." : ""));
- while (!randomThread.isDone() || (!packageListener.isDone()) || (!activityListener.isDone()) || (!networkListener.isDone()) || (!H5Listener.isDone())) {
- }
- }
-
- public void publicStep(HandleDes handleDes, String name, JSONArray stepArray) {
- handleDes.setStepDes("执行公共步骤 " + name);
- log.sendStepLog(StepType.WARN, "公共步骤 " + name + " 开始执行", "");
- for (Object publicStep : stepArray) {
- JSONObject stepDetail = (JSONObject) publicStep;
- try {
- runStep(stepDetail);
- } catch (Throwable e) {
- handleDes.setE(e);
- break;
- }
- }
- }
-
- public WebElement findEle(String selector, String pathValue) {
- WebElement we = null;
- switch (selector) {
- case "id":
- we = androidDriver.findElementById(pathValue);
- break;
- case "name":
- we = androidDriver.findElementByName(pathValue);
- break;
- case "xpath":
- we = androidDriver.findElementByXPath(pathValue);
- break;
- case "cssSelector":
- we = androidDriver.findElementByCssSelector(pathValue);
- break;
- case "className":
- we = androidDriver.findElementByClassName(pathValue);
- break;
- case "tagName":
- we = androidDriver.findElementByTagName(pathValue);
- break;
- case "linkText":
- we = androidDriver.findElementByLinkText(pathValue);
- break;
- case "partialLinkText":
- we = androidDriver.findElementByPartialLinkText(pathValue);
- break;
- default:
- log.sendStepLog(StepType.ERROR, "查找控件元素失败", "这个控件元素类型: " + selector + " 不存在!!!");
- break;
- }
- return we;
- }
-
- public void runStep(JSONObject stepJSON) throws Throwable {
- JSONObject step = stepJSON.getJSONObject("step");
- JSONArray eleList = step.getJSONArray("elements");
- HandleDes handleDes = new HandleDes();
- switch (step.getString("stepType")) {
- case "toWebView":
- toWebView(handleDes, step.getString("content"));
- break;
- case "toHandle":
- toHandle(handleDes, step.getString("content"));
- break;
- case "readText":
- readText(handleDes, step.getString("content"), step.getString("text"));
- break;
- case "clickByImg":
- clickByImg(handleDes, eleList.getJSONObject(0).getString("eleName")
- , eleList.getJSONObject(0).getString("eleValue"));
- break;
- case "click":
- click(handleDes, eleList.getJSONObject(0).getString("eleName"), eleList.getJSONObject(0).getString("eleType")
- , eleList.getJSONObject(0).getString("eleValue"));
- break;
- case "getTitle":
- getTitle(handleDes, step.getString("content"));
- break;
- case "sendKeys":
- sendKeys(handleDes, eleList.getJSONObject(0).getString("eleName"), eleList.getJSONObject(0).getString("eleType")
- , eleList.getJSONObject(0).getString("eleValue"), step.getString("content"));
- break;
- case "getText":
- getTextAndAssert(handleDes, eleList.getJSONObject(0).getString("eleName"), eleList.getJSONObject(0).getString("eleType")
- , eleList.getJSONObject(0).getString("eleValue"), step.getString("content"));
- break;
- case "clear":
- clear(handleDes, eleList.getJSONObject(0).getString("eleName"), eleList.getJSONObject(0).getString("eleType")
- , eleList.getJSONObject(0).getString("eleValue"));
- break;
- case "longPress":
- longPress(handleDes, eleList.getJSONObject(0).getString("eleName"), eleList.getJSONObject(0).getString("eleType")
- , eleList.getJSONObject(0).getString("eleValue"), Integer.parseInt(step.getString("content")));
- break;
- case "swipe":
- swipe(handleDes, eleList.getJSONObject(0).getString("eleName"), eleList.getJSONObject(0).getString("eleValue")
- , eleList.getJSONObject(1).getString("eleName"), eleList.getJSONObject(1).getString("eleValue"));
- break;
- case "tap":
- tap(handleDes, eleList.getJSONObject(0).getString("eleName"), eleList.getJSONObject(0).getString("eleValue"));
- break;
- case "longPressPoint":
- longPressPoint(handleDes, eleList.getJSONObject(0).getString("eleName"), eleList.getJSONObject(0).getString("eleValue")
- , Integer.parseInt(step.getString("content")));
- break;
- case "pause":
- pause(handleDes, Integer.parseInt(step.getString("content")));
- break;
- case "checkImage":
- checkImage(handleDes, eleList.getJSONObject(0).getString("eleName"), eleList.getJSONObject(0).getString("eleValue")
- , step.getDouble("content"));
- break;
- case "stepScreen":
- stepScreen(handleDes);
- break;
- case "openApp":
- openApp(handleDes, step.getString("text"));
- break;
- case "terminate":
- terminate(handleDes, step.getString("text"));
- break;
- case "install":
- install(handleDes, step.getString("text"));
- break;
- case "uninstall":
- uninstall(handleDes, step.getString("text"));
- break;
- case "runBack":
- runBackground(handleDes, Long.parseLong(step.getString("content")));
- break;
- case "screenSub":
- case "screenAdd":
- case "screenAbort":
- rotateDevice(handleDes, step.getString("stepType"));
- break;
- case "lock":
- lock(handleDes);
- break;
- case "unLock":
- unLock(handleDes);
- break;
- case "airPlaneMode":
- airPlaneMode(handleDes);
- break;
- case "wifiMode":
- wifiMode(handleDes);
- break;
- case "locationMode":
- locationMode(handleDes);
- break;
- case "zoom":
- multiAction(handleDes, eleList.getJSONObject(0).getString("eleName"), eleList.getJSONObject(0).getString("eleValue")
- , eleList.getJSONObject(1).getString("eleName"), eleList.getJSONObject(1).getString("eleValue")
- , eleList.getJSONObject(2).getString("eleName"), eleList.getJSONObject(2).getString("eleValue")
- , eleList.getJSONObject(3).getString("eleName"), eleList.getJSONObject(3).getString("eleValue"));
- break;
- case "keyCode":
- keyCode(handleDes, step.getString("content"));
- break;
- case "assertEquals":
- case "assertTrue":
- case "assertNotTrue":
- String actual = replaceTrans(step.getString("text"));
- String expect = replaceTrans(step.getString("content"));
- asserts(handleDes, actual, expect, step.getString("stepType"));
- break;
- case "getTextValue":
- globalParams.put(step.getString("content"), getText(handleDes, eleList.getJSONObject(0).getString("eleName")
- , eleList.getJSONObject(0).getString("eleType"), eleList.getJSONObject(0).getString("eleValue")));
- break;
- case "hideKey":
- hideKey(handleDes);
- break;
- case "monkey":
- runMonkey(handleDes, step.getJSONObject("content"), step.getJSONArray("text").toJavaList(JSONObject.class));
- break;
- case "publicStep":
- publicStep(handleDes, step.getString("content"), stepJSON.getJSONArray("pubSteps"));
- }
- switchType(step.getInteger("error"), handleDes.getStepDes(), handleDes.getDetail(), handleDes.getE());
- }
-
- public void switchType(int error, String step, String detail, Throwable e) throws Throwable {
- if (e != null) {
- switch (error) {
- case ErrorType.IGNORE:
- log.sendStepLog(StepType.PASS, step + "异常!已忽略...", detail);
- break;
- case ErrorType.WARNING:
- log.sendStepLog(StepType.WARN, step + "异常!", detail);
- setResultDetailStatus(ResultDetailStatus.WARN);
- errorScreen();
- exceptionLog(e);
- break;
- case ErrorType.SHUTDOWN:
- log.sendStepLog(StepType.ERROR, step + "异常!", detail);
- setResultDetailStatus(ResultDetailStatus.FAIL);
- errorScreen();
- exceptionLog(e);
- throw e;
- }
- } else {
- log.sendStepLog(StepType.PASS, step, detail);
- }
- }
-}
+package org.cloud.sonic.agent.automation;
+
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.android.ddmlib.IDevice;
+import org.cloud.sonic.agent.bridge.android.AndroidDeviceBridgeTool;
+import org.cloud.sonic.agent.bridge.android.AndroidDeviceThreadPool;
+import org.cloud.sonic.agent.interfaces.ErrorType;
+import org.cloud.sonic.agent.interfaces.ResultDetailStatus;
+import org.cloud.sonic.agent.interfaces.StepType;
+import org.cloud.sonic.agent.tools.*;
+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;
+import io.appium.java_client.android.appmanagement.AndroidTerminateApplicationOptions;
+import io.appium.java_client.android.nativekey.AndroidKey;
+import io.appium.java_client.android.nativekey.KeyEvent;
+import io.appium.java_client.remote.AndroidMobileCapabilityType;
+import io.appium.java_client.remote.AutomationName;
+import io.appium.java_client.remote.MobileCapabilityType;
+import io.appium.java_client.touch.WaitOptions;
+import io.appium.java_client.touch.offset.PointOption;
+import org.cloud.sonic.agent.tools.*;
+import org.jsoup.Jsoup;
+import org.jsoup.nodes.Attribute;
+import org.jsoup.nodes.Document;
+import org.openqa.selenium.*;
+import org.openqa.selenium.chrome.ChromeOptions;
+import org.openqa.selenium.remote.DesiredCapabilities;
+import org.springframework.core.env.Environment;
+import org.springframework.core.io.FileSystemResource;
+import org.springframework.http.ResponseEntity;
+import org.springframework.util.Base64Utils;
+import org.springframework.util.FileCopyUtils;
+import org.springframework.util.LinkedMultiValueMap;
+import org.springframework.util.MultiValueMap;
+import org.springframework.web.client.RestTemplate;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.time.Duration;
+import java.util.*;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+
+import static org.testng.Assert.*;
+
+/**
+ * @author ZhouYiXun
+ * @des 安卓自动化处理类
+ * @date 2021/8/16 20:10
+ */
+public class AndroidStepHandler {
+ public LogTool log = new LogTool();
+ private RestTemplate restTemplate = SpringTool.getBean(RestTemplate.class);
+ private Environment environment = SpringTool.getBean(Environment.class);
+ private String baseUrl = "http://" + environment.getProperty("sonic.server.host")
+ + ":" + environment.getProperty("sonic.server.folder-port") + "/api/folder";
+ private AndroidDriver androidDriver;
+ private JSONObject globalParams = new JSONObject();
+ //包版本
+// private String version = "";
+ //测试起始时间
+ private long startTime;
+ //测试的包名
+ private String testPackage = "";
+ private String udId = "";
+ //测试状态
+ private int status = 1;
+
+ public void setTestMode(int caseId, int resultId, String udId, String type, String sessionId) {
+ log.caseId = caseId;
+ log.resultId = resultId;
+ log.udId = udId;
+ log.type = type;
+ log.sessionId = sessionId;
+ }
+
+ public void setGlobalParams(JSONObject jsonObject) {
+ globalParams = jsonObject;
+ }
+
+ /**
+ * @return
+ * @author ZhouYiXun
+ * @des new时开始计时
+ * @date 2021/8/16 20:01
+ */
+ public AndroidStepHandler() {
+ startTime = Calendar.getInstance().getTimeInMillis();
+ }
+
+ /**
+ * @param udId
+ * @return void
+ * @author ZhouYiXun
+ * @des 启动安卓驱动,连接设备
+ * @date 2021/8/16 20:01
+ */
+ public void startAndroidDriver(String udId) throws InterruptedException {
+ this.udId = udId;
+ DesiredCapabilities desiredCapabilities = new DesiredCapabilities();
+ //微信webView配置
+ ChromeOptions chromeOptions = new ChromeOptions();
+ chromeOptions.setExperimentalOption("androidProcess", "com.tencent.mm:tools");
+ desiredCapabilities.setCapability(ChromeOptions.CAPABILITY, chromeOptions);
+ //webView通用配置,自动下载匹配的driver
+ desiredCapabilities.setCapability(AndroidMobileCapabilityType.RECREATE_CHROME_DRIVER_SESSIONS, true);
+ desiredCapabilities.setCapability(AndroidMobileCapabilityType.CHROMEDRIVER_EXECUTABLE_DIR, "webview");
+ desiredCapabilities.setCapability(AndroidMobileCapabilityType.CHROMEDRIVER_CHROME_MAPPING_FILE, "webview/version.json");
+ //平台
+ desiredCapabilities.setCapability(AndroidMobileCapabilityType.PLATFORM_NAME, Platform.ANDROID);
+ //选用的自动化框架
+ desiredCapabilities.setCapability(MobileCapabilityType.AUTOMATION_NAME, AutomationName.ANDROID_UIAUTOMATOR2);
+ //关闭运行时阻塞其他Accessibility服务,开启的话其他不能使用了
+ desiredCapabilities.setCapability("disableSuppressAccessibilityService", true);
+ //adb指令超时时间
+ desiredCapabilities.setCapability(AndroidMobileCapabilityType.ADB_EXEC_TIMEOUT, 7200000);
+ //UIA2安装超时时间
+ desiredCapabilities.setCapability("uiautomator2ServerInstallTimeout", 600000);
+
+ //io.appium.uiautomator2.server io.appium.uiautomator2.server.test //io.appium.settings
+// desiredCapabilities.setCapability("skipServerInstallation",true);
+// desiredCapabilities.setCapability("disableWindowAnimation",true);
+// desiredCapabilities.setCapability("skipDeviceInitialization",true);
+ //等待新命令超时时间
+ desiredCapabilities.setCapability(MobileCapabilityType.NEW_COMMAND_TIMEOUT, 7200);
+ //不重置应用
+ desiredCapabilities.setCapability(MobileCapabilityType.NO_RESET, true);
+ //单独唤起应用的话,这个需要设置空字符串
+ desiredCapabilities.setCapability(MobileCapabilityType.BROWSER_NAME, "");
+ //指定设备序列号
+ desiredCapabilities.setCapability(MobileCapabilityType.UDID, udId);
+ //随机systemPort
+ desiredCapabilities.setCapability(AndroidMobileCapabilityType.SYSTEM_PORT, PortTool.getPort());
+ 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, "连接设备驱动失败!", "");
+ //测试标记为失败
+ setResultDetailStatus(ResultDetailStatus.FAIL);
+ throw e;
+ }
+ Capabilities capabilities = androidDriver.getCapabilities();
+ Thread.sleep(100);
+ log.androidInfo("Android", capabilities.getCapability("platformVersion").toString(),
+ udId, capabilities.getCapability("deviceManufacturer").toString(),
+ capabilities.getCapability("deviceModel").toString(),
+ capabilities.getCapability("deviceApiLevel").toString(),
+ capabilities.getCapability("deviceScreenSize").toString());
+ }
+
+ /**
+ * @return void
+ * @author ZhouYiXun
+ * @des 关闭driver
+ * @date 2021/8/16 20:21
+ */
+ public void closeAndroidDriver() {
+ try {
+ if (androidDriver != null) {
+ //终止测试包
+ if (!testPackage.equals("")) {
+ try {
+ androidDriver.terminateApp(testPackage, new AndroidTerminateApplicationOptions().withTimeout(Duration.ofMillis(1000)));
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ androidDriver.quit();
+ log.sendStepLog(StepType.PASS, "退出连接设备", "");
+ }
+ } catch (Exception e) {
+ log.sendStepLog(StepType.WARN, "测试终止异常!请检查设备连接状态", "");
+ //测试异常
+ setResultDetailStatus(ResultDetailStatus.WARN);
+ e.printStackTrace();
+ }
+ }
+
+ public void waitDevice(int waitCount) {
+ log.sendStepLog(StepType.INFO, "设备非空闲状态!第" + waitCount + "次等待连接...", "");
+ }
+
+ public void waitDeviceTimeOut() {
+ log.sendStepLog(StepType.ERROR, "等待设备超时!测试跳过!", "");
+ //测试标记为异常
+ setResultDetailStatus(ResultDetailStatus.WARN);
+ }
+
+ public AndroidDriver getAndroidDriver() {
+ return androidDriver;
+ }
+
+ /**
+ * @param status
+ * @return void
+ * @author ZhouYiXun
+ * @des 设置测试状态
+ * @date 2021/8/16 23:46
+ */
+ public void setResultDetailStatus(int status) {
+ if (status > this.status) {
+ this.status = status;
+ }
+ }
+
+ public void sendStatus() {
+ log.sendStatusLog(status);
+ }
+
+ //判断有无出错
+ public int getStatus() {
+ return status;
+ }
+
+ //调试每次重设状态
+ public void resetResultDetailStatus() {
+ status = 1;
+ }
+
+ /**
+ * @return boolean
+ * @author ZhouYiXun
+ * @des 检测是否低电量
+ * @date 2021/8/16 23:16
+ */
+ public boolean getBattery() {
+ double battery = androidDriver.getBatteryInfo().getLevel();
+ if (battery <= 0.1) {
+ log.sendStepLog(StepType.ERROR, "设备电量过低!", "跳过本次测试...");
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * @return void
+ * @author ZhouYiXun
+ * @des 获取性能信息(Appium自带的cpu和network方法貌似有bug, 后续再优化)
+ * @date 2021/8/16 23:16
+ */
+ public void getPerform() {
+ if (!testPackage.equals("")) {
+ List performanceData = Arrays.asList("memoryinfo", "batteryinfo");
+ for (String performName : performanceData) {
+ List> re = androidDriver.getPerformanceData(testPackage, performName, 1);
+ List mem;
+ if (performName.equals("memoryinfo")) {
+ mem = Arrays.asList(0, 1, 2, 5, 6, 7);
+ } else {
+ mem = Collections.singletonList(0);
+ }
+ JSONObject perform = new JSONObject();
+ for (Integer memNum : mem) {
+ perform.put(re.get(0).get(memNum).toString(), re.get(1).get(memNum));
+ }
+ log.sendPerLog(testPackage, performName.equals("memoryinfo") ? 1 : 2, perform);
+ }
+ }
+ }
+
+ //配合前端渲染,需要每个节点加上id
+ private int xpathId = 1;
+
+ /**
+ * @return com.alibaba.fastjson.JSONArray
+ * @author ZhouYiXun
+ * @des 获取页面xpath信息
+ * @date 2021/8/16 23:16
+ */
+ public JSONArray getResource() {
+ androidDriver.context("NATIVE_APP");
+ JSONArray elementList = new JSONArray();
+ Document doc = Jsoup.parse(androidDriver.getPageSource());
+ String xpath = "/hierarchy";
+ elementList.addAll(getChildren(doc.body().children().get(0).children(), xpath));
+ xpathId = 1;
+ return elementList;
+ }
+
+ /**
+ * @param elements
+ * @param xpath 父级节点xpath
+ * @return com.alibaba.fastjson.JSONArray
+ * @author ZhouYiXun
+ * @des 获取子节点信息
+ * @date 2021/8/16 23:36
+ */
+ public JSONArray getChildren(org.jsoup.select.Elements elements, String xpath) {
+ JSONArray elementList = new JSONArray();
+ for (int i = 0; i < elements.size(); i++) {
+ JSONObject ele = new JSONObject();
+ //tag次数
+ int tagCount = 0;
+ //兄弟节点index
+ int siblingIndex = 0;
+ String indexXpath;
+ for (int j = 0; j < elements.size(); j++) {
+ if (elements.get(j).attr("class").equals(elements.get(i).attr("class"))) {
+ tagCount++;
+ }
+ //当i==j时候,兄弟节点index等于tag出现次数,因为xpath多个tag的时候,[]里面下标是从1开始
+ if (i == j) {
+ siblingIndex = tagCount;
+ }
+ }
+ //如果tag出现次数等于1,xpath结尾不添加[]
+ if (tagCount == 1) {
+ indexXpath = xpath + "/" + elements.get(i).attr("class");
+ } else {
+ indexXpath = xpath + "/" + elements.get(i).attr("class") + "[" + siblingIndex + "]";
+ }
+ ele.put("id", xpathId);
+ xpathId++;
+ ele.put("label", "<" + elements.get(i).attr("class") + ">");
+ JSONObject detail = new JSONObject();
+ detail.put("xpath", indexXpath);
+ for (Attribute attr : elements.get(i).attributes()) {
+ //把bounds字段拆出来解析,方便前端进行截取
+ if (attr.getKey().equals("bounds")) {
+ String bounds = attr.getValue().replace("][", ":");
+ String pointStart = bounds.substring(1, bounds.indexOf(":"));
+ String pointEnd = bounds.substring(bounds.indexOf(":") + 1, bounds.indexOf("]"));
+ detail.put("bStart", pointStart);
+ detail.put("bEnd", pointEnd);
+ }
+ detail.put(attr.getKey(), attr.getValue());
+ }
+ ele.put("detail", detail);
+ if (elements.get(i).children().size() > 0) {
+ ele.put("children", getChildren(elements.get(i).children(), indexXpath));
+ }
+ elementList.add(ele);
+ }
+ return elementList;
+ }
+
+ /**
+ * @return void
+ * @author ZhouYiXun
+ * @des 开始录像
+ * @date 2021/8/16 23:56
+ */
+ public void startRecord() {
+ try {
+ AndroidStartScreenRecordingOptions recordOption = new AndroidStartScreenRecordingOptions();
+ //限制30分钟,appium支持的最长时间
+ recordOption.withTimeLimit(Duration.ofMinutes(30));
+ //开启bugReport,开启后录像会有相关附加信息
+ recordOption.enableBugReport();
+ //是否强制终止上次录像并开始新的录像
+ recordOption.enableForcedRestart();
+ //限制码率,防止录像过大
+ recordOption.withBitRate(3000000);
+ androidDriver.startRecordingScreen(recordOption);
+ } catch (Exception e) {
+ log.sendRecordLog(false, "", "");
+ }
+ }
+
+ /**
+ * @return void
+ * @author ZhouYiXun
+ * @des 停止录像
+ * @date 2021/8/16 23:56
+ */
+ public void stopRecord() {
+ File recordDir = new File("test-output/record");
+ if (!recordDir.exists()) {
+ recordDir.mkdirs();
+ }
+ long timeMillis = Calendar.getInstance().getTimeInMillis();
+ String fileName = timeMillis + "_" + udId.substring(0, 4) + ".mp4";
+ File uploadFile = new File(recordDir + File.separator + fileName);
+ try {
+ //加锁防止内存泄漏
+ synchronized (AndroidStepHandler.class) {
+ FileOutputStream fileOutputStream = new FileOutputStream(uploadFile);
+ byte[] bytes = Base64Utils.decodeFromString((androidDriver.stopRecordingScreen()));
+ fileOutputStream.write(bytes);
+ fileOutputStream.close();
+ }
+ log.sendRecordLog(true, fileName, UploadTools.uploadPatchRecord(uploadFile));
+ } catch (Exception e) {
+ log.sendRecordLog(false, fileName, "");
+ }
+ }
+
+// public void settingSonicPlugins(IDevice iDevice) {
+// try {
+// androidDriver.activateApp("com.sonic.plugins");
+// try {
+// Thread.sleep(1000);
+// } catch (Exception e) {
+// }
+// log.sendStepLog(StepType.INFO, "已安装Sonic插件!", "");
+// } catch (Exception e) {
+// log.sendStepLog(StepType.ERROR, "未安装Sonic插件!", "");
+// throw e;
+// }
+// try {
+// if (!androidDriver.currentActivity().equals("com.sonic.plugins.MainActivity")) {
+// try {
+// AndroidDeviceBridgeTool.executeCommand(iDevice, "input keyevent 4");
+// Thread.sleep(1000);
+// } catch (Exception e) {
+// }
+// }
+// findEle("xpath", "//android.widget.TextView[@text='服务状态:已开启']");
+// } catch (Exception e) {
+// log.sendStepLog(StepType.ERROR, "未开启Sonic插件服务!请到辅助功能或无障碍开启", "");
+// throw e;
+// }
+// try {
+// findEle("id", "com.sonic.plugins:id/password_edit").clear();
+// if (AndroidPasswordMap.getMap().get(log.udId) != null
+// && (AndroidPasswordMap.getMap().get(log.udId) != null)
+// && (!AndroidPasswordMap.getMap().get(log.udId).equals(""))) {
+// findEle("id", "com.sonic.plugins:id/password_edit").sendKeys(AndroidPasswordMap.getMap().get(log.udId));
+// } else {
+// findEle("id", "com.sonic.plugins:id/password_edit").sendKeys("sonic123456");
+// }
+// findEle("id", "com.sonic.plugins:id/save").click();
+// } catch (Exception e) {
+// log.sendStepLog(StepType.ERROR, "配置Sonic插件服务失败!", "");
+// throw e;
+// }
+// }
+
+ public void install(HandleDes handleDes, String path) {
+ handleDes.setStepDes("安装应用");
+ handleDes.setDetail("App安装路径: " + path);
+// IDevice iDevice = AndroidDeviceBridgeTool.getIDeviceByUdId(log.udId);
+// String manufacturer = iDevice.getProperty(IDevice.PROP_DEVICE_MANUFACTURER);
+ try {
+ androidDriver.unlockDevice();
+ if (androidDriver.getConnection().isAirplaneModeEnabled()) {
+ androidDriver.toggleAirplaneMode();
+ }
+ if (!androidDriver.getConnection().isWiFiEnabled()) {
+ androidDriver.toggleWifi();
+ }
+ } catch (Exception e) {
+ log.sendStepLog(StepType.WARN, "安装前准备跳过...", "");
+ }
+ log.sendStepLog(StepType.INFO, "", "开始安装App,请稍后...");
+// if (manufacturer.equals("OPPO") || manufacturer.equals("vivo") || manufacturer.equals("Meizu")) {
+// settingSonicPlugins(iDevice);
+// AndroidDeviceBridgeTool.executeCommand(iDevice, "input keyevent 3");
+// }
+// //单独适配一下oppo
+// if (manufacturer.equals("OPPO")) {
+// try {
+// androidDriver.installApp(path, new AndroidInstallApplicationOptions()
+// .withAllowTestPackagesEnabled().withReplaceEnabled()
+// .withGrantPermissionsEnabled().withTimeout(Duration.ofMillis(60000)));
+// } catch (Exception e) {
+// }
+// //单独再适配colorOs
+// if (androidDriver.currentActivity().equals(".verification.login.AccountActivity")) {
+// try {
+// if (AndroidPasswordMap.getMap().get(log.udId) != null
+// && (AndroidPasswordMap.getMap().get(log.udId) != null)
+// && (!AndroidPasswordMap.getMap().get(log.udId).equals(""))) {
+// findEle("id", "com.coloros.safecenter:id/et_login_passwd_edit"
+// ).sendKeys(AndroidPasswordMap.getMap().get(log.udId));
+// } else {
+// findEle("id", "com.coloros.safecenter:id/et_login_passwd_edit"
+// ).sendKeys("sonic123456");
+// }
+// findEle("id", "android:id/button1").click();
+// } catch (Exception e) {
+// }
+// }
+// AtomicInteger tryTime = new AtomicInteger(0);
+// AndroidDeviceThreadPool.cachedThreadPool.execute(() -> {
+// while (tryTime.get() < 20) {
+// tryTime.getAndIncrement();
+// //部分oppo有继续安装
+// try {
+// WebElement getContinueButton = findEle("id", "com.android.packageinstaller:id/virus_scan_panel");
+// Thread.sleep(2000);
+// AndroidDeviceBridgeTool.executeCommand(iDevice,
+// String.format("input tap %d %d", (getContinueButton.getRect().width) / 2
+// , getContinueButton.getRect().y + getContinueButton.getRect().height));
+// Thread.sleep(2000);
+// } catch (Exception e) {
+// e.printStackTrace();
+// }
+// //低版本oppo安装按钮在右边
+// try {
+// findEle("id", "com.android.packageinstaller:id/install_confirm_panel");
+// WebElement getInstallButton = findEle("id", "com.android.packageinstaller:id/bottom_button_layout");
+// Thread.sleep(2000);
+// AndroidDeviceBridgeTool.executeCommand(iDevice, String.format("input tap %d %d"
+// , ((getInstallButton.getRect().width) / 4) * 3
+// , getInstallButton.getRect().y + (getInstallButton.getRect().height) / 2));
+// Thread.sleep(2000);
+// } catch (Exception e) {
+// e.printStackTrace();
+// }
+// //部分oppo无法点击
+// try {
+// findEle("xpath", "//*[@text='应用权限']");
+// WebElement getInstallButton = findEle("id", "com.android.packageinstaller:id/install_confirm_panel");
+// Thread.sleep(2000);
+// AndroidDeviceBridgeTool.executeCommand(iDevice, String.format("input tap %d %d"
+// , (getInstallButton.getRect().width) / 2, getInstallButton.getRect().y + getInstallButton.getRect().height));
+// Thread.sleep(2000);
+// } catch (Exception e) {
+// e.printStackTrace();
+// }
+// if (!androidDriver.getCurrentPackage().equals("com.android.packageinstaller")) {
+// break;
+// }
+// }
+// });
+// while (androidDriver.getCurrentPackage().equals("com.android.packageinstaller") && tryTime.get() < 20) {
+// try {
+// findEle("xpath", "//*[@text='完成']").click();
+// } catch (Exception e) {
+// }
+// }
+// } else {
+ try {
+ androidDriver.installApp(path, new AndroidInstallApplicationOptions()
+ .withAllowTestPackagesEnabled().withReplaceEnabled()
+ .withGrantPermissionsEnabled().withTimeout(Duration.ofMillis(60000)));
+ } catch (Exception e) {
+ handleDes.setE(e);
+ return;
+ }
+// }
+ }
+
+ public void uninstall(HandleDes handleDes, String appPackage) {
+ handleDes.setStepDes("卸载应用");
+ handleDes.setDetail("App包名: " + appPackage);
+ try {
+ androidDriver.removeApp(appPackage);
+ } catch (Exception e) {
+ handleDes.setE(e);
+ }
+ }
+
+ /**
+ * @param packageName
+ * @return void
+ * @author ZhouYiXun
+ * @des 终止app
+ * @date 2021/8/16 23:46
+ */
+ public void terminate(HandleDes handleDes, String packageName) {
+ handleDes.setStepDes("终止应用");
+ handleDes.setDetail("应用包名: " + packageName);
+ try {
+ androidDriver.terminateApp(packageName, new AndroidTerminateApplicationOptions().withTimeout(Duration.ofMillis(1000)));
+ } catch (Exception e) {
+ handleDes.setE(e);
+ }
+ }
+
+ public void runBackground(HandleDes handleDes, long time) {
+ handleDes.setStepDes("后台运行应用");
+ handleDes.setDetail("后台运行App " + time + " ms");
+ try {
+ androidDriver.runAppInBackground(Duration.ofMillis(time));
+ } catch (Exception e) {
+ handleDes.setE(e);
+ }
+ }
+
+ public void openApp(HandleDes handleDes, String appPackage) {
+ handleDes.setStepDes("打开应用");
+ handleDes.setDetail("App包名: " + appPackage);
+ try {
+ testPackage = appPackage;
+ androidDriver.activateApp(appPackage);
+ } catch (Exception e) {
+ handleDes.setE(e);
+ }
+ }
+
+ public void rotateDevice(HandleDes handleDes, String text) {
+ try {
+ String s = "";
+ switch (text) {
+ case "screenSub":
+ s = "sub";
+ handleDes.setStepDes("左转屏幕");
+ break;
+ case "screenAdd":
+ s = "add";
+ handleDes.setStepDes("右转屏幕");
+ break;
+ case "screenAbort":
+ s = "abort";
+ handleDes.setStepDes("关闭自动旋转");
+ break;
+ }
+ AndroidDeviceBridgeTool.screen(AndroidDeviceBridgeTool.getIDeviceByUdId(udId), s);
+ } catch (Exception e) {
+ handleDes.setE(e);
+ }
+ }
+
+ public void lock(HandleDes handleDes) {
+ handleDes.setStepDes("锁定屏幕");
+ try {
+ androidDriver.lockDevice();
+ } catch (Exception e) {
+ handleDes.setE(e);
+ }
+ }
+
+ public void unLock(HandleDes handleDes) {
+ handleDes.setStepDes("解锁屏幕");
+ try {
+ androidDriver.unlockDevice();
+ } catch (Exception e) {
+ handleDes.setE(e);
+ }
+ }
+
+ public void airPlaneMode(HandleDes handleDes) {
+ handleDes.setStepDes("切换飞行模式");
+ try {
+ androidDriver.toggleAirplaneMode();
+ } catch (Exception e) {
+ handleDes.setE(e);
+ }
+ }
+
+ public void wifiMode(HandleDes handleDes) {
+ handleDes.setStepDes("打开WIFI网络");
+ try {
+ if (!androidDriver.getConnection().isWiFiEnabled()) {
+ androidDriver.toggleWifi();
+ }
+ } catch (Exception e) {
+ handleDes.setE(e);
+ }
+ }
+
+ public void locationMode(HandleDes handleDes) {
+ handleDes.setStepDes("切换位置服务");
+ try {
+ androidDriver.toggleLocationServices();
+ } catch (Exception e) {
+ handleDes.setE(e);
+ }
+ }
+
+ public void asserts(HandleDes handleDes, String actual, String expect, String type) {
+ handleDes.setDetail("真实值: " + actual + " 期望值: " + expect);
+ try {
+ switch (type) {
+ case "assertEquals":
+ handleDes.setStepDes("断言验证(相等)");
+ assertEquals(actual, expect);
+ break;
+ case "assertTrue":
+ handleDes.setStepDes("断言验证(包含)");
+ assertTrue(actual.contains(expect));
+ break;
+ case "assertNotTrue":
+ handleDes.setStepDes("断言验证(不包含)");
+ assertFalse(actual.contains(expect));
+ break;
+ }
+ } catch (AssertionError e) {
+ handleDes.setE(e);
+ }
+ }
+
+ public String getText(HandleDes handleDes, String des, String selector, String pathValue) {
+ String s = "";
+ handleDes.setStepDes("获取" + des + "文本");
+ handleDes.setDetail("获取" + selector + ":" + pathValue + "文本");
+ try {
+ s = findEle(selector, pathValue).getText();
+ log.sendStepLog(StepType.INFO, "", "文本获取结果: " + s);
+ } catch (Exception e) {
+ handleDes.setE(e);
+ }
+ return s;
+ }
+
+ public void hideKey(HandleDes handleDes) {
+ handleDes.setStepDes("隐藏键盘");
+ handleDes.setDetail("隐藏弹出键盘");
+ try {
+ androidDriver.hideKeyboard();
+ } catch (Exception e) {
+ handleDes.setE(e);
+ }
+ }
+
+ public void toWebView(HandleDes handleDes, String webViewName) {
+ handleDes.setStepDes("切换到" + webViewName);
+ try {
+ androidDriver.context(webViewName);
+ } catch (Exception e) {
+ handleDes.setE(e);
+ }
+ }
+
+ public void click(HandleDes handleDes, String des, String selector, String pathValue) {
+ handleDes.setStepDes("点击" + des);
+ handleDes.setDetail("点击" + selector + ": " + pathValue);
+ try {
+ findEle(selector, pathValue).click();
+ } catch (Exception e) {
+ handleDes.setE(e);
+ }
+ }
+
+ public void sendKeys(HandleDes handleDes, String des, String selector, String pathValue, String keys) {
+ if (keys.contains("{{random}}")) {
+ String random = (int) (Math.random() * 10 + Math.random() * 10 * 2) + 5 + "";
+ keys = keys.replace("{{random}}", random);
+ }
+ if (keys.contains("{{timestamp}}")) {
+ String timeMillis = Calendar.getInstance().getTimeInMillis() + "";
+ keys = keys.replace("{{timestamp}}", timeMillis);
+ }
+ keys = replaceTrans(keys);
+ handleDes.setStepDes("对" + des + "输入内容");
+ handleDes.setDetail("对" + selector + ": " + pathValue + " 输入: " + keys);
+ try {
+ findEle(selector, pathValue).sendKeys(keys);
+ } catch (Exception e) {
+ handleDes.setE(e);
+ }
+ }
+
+ public void getTextAndAssert(HandleDes handleDes, String des, String selector, String pathValue, String expect) {
+ handleDes.setStepDes("获取" + des + "文本");
+ handleDes.setDetail("获取" + selector + ":" + pathValue + "文本");
+ try {
+ String s = findEle(selector, pathValue).getText();
+ log.sendStepLog(StepType.INFO, "", "文本获取结果: " + s);
+ try {
+ expect = replaceTrans(expect);
+ assertEquals(s, expect);
+ log.sendStepLog(StepType.INFO, "验证文本", "真实值: " + s + " 期望值: " + expect);
+ } catch (AssertionError e) {
+ log.sendStepLog(StepType.ERROR, "验证" + des + "文本失败!", "");
+ handleDes.setE(e);
+ }
+ } catch (Exception e) {
+ handleDes.setE(e);
+ }
+ }
+
+ public void longPressPoint(HandleDes handleDes, String des, String xy, int time) {
+ int x = Integer.parseInt(xy.substring(0, xy.indexOf(",")));
+ int y = Integer.parseInt(xy.substring(xy.indexOf(",") + 1));
+ handleDes.setStepDes("长按" + des);
+ handleDes.setDetail("长按坐标" + time + "毫秒 (" + x + "," + y + ")");
+ try {
+ TouchAction ta = new TouchAction(androidDriver);
+ ta.longPress(PointOption.point(x, y)).waitAction(WaitOptions.waitOptions(Duration.ofMillis(time))).release().perform();
+ } catch (Exception e) {
+ handleDes.setE(e);
+ }
+ }
+
+ public void keyCode(HandleDes handleDes, String key) {
+ handleDes.setStepDes("按系统按键" + key + "键");
+ try {
+ androidDriver.pressKey(new KeyEvent().withKey(AndroidKey.valueOf(key)));
+ } catch (Exception e) {
+ handleDes.setE(e);
+ }
+ }
+
+ public void multiAction(HandleDes handleDes, String des1, String xy1, String des2, String xy2, String des3, String xy3, String des4, String xy4) {
+ int x1 = Integer.parseInt(xy1.substring(0, xy1.indexOf(",")));
+ 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));
+ int x3 = Integer.parseInt(xy3.substring(0, xy3.indexOf(",")));
+ int y3 = Integer.parseInt(xy3.substring(xy3.indexOf(",") + 1));
+ int x4 = Integer.parseInt(xy4.substring(0, xy4.indexOf(",")));
+ int y4 = Integer.parseInt(xy4.substring(xy4.indexOf(",") + 1));
+ String detail = "坐标" + des1 + "( " + x1 + ", " + y1 + " )移动到坐标" + des2 + "( " + x2 + ", " + y2 + " ),同时坐标" + des3 + "( " + x3 + ", " + y3 + " )移动到坐标" + des4 + "( " + x4 + ", " + y4 + " )";
+ handleDes.setStepDes("双指操作");
+ handleDes.setDetail(detail);
+ try {
+ TouchAction hand1 = new TouchAction(androidDriver);
+ TouchAction hand2 = new TouchAction(androidDriver);
+ MultiTouchAction multiTouchAction = new MultiTouchAction(androidDriver);
+ hand1.press(PointOption.point(x1, y1)).moveTo(PointOption.point(x2, y2)).release();
+ hand2.press(PointOption.point(x3, y3)).moveTo(PointOption.point(x4, y4)).release();
+ multiTouchAction.add(hand1);
+ multiTouchAction.add(hand2);
+ multiTouchAction.perform();
+ } catch (Exception e) {
+ handleDes.setE(e);
+ }
+ }
+
+ public void tap(HandleDes handleDes, String des, String xy) {
+ int x = Integer.parseInt(xy.substring(0, xy.indexOf(",")));
+ int y = Integer.parseInt(xy.substring(xy.indexOf(",") + 1));
+ handleDes.setStepDes("点击" + des);
+ handleDes.setDetail("点击坐标(" + x + "," + y + ")");
+ try {
+ TouchAction ta = new TouchAction(androidDriver);
+ ta.tap(PointOption.point(x, y)).perform();
+ } catch (Exception e) {
+ handleDes.setE(e);
+ }
+ }
+
+ public void swipe(HandleDes handleDes, String des1, String xy1, String des2, String xy2) {
+ int x1 = Integer.parseInt(xy1.substring(0, xy1.indexOf(",")));
+ 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));
+ handleDes.setStepDes("滑动拖拽" + des1 + "到" + des2);
+ handleDes.setDetail("拖动坐标(" + x1 + "," + y1 + ")到(" + x2 + "," + y2 + ")");
+ try {
+ TouchAction ta = new TouchAction(androidDriver);
+ ta.press(PointOption.point(x1, y1)).waitAction(WaitOptions.waitOptions(Duration.ofMillis(300))).moveTo(PointOption.point(x2, y2)).release().perform();
+ } catch (Exception e) {
+ handleDes.setE(e);
+ }
+ }
+
+ public void longPress(HandleDes handleDes, String des, String selector, String pathValue, int time) {
+ handleDes.setStepDes("长按" + des);
+ handleDes.setDetail("长按控件元素" + time + "毫秒 ");
+ try {
+ TouchAction ta = new TouchAction(androidDriver);
+ WebElement webElement = findEle(selector, pathValue);
+ int x = webElement.getLocation().getX();
+ int y = webElement.getLocation().getY();
+ Duration duration = Duration.ofMillis(time);
+ ta.longPress(PointOption.point(x, y)).waitAction(WaitOptions.waitOptions(duration)).release().perform();
+ } catch (Exception e) {
+ handleDes.setE(e);
+ }
+ }
+
+ public void clear(HandleDes handleDes, String des, String selector, String pathValue) {
+ handleDes.setStepDes("清空" + des);
+ handleDes.setDetail("清空" + selector + ": " + pathValue);
+ try {
+ findEle(selector, pathValue).clear();
+ } catch (Exception e) {
+ handleDes.setE(e);
+ }
+ }
+
+ public void getTitle(HandleDes handleDes, String expect) {
+ String title = androidDriver.getTitle();
+ handleDes.setStepDes("验证网页标题");
+ handleDes.setDetail("标题:" + title + ",期望值:" + expect);
+ try {
+ assertEquals(title, expect);
+ } catch (AssertionError e) {
+ handleDes.setE(e);
+ }
+ }
+
+ public void clickByImg(HandleDes handleDes, String des, String pathValue) throws Exception {
+ handleDes.setStepDes("点击图片" + des);
+ handleDes.setDetail(pathValue);
+ File file = null;
+ if (pathValue.startsWith("http")) {
+ try {
+ file = DownImageTool.download(pathValue);
+ } catch (Exception e) {
+ handleDes.setE(e);
+ return;
+ }
+ }
+ File localCap = getScreenToLocal();
+ FindResult findResult;
+ FileSystemResource resource1 = new FileSystemResource(file);
+ FileSystemResource resource2 = new FileSystemResource(localCap);
+ MultiValueMap param = new LinkedMultiValueMap<>();
+ param.add("file1", resource1);
+ param.add("file2", resource2);
+ param.add("type", "finder");
+ try {
+ ResponseEntity responseEntity =
+ restTemplate.postForEntity(baseUrl + "/upload/cv", param, JSONObject.class);
+ if (responseEntity.getBody().getInteger("code") == 2000) {
+ findResult = responseEntity.getBody().getJSONObject("data").toJavaObject(FindResult.class);
+ if (findResult != null) {
+ try {
+ log.sendStepLog(StepType.INFO, "图片定位到坐标:(" + findResult.getX() + "," + findResult.getY() + ") 耗时:" + findResult.getTime() + " ms",
+ findResult.getUrl());
+ TouchAction ta = new TouchAction(androidDriver);
+ ta.tap(PointOption.point(findResult.getX(), findResult.getY())).perform();
+ } catch (Exception e) {
+ log.sendStepLog(StepType.ERROR, "点击" + des + "失败!", "");
+ handleDes.setE(e);
+ }
+ }
+ } else if (responseEntity.getBody().getInteger("code") == 4003) {
+ handleDes.setE(new Exception("图像匹配失败!"));
+ } else {
+ handleDes.setE(new Exception("点击失败!cv服务出错!"));
+ }
+ } catch (Exception e) {
+ handleDes.setE(new Exception("点击失败!cv服务访问出错!"));
+ } finally {
+ file.delete();
+ localCap.delete();
+ }
+ }
+
+ public void readText(HandleDes handleDes, String language, String text) throws Exception {
+// TextReader textReader = new TextReader();
+// String result = textReader.getTessResult(getScreenToLocal(), language);
+// log.sendStepLog(StepType.INFO, "",
+// "图像文字识别结果:
" + result);
+// String filter = result.replaceAll(" ", "");
+ handleDes.setStepDes("图像文字识别");
+ handleDes.setDetail("(该功能暂时关闭)期望包含文本:" + text);
+// if (!filter.contains(text)) {
+// handleDes.setE(new Exception("图像文字识别不通过!"));
+// }
+ }
+
+ public void toHandle(HandleDes handleDes, String titleName) throws Exception {
+ handleDes.setStepDes("切换Handle");
+ Thread.sleep(1000);
+ Set handle = androidDriver.getWindowHandles();//获取handles
+ String ha;
+ for (int i = 1; i <= handle.size(); i++) {
+ ha = (String) handle.toArray()[handle.size() - i];//查找handle
+ try {
+ androidDriver.switchTo().window(ha);//切换到最后一个handle
+ } catch (Exception e) {
+ }
+ if (androidDriver.getTitle().equals(titleName)) {
+ handleDes.setDetail("切换到Handle:" + ha);
+ log.sendStepLog(StepType.INFO, "页面标题:" + androidDriver.getTitle(), "");
+ break;
+ }
+ }
+ }
+
+ public File getScreenToLocal() {
+ File file = ((TakesScreenshot) androidDriver).getScreenshotAs(OutputType.FILE);
+ File resultFile = new File("test-output/" + log.udId + Calendar.getInstance().getTimeInMillis() + ".jpg");
+ try {
+ FileCopyUtils.copy(file, resultFile);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return resultFile;
+ }
+
+ public String replaceTrans(String text) {
+ if (text.contains("{{") && text.contains("}}")) {
+ String tail = text.substring(text.indexOf("{{") + 2);
+ if (tail.contains("}}")) {
+ String child = tail.substring(tail.indexOf("}}") + 2);
+ String middle = tail.substring(0, tail.indexOf("}}"));
+ text = text.substring(0, text.indexOf("}}") + 2);
+ if (globalParams.getString(middle) != null) {
+ text = text.replace("{{" + middle + "}}", globalParams.getString(middle));
+ }
+ text = text + replaceTrans(child);
+ }
+ }
+ return text;
+ }
+
+ public void checkImage(HandleDes handleDes, String des, String pathValue, double matchThreshold) throws Exception {
+ log.sendStepLog(StepType.INFO, "开始检测" + des + "兼容", "检测与当前设备截图相似度,期望相似度为" + matchThreshold + "%");
+ File file = null;
+ if (pathValue.startsWith("http")) {
+ file = DownImageTool.download(pathValue);
+ }
+ File localCap = getScreenToLocal();
+ FileSystemResource resource1 = new FileSystemResource(file);
+ FileSystemResource resource2 = new FileSystemResource(localCap);
+ MultiValueMap param = new LinkedMultiValueMap<>();
+ param.add("file1", resource1);
+ param.add("file2", resource2);
+ param.add("type", "checker");
+ try {
+ ResponseEntity responseEntity =
+ restTemplate.postForEntity(baseUrl + "/upload/cv", param, JSONObject.class);
+ if (responseEntity.getBody().getInteger("code") == 2000) {
+ double score = responseEntity.getBody().getDouble("data");
+ handleDes.setStepDes("检测" + des + "图片相似度");
+ handleDes.setDetail("相似度为" + score * 100 + "%");
+ if (score == 0) {
+ handleDes.setE(new Exception("图片相似度检测不通过!比对图片分辨率不一致!"));
+ } else if (score < (matchThreshold / 100)) {
+ handleDes.setE(new Exception("图片相似度检测不通过!expect " + matchThreshold + " but " + score * 100));
+ }
+ } else {
+ handleDes.setE(new Exception("图片相似度检测出错!cv服务出错!"));
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ handleDes.setE(new Exception("图片相似度检测出错!cv服务访问出错!"));
+ } finally {
+ file.delete();
+ localCap.delete();
+ }
+ }
+
+ public void exceptionLog(Throwable e) {
+ log.sendStepLog(StepType.WARN, "", "异常信息: " + e.fillInStackTrace().toString());
+ }
+
+ public void errorScreen() {
+ try {
+ androidDriver.context("NATIVE_APP");//先切换回app
+ log.sendStepLog(StepType.WARN, "获取异常截图", UploadTools
+ .upload(((TakesScreenshot) androidDriver).getScreenshotAs(OutputType.FILE), "imageFiles"));
+ } catch (Exception e) {
+ log.sendStepLog(StepType.ERROR, "捕获截图失败", "");
+ }
+ }
+
+ public String stepScreen(HandleDes handleDes) {
+ handleDes.setStepDes("获取截图");
+ String url = "";
+ try {
+ androidDriver.context("NATIVE_APP");//先切换回app
+ url = UploadTools.upload(((TakesScreenshot) androidDriver)
+ .getScreenshotAs(OutputType.FILE), "imageFiles");
+ handleDes.setDetail(url);
+ } catch (Exception e) {
+ handleDes.setE(e);
+ }
+ return url;
+ }
+
+ public Set getWebView() {
+ Set contextNames = androidDriver.getContextHandles();
+ return contextNames;
+ }
+
+ public String getCurrentActivity() {
+ return androidDriver.currentActivity();
+ }
+
+ public void pause(HandleDes handleDes, int time) {
+ handleDes.setStepDes("强制等待");
+ handleDes.setDetail("等待" + time + " ms");
+ try {
+ Thread.sleep(time);
+ } catch (InterruptedException e) {
+ handleDes.setE(e);
+ }
+ }
+
+ public void runMonkey(HandleDes handleDes, JSONObject content, List text) {
+ handleDes.setStepDes("运行随机事件测试完毕");
+ String packageName = content.getString("packageName");
+ int pctNum = content.getInteger("pctNum");
+ if (!androidDriver.isAppInstalled(packageName)) {
+ log.sendStepLog(StepType.ERROR, "应用未安装!", "设备未安装 " + packageName);
+ handleDes.setE(new Exception("未安装应用"));
+ return;
+ }
+ IDevice iDevice = AndroidDeviceBridgeTool.getIDeviceByUdId(udId);
+ JSONArray options = content.getJSONArray("options");
+ int width = androidDriver.manage().window().getSize().width;
+ int height = androidDriver.manage().window().getSize().height;
+ int sleepTime = 50;
+ int systemEvent = 0;
+ int tapEvent = 0;
+ int longPressEvent = 0;
+ int swipeEvent = 0;
+ int zoomEvent = 0;
+ int navEvent = 0;
+ boolean isOpenH5Listener = false;
+ boolean isOpenPackageListener = false;
+ boolean isOpenActivityListener = false;
+ boolean isOpenNetworkListener = false;
+ if (!options.isEmpty()) {
+ for (int i = options.size() - 1; i >= 0; i--) {
+ JSONObject jsonOption = (JSONObject) options.get(i);
+ if (jsonOption.getString("name").equals("sleepTime")) {
+ sleepTime = jsonOption.getInteger("value");
+ }
+ if (jsonOption.getString("name").equals("systemEvent")) {
+ systemEvent = jsonOption.getInteger("value");
+ }
+ if (jsonOption.getString("name").equals("tapEvent")) {
+ tapEvent = jsonOption.getInteger("value");
+ }
+ if (jsonOption.getString("name").equals("longPressEvent")) {
+ longPressEvent = jsonOption.getInteger("value");
+ }
+ if (jsonOption.getString("name").equals("swipeEvent")) {
+ swipeEvent = jsonOption.getInteger("value");
+ }
+ if (jsonOption.getString("name").equals("zoomEvent")) {
+ zoomEvent = jsonOption.getInteger("value");
+ }
+ if (jsonOption.getString("name").equals("navEvent")) {
+ navEvent = jsonOption.getInteger("value");
+ }
+ if (jsonOption.getString("name").equals("isOpenH5Listener")) {
+ isOpenH5Listener = jsonOption.getBoolean("value");
+ }
+ if (jsonOption.getString("name").equals("isOpenPackageListener")) {
+ isOpenPackageListener = jsonOption.getBoolean("value");
+ }
+ if (jsonOption.getString("name").equals("isOpenActivityListener")) {
+ isOpenActivityListener = jsonOption.getBoolean("value");
+ }
+ if (jsonOption.getString("name").equals("isOpenNetworkListener")) {
+ isOpenNetworkListener = jsonOption.getBoolean("value");
+ }
+ options.remove(options.get(i));
+ }
+ }
+ int finalSleepTime = sleepTime;
+ int finalTapEvent = tapEvent;
+ int finalLongPressEvent = longPressEvent;
+ int finalSwipeEvent = swipeEvent;
+ int finalZoomEvent = zoomEvent;
+ int finalSystemEvent = systemEvent;
+ int finalNavEvent = navEvent;
+ Future> randomThread = AndroidDeviceThreadPool.cachedThreadPool.submit(() -> {
+ log.sendStepLog(StepType.INFO, "", "随机事件数:" + pctNum +
+ "
目标应用:" + packageName
+ + "
用户操作时延:" + finalSleepTime + " ms"
+ + "
轻触事件权重:" + finalTapEvent
+ + "
长按事件权重:" + finalLongPressEvent
+ + "
滑动事件权重:" + finalSwipeEvent
+ + "
多点触控事件权重:" + finalZoomEvent
+ + "
物理按键事件权重:" + finalSystemEvent
+ + "
系统事件权重:" + finalNavEvent
+ );
+ openApp(new HandleDes(), packageName);
+ TouchAction ta = new TouchAction(androidDriver);
+ TouchAction ta2 = new TouchAction(androidDriver);
+ MultiTouchAction multiTouchAction = new MultiTouchAction(androidDriver);
+ int totalCount = finalSystemEvent + finalTapEvent + finalLongPressEvent + finalSwipeEvent + finalZoomEvent + finalNavEvent;
+ for (int i = 0; i < pctNum; i++) {
+ try {
+ int random = new Random().nextInt(totalCount);
+ if (random >= 0 && random < finalSystemEvent) {
+ int key = new Random().nextInt(9);
+ String keyType = "";
+ switch (key) {
+ case 0:
+ keyType = "HOME";
+ break;
+ case 1:
+ keyType = "BACK";
+ break;
+ case 2:
+ keyType = "MENU";
+ break;
+ case 3:
+ keyType = "APP_SWITCH";
+ break;
+ case 4:
+ keyType = "BRIGHTNESS_DOWN";
+ break;
+ case 5:
+ keyType = "BRIGHTNESS_UP";
+ break;
+ case 6:
+ keyType = "VOLUME_UP";
+ break;
+ case 7:
+ keyType = "VOLUME_DOWN";
+ break;
+ case 8:
+ keyType = "VOLUME_MUTE";
+ break;
+ }
+ androidDriver.pressKey(new KeyEvent(AndroidKey.valueOf(keyType)));
+ }
+ if (random >= finalSystemEvent && random < (finalSystemEvent + finalTapEvent)) {
+ int x = new Random().nextInt(width - 60) + 60;
+ int y = new Random().nextInt(height - 60) + 60;
+ ta.tap(PointOption.point(x, y)).perform();
+ }
+ if (random >= (finalSystemEvent + finalTapEvent) && random < (finalSystemEvent + finalTapEvent + finalLongPressEvent)) {
+ int x = new Random().nextInt(width - 60) + 60;
+ int y = new Random().nextInt(height - 60) + 60;
+ ta.longPress(PointOption.point(x, y)).waitAction(WaitOptions.waitOptions(Duration.ofSeconds(new Random().nextInt(3) + 1))).release().perform();
+ }
+ if (random >= (finalSystemEvent + finalTapEvent + finalLongPressEvent) && random < (finalSystemEvent + finalTapEvent + finalLongPressEvent + finalSwipeEvent)) {
+ int x1 = new Random().nextInt(width - 60) + 60;
+ int y1 = new Random().nextInt(height - 80) + 80;
+ int x2 = new Random().nextInt(width - 60) + 60;
+ int y2 = new Random().nextInt(height - 80) + 80;
+ ta.press(PointOption.point(x1, y1)).waitAction(WaitOptions.waitOptions(Duration.ofMillis(200))).moveTo(PointOption.point(x2, y2)).release().perform();
+ }
+ if (random >= (finalSystemEvent + finalTapEvent + finalLongPressEvent + finalSwipeEvent) && random < (finalSystemEvent + finalTapEvent + finalLongPressEvent + finalSwipeEvent + finalZoomEvent)) {
+ int x1 = new Random().nextInt(width - 80);
+ int y1 = new Random().nextInt(height - 80);
+ int x2 = new Random().nextInt(width - 100);
+ int y2 = new Random().nextInt(height - 80);
+ int x3 = new Random().nextInt(width - 100);
+ int y3 = new Random().nextInt(height - 80);
+ int x4 = new Random().nextInt(width - 100);
+ int y4 = new Random().nextInt(height - 80);
+ ta.press(PointOption.point(x1, y1)).waitAction(WaitOptions.waitOptions(Duration.ofMillis(200))).moveTo(PointOption.point(x2, y2)).release();
+ ta2.press(PointOption.point(x3, y3)).waitAction(WaitOptions.waitOptions(Duration.ofMillis(200))).moveTo(PointOption.point(x4, y4)).release();
+ multiTouchAction.add(ta);
+ multiTouchAction.add(ta2);
+ multiTouchAction.perform();
+ }
+ if (random >= (finalSystemEvent + finalTapEvent + finalLongPressEvent + finalSwipeEvent + finalZoomEvent) && random < (finalSystemEvent + finalTapEvent + finalLongPressEvent + finalSwipeEvent + finalZoomEvent + finalNavEvent)) {
+ androidDriver.toggleWifi();
+ }
+ Thread.sleep(finalSleepTime);
+ } catch (Throwable e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ );
+ Boolean finalIsOpenH5Listener = isOpenH5Listener;
+ Future> H5Listener = AndroidDeviceThreadPool.cachedThreadPool.submit(() -> {
+ if (finalIsOpenH5Listener) {
+ int h5Time = 0;
+ while (!randomThread.isDone()) {
+ try {
+ Thread.sleep(8000);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ try {
+ if (androidDriver.findElementsByClassName("android.webkit.WebView").size() > 0) {
+ h5Time++;
+ AndroidDeviceBridgeTool.executeCommand(iDevice, "input keyevent 4");
+ } else {
+ h5Time = 0;
+ }
+ if (h5Time >= 12) {
+ androidDriver.terminateApp(packageName, new AndroidTerminateApplicationOptions().withTimeout(Duration.ofMillis(1000)));
+ h5Time = 0;
+ }
+ } catch (Throwable e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+ );
+ boolean finalIsOpenPackageListener = isOpenPackageListener;
+ Future> packageListener = AndroidDeviceThreadPool.cachedThreadPool.submit(() -> {
+ if (finalIsOpenPackageListener) {
+ while (!randomThread.isDone()) {
+ int waitTime = 0;
+ while (waitTime <= 10 && (!randomThread.isDone())) {
+ try {
+ Thread.sleep(5000);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ if (!androidDriver.getCurrentPackage().equals(packageName)) {
+ androidDriver.activateApp(packageName);
+ }
+ waitTime++;
+ }
+ androidDriver.activateApp(packageName);
+ }
+ }
+ }
+ );
+ boolean finalIsOpenActivityListener = isOpenActivityListener;
+ Future> activityListener = AndroidDeviceThreadPool.cachedThreadPool.submit(() -> {
+ if (finalIsOpenActivityListener) {
+ if (text.isEmpty()) {
+ return;
+ }
+ Set blackList = new HashSet<>();
+ for (JSONObject activities : text) {
+ blackList.add(activities.getString("name"));
+ }
+ while (!randomThread.isDone()) {
+ try {
+ Thread.sleep(8000);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ if (blackList.contains(getCurrentActivity())) {
+ AndroidDeviceBridgeTool.executeCommand(iDevice, "input keyevent 4");
+ } else continue;
+ try {
+ Thread.sleep(8000);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ if (blackList.contains(getCurrentActivity())) {
+ androidDriver.terminateApp(packageName, new AndroidTerminateApplicationOptions().withTimeout(Duration.ofMillis(1000)));
+ }
+ }
+ }
+ }
+ );
+ boolean finalIsOpenNetworkListener = isOpenNetworkListener;
+ Future> networkListener = AndroidDeviceThreadPool.cachedThreadPool.submit(() -> {
+ if (finalIsOpenNetworkListener) {
+ while (!randomThread.isDone()) {
+ try {
+ Thread.sleep(8000);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ if (androidDriver.getConnection().isAirplaneModeEnabled()) {
+ androidDriver.toggleAirplaneMode();
+ }
+ try {
+ Thread.sleep(8000);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ if (!androidDriver.getConnection().isWiFiEnabled()) {
+ androidDriver.toggleWifi();
+ }
+ }
+ }
+ }
+ );
+ try {
+ Thread.sleep(500);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+// if (version.length() == 0) {
+// version = AndroidDeviceBridgeTool.getAppOnlyVersion(udId, packageName);
+// }
+ log.sendStepLog(StepType.INFO, "", "测试目标包:" + packageName +
+ (isOpenPackageListener ? "
应用包名监听器已开启..." : "") +
+ (isOpenH5Listener ? "
H5页面监听器已开启..." : "") +
+ (isOpenActivityListener ? "
黑名单Activity监听器..." : "") +
+ (isOpenNetworkListener ? "
网络状态监听器已开启..." : ""));
+ while (!randomThread.isDone() || (!packageListener.isDone()) || (!activityListener.isDone()) || (!networkListener.isDone()) || (!H5Listener.isDone())) {
+ }
+ }
+
+ public void publicStep(HandleDes handleDes, String name, JSONArray stepArray) {
+ handleDes.setStepDes("执行公共步骤 " + name);
+ log.sendStepLog(StepType.WARN, "公共步骤 " + name + " 开始执行", "");
+ for (Object publicStep : stepArray) {
+ JSONObject stepDetail = (JSONObject) publicStep;
+ try {
+ runStep(stepDetail);
+ } catch (Throwable e) {
+ handleDes.setE(e);
+ break;
+ }
+ }
+ }
+
+ public WebElement findEle(String selector, String pathValue) {
+ WebElement we = null;
+ switch (selector) {
+ case "id":
+ we = androidDriver.findElementById(pathValue);
+ break;
+ case "name":
+ we = androidDriver.findElementByName(pathValue);
+ break;
+ case "xpath":
+ we = androidDriver.findElementByXPath(pathValue);
+ break;
+ case "cssSelector":
+ we = androidDriver.findElementByCssSelector(pathValue);
+ break;
+ case "className":
+ we = androidDriver.findElementByClassName(pathValue);
+ break;
+ case "tagName":
+ we = androidDriver.findElementByTagName(pathValue);
+ break;
+ case "linkText":
+ we = androidDriver.findElementByLinkText(pathValue);
+ break;
+ case "partialLinkText":
+ we = androidDriver.findElementByPartialLinkText(pathValue);
+ break;
+ default:
+ log.sendStepLog(StepType.ERROR, "查找控件元素失败", "这个控件元素类型: " + selector + " 不存在!!!");
+ break;
+ }
+ return we;
+ }
+
+ public void runStep(JSONObject stepJSON) throws Throwable {
+ JSONObject step = stepJSON.getJSONObject("step");
+ JSONArray eleList = step.getJSONArray("elements");
+ HandleDes handleDes = new HandleDes();
+ switch (step.getString("stepType")) {
+ case "toWebView":
+ toWebView(handleDes, step.getString("content"));
+ break;
+ case "toHandle":
+ toHandle(handleDes, step.getString("content"));
+ break;
+ case "readText":
+ readText(handleDes, step.getString("content"), step.getString("text"));
+ break;
+ case "clickByImg":
+ clickByImg(handleDes, eleList.getJSONObject(0).getString("eleName")
+ , eleList.getJSONObject(0).getString("eleValue"));
+ break;
+ case "click":
+ click(handleDes, eleList.getJSONObject(0).getString("eleName"), eleList.getJSONObject(0).getString("eleType")
+ , eleList.getJSONObject(0).getString("eleValue"));
+ break;
+ case "getTitle":
+ getTitle(handleDes, step.getString("content"));
+ break;
+ case "sendKeys":
+ sendKeys(handleDes, eleList.getJSONObject(0).getString("eleName"), eleList.getJSONObject(0).getString("eleType")
+ , eleList.getJSONObject(0).getString("eleValue"), step.getString("content"));
+ break;
+ case "getText":
+ getTextAndAssert(handleDes, eleList.getJSONObject(0).getString("eleName"), eleList.getJSONObject(0).getString("eleType")
+ , eleList.getJSONObject(0).getString("eleValue"), step.getString("content"));
+ break;
+ case "clear":
+ clear(handleDes, eleList.getJSONObject(0).getString("eleName"), eleList.getJSONObject(0).getString("eleType")
+ , eleList.getJSONObject(0).getString("eleValue"));
+ break;
+ case "longPress":
+ longPress(handleDes, eleList.getJSONObject(0).getString("eleName"), eleList.getJSONObject(0).getString("eleType")
+ , eleList.getJSONObject(0).getString("eleValue"), Integer.parseInt(step.getString("content")));
+ break;
+ case "swipe":
+ swipe(handleDes, eleList.getJSONObject(0).getString("eleName"), eleList.getJSONObject(0).getString("eleValue")
+ , eleList.getJSONObject(1).getString("eleName"), eleList.getJSONObject(1).getString("eleValue"));
+ break;
+ case "tap":
+ tap(handleDes, eleList.getJSONObject(0).getString("eleName"), eleList.getJSONObject(0).getString("eleValue"));
+ break;
+ case "longPressPoint":
+ longPressPoint(handleDes, eleList.getJSONObject(0).getString("eleName"), eleList.getJSONObject(0).getString("eleValue")
+ , Integer.parseInt(step.getString("content")));
+ break;
+ case "pause":
+ pause(handleDes, Integer.parseInt(step.getString("content")));
+ break;
+ case "checkImage":
+ checkImage(handleDes, eleList.getJSONObject(0).getString("eleName"), eleList.getJSONObject(0).getString("eleValue")
+ , step.getDouble("content"));
+ break;
+ case "stepScreen":
+ stepScreen(handleDes);
+ break;
+ case "openApp":
+ openApp(handleDes, step.getString("text"));
+ break;
+ case "terminate":
+ terminate(handleDes, step.getString("text"));
+ break;
+ case "install":
+ install(handleDes, step.getString("text"));
+ break;
+ case "uninstall":
+ uninstall(handleDes, step.getString("text"));
+ break;
+ case "runBack":
+ runBackground(handleDes, Long.parseLong(step.getString("content")));
+ break;
+ case "screenSub":
+ case "screenAdd":
+ case "screenAbort":
+ rotateDevice(handleDes, step.getString("stepType"));
+ break;
+ case "lock":
+ lock(handleDes);
+ break;
+ case "unLock":
+ unLock(handleDes);
+ break;
+ case "airPlaneMode":
+ airPlaneMode(handleDes);
+ break;
+ case "wifiMode":
+ wifiMode(handleDes);
+ break;
+ case "locationMode":
+ locationMode(handleDes);
+ break;
+ case "zoom":
+ multiAction(handleDes, eleList.getJSONObject(0).getString("eleName"), eleList.getJSONObject(0).getString("eleValue")
+ , eleList.getJSONObject(1).getString("eleName"), eleList.getJSONObject(1).getString("eleValue")
+ , eleList.getJSONObject(2).getString("eleName"), eleList.getJSONObject(2).getString("eleValue")
+ , eleList.getJSONObject(3).getString("eleName"), eleList.getJSONObject(3).getString("eleValue"));
+ break;
+ case "keyCode":
+ keyCode(handleDes, step.getString("content"));
+ break;
+ case "assertEquals":
+ case "assertTrue":
+ case "assertNotTrue":
+ String actual = replaceTrans(step.getString("text"));
+ String expect = replaceTrans(step.getString("content"));
+ asserts(handleDes, actual, expect, step.getString("stepType"));
+ break;
+ case "getTextValue":
+ globalParams.put(step.getString("content"), getText(handleDes, eleList.getJSONObject(0).getString("eleName")
+ , eleList.getJSONObject(0).getString("eleType"), eleList.getJSONObject(0).getString("eleValue")));
+ break;
+ case "hideKey":
+ hideKey(handleDes);
+ break;
+ case "monkey":
+ runMonkey(handleDes, step.getJSONObject("content"), step.getJSONArray("text").toJavaList(JSONObject.class));
+ break;
+ case "publicStep":
+ publicStep(handleDes, step.getString("content"), stepJSON.getJSONArray("pubSteps"));
+ }
+ switchType(step.getInteger("error"), handleDes.getStepDes(), handleDes.getDetail(), handleDes.getE());
+ }
+
+ public void switchType(int error, String step, String detail, Throwable e) throws Throwable {
+ if (e != null) {
+ switch (error) {
+ case ErrorType.IGNORE:
+ log.sendStepLog(StepType.PASS, step + "异常!已忽略...", detail);
+ break;
+ case ErrorType.WARNING:
+ log.sendStepLog(StepType.WARN, step + "异常!", detail);
+ setResultDetailStatus(ResultDetailStatus.WARN);
+ errorScreen();
+ exceptionLog(e);
+ break;
+ case ErrorType.SHUTDOWN:
+ log.sendStepLog(StepType.ERROR, step + "异常!", detail);
+ setResultDetailStatus(ResultDetailStatus.FAIL);
+ errorScreen();
+ exceptionLog(e);
+ throw e;
+ }
+ } else {
+ log.sendStepLog(StepType.PASS, step, detail);
+ }
+ }
+}
diff --git a/src/main/java/com/sonic/agent/automation/AppiumServer.java b/src/main/java/org/cloud/sonic/agent/automation/AppiumServer.java
similarity index 93%
rename from src/main/java/com/sonic/agent/automation/AppiumServer.java
rename to src/main/java/org/cloud/sonic/agent/automation/AppiumServer.java
index 707e79f5..1485c654 100644
--- a/src/main/java/com/sonic/agent/automation/AppiumServer.java
+++ b/src/main/java/org/cloud/sonic/agent/automation/AppiumServer.java
@@ -1,33 +1,33 @@
-package com.sonic.agent.automation;
-
-import io.appium.java_client.service.local.AppiumDriverLocalService;
-import io.appium.java_client.service.local.AppiumServiceBuilder;
-import io.appium.java_client.service.local.flags.GeneralServerFlag;
-
-/**
- * @author ZhouYiXun
- * @des
- * @date 2021/8/27 17:24
- */
-public class AppiumServer {
- public static AppiumDriverLocalService service;
-
- /**
- * @return void
- * @author ZhouYiXun
- * @des 启动appium服务
- * @date 2021/8/16 20:01
- */
- public static void start() {
- service = AppiumDriverLocalService.buildService(new AppiumServiceBuilder().usingAnyFreePort()
- .withArgument(GeneralServerFlag.LOG_LEVEL, "error")
- .withArgument(GeneralServerFlag.ALLOW_INSECURE, "chromedriver_autodownload"));
- service.start();
- }
-
- public static void close() {
- if (service != null && service.isRunning()) {
- service.stop();
- }
- }
-}
+package org.cloud.sonic.agent.automation;
+
+import io.appium.java_client.service.local.AppiumDriverLocalService;
+import io.appium.java_client.service.local.AppiumServiceBuilder;
+import io.appium.java_client.service.local.flags.GeneralServerFlag;
+
+/**
+ * @author ZhouYiXun
+ * @des
+ * @date 2021/8/27 17:24
+ */
+public class AppiumServer {
+ public static AppiumDriverLocalService service;
+
+ /**
+ * @return void
+ * @author ZhouYiXun
+ * @des 启动appium服务
+ * @date 2021/8/16 20:01
+ */
+ public static void start() {
+ service = AppiumDriverLocalService.buildService(new AppiumServiceBuilder().usingAnyFreePort()
+ .withArgument(GeneralServerFlag.LOG_LEVEL, "error")
+ .withArgument(GeneralServerFlag.ALLOW_INSECURE, "chromedriver_autodownload"));
+ service.start();
+ }
+
+ public static void close() {
+ if (service != null && service.isRunning()) {
+ service.stop();
+ }
+ }
+}
diff --git a/src/main/java/com/sonic/agent/automation/FindResult.java b/src/main/java/org/cloud/sonic/agent/automation/FindResult.java
similarity index 95%
rename from src/main/java/com/sonic/agent/automation/FindResult.java
rename to src/main/java/org/cloud/sonic/agent/automation/FindResult.java
index db6877bf..70b6f938 100644
--- a/src/main/java/com/sonic/agent/automation/FindResult.java
+++ b/src/main/java/org/cloud/sonic/agent/automation/FindResult.java
@@ -1,4 +1,4 @@
-package com.sonic.agent.automation;
+package org.cloud.sonic.agent.automation;
public class FindResult {
private int x;
diff --git a/src/main/java/com/sonic/agent/automation/HandleDes.java b/src/main/java/org/cloud/sonic/agent/automation/HandleDes.java
similarity index 91%
rename from src/main/java/com/sonic/agent/automation/HandleDes.java
rename to src/main/java/org/cloud/sonic/agent/automation/HandleDes.java
index fb30e103..6932ddbd 100644
--- a/src/main/java/com/sonic/agent/automation/HandleDes.java
+++ b/src/main/java/org/cloud/sonic/agent/automation/HandleDes.java
@@ -1,51 +1,51 @@
-package com.sonic.agent.automation;
-
-/**
- * @author ZhouYiXun
- * @des
- * @date 2021/8/26 23:46
- */
-public class HandleDes {
- private String stepDes;
- private String detail;
- private Throwable e;
-
- public HandleDes(){
- this.stepDes = "";
- this.detail = "";
- this.e = null;
- }
-
- public String getStepDes() {
- return stepDes;
- }
-
- public void setStepDes(String stepDes) {
- this.stepDes = stepDes;
- }
-
- public String getDetail() {
- return detail;
- }
-
- public void setDetail(String detail) {
- this.detail = detail;
- }
-
- public Throwable getE() {
- return e;
- }
-
- public void setE(Throwable e) {
- this.e = e;
- }
-
- @Override
- public String toString() {
- return "HandleDes{" +
- "stepDes='" + stepDes + '\'' +
- ", detail='" + detail + '\'' +
- ", e=" + e +
- '}';
- }
-}
+package org.cloud.sonic.agent.automation;
+
+/**
+ * @author ZhouYiXun
+ * @des
+ * @date 2021/8/26 23:46
+ */
+public class HandleDes {
+ private String stepDes;
+ private String detail;
+ private Throwable e;
+
+ public HandleDes(){
+ this.stepDes = "";
+ this.detail = "";
+ this.e = null;
+ }
+
+ public String getStepDes() {
+ return stepDes;
+ }
+
+ public void setStepDes(String stepDes) {
+ this.stepDes = stepDes;
+ }
+
+ public String getDetail() {
+ return detail;
+ }
+
+ public void setDetail(String detail) {
+ this.detail = detail;
+ }
+
+ public Throwable getE() {
+ return e;
+ }
+
+ public void setE(Throwable e) {
+ this.e = e;
+ }
+
+ @Override
+ public String toString() {
+ return "HandleDes{" +
+ "stepDes='" + stepDes + '\'' +
+ ", detail='" + detail + '\'' +
+ ", e=" + e +
+ '}';
+ }
+}
diff --git a/src/main/java/com/sonic/agent/automation/IOSStepHandler.java b/src/main/java/org/cloud/sonic/agent/automation/IOSStepHandler.java
similarity index 98%
rename from src/main/java/com/sonic/agent/automation/IOSStepHandler.java
rename to src/main/java/org/cloud/sonic/agent/automation/IOSStepHandler.java
index e87d0d8e..e03831aa 100644
--- a/src/main/java/com/sonic/agent/automation/IOSStepHandler.java
+++ b/src/main/java/org/cloud/sonic/agent/automation/IOSStepHandler.java
@@ -1,25 +1,22 @@
-package com.sonic.agent.automation;
+package org.cloud.sonic.agent.automation;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
-import com.sonic.agent.bridge.ios.TIDeviceTool;
-import com.sonic.agent.interfaces.ErrorType;
-import com.sonic.agent.interfaces.ResultDetailStatus;
-import com.sonic.agent.interfaces.StepType;
-import com.sonic.agent.maps.IOSProcessMap;
-import com.sonic.agent.maps.IOSSizeMap;
-import com.sonic.agent.tools.DownImageTool;
-import com.sonic.agent.tools.LogTool;
-import com.sonic.agent.tools.SpringTool;
-import com.sonic.agent.tools.UploadTools;
-import io.appium.java_client.MobileBy;
+import org.cloud.sonic.agent.bridge.ios.TIDeviceTool;
+import org.cloud.sonic.agent.interfaces.ErrorType;
+import org.cloud.sonic.agent.interfaces.ResultDetailStatus;
+import org.cloud.sonic.agent.interfaces.StepType;
+import org.cloud.sonic.agent.maps.IOSProcessMap;
+import org.cloud.sonic.agent.maps.IOSSizeMap;
+import org.cloud.sonic.agent.tools.DownImageTool;
+import org.cloud.sonic.agent.tools.LogTool;
+import org.cloud.sonic.agent.tools.SpringTool;
+import org.cloud.sonic.agent.tools.UploadTools;
import io.appium.java_client.MultiTouchAction;
import io.appium.java_client.Setting;
import io.appium.java_client.TouchAction;
import io.appium.java_client.android.appmanagement.AndroidTerminateApplicationOptions;
-import io.appium.java_client.android.nativekey.AndroidKey;
-import io.appium.java_client.android.nativekey.KeyEvent;
import io.appium.java_client.appmanagement.BaseInstallApplicationOptions;
import io.appium.java_client.appmanagement.BaseTerminateApplicationOptions;
import io.appium.java_client.ios.IOSDriver;
@@ -37,7 +34,6 @@
import org.openqa.selenium.TakesScreenshot;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.remote.DesiredCapabilities;
-import org.openqa.selenium.support.ui.ExpectedConditions;
import org.springframework.core.env.Environment;
import org.springframework.core.io.FileSystemResource;
import org.springframework.http.ResponseEntity;
diff --git a/src/main/java/com/sonic/agent/automation/PackageHandler.java b/src/main/java/org/cloud/sonic/agent/automation/PackageHandler.java
similarity index 67%
rename from src/main/java/com/sonic/agent/automation/PackageHandler.java
rename to src/main/java/org/cloud/sonic/agent/automation/PackageHandler.java
index d41dcd1e..943aef8b 100644
--- a/src/main/java/com/sonic/agent/automation/PackageHandler.java
+++ b/src/main/java/org/cloud/sonic/agent/automation/PackageHandler.java
@@ -1,9 +1,9 @@
-package com.sonic.agent.automation;
-
-/**
- * @author ZhouYiXun
- * @des
- * @date 2021/8/26 22:32
- */
-public class PackageHandler {
-}
+package org.cloud.sonic.agent.automation;
+
+/**
+ * @author ZhouYiXun
+ * @des
+ * @date 2021/8/26 22:32
+ */
+public class PackageHandler {
+}
diff --git a/src/main/java/com/sonic/agent/automation/RemoteDebugDriver.java b/src/main/java/org/cloud/sonic/agent/automation/RemoteDebugDriver.java
similarity index 95%
rename from src/main/java/com/sonic/agent/automation/RemoteDebugDriver.java
rename to src/main/java/org/cloud/sonic/agent/automation/RemoteDebugDriver.java
index 56ac8fe8..201802d7 100644
--- a/src/main/java/com/sonic/agent/automation/RemoteDebugDriver.java
+++ b/src/main/java/org/cloud/sonic/agent/automation/RemoteDebugDriver.java
@@ -1,78 +1,78 @@
-package com.sonic.agent.automation;
-
-import com.sonic.agent.tools.PortTool;
-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.autoconfigure.condition.ConditionalOnProperty;
-import org.springframework.context.ApplicationListener;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.context.event.ContextRefreshedEvent;
-import org.springframework.lang.NonNull;
-
-/**
- * @author ZhouYiXun
- * @des
- * @date 2021/10/29 0:28
- */
-@ConditionalOnProperty(value = "modules.webview.enable", havingValue = "true")
-@Configuration
-public class RemoteDebugDriver implements ApplicationListener {
- private static final Logger logger = LoggerFactory.getLogger(RemoteDebugDriver.class);
- private static String chromePath;
- public static int chromePort;
- public static WebDriver webDriver;
- @Value("${modules.webview.chrome-driver-path}")
- private String path;
- @Value("${modules.webview.chrome-driver-debug-port}")
- private int port;
-
- @Bean
- public void setChromePath() {
- chromePath = path;
- chromePort = port;
- }
-
- @Override
- public void onApplicationEvent(@NonNull ContextRefreshedEvent event) {
- startChromeDriver();
- }
-
- public static void startChromeDriver() {
- logger.info("开启webview相关功能");
- System.setProperty("webdriver.chrome.silentOutput", "true");
- try {
- DesiredCapabilities desiredCapabilities = new DesiredCapabilities();
- ChromeOptions chromeOptions = new ChromeOptions();
- System.setProperty("webdriver.chrome.driver", chromePath);
- if (chromePort == 0) {
- int debugPort = PortTool.getPort();
- chromePort = debugPort;
- chromeOptions.addArguments("--remote-debugging-port=" + debugPort);
- } else {
- chromeOptions.addArguments("--remote-debugging-port=" + chromePort);
- }
- chromeOptions.addArguments("--remote-debugging-address=0.0.0.0");
- 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);
- logger.info("chromeDriver启动完毕!");
- } catch (Exception e) {
- logger.info("chromeDriver启动失败!");
- }
- }
-
- public static void close() {
- if (webDriver != null) {
- webDriver.quit();
- }
- }
-}
+package org.cloud.sonic.agent.automation;
+
+import org.cloud.sonic.agent.tools.PortTool;
+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.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.context.ApplicationListener;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.event.ContextRefreshedEvent;
+import org.springframework.lang.NonNull;
+
+/**
+ * @author ZhouYiXun
+ * @des
+ * @date 2021/10/29 0:28
+ */
+@ConditionalOnProperty(value = "modules.webview.enable", havingValue = "true")
+@Configuration
+public class RemoteDebugDriver implements ApplicationListener {
+ private static final Logger logger = LoggerFactory.getLogger(RemoteDebugDriver.class);
+ private static String chromePath;
+ public static int chromePort;
+ public static WebDriver webDriver;
+ @Value("${modules.webview.chrome-driver-path}")
+ private String path;
+ @Value("${modules.webview.chrome-driver-debug-port}")
+ private int port;
+
+ @Bean
+ public void setChromePath() {
+ chromePath = path;
+ chromePort = port;
+ }
+
+ @Override
+ public void onApplicationEvent(@NonNull ContextRefreshedEvent event) {
+ startChromeDriver();
+ }
+
+ public static void startChromeDriver() {
+ logger.info("开启webview相关功能");
+ System.setProperty("webdriver.chrome.silentOutput", "true");
+ try {
+ DesiredCapabilities desiredCapabilities = new DesiredCapabilities();
+ ChromeOptions chromeOptions = new ChromeOptions();
+ System.setProperty("webdriver.chrome.driver", chromePath);
+ if (chromePort == 0) {
+ int debugPort = PortTool.getPort();
+ chromePort = debugPort;
+ chromeOptions.addArguments("--remote-debugging-port=" + debugPort);
+ } else {
+ chromeOptions.addArguments("--remote-debugging-port=" + chromePort);
+ }
+ chromeOptions.addArguments("--remote-debugging-address=0.0.0.0");
+ 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);
+ logger.info("chromeDriver启动完毕!");
+ } catch (Exception e) {
+ logger.info("chromeDriver启动失败!");
+ }
+ }
+
+ public static void close() {
+ if (webDriver != null) {
+ webDriver.quit();
+ }
+ }
+}
diff --git a/src/main/java/com/sonic/agent/bridge/android/AndroidDeviceBridgeTool.java b/src/main/java/org/cloud/sonic/agent/bridge/android/AndroidDeviceBridgeTool.java
similarity index 96%
rename from src/main/java/com/sonic/agent/bridge/android/AndroidDeviceBridgeTool.java
rename to src/main/java/org/cloud/sonic/agent/bridge/android/AndroidDeviceBridgeTool.java
index 7f1e245b..1eca98db 100644
--- a/src/main/java/com/sonic/agent/bridge/android/AndroidDeviceBridgeTool.java
+++ b/src/main/java/org/cloud/sonic/agent/bridge/android/AndroidDeviceBridgeTool.java
@@ -1,406 +1,406 @@
-package com.sonic.agent.bridge.android;
-
-import com.android.ddmlib.*;
-import com.sonic.agent.tests.android.AndroidTemperThread;
-import com.sonic.agent.tools.DownImageTool;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
-import org.springframework.context.ApplicationListener;
-import org.springframework.context.annotation.DependsOn;
-import org.springframework.context.event.ContextRefreshedEvent;
-import org.springframework.lang.NonNull;
-import org.springframework.stereotype.Component;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.concurrent.TimeUnit;
-
-/**
- * @author ZhouYiXun
- * @des ADB工具类
- * @date 2021/08/16 19:26
- */
-@ConditionalOnProperty(value = "modules.android.enable", havingValue = "true")
-@DependsOn({"androidThreadPoolInit", "nettyMsgInit"})
-@Component
-public class AndroidDeviceBridgeTool implements ApplicationListener {
- private static final Logger logger = LoggerFactory.getLogger(AndroidDeviceBridgeTool.class);
- public static AndroidDebugBridge androidDebugBridge = null;
- private AndroidTemperThread androidTemperThread = null;
-
- @Autowired
- private AndroidDeviceStatusListener androidDeviceStatusListener;
-
-
- @Override
- public void onApplicationEvent(@NonNull ContextRefreshedEvent event) {
- logger.info("开启安卓相关功能");
- }
-
- /**
- * @return java.lang.String
- * @author ZhouYiXun
- * @des 获取系统安卓SDK路径
- * @date 2021/8/16 19:35
- */
- private static String getADBPathFromSystemEnv() {
- String path = System.getenv("ANDROID_HOME");
- if (path != null) {
- path += File.separator + "platform-tools" + File.separator + "adb";
- } else {
- logger.error("获取ANDROID_HOME环境变量失败!");
- return null;
- }
- return path;
- }
-
- /**
- * @return void
- * @author ZhouYiXun
- * @des 定义方法
- * @date 2021/8/16 19:36
- */
- public void init() {
- //获取系统SDK路径
- String systemADBPath = getADBPathFromSystemEnv();
- //添加设备上下线监听
- androidDebugBridge.addDeviceChangeListener(androidDeviceStatusListener);
- try {
- AndroidDebugBridge.init(false);
- } catch (IllegalStateException e) {
- logger.warn("AndroidDebugBridge已经初始化过,无需再初始化");
- }
- //开始创建ADB
- androidDebugBridge = AndroidDebugBridge.createBridge(systemADBPath, true, Long.MAX_VALUE, TimeUnit.MILLISECONDS);
- if (androidDebugBridge != null) {
- logger.info("安卓设备监听已开启");
- }
- int count = 0;
- //获取设备列表,超时后退出
- while (androidDebugBridge.hasInitialDeviceList() == false) {
- try {
- Thread.sleep(1000);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- count++;
- if (count > 200) {
- break;
- }
- }
- if (androidTemperThread == null || !androidTemperThread.isAlive()) {
- androidTemperThread = new AndroidTemperThread();
- androidTemperThread.start();
- }
- }
-
- /**
- * @return com.android.ddmlib.IDevice[]
- * @author ZhouYiXun
- * @des 获取真实在线设备列表
- * @date 2021/8/16 19:38
- */
- public static IDevice[] getRealOnLineDevices() {
- if (androidDebugBridge != null) {
- return androidDebugBridge.getDevices();
- } else {
- return null;
- }
- }
-
- /**
- * @param iDevice
- * @return void
- * @author ZhouYiXun
- * @des 重启设备
- * @date 2021/8/16 19:41
- */
- public static void reboot(IDevice iDevice) {
- if (iDevice != null) {
- executeCommand(iDevice, "reboot");
- }
- }
-
- /**
- * @param udId
- * @return com.android.ddmlib.IDevice
- * @author ZhouYiXun
- * @des 根据udId获取iDevice对象
- * @date 2021/8/16 19:42
- */
- public static IDevice getIDeviceByUdId(String udId) {
- IDevice iDevice = null;
- for (IDevice device : AndroidDeviceBridgeTool.getRealOnLineDevices()) {
- //如果设备是在线状态并且序列号相等,则就是这个设备
- if (device.getState().equals(IDevice.DeviceState.ONLINE)
- && device.getSerialNumber().equals(udId)) {
- iDevice = device;
- break;
- }
- }
- if (iDevice == null) {
- logger.info("设备未连接!");
- }
- return iDevice;
- }
-
- /**
- * @param iDevice
- * @return java.lang.String
- * @author ZhouYiXun
- * @des 获取屏幕大小
- * @date 2021/8/16 19:44
- */
- public static String getScreenSize(IDevice iDevice) {
- String size = "";
- try {
- size = executeCommand(iDevice, "wm size");
- if (size.contains("Override size")) {
- size = size.substring(size.indexOf("Override size"));
- } else {
- size = size.split(":")[1];
- }
- //注意顺序问题
- size = size.trim()
- .replace(":", "")
- .replace("Override size", "")
- .replace("\r", "")
- .replace("\n", "")
- .replace(" ", "");
- if (size.length() > 20) {
- size = "未知";
- }
- } catch (Exception e) {
- logger.info("获取屏幕尺寸失败!拔插瞬间可忽略该错误...");
- }
- return size;
- }
-
- /**
- * @param iDevice
- * @param command
- * @return java.lang.String
- * @author ZhouYiXun
- * @des 发送shell指令给对应设备
- * @date 2021/8/16 19:47
- */
- public static String executeCommand(IDevice iDevice, String command) {
- CollectingOutputReceiver output = new CollectingOutputReceiver();
- try {
- iDevice.executeShellCommand(command, output, 0, TimeUnit.MILLISECONDS);
- } catch (Exception e) {
- logger.info("发送shell指令 {} 给设备 {} 异常!"
- , command, iDevice.getSerialNumber());
- logger.error(e.getMessage());
- }
- return output.getOutput();
- }
-
- /**
- * @param iDevice
- * @param port
- * @param service
- * @return void
- * @author ZhouYiXun
- * @des 同adb forward指令,将设备内进程的端口暴露给pc本地,但是只能转发给localhost,不能转发给ipv4
- * @date 2021/8/16 19:52
- */
- public static void forward(IDevice iDevice, int port, String service) {
- try {
- logger.info("{} 设备 {} 服务端口转发到:{}", iDevice.getSerialNumber(), service, port);
- iDevice.createForward(port, service, IDevice.DeviceUnixSocketNamespace.ABSTRACT);
- } catch (Exception e) {
- logger.error(e.getMessage());
- }
- }
-
- /**
- * @param iDevice
- * @param port
- * @param serviceName
- * @return void
- * @author ZhouYiXun
- * @des 去掉转发
- * @date 2021/8/16 19:53
- */
- public static void removeForward(IDevice iDevice, int port, String serviceName) {
- try {
- logger.info("{} 设备 {} 服务端口取消转发到:{}", iDevice.getSerialNumber(), serviceName, port);
- iDevice.removeForward(port, serviceName, IDevice.DeviceUnixSocketNamespace.ABSTRACT);
- } catch (Exception e) {
- logger.error(e.getMessage());
- }
- }
-
- /**
- * @param iDevice
- * @param localPath
- * @param remotePath
- * @return void
- * @author ZhouYiXun
- * @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;
-// }
-// });
-// }
-
- /**
- * @param iDevice
- * @param keyNum
- * @return void
- * @author ZhouYiXun
- * @des 输入对应按键
- * @date 2021/8/16 19:59
- */
- public static void pressKey(IDevice iDevice, int keyNum) {
- executeCommand(iDevice, String.format("input keyevent %s", keyNum));
- }
-
- /**
- * @param iDevice
- * @param key
- * @return java.lang.String
- * @author ZhouYiXun
- * @des 获取设备配置信息
- * @date 2021/8/16 20:01
- */
- public static String getProperties(IDevice iDevice, String key) {
- return iDevice.getProperty(key);
- }
-
- /**
- * @param sdk
- * @return java.lang.String
- * @author ZhouYiXun
- * @des 根据sdk匹配对应的文件
- * @date 2021/8/16 20:01
- */
- public static String matchMiniCapFile(String sdk) {
- String filePath;
- if (Integer.valueOf(sdk) < 16) {
- filePath = "minicap-nopie";
- } else {
- filePath = "minicap";
- }
- return filePath;
- }
-
- public static void screen(IDevice iDevice, String type) {
- int p = getScreen(iDevice);
- try {
- switch (type) {
- case "abort":
- executeCommand(iDevice, "content insert --uri content://settings/system --bind name:s:accelerometer_rotation --bind value:i:0");
- break;
- case "add":
- if (p == 3) {
- p = 0;
- } else {
- p++;
- }
- executeCommand(iDevice, "content insert --uri content://settings/system --bind name:s:user_rotation --bind value:i:" + p);
- break;
- case "sub":
- if (p == 0) {
- p = 3;
- } else {
- p--;
- }
- executeCommand(iDevice, "content insert --uri content://settings/system --bind name:s:user_rotation --bind value:i:" + p);
- break;
- }
- } catch (Exception e) {
- logger.error(e.getMessage());
- }
- }
-
- public static int getScreen(IDevice iDevice) {
- try {
- return Integer.parseInt(executeCommand(iDevice, "settings get system user_rotation")
- .trim().replaceAll("\n", "")
- .replace("\t", ""));
- } catch (Exception e) {
- logger.error(e.getMessage());
- return 0;
- }
- }
-
- public static void pushYadb(IDevice iDevice) {
- 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);
- 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();
- }
- }
-
- public static void searchDevice(IDevice iDevice) {
- executeCommand(iDevice, "am start -n com.sonic.plugins.assist/com.sonic.plugins.assist.SearchActivity");
- }
-
- public static void controlBattery(IDevice iDevice, int type) {
- if (type == 0) {
- executeCommand(iDevice, "dumpsys battery unplug && dumpsys battery set status 1");
- }
- if (type == 1) {
- executeCommand(iDevice, "dumpsys battery reset");
- }
- }
-
- /**
- * @param udId
- * @param packageName
- * @return java.lang.String
- * @author ZhouYiXun
- * @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", "");
-// }
-}
+package org.cloud.sonic.agent.bridge.android;
+
+import com.android.ddmlib.*;
+import org.cloud.sonic.agent.tests.android.AndroidTemperThread;
+import org.cloud.sonic.agent.tools.DownImageTool;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.context.ApplicationListener;
+import org.springframework.context.annotation.DependsOn;
+import org.springframework.context.event.ContextRefreshedEvent;
+import org.springframework.lang.NonNull;
+import org.springframework.stereotype.Component;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * @author ZhouYiXun
+ * @des ADB工具类
+ * @date 2021/08/16 19:26
+ */
+@ConditionalOnProperty(value = "modules.android.enable", havingValue = "true")
+@DependsOn({"androidThreadPoolInit", "nettyMsgInit"})
+@Component
+public class AndroidDeviceBridgeTool implements ApplicationListener {
+ private static final Logger logger = LoggerFactory.getLogger(AndroidDeviceBridgeTool.class);
+ public static AndroidDebugBridge androidDebugBridge = null;
+ private AndroidTemperThread androidTemperThread = null;
+
+ @Autowired
+ private AndroidDeviceStatusListener androidDeviceStatusListener;
+
+
+ @Override
+ public void onApplicationEvent(@NonNull ContextRefreshedEvent event) {
+ logger.info("开启安卓相关功能");
+ }
+
+ /**
+ * @return java.lang.String
+ * @author ZhouYiXun
+ * @des 获取系统安卓SDK路径
+ * @date 2021/8/16 19:35
+ */
+ private static String getADBPathFromSystemEnv() {
+ String path = System.getenv("ANDROID_HOME");
+ if (path != null) {
+ path += File.separator + "platform-tools" + File.separator + "adb";
+ } else {
+ logger.error("获取ANDROID_HOME环境变量失败!");
+ return null;
+ }
+ return path;
+ }
+
+ /**
+ * @return void
+ * @author ZhouYiXun
+ * @des 定义方法
+ * @date 2021/8/16 19:36
+ */
+ public void init() {
+ //获取系统SDK路径
+ String systemADBPath = getADBPathFromSystemEnv();
+ //添加设备上下线监听
+ androidDebugBridge.addDeviceChangeListener(androidDeviceStatusListener);
+ try {
+ AndroidDebugBridge.init(false);
+ } catch (IllegalStateException e) {
+ logger.warn("AndroidDebugBridge已经初始化过,无需再初始化");
+ }
+ //开始创建ADB
+ androidDebugBridge = AndroidDebugBridge.createBridge(systemADBPath, true, Long.MAX_VALUE, TimeUnit.MILLISECONDS);
+ if (androidDebugBridge != null) {
+ logger.info("安卓设备监听已开启");
+ }
+ int count = 0;
+ //获取设备列表,超时后退出
+ while (androidDebugBridge.hasInitialDeviceList() == false) {
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ count++;
+ if (count > 200) {
+ break;
+ }
+ }
+ if (androidTemperThread == null || !androidTemperThread.isAlive()) {
+ androidTemperThread = new AndroidTemperThread();
+ androidTemperThread.start();
+ }
+ }
+
+ /**
+ * @return com.android.ddmlib.IDevice[]
+ * @author ZhouYiXun
+ * @des 获取真实在线设备列表
+ * @date 2021/8/16 19:38
+ */
+ public static IDevice[] getRealOnLineDevices() {
+ if (androidDebugBridge != null) {
+ return androidDebugBridge.getDevices();
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * @param iDevice
+ * @return void
+ * @author ZhouYiXun
+ * @des 重启设备
+ * @date 2021/8/16 19:41
+ */
+ public static void reboot(IDevice iDevice) {
+ if (iDevice != null) {
+ executeCommand(iDevice, "reboot");
+ }
+ }
+
+ /**
+ * @param udId
+ * @return com.android.ddmlib.IDevice
+ * @author ZhouYiXun
+ * @des 根据udId获取iDevice对象
+ * @date 2021/8/16 19:42
+ */
+ public static IDevice getIDeviceByUdId(String udId) {
+ IDevice iDevice = null;
+ for (IDevice device : AndroidDeviceBridgeTool.getRealOnLineDevices()) {
+ //如果设备是在线状态并且序列号相等,则就是这个设备
+ if (device.getState().equals(IDevice.DeviceState.ONLINE)
+ && device.getSerialNumber().equals(udId)) {
+ iDevice = device;
+ break;
+ }
+ }
+ if (iDevice == null) {
+ logger.info("设备未连接!");
+ }
+ return iDevice;
+ }
+
+ /**
+ * @param iDevice
+ * @return java.lang.String
+ * @author ZhouYiXun
+ * @des 获取屏幕大小
+ * @date 2021/8/16 19:44
+ */
+ public static String getScreenSize(IDevice iDevice) {
+ String size = "";
+ try {
+ size = executeCommand(iDevice, "wm size");
+ if (size.contains("Override size")) {
+ size = size.substring(size.indexOf("Override size"));
+ } else {
+ size = size.split(":")[1];
+ }
+ //注意顺序问题
+ size = size.trim()
+ .replace(":", "")
+ .replace("Override size", "")
+ .replace("\r", "")
+ .replace("\n", "")
+ .replace(" ", "");
+ if (size.length() > 20) {
+ size = "未知";
+ }
+ } catch (Exception e) {
+ logger.info("获取屏幕尺寸失败!拔插瞬间可忽略该错误...");
+ }
+ return size;
+ }
+
+ /**
+ * @param iDevice
+ * @param command
+ * @return java.lang.String
+ * @author ZhouYiXun
+ * @des 发送shell指令给对应设备
+ * @date 2021/8/16 19:47
+ */
+ public static String executeCommand(IDevice iDevice, String command) {
+ CollectingOutputReceiver output = new CollectingOutputReceiver();
+ try {
+ iDevice.executeShellCommand(command, output, 0, TimeUnit.MILLISECONDS);
+ } catch (Exception e) {
+ logger.info("发送shell指令 {} 给设备 {} 异常!"
+ , command, iDevice.getSerialNumber());
+ logger.error(e.getMessage());
+ }
+ return output.getOutput();
+ }
+
+ /**
+ * @param iDevice
+ * @param port
+ * @param service
+ * @return void
+ * @author ZhouYiXun
+ * @des 同adb forward指令,将设备内进程的端口暴露给pc本地,但是只能转发给localhost,不能转发给ipv4
+ * @date 2021/8/16 19:52
+ */
+ public static void forward(IDevice iDevice, int port, String service) {
+ try {
+ logger.info("{} 设备 {} 服务端口转发到:{}", iDevice.getSerialNumber(), service, port);
+ iDevice.createForward(port, service, IDevice.DeviceUnixSocketNamespace.ABSTRACT);
+ } catch (Exception e) {
+ logger.error(e.getMessage());
+ }
+ }
+
+ /**
+ * @param iDevice
+ * @param port
+ * @param serviceName
+ * @return void
+ * @author ZhouYiXun
+ * @des 去掉转发
+ * @date 2021/8/16 19:53
+ */
+ public static void removeForward(IDevice iDevice, int port, String serviceName) {
+ try {
+ logger.info("{} 设备 {} 服务端口取消转发到:{}", iDevice.getSerialNumber(), serviceName, port);
+ iDevice.removeForward(port, serviceName, IDevice.DeviceUnixSocketNamespace.ABSTRACT);
+ } catch (Exception e) {
+ logger.error(e.getMessage());
+ }
+ }
+
+ /**
+ * @param iDevice
+ * @param localPath
+ * @param remotePath
+ * @return void
+ * @author ZhouYiXun
+ * @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;
+// }
+// });
+// }
+
+ /**
+ * @param iDevice
+ * @param keyNum
+ * @return void
+ * @author ZhouYiXun
+ * @des 输入对应按键
+ * @date 2021/8/16 19:59
+ */
+ public static void pressKey(IDevice iDevice, int keyNum) {
+ executeCommand(iDevice, String.format("input keyevent %s", keyNum));
+ }
+
+ /**
+ * @param iDevice
+ * @param key
+ * @return java.lang.String
+ * @author ZhouYiXun
+ * @des 获取设备配置信息
+ * @date 2021/8/16 20:01
+ */
+ public static String getProperties(IDevice iDevice, String key) {
+ return iDevice.getProperty(key);
+ }
+
+ /**
+ * @param sdk
+ * @return java.lang.String
+ * @author ZhouYiXun
+ * @des 根据sdk匹配对应的文件
+ * @date 2021/8/16 20:01
+ */
+ public static String matchMiniCapFile(String sdk) {
+ String filePath;
+ if (Integer.valueOf(sdk) < 16) {
+ filePath = "minicap-nopie";
+ } else {
+ filePath = "minicap";
+ }
+ return filePath;
+ }
+
+ public static void screen(IDevice iDevice, String type) {
+ int p = getScreen(iDevice);
+ try {
+ switch (type) {
+ case "abort":
+ executeCommand(iDevice, "content insert --uri content://settings/system --bind name:s:accelerometer_rotation --bind value:i:0");
+ break;
+ case "add":
+ if (p == 3) {
+ p = 0;
+ } else {
+ p++;
+ }
+ executeCommand(iDevice, "content insert --uri content://settings/system --bind name:s:user_rotation --bind value:i:" + p);
+ break;
+ case "sub":
+ if (p == 0) {
+ p = 3;
+ } else {
+ p--;
+ }
+ executeCommand(iDevice, "content insert --uri content://settings/system --bind name:s:user_rotation --bind value:i:" + p);
+ break;
+ }
+ } catch (Exception e) {
+ logger.error(e.getMessage());
+ }
+ }
+
+ public static int getScreen(IDevice iDevice) {
+ try {
+ return Integer.parseInt(executeCommand(iDevice, "settings get system user_rotation")
+ .trim().replaceAll("\n", "")
+ .replace("\t", ""));
+ } catch (Exception e) {
+ logger.error(e.getMessage());
+ return 0;
+ }
+ }
+
+ public static void pushYadb(IDevice iDevice) {
+ 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);
+ 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();
+ }
+ }
+
+ public static void searchDevice(IDevice iDevice) {
+ executeCommand(iDevice, "am start -n com.sonic.plugins.assist/com.sonic.plugins.assist.SearchActivity");
+ }
+
+ public static void controlBattery(IDevice iDevice, int type) {
+ if (type == 0) {
+ executeCommand(iDevice, "dumpsys battery unplug && dumpsys battery set status 1");
+ }
+ if (type == 1) {
+ executeCommand(iDevice, "dumpsys battery reset");
+ }
+ }
+
+ /**
+ * @param udId
+ * @param packageName
+ * @return java.lang.String
+ * @author ZhouYiXun
+ * @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", "");
+// }
+}
diff --git a/src/main/java/com/sonic/agent/bridge/android/AndroidDeviceLocalStatus.java b/src/main/java/org/cloud/sonic/agent/bridge/android/AndroidDeviceLocalStatus.java
similarity index 90%
rename from src/main/java/com/sonic/agent/bridge/android/AndroidDeviceLocalStatus.java
rename to src/main/java/org/cloud/sonic/agent/bridge/android/AndroidDeviceLocalStatus.java
index 053c4300..fa12cfb8 100644
--- a/src/main/java/com/sonic/agent/bridge/android/AndroidDeviceLocalStatus.java
+++ b/src/main/java/org/cloud/sonic/agent/bridge/android/AndroidDeviceLocalStatus.java
@@ -1,97 +1,97 @@
-package com.sonic.agent.bridge.android;
-
-import com.alibaba.fastjson.JSONObject;
-import com.sonic.agent.interfaces.DeviceStatus;
-import com.sonic.agent.maps.AndroidDeviceManagerMap;
-import com.sonic.agent.netty.NettyThreadPool;
-
-/**
- * @author ZhouYiXun
- * @des 本地自定义的状态变更,不是通过adb的变更
- * @date 2021/08/16 19:26
- */
-public class AndroidDeviceLocalStatus {
-
- /**
- * @param udId
- * @param status
- * @return void
- * @author ZhouYiXun
- * @des 发送状态变更消息
- * @date 2021/8/16 20:56
- */
- public static void send(String udId, String status) {
- JSONObject deviceDetail = new JSONObject();
- deviceDetail.put("msg", "deviceDetail");
- deviceDetail.put("udId", udId);
- deviceDetail.put("status", status);
- NettyThreadPool.send(deviceDetail);
- }
-
- /**
- * @param udId
- * @return void
- * @author ZhouYiXun
- * @des 开始测试
- * @date 2021/8/16 20:57
- */
- public static boolean startTest(String udId) {
- synchronized (AndroidDeviceLocalStatus.class) {
- if (AndroidDeviceManagerMap.getMap().get(udId) == null) {
- send(udId, DeviceStatus.TESTING);
- AndroidDeviceManagerMap.getMap().put(udId, DeviceStatus.TESTING);
- return true;
- } else {
- return false;
- }
- }
- }
-
- /**
- * @param udId
- * @return void
- * @author ZhouYiXun
- * @des 开始调试
- * @date 2021/8/16 20:57
- */
- public static void startDebug(String udId) {
- send(udId, DeviceStatus.DEBUGGING);
- AndroidDeviceManagerMap.getMap().put(udId, DeviceStatus.DEBUGGING);
- }
-
- /**
- * @param udId
- * @return void
- * @author ZhouYiXun
- * @des 使用完毕
- * @date 2021/8/16 19:47
- */
- public static void finish(String udId) {
- if (AndroidDeviceBridgeTool.getIDeviceByUdId(udId) != null
- && AndroidDeviceManagerMap.getMap().get(udId) != null) {
- if (AndroidDeviceManagerMap.getMap().get(udId).equals(DeviceStatus.DEBUGGING)
- || AndroidDeviceManagerMap.getMap().get(udId).equals(DeviceStatus.TESTING)) {
- send(udId, DeviceStatus.ONLINE);
- }
- }
- AndroidDeviceManagerMap.getMap().remove(udId);
- }
-
- /**
- * @param udId
- * @return void
- * @author ZhouYiXun
- * @des 使用完毕异常
- * @date 2021/8/16 19:47
- */
- public static void finishError(String udId) {
- if (AndroidDeviceBridgeTool.getIDeviceByUdId(udId) != null
- && AndroidDeviceManagerMap.getMap().get(udId) != null) {
- if (AndroidDeviceManagerMap.getMap().get(udId).equals(DeviceStatus.DEBUGGING)
- || AndroidDeviceManagerMap.getMap().get(udId).equals(DeviceStatus.TESTING)) {
- send(udId, DeviceStatus.ERROR);
- }
- }
- AndroidDeviceManagerMap.getMap().remove(udId);
- }
-}
+package org.cloud.sonic.agent.bridge.android;
+
+import com.alibaba.fastjson.JSONObject;
+import org.cloud.sonic.agent.interfaces.DeviceStatus;
+import org.cloud.sonic.agent.maps.AndroidDeviceManagerMap;
+import org.cloud.sonic.agent.netty.NettyThreadPool;
+
+/**
+ * @author ZhouYiXun
+ * @des 本地自定义的状态变更,不是通过adb的变更
+ * @date 2021/08/16 19:26
+ */
+public class AndroidDeviceLocalStatus {
+
+ /**
+ * @param udId
+ * @param status
+ * @return void
+ * @author ZhouYiXun
+ * @des 发送状态变更消息
+ * @date 2021/8/16 20:56
+ */
+ public static void send(String udId, String status) {
+ JSONObject deviceDetail = new JSONObject();
+ deviceDetail.put("msg", "deviceDetail");
+ deviceDetail.put("udId", udId);
+ deviceDetail.put("status", status);
+ NettyThreadPool.send(deviceDetail);
+ }
+
+ /**
+ * @param udId
+ * @return void
+ * @author ZhouYiXun
+ * @des 开始测试
+ * @date 2021/8/16 20:57
+ */
+ public static boolean startTest(String udId) {
+ synchronized (AndroidDeviceLocalStatus.class) {
+ if (AndroidDeviceManagerMap.getMap().get(udId) == null) {
+ send(udId, DeviceStatus.TESTING);
+ AndroidDeviceManagerMap.getMap().put(udId, DeviceStatus.TESTING);
+ return true;
+ } else {
+ return false;
+ }
+ }
+ }
+
+ /**
+ * @param udId
+ * @return void
+ * @author ZhouYiXun
+ * @des 开始调试
+ * @date 2021/8/16 20:57
+ */
+ public static void startDebug(String udId) {
+ send(udId, DeviceStatus.DEBUGGING);
+ AndroidDeviceManagerMap.getMap().put(udId, DeviceStatus.DEBUGGING);
+ }
+
+ /**
+ * @param udId
+ * @return void
+ * @author ZhouYiXun
+ * @des 使用完毕
+ * @date 2021/8/16 19:47
+ */
+ public static void finish(String udId) {
+ if (AndroidDeviceBridgeTool.getIDeviceByUdId(udId) != null
+ && AndroidDeviceManagerMap.getMap().get(udId) != null) {
+ if (AndroidDeviceManagerMap.getMap().get(udId).equals(DeviceStatus.DEBUGGING)
+ || AndroidDeviceManagerMap.getMap().get(udId).equals(DeviceStatus.TESTING)) {
+ send(udId, DeviceStatus.ONLINE);
+ }
+ }
+ AndroidDeviceManagerMap.getMap().remove(udId);
+ }
+
+ /**
+ * @param udId
+ * @return void
+ * @author ZhouYiXun
+ * @des 使用完毕异常
+ * @date 2021/8/16 19:47
+ */
+ public static void finishError(String udId) {
+ if (AndroidDeviceBridgeTool.getIDeviceByUdId(udId) != null
+ && AndroidDeviceManagerMap.getMap().get(udId) != null) {
+ if (AndroidDeviceManagerMap.getMap().get(udId).equals(DeviceStatus.DEBUGGING)
+ || AndroidDeviceManagerMap.getMap().get(udId).equals(DeviceStatus.TESTING)) {
+ send(udId, DeviceStatus.ERROR);
+ }
+ }
+ AndroidDeviceManagerMap.getMap().remove(udId);
+ }
+}
diff --git a/src/main/java/com/sonic/agent/bridge/android/AndroidDeviceStatusListener.java b/src/main/java/org/cloud/sonic/agent/bridge/android/AndroidDeviceStatusListener.java
similarity index 90%
rename from src/main/java/com/sonic/agent/bridge/android/AndroidDeviceStatusListener.java
rename to src/main/java/org/cloud/sonic/agent/bridge/android/AndroidDeviceStatusListener.java
index 268ff575..698418e3 100644
--- a/src/main/java/com/sonic/agent/bridge/android/AndroidDeviceStatusListener.java
+++ b/src/main/java/org/cloud/sonic/agent/bridge/android/AndroidDeviceStatusListener.java
@@ -1,67 +1,67 @@
-package com.sonic.agent.bridge.android;
-
-import com.alibaba.fastjson.JSONObject;
-import com.android.ddmlib.AndroidDebugBridge;
-import com.android.ddmlib.IDevice;
-import com.sonic.agent.interfaces.PlatformType;
-import com.sonic.agent.maps.AndroidDeviceManagerMap;
-import com.sonic.agent.netty.NettyThreadPool;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.stereotype.Component;
-
-/**
- * @author ZhouYiXun
- * @des adb上下线监听,发送对应给server
- * @date 2021/08/16 19:26
- */
-@Component
-public class AndroidDeviceStatusListener implements AndroidDebugBridge.IDeviceChangeListener {
- private final Logger logger = LoggerFactory.getLogger(AndroidDeviceStatusListener.class);
-
- /**
- * @param device
- * @return void
- * @author ZhouYiXun
- * @des 发送设备状态
- * @date 2021/8/16 19:58
- */
- private void send(IDevice device) {
- JSONObject deviceDetail = new JSONObject();
- deviceDetail.put("msg", "deviceDetail");
- deviceDetail.put("udId", device.getSerialNumber());
- deviceDetail.put("name", device.getProperty("ro.product.name"));
- deviceDetail.put("model", device.getProperty(IDevice.PROP_DEVICE_MODEL));
- deviceDetail.put("status", device.getState());
- deviceDetail.put("platform", PlatformType.ANDROID);
- deviceDetail.put("version", device.getProperty(IDevice.PROP_BUILD_VERSION));
- deviceDetail.put("size", AndroidDeviceBridgeTool.getScreenSize(device));
- deviceDetail.put("cpu", device.getProperty(IDevice.PROP_DEVICE_CPU_ABI));
- deviceDetail.put("manufacturer", device.getProperty(IDevice.PROP_DEVICE_MANUFACTURER));
- NettyThreadPool.send(deviceDetail);
- }
-
- @Override
- public void deviceConnected(IDevice device) {
- logger.info("Android设备:" + device.getSerialNumber() + " ONLINE!");
- AndroidDeviceManagerMap.getMap().remove(device.getSerialNumber());
- send(device);
- }
-
- @Override
- public void deviceDisconnected(IDevice device) {
- logger.info("Android设备:" + device.getSerialNumber() + " OFFLINE!");
- AndroidDeviceManagerMap.getMap().remove(device.getSerialNumber());
- send(device);
- }
-
- @Override
- public void deviceChanged(IDevice device, int changeMask) {
- if (device.isOnline()) {
- logger.info("Android设备:" + device.getSerialNumber() + " ONLINE!");
- } else {
- logger.info("Android设备:" + device.getSerialNumber() + " OFFLINE!");
- }
- send(device);
- }
+package org.cloud.sonic.agent.bridge.android;
+
+import com.alibaba.fastjson.JSONObject;
+import com.android.ddmlib.AndroidDebugBridge;
+import com.android.ddmlib.IDevice;
+import org.cloud.sonic.agent.interfaces.PlatformType;
+import org.cloud.sonic.agent.maps.AndroidDeviceManagerMap;
+import org.cloud.sonic.agent.netty.NettyThreadPool;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+
+/**
+ * @author ZhouYiXun
+ * @des adb上下线监听,发送对应给server
+ * @date 2021/08/16 19:26
+ */
+@Component
+public class AndroidDeviceStatusListener implements AndroidDebugBridge.IDeviceChangeListener {
+ private final Logger logger = LoggerFactory.getLogger(AndroidDeviceStatusListener.class);
+
+ /**
+ * @param device
+ * @return void
+ * @author ZhouYiXun
+ * @des 发送设备状态
+ * @date 2021/8/16 19:58
+ */
+ private void send(IDevice device) {
+ JSONObject deviceDetail = new JSONObject();
+ deviceDetail.put("msg", "deviceDetail");
+ deviceDetail.put("udId", device.getSerialNumber());
+ deviceDetail.put("name", device.getProperty("ro.product.name"));
+ deviceDetail.put("model", device.getProperty(IDevice.PROP_DEVICE_MODEL));
+ deviceDetail.put("status", device.getState());
+ deviceDetail.put("platform", PlatformType.ANDROID);
+ deviceDetail.put("version", device.getProperty(IDevice.PROP_BUILD_VERSION));
+ deviceDetail.put("size", AndroidDeviceBridgeTool.getScreenSize(device));
+ deviceDetail.put("cpu", device.getProperty(IDevice.PROP_DEVICE_CPU_ABI));
+ deviceDetail.put("manufacturer", device.getProperty(IDevice.PROP_DEVICE_MANUFACTURER));
+ NettyThreadPool.send(deviceDetail);
+ }
+
+ @Override
+ public void deviceConnected(IDevice device) {
+ logger.info("Android设备:" + device.getSerialNumber() + " ONLINE!");
+ AndroidDeviceManagerMap.getMap().remove(device.getSerialNumber());
+ send(device);
+ }
+
+ @Override
+ public void deviceDisconnected(IDevice device) {
+ logger.info("Android设备:" + device.getSerialNumber() + " OFFLINE!");
+ AndroidDeviceManagerMap.getMap().remove(device.getSerialNumber());
+ send(device);
+ }
+
+ @Override
+ public void deviceChanged(IDevice device, int changeMask) {
+ if (device.isOnline()) {
+ logger.info("Android设备:" + device.getSerialNumber() + " ONLINE!");
+ } else {
+ logger.info("Android设备:" + device.getSerialNumber() + " OFFLINE!");
+ }
+ send(device);
+ }
}
\ No newline at end of file
diff --git a/src/main/java/com/sonic/agent/bridge/android/AndroidDeviceThreadPool.java b/src/main/java/org/cloud/sonic/agent/bridge/android/AndroidDeviceThreadPool.java
similarity index 91%
rename from src/main/java/com/sonic/agent/bridge/android/AndroidDeviceThreadPool.java
rename to src/main/java/org/cloud/sonic/agent/bridge/android/AndroidDeviceThreadPool.java
index bfd04dbf..38a85846 100644
--- a/src/main/java/com/sonic/agent/bridge/android/AndroidDeviceThreadPool.java
+++ b/src/main/java/org/cloud/sonic/agent/bridge/android/AndroidDeviceThreadPool.java
@@ -1,24 +1,24 @@
-package com.sonic.agent.bridge.android;
-
-import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-
-/**
- * @author ZhouYiXun
- * @des 所有安卓相关线程都放这个线程池
- * @date 2021/08/16 19:26
- */
-@Configuration
-@ConditionalOnProperty(value = "modules.android.enable", havingValue = "true")
-public class AndroidDeviceThreadPool {
- public static ExecutorService cachedThreadPool;
-
- @Bean
- public void androidThreadPoolInit() {
- cachedThreadPool = Executors.newCachedThreadPool();
- }
+package org.cloud.sonic.agent.bridge.android;
+
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+/**
+ * @author ZhouYiXun
+ * @des 所有安卓相关线程都放这个线程池
+ * @date 2021/08/16 19:26
+ */
+@Configuration
+@ConditionalOnProperty(value = "modules.android.enable", havingValue = "true")
+public class AndroidDeviceThreadPool {
+ public static ExecutorService cachedThreadPool;
+
+ @Bean
+ public void androidThreadPoolInit() {
+ cachedThreadPool = Executors.newCachedThreadPool();
+ }
}
\ No newline at end of file
diff --git a/src/main/java/com/sonic/agent/bridge/ios/IOSDeviceLocalStatus.java b/src/main/java/org/cloud/sonic/agent/bridge/ios/IOSDeviceLocalStatus.java
similarity index 88%
rename from src/main/java/com/sonic/agent/bridge/ios/IOSDeviceLocalStatus.java
rename to src/main/java/org/cloud/sonic/agent/bridge/ios/IOSDeviceLocalStatus.java
index 960daeeb..8559c767 100644
--- a/src/main/java/com/sonic/agent/bridge/ios/IOSDeviceLocalStatus.java
+++ b/src/main/java/org/cloud/sonic/agent/bridge/ios/IOSDeviceLocalStatus.java
@@ -1,10 +1,10 @@
-package com.sonic.agent.bridge.ios;
+package org.cloud.sonic.agent.bridge.ios;
import com.alibaba.fastjson.JSONObject;
-import com.sonic.agent.interfaces.DeviceStatus;
-import com.sonic.agent.maps.IOSDeviceManagerMap;
-import com.sonic.agent.maps.IOSSizeMap;
-import com.sonic.agent.netty.NettyThreadPool;
+import org.cloud.sonic.agent.interfaces.DeviceStatus;
+import org.cloud.sonic.agent.maps.IOSDeviceManagerMap;
+import org.cloud.sonic.agent.maps.IOSSizeMap;
+import org.cloud.sonic.agent.netty.NettyThreadPool;
public class IOSDeviceLocalStatus {
diff --git a/src/main/java/com/sonic/agent/bridge/ios/IOSDeviceThreadPool.java b/src/main/java/org/cloud/sonic/agent/bridge/ios/IOSDeviceThreadPool.java
similarity index 91%
rename from src/main/java/com/sonic/agent/bridge/ios/IOSDeviceThreadPool.java
rename to src/main/java/org/cloud/sonic/agent/bridge/ios/IOSDeviceThreadPool.java
index b26941cd..2f92e801 100644
--- a/src/main/java/com/sonic/agent/bridge/ios/IOSDeviceThreadPool.java
+++ b/src/main/java/org/cloud/sonic/agent/bridge/ios/IOSDeviceThreadPool.java
@@ -1,24 +1,24 @@
-package com.sonic.agent.bridge.ios;
-
-import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-
-/**
- * @author ZhouYiXun
- * @des 所有iOS相关线程都放这个线程池
- * @date 2021/08/25 19:26
- */
-@Configuration
-@ConditionalOnProperty(value = "modules.ios.enable", havingValue = "true")
-public class IOSDeviceThreadPool {
- public static ExecutorService cachedThreadPool;
-
- @Bean
- public void iOSThreadPoolInit() {
- cachedThreadPool = Executors.newCachedThreadPool();
- }
+package org.cloud.sonic.agent.bridge.ios;
+
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+/**
+ * @author ZhouYiXun
+ * @des 所有iOS相关线程都放这个线程池
+ * @date 2021/08/25 19:26
+ */
+@Configuration
+@ConditionalOnProperty(value = "modules.ios.enable", havingValue = "true")
+public class IOSDeviceThreadPool {
+ public static ExecutorService cachedThreadPool;
+
+ @Bean
+ public void iOSThreadPoolInit() {
+ cachedThreadPool = Executors.newCachedThreadPool();
+ }
}
\ No newline at end of file
diff --git a/src/main/java/com/sonic/agent/bridge/ios/TIDeviceTool.java b/src/main/java/org/cloud/sonic/agent/bridge/ios/TIDeviceTool.java
similarity index 95%
rename from src/main/java/com/sonic/agent/bridge/ios/TIDeviceTool.java
rename to src/main/java/org/cloud/sonic/agent/bridge/ios/TIDeviceTool.java
index 4143bd9d..341ca380 100644
--- a/src/main/java/com/sonic/agent/bridge/ios/TIDeviceTool.java
+++ b/src/main/java/org/cloud/sonic/agent/bridge/ios/TIDeviceTool.java
@@ -1,14 +1,14 @@
-package com.sonic.agent.bridge.ios;
+package org.cloud.sonic.agent.bridge.ios;
import com.alibaba.fastjson.JSONObject;
-import com.sonic.agent.interfaces.PlatformType;
-import com.sonic.agent.maps.IOSDeviceManagerMap;
-import com.sonic.agent.maps.IOSProcessMap;
-import com.sonic.agent.maps.IOSSizeMap;
-import com.sonic.agent.netty.NettyClientHandler;
-import com.sonic.agent.netty.NettyThreadPool;
-import com.sonic.agent.tools.PortTool;
-import com.sonic.agent.tools.ProcessCommandTool;
+import org.cloud.sonic.agent.interfaces.PlatformType;
+import org.cloud.sonic.agent.maps.IOSDeviceManagerMap;
+import org.cloud.sonic.agent.maps.IOSProcessMap;
+import org.cloud.sonic.agent.maps.IOSSizeMap;
+import org.cloud.sonic.agent.netty.NettyClientHandler;
+import org.cloud.sonic.agent.netty.NettyThreadPool;
+import org.cloud.sonic.agent.tools.PortTool;
+import org.cloud.sonic.agent.tools.ProcessCommandTool;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
diff --git a/src/main/java/com/sonic/agent/config/RestTemplateConfig.java b/src/main/java/org/cloud/sonic/agent/config/RestTemplateConfig.java
similarity index 93%
rename from src/main/java/com/sonic/agent/config/RestTemplateConfig.java
rename to src/main/java/org/cloud/sonic/agent/config/RestTemplateConfig.java
index 52f34da6..c3d85a24 100644
--- a/src/main/java/com/sonic/agent/config/RestTemplateConfig.java
+++ b/src/main/java/org/cloud/sonic/agent/config/RestTemplateConfig.java
@@ -1,24 +1,24 @@
-package com.sonic.agent.config;
-
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.http.client.ClientHttpRequestFactory;
-import org.springframework.http.client.SimpleClientHttpRequestFactory;
-import org.springframework.web.client.RestTemplate;
-
-@Configuration
-public class RestTemplateConfig {
-
- @Bean
- public RestTemplate restTemplate(ClientHttpRequestFactory factory) {
- return new RestTemplate(factory);
- }
-
- @Bean
- public ClientHttpRequestFactory simpleClientHttpRequestFactory() {
- SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
- factory.setReadTimeout(120000);
- factory.setConnectTimeout(150000);
- return factory;
- }
+package org.cloud.sonic.agent.config;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.http.client.ClientHttpRequestFactory;
+import org.springframework.http.client.SimpleClientHttpRequestFactory;
+import org.springframework.web.client.RestTemplate;
+
+@Configuration
+public class RestTemplateConfig {
+
+ @Bean
+ public RestTemplate restTemplate(ClientHttpRequestFactory factory) {
+ return new RestTemplate(factory);
+ }
+
+ @Bean
+ public ClientHttpRequestFactory simpleClientHttpRequestFactory() {
+ SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
+ factory.setReadTimeout(120000);
+ factory.setConnectTimeout(150000);
+ return factory;
+ }
}
\ No newline at end of file
diff --git a/src/main/java/com/sonic/agent/interfaces/DeviceStatus.java b/src/main/java/org/cloud/sonic/agent/interfaces/DeviceStatus.java
similarity index 87%
rename from src/main/java/com/sonic/agent/interfaces/DeviceStatus.java
rename to src/main/java/org/cloud/sonic/agent/interfaces/DeviceStatus.java
index 93ee781a..987a1599 100644
--- a/src/main/java/com/sonic/agent/interfaces/DeviceStatus.java
+++ b/src/main/java/org/cloud/sonic/agent/interfaces/DeviceStatus.java
@@ -1,16 +1,16 @@
-package com.sonic.agent.interfaces;
-
-/**
- * @author ZhouYiXun
- * @des 枚举设备状态
- * @date 2021/08/16 19:26
- */
-public interface DeviceStatus {
- String ONLINE = "ONLINE";
- String OFFLINE = "OFFLINE";
- String TESTING = "TESTING";
- String DEBUGGING = "DEBUGGING";
- String ERROR = "ERROR";
- String UNAUTHORIZED = "UNAUTHORIZED";
- String DISCONNECTED = "DISCONNECTED";
-}
+package org.cloud.sonic.agent.interfaces;
+
+/**
+ * @author ZhouYiXun
+ * @des 枚举设备状态
+ * @date 2021/08/16 19:26
+ */
+public interface DeviceStatus {
+ String ONLINE = "ONLINE";
+ String OFFLINE = "OFFLINE";
+ String TESTING = "TESTING";
+ String DEBUGGING = "DEBUGGING";
+ String ERROR = "ERROR";
+ String UNAUTHORIZED = "UNAUTHORIZED";
+ String DISCONNECTED = "DISCONNECTED";
+}
diff --git a/src/main/java/com/sonic/agent/interfaces/ErrorType.java b/src/main/java/org/cloud/sonic/agent/interfaces/ErrorType.java
similarity index 68%
rename from src/main/java/com/sonic/agent/interfaces/ErrorType.java
rename to src/main/java/org/cloud/sonic/agent/interfaces/ErrorType.java
index 74776a73..a9f78c64 100644
--- a/src/main/java/com/sonic/agent/interfaces/ErrorType.java
+++ b/src/main/java/org/cloud/sonic/agent/interfaces/ErrorType.java
@@ -1,7 +1,7 @@
-package com.sonic.agent.interfaces;
-
-public interface ErrorType {
- int IGNORE = 1;
- int WARNING = 2;
- int SHUTDOWN = 3;
-}
+package org.cloud.sonic.agent.interfaces;
+
+public interface ErrorType {
+ int IGNORE = 1;
+ int WARNING = 2;
+ int SHUTDOWN = 3;
+}
diff --git a/src/main/java/com/sonic/agent/interfaces/PlatformType.java b/src/main/java/org/cloud/sonic/agent/interfaces/PlatformType.java
similarity index 81%
rename from src/main/java/com/sonic/agent/interfaces/PlatformType.java
rename to src/main/java/org/cloud/sonic/agent/interfaces/PlatformType.java
index 5c65dcd3..a685d114 100644
--- a/src/main/java/com/sonic/agent/interfaces/PlatformType.java
+++ b/src/main/java/org/cloud/sonic/agent/interfaces/PlatformType.java
@@ -1,14 +1,14 @@
-package com.sonic.agent.interfaces;
-
-/**
- * @author ZhouYiXun
- * @des 定义全局平台类型
- * @date 2021/8/15 19:26
- */
-public interface PlatformType {
- int ANDROID = 1;
- int IOS = 2;
- int WINDOWS = 3;
- int MAC = 4;
- int WEB = 5;
-}
+package org.cloud.sonic.agent.interfaces;
+
+/**
+ * @author ZhouYiXun
+ * @des 定义全局平台类型
+ * @date 2021/8/15 19:26
+ */
+public interface PlatformType {
+ int ANDROID = 1;
+ int IOS = 2;
+ int WINDOWS = 3;
+ int MAC = 4;
+ int WEB = 5;
+}
diff --git a/src/main/java/com/sonic/agent/interfaces/ResultDetailStatus.java b/src/main/java/org/cloud/sonic/agent/interfaces/ResultDetailStatus.java
similarity index 68%
rename from src/main/java/com/sonic/agent/interfaces/ResultDetailStatus.java
rename to src/main/java/org/cloud/sonic/agent/interfaces/ResultDetailStatus.java
index ffafd66b..9eb870d8 100644
--- a/src/main/java/com/sonic/agent/interfaces/ResultDetailStatus.java
+++ b/src/main/java/org/cloud/sonic/agent/interfaces/ResultDetailStatus.java
@@ -1,7 +1,7 @@
-package com.sonic.agent.interfaces;
-
-public interface ResultDetailStatus {
- int PASS = 1;
- int WARN = 2;
- int FAIL = 3;
-}
+package org.cloud.sonic.agent.interfaces;
+
+public interface ResultDetailStatus {
+ int PASS = 1;
+ int WARN = 2;
+ int FAIL = 3;
+}
diff --git a/src/main/java/com/sonic/agent/interfaces/StepType.java b/src/main/java/org/cloud/sonic/agent/interfaces/StepType.java
similarity index 78%
rename from src/main/java/com/sonic/agent/interfaces/StepType.java
rename to src/main/java/org/cloud/sonic/agent/interfaces/StepType.java
index d1a54f05..67fdd07f 100644
--- a/src/main/java/com/sonic/agent/interfaces/StepType.java
+++ b/src/main/java/org/cloud/sonic/agent/interfaces/StepType.java
@@ -1,13 +1,13 @@
-package com.sonic.agent.interfaces;
-
-/**
- * @author ZhouYiXun
- * @des 定义log类型
- * @date 2021/8/15 19:26
- */
-public interface StepType {
- int INFO = 1;
- int PASS = 2;
- int WARN = 3;
- int ERROR = 4;
-}
+package org.cloud.sonic.agent.interfaces;
+
+/**
+ * @author ZhouYiXun
+ * @des 定义log类型
+ * @date 2021/8/15 19:26
+ */
+public interface StepType {
+ int INFO = 1;
+ int PASS = 2;
+ int WARN = 3;
+ int ERROR = 4;
+}
diff --git a/src/main/java/com/sonic/agent/maps/AndroidDeviceManagerMap.java b/src/main/java/org/cloud/sonic/agent/maps/AndroidDeviceManagerMap.java
similarity index 89%
rename from src/main/java/com/sonic/agent/maps/AndroidDeviceManagerMap.java
rename to src/main/java/org/cloud/sonic/agent/maps/AndroidDeviceManagerMap.java
index e28c39fb..066441e0 100644
--- a/src/main/java/com/sonic/agent/maps/AndroidDeviceManagerMap.java
+++ b/src/main/java/org/cloud/sonic/agent/maps/AndroidDeviceManagerMap.java
@@ -1,16 +1,16 @@
-package com.sonic.agent.maps;
-
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-
-/**
- * @author ZhouYiXun
- * @des 本地自己维护一下设备状态
- * @date 2021/08/16 10:26
- */
-public class AndroidDeviceManagerMap {
- private static Map deviceStatusMap = new ConcurrentHashMap();
- public static Map getMap() {
- return deviceStatusMap;
- }
-}
+package org.cloud.sonic.agent.maps;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * @author ZhouYiXun
+ * @des 本地自己维护一下设备状态
+ * @date 2021/08/16 10:26
+ */
+public class AndroidDeviceManagerMap {
+ private static Map deviceStatusMap = new ConcurrentHashMap();
+ public static Map getMap() {
+ return deviceStatusMap;
+ }
+}
diff --git a/src/main/java/com/sonic/agent/maps/AndroidPasswordMap.java b/src/main/java/org/cloud/sonic/agent/maps/AndroidPasswordMap.java
similarity index 88%
rename from src/main/java/com/sonic/agent/maps/AndroidPasswordMap.java
rename to src/main/java/org/cloud/sonic/agent/maps/AndroidPasswordMap.java
index 05ae3694..5bb2bb88 100644
--- a/src/main/java/com/sonic/agent/maps/AndroidPasswordMap.java
+++ b/src/main/java/org/cloud/sonic/agent/maps/AndroidPasswordMap.java
@@ -1,16 +1,16 @@
-package com.sonic.agent.maps;
-
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-
-/**
- * @author ZhouYiXun
- * @des 存放密码
- * @date 2021/8/27 22:01
- */
-public class AndroidPasswordMap {
- private static Map devicePasswordMap = new ConcurrentHashMap();
- public static Map getMap() {
- return devicePasswordMap;
- }
-}
+package org.cloud.sonic.agent.maps;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * @author ZhouYiXun
+ * @des 存放密码
+ * @date 2021/8/27 22:01
+ */
+public class AndroidPasswordMap {
+ private static Map devicePasswordMap = new ConcurrentHashMap();
+ public static Map getMap() {
+ return devicePasswordMap;
+ }
+}
diff --git a/src/main/java/com/sonic/agent/maps/DevicesLockMap.java b/src/main/java/org/cloud/sonic/agent/maps/DevicesLockMap.java
similarity index 98%
rename from src/main/java/com/sonic/agent/maps/DevicesLockMap.java
rename to src/main/java/org/cloud/sonic/agent/maps/DevicesLockMap.java
index 6b1de9bb..0a9a4201 100644
--- a/src/main/java/com/sonic/agent/maps/DevicesLockMap.java
+++ b/src/main/java/org/cloud/sonic/agent/maps/DevicesLockMap.java
@@ -1,4 +1,4 @@
-package com.sonic.agent.maps;
+package org.cloud.sonic.agent.maps;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
diff --git a/src/main/java/com/sonic/agent/maps/GlobalProcessMap.java b/src/main/java/org/cloud/sonic/agent/maps/GlobalProcessMap.java
similarity index 88%
rename from src/main/java/com/sonic/agent/maps/GlobalProcessMap.java
rename to src/main/java/org/cloud/sonic/agent/maps/GlobalProcessMap.java
index 10118663..10d2b05f 100644
--- a/src/main/java/com/sonic/agent/maps/GlobalProcessMap.java
+++ b/src/main/java/org/cloud/sonic/agent/maps/GlobalProcessMap.java
@@ -1,4 +1,4 @@
-package com.sonic.agent.maps;
+package org.cloud.sonic.agent.maps;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
diff --git a/src/main/java/com/sonic/agent/maps/HandlerMap.java b/src/main/java/org/cloud/sonic/agent/maps/HandlerMap.java
similarity index 77%
rename from src/main/java/com/sonic/agent/maps/HandlerMap.java
rename to src/main/java/org/cloud/sonic/agent/maps/HandlerMap.java
index c0d188a3..ce29537b 100644
--- a/src/main/java/com/sonic/agent/maps/HandlerMap.java
+++ b/src/main/java/org/cloud/sonic/agent/maps/HandlerMap.java
@@ -1,19 +1,19 @@
-package com.sonic.agent.maps;
-
-import com.sonic.agent.automation.AndroidStepHandler;
-import com.sonic.agent.automation.IOSStepHandler;
-
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-
-public class HandlerMap {
- private static Map androidHandlerMap = new ConcurrentHashMap();
- public static Map getAndroidMap() {
- return androidHandlerMap;
- }
-
- private static Map iosHandlerMap = new ConcurrentHashMap();
- public static Map getIOSMap() {
- return iosHandlerMap;
- }
-}
+package org.cloud.sonic.agent.maps;
+
+import org.cloud.sonic.agent.automation.AndroidStepHandler;
+import org.cloud.sonic.agent.automation.IOSStepHandler;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+public class HandlerMap {
+ private static Map androidHandlerMap = new ConcurrentHashMap();
+ public static Map getAndroidMap() {
+ return androidHandlerMap;
+ }
+
+ private static Map iosHandlerMap = new ConcurrentHashMap();
+ public static Map getIOSMap() {
+ return iosHandlerMap;
+ }
+}
diff --git a/src/main/java/com/sonic/agent/maps/IOSDeviceManagerMap.java b/src/main/java/org/cloud/sonic/agent/maps/IOSDeviceManagerMap.java
similarity index 89%
rename from src/main/java/com/sonic/agent/maps/IOSDeviceManagerMap.java
rename to src/main/java/org/cloud/sonic/agent/maps/IOSDeviceManagerMap.java
index 46d04bbe..bc722405 100644
--- a/src/main/java/com/sonic/agent/maps/IOSDeviceManagerMap.java
+++ b/src/main/java/org/cloud/sonic/agent/maps/IOSDeviceManagerMap.java
@@ -1,16 +1,16 @@
-package com.sonic.agent.maps;
-
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-
-/**
- * @author ZhouYiXun
- * @des 本地自己维护一下设备状态
- * @date 2021/08/16 10:26
- */
-public class IOSDeviceManagerMap {
- private static Map deviceStatusMap = new ConcurrentHashMap();
- public static Map getMap() {
- return deviceStatusMap;
- }
-}
+package org.cloud.sonic.agent.maps;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * @author ZhouYiXun
+ * @des 本地自己维护一下设备状态
+ * @date 2021/08/16 10:26
+ */
+public class IOSDeviceManagerMap {
+ private static Map deviceStatusMap = new ConcurrentHashMap();
+ public static Map getMap() {
+ return deviceStatusMap;
+ }
+}
diff --git a/src/main/java/com/sonic/agent/maps/IOSProcessMap.java b/src/main/java/org/cloud/sonic/agent/maps/IOSProcessMap.java
similarity index 89%
rename from src/main/java/com/sonic/agent/maps/IOSProcessMap.java
rename to src/main/java/org/cloud/sonic/agent/maps/IOSProcessMap.java
index fafe253a..1af8024a 100644
--- a/src/main/java/com/sonic/agent/maps/IOSProcessMap.java
+++ b/src/main/java/org/cloud/sonic/agent/maps/IOSProcessMap.java
@@ -1,4 +1,4 @@
-package com.sonic.agent.maps;
+package org.cloud.sonic.agent.maps;
import java.util.List;
import java.util.Map;
diff --git a/src/main/java/com/sonic/agent/maps/IOSSizeMap.java b/src/main/java/org/cloud/sonic/agent/maps/IOSSizeMap.java
similarity index 88%
rename from src/main/java/com/sonic/agent/maps/IOSSizeMap.java
rename to src/main/java/org/cloud/sonic/agent/maps/IOSSizeMap.java
index 1a89d365..084f5d36 100644
--- a/src/main/java/com/sonic/agent/maps/IOSSizeMap.java
+++ b/src/main/java/org/cloud/sonic/agent/maps/IOSSizeMap.java
@@ -1,4 +1,4 @@
-package com.sonic.agent.maps;
+package org.cloud.sonic.agent.maps;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
diff --git a/src/main/java/com/sonic/agent/maps/MiniCapMap.java b/src/main/java/org/cloud/sonic/agent/maps/MiniCapMap.java
similarity index 90%
rename from src/main/java/com/sonic/agent/maps/MiniCapMap.java
rename to src/main/java/org/cloud/sonic/agent/maps/MiniCapMap.java
index 83fe5c89..b1692f24 100644
--- a/src/main/java/com/sonic/agent/maps/MiniCapMap.java
+++ b/src/main/java/org/cloud/sonic/agent/maps/MiniCapMap.java
@@ -1,4 +1,4 @@
-package com.sonic.agent.maps;
+package org.cloud.sonic.agent.maps;
import javax.websocket.Session;
import java.util.Map;
diff --git a/src/main/java/com/sonic/agent/maps/WebSocketSessionMap.java b/src/main/java/org/cloud/sonic/agent/maps/WebSocketSessionMap.java
similarity index 96%
rename from src/main/java/com/sonic/agent/maps/WebSocketSessionMap.java
rename to src/main/java/org/cloud/sonic/agent/maps/WebSocketSessionMap.java
index a9078f75..e46ca6f8 100644
--- a/src/main/java/com/sonic/agent/maps/WebSocketSessionMap.java
+++ b/src/main/java/org/cloud/sonic/agent/maps/WebSocketSessionMap.java
@@ -1,4 +1,4 @@
-package com.sonic.agent.maps;
+package org.cloud.sonic.agent.maps;
import org.springframework.lang.NonNull;
import org.springframework.util.Assert;
diff --git a/src/main/java/com/sonic/agent/netty/MarshallingCodeCFactory.java b/src/main/java/org/cloud/sonic/agent/netty/MarshallingCodeCFactory.java
similarity index 97%
rename from src/main/java/com/sonic/agent/netty/MarshallingCodeCFactory.java
rename to src/main/java/org/cloud/sonic/agent/netty/MarshallingCodeCFactory.java
index 9a33038a..09bd5d88 100644
--- a/src/main/java/com/sonic/agent/netty/MarshallingCodeCFactory.java
+++ b/src/main/java/org/cloud/sonic/agent/netty/MarshallingCodeCFactory.java
@@ -1,4 +1,4 @@
-package com.sonic.agent.netty;
+package org.cloud.sonic.agent.netty;
import io.netty.handler.codec.marshalling.*;
import org.jboss.marshalling.MarshallerFactory;
diff --git a/src/main/java/com/sonic/agent/netty/NettyClient.java b/src/main/java/org/cloud/sonic/agent/netty/NettyClient.java
similarity index 93%
rename from src/main/java/com/sonic/agent/netty/NettyClient.java
rename to src/main/java/org/cloud/sonic/agent/netty/NettyClient.java
index 55245ae0..9292c17b 100644
--- a/src/main/java/com/sonic/agent/netty/NettyClient.java
+++ b/src/main/java/org/cloud/sonic/agent/netty/NettyClient.java
@@ -1,8 +1,8 @@
-package com.sonic.agent.netty;
+package org.cloud.sonic.agent.netty;
-import com.sonic.agent.bridge.android.AndroidDeviceBridgeTool;
-import com.sonic.agent.bridge.ios.TIDeviceTool;
-import com.sonic.agent.tools.SpringTool;
+import org.cloud.sonic.agent.bridge.android.AndroidDeviceBridgeTool;
+import org.cloud.sonic.agent.bridge.ios.TIDeviceTool;
+import org.cloud.sonic.agent.tools.SpringTool;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
@@ -14,7 +14,6 @@
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
-import org.springframework.context.annotation.DependsOn;
import org.springframework.stereotype.Component;
import java.util.concurrent.TimeUnit;
diff --git a/src/main/java/com/sonic/agent/netty/NettyClientHandler.java b/src/main/java/org/cloud/sonic/agent/netty/NettyClientHandler.java
similarity index 93%
rename from src/main/java/com/sonic/agent/netty/NettyClientHandler.java
rename to src/main/java/org/cloud/sonic/agent/netty/NettyClientHandler.java
index 0e80454a..d736984c 100644
--- a/src/main/java/com/sonic/agent/netty/NettyClientHandler.java
+++ b/src/main/java/org/cloud/sonic/agent/netty/NettyClientHandler.java
@@ -1,25 +1,24 @@
-package com.sonic.agent.netty;
+package org.cloud.sonic.agent.netty;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.android.ddmlib.IDevice;
-import com.sonic.agent.automation.AndroidStepHandler;
-import com.sonic.agent.automation.IOSStepHandler;
-import com.sonic.agent.bridge.android.AndroidDeviceBridgeTool;
-import com.sonic.agent.bridge.ios.TIDeviceTool;
-import com.sonic.agent.interfaces.PlatformType;
-import com.sonic.agent.maps.AndroidPasswordMap;
-import com.sonic.agent.maps.HandlerMap;
-import com.sonic.agent.tests.AndroidTests;
-import com.sonic.agent.tests.IOSTests;
-import com.sonic.agent.tests.TaskManager;
+import org.cloud.sonic.agent.automation.AndroidStepHandler;
+import org.cloud.sonic.agent.automation.IOSStepHandler;
+import org.cloud.sonic.agent.bridge.android.AndroidDeviceBridgeTool;
+import org.cloud.sonic.agent.bridge.ios.TIDeviceTool;
+import org.cloud.sonic.agent.interfaces.PlatformType;
+import org.cloud.sonic.agent.maps.AndroidPasswordMap;
+import org.cloud.sonic.agent.maps.HandlerMap;
+import org.cloud.sonic.agent.tests.AndroidTests;
+import org.cloud.sonic.agent.tests.IOSTests;
+import org.cloud.sonic.agent.tests.TaskManager;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import org.springframework.stereotype.Component;
import org.testng.TestNG;
import org.testng.xml.XmlClass;
import org.testng.xml.XmlSuite;
diff --git a/src/main/java/com/sonic/agent/netty/NettyThreadPool.java b/src/main/java/org/cloud/sonic/agent/netty/NettyThreadPool.java
similarity index 96%
rename from src/main/java/com/sonic/agent/netty/NettyThreadPool.java
rename to src/main/java/org/cloud/sonic/agent/netty/NettyThreadPool.java
index 14153385..38691c6e 100644
--- a/src/main/java/com/sonic/agent/netty/NettyThreadPool.java
+++ b/src/main/java/org/cloud/sonic/agent/netty/NettyThreadPool.java
@@ -1,7 +1,7 @@
-package com.sonic.agent.netty;
+package org.cloud.sonic.agent.netty;
import com.alibaba.fastjson.JSONObject;
-import com.sonic.agent.tools.AgentTool;
+import org.cloud.sonic.agent.tools.AgentTool;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
diff --git a/src/main/java/com/sonic/agent/netty/SecurityHandler.java b/src/main/java/org/cloud/sonic/agent/netty/SecurityHandler.java
similarity index 97%
rename from src/main/java/com/sonic/agent/netty/SecurityHandler.java
rename to src/main/java/org/cloud/sonic/agent/netty/SecurityHandler.java
index ce9f1fb8..52be2215 100644
--- a/src/main/java/com/sonic/agent/netty/SecurityHandler.java
+++ b/src/main/java/org/cloud/sonic/agent/netty/SecurityHandler.java
@@ -1,8 +1,8 @@
-package com.sonic.agent.netty;
+package org.cloud.sonic.agent.netty;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
-import com.sonic.agent.tools.AgentTool;
+import org.cloud.sonic.agent.tools.AgentTool;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
diff --git a/src/main/java/com/sonic/agent/tests/AndroidTests.java b/src/main/java/org/cloud/sonic/agent/tests/AndroidTests.java
similarity index 88%
rename from src/main/java/com/sonic/agent/tests/AndroidTests.java
rename to src/main/java/org/cloud/sonic/agent/tests/AndroidTests.java
index 3884d7b8..b1c903c9 100644
--- a/src/main/java/com/sonic/agent/tests/AndroidTests.java
+++ b/src/main/java/org/cloud/sonic/agent/tests/AndroidTests.java
@@ -1,66 +1,66 @@
-package com.sonic.agent.tests;
-
-import com.alibaba.fastjson.JSON;
-import com.alibaba.fastjson.JSONObject;
-import com.sonic.agent.automation.AndroidStepHandler;
-import com.sonic.agent.bridge.android.AndroidDeviceBridgeTool;
-import com.sonic.agent.interfaces.DeviceStatus;
-import com.sonic.agent.tests.android.AndroidTestTaskBootThread;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.testng.ITestContext;
-import org.testng.annotations.DataProvider;
-import org.testng.annotations.Test;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * @author ZhouYiXun
- * @des 安卓测试执行类
- * @date 2021/8/25 20:50
- */
-public class AndroidTests {
- private final Logger logger = LoggerFactory.getLogger(AndroidTests.class);
-
- @DataProvider(name = "testData", parallel = true)
- public Object[][] getTestData(ITestContext context) {
- JSONObject dataInfo = JSON.parseObject(context.getCurrentXmlTest().getParameter("dataInfo"));
- List dataProvider = new ArrayList<>();
- for (JSONObject iDevice : dataInfo.getJSONArray("device").toJavaList(JSONObject.class)) {
- String udId = iDevice.getString("udId");
- if (AndroidDeviceBridgeTool.getIDeviceByUdId(udId) == null || !AndroidDeviceBridgeTool.getIDeviceByUdId(udId)
- .getState().toString().equals("ONLINE")) {
- continue;
- }
- JSONObject deviceTestData = new JSONObject();
- deviceTestData.put("steps", dataInfo.getJSONArray("steps"));
- deviceTestData.put("rid", dataInfo.getInteger("rid"));
- deviceTestData.put("cid", dataInfo.getInteger("cid"));
- deviceTestData.put("gp", dataInfo.getJSONObject("gp"));
- deviceTestData.put("device", iDevice);
- dataProvider.add(deviceTestData);
- }
- Object[][] testDataProvider = new Object[dataProvider.size()][];
- for (int i = 0; i < dataProvider.size(); i++) {
- testDataProvider[i] = new Object[]{dataProvider.get(i)};
- }
- return testDataProvider;
- }
-
- @Test(dataProvider = "testData")
- public void run(JSONObject jsonObject) throws IOException {
- AndroidStepHandler androidStepHandler = new AndroidStepHandler();
- int rid = jsonObject.getInteger("rid");
- int cid = jsonObject.getInteger("cid");
- String udId = jsonObject.getJSONObject("device").getString("udId");
- JSONObject gp = jsonObject.getJSONObject("gp");
- androidStepHandler.setGlobalParams(gp);
- androidStepHandler.setTestMode(cid, rid, udId, DeviceStatus.TESTING, "");
-
- // 启动任务
- AndroidTestTaskBootThread bootThread = new AndroidTestTaskBootThread(jsonObject, androidStepHandler);
- TaskManager.startBootThread(bootThread);
- }
-}
+package org.cloud.sonic.agent.tests;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import org.cloud.sonic.agent.automation.AndroidStepHandler;
+import org.cloud.sonic.agent.bridge.android.AndroidDeviceBridgeTool;
+import org.cloud.sonic.agent.interfaces.DeviceStatus;
+import org.cloud.sonic.agent.tests.android.AndroidTestTaskBootThread;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.ITestContext;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author ZhouYiXun
+ * @des 安卓测试执行类
+ * @date 2021/8/25 20:50
+ */
+public class AndroidTests {
+ private final Logger logger = LoggerFactory.getLogger(AndroidTests.class);
+
+ @DataProvider(name = "testData", parallel = true)
+ public Object[][] getTestData(ITestContext context) {
+ JSONObject dataInfo = JSON.parseObject(context.getCurrentXmlTest().getParameter("dataInfo"));
+ List dataProvider = new ArrayList<>();
+ for (JSONObject iDevice : dataInfo.getJSONArray("device").toJavaList(JSONObject.class)) {
+ String udId = iDevice.getString("udId");
+ if (AndroidDeviceBridgeTool.getIDeviceByUdId(udId) == null || !AndroidDeviceBridgeTool.getIDeviceByUdId(udId)
+ .getState().toString().equals("ONLINE")) {
+ continue;
+ }
+ JSONObject deviceTestData = new JSONObject();
+ deviceTestData.put("steps", dataInfo.getJSONArray("steps"));
+ deviceTestData.put("rid", dataInfo.getInteger("rid"));
+ deviceTestData.put("cid", dataInfo.getInteger("cid"));
+ deviceTestData.put("gp", dataInfo.getJSONObject("gp"));
+ deviceTestData.put("device", iDevice);
+ dataProvider.add(deviceTestData);
+ }
+ Object[][] testDataProvider = new Object[dataProvider.size()][];
+ for (int i = 0; i < dataProvider.size(); i++) {
+ testDataProvider[i] = new Object[]{dataProvider.get(i)};
+ }
+ return testDataProvider;
+ }
+
+ @Test(dataProvider = "testData")
+ public void run(JSONObject jsonObject) throws IOException {
+ AndroidStepHandler androidStepHandler = new AndroidStepHandler();
+ int rid = jsonObject.getInteger("rid");
+ int cid = jsonObject.getInteger("cid");
+ String udId = jsonObject.getJSONObject("device").getString("udId");
+ JSONObject gp = jsonObject.getJSONObject("gp");
+ androidStepHandler.setGlobalParams(gp);
+ androidStepHandler.setTestMode(cid, rid, udId, DeviceStatus.TESTING, "");
+
+ // 启动任务
+ AndroidTestTaskBootThread bootThread = new AndroidTestTaskBootThread(jsonObject, androidStepHandler);
+ TaskManager.startBootThread(bootThread);
+ }
+}
diff --git a/src/main/java/com/sonic/agent/tests/IOSTests.java b/src/main/java/org/cloud/sonic/agent/tests/IOSTests.java
similarity index 89%
rename from src/main/java/com/sonic/agent/tests/IOSTests.java
rename to src/main/java/org/cloud/sonic/agent/tests/IOSTests.java
index 01415c56..740310d1 100644
--- a/src/main/java/com/sonic/agent/tests/IOSTests.java
+++ b/src/main/java/org/cloud/sonic/agent/tests/IOSTests.java
@@ -1,65 +1,65 @@
-package com.sonic.agent.tests;
-
-import com.alibaba.fastjson.JSON;
-import com.alibaba.fastjson.JSONObject;
-import com.sonic.agent.automation.IOSStepHandler;
-import com.sonic.agent.bridge.ios.TIDeviceTool;
-import com.sonic.agent.interfaces.DeviceStatus;
-import com.sonic.agent.tests.ios.IOSTestTaskBootThread;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.testng.ITestContext;
-import org.testng.annotations.DataProvider;
-import org.testng.annotations.Test;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * @author ZhouYiXun
- * @des iOS测试执行类
- * @date 2021/8/25 20:51
- */
-public class IOSTests {
- private final Logger logger = LoggerFactory.getLogger(IOSTests.class);
-
- @DataProvider(name = "testData", parallel = true)
- public Object[][] getTestData(ITestContext context) {
- JSONObject dataInfo = JSON.parseObject(context.getCurrentXmlTest().getParameter("dataInfo"));
- List dataProvider = new ArrayList<>();
- for (JSONObject device : dataInfo.getJSONArray("device").toJavaList(JSONObject.class)) {
- String udId = device.getString("udId");
- if (!TIDeviceTool.getDeviceList().contains(udId)) {
- continue;
- }
- JSONObject deviceTestData = new JSONObject();
- deviceTestData.put("steps", dataInfo.getJSONArray("steps"));
- deviceTestData.put("rid", dataInfo.getInteger("rid"));
- deviceTestData.put("cid", dataInfo.getInteger("cid"));
- deviceTestData.put("gp", dataInfo.getJSONObject("gp"));
- deviceTestData.put("device", device);
- dataProvider.add(deviceTestData);
- }
- Object[][] testDataProvider = new Object[dataProvider.size()][];
- for (int i = 0; i < dataProvider.size(); i++) {
- testDataProvider[i] = new Object[]{dataProvider.get(i)};
- }
- return testDataProvider;
- }
-
- @Test(dataProvider = "testData")
- public void run(JSONObject jsonObject) throws IOException {
- IOSStepHandler iosStepHandler = new IOSStepHandler();
- int rid = jsonObject.getInteger("rid");
- int cid = jsonObject.getInteger("cid");
- String udId = jsonObject.getJSONObject("device").getString("udId");
- JSONObject gp = jsonObject.getJSONObject("gp");
- iosStepHandler.setGlobalParams(gp);
- iosStepHandler.setTestMode(cid, rid, udId, DeviceStatus.TESTING, "");
-
- // 启动任务
- IOSTestTaskBootThread bootThread = new IOSTestTaskBootThread(jsonObject, iosStepHandler);
- TaskManager.startBootThread(bootThread);
- }
-}
+package org.cloud.sonic.agent.tests;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import org.cloud.sonic.agent.automation.IOSStepHandler;
+import org.cloud.sonic.agent.bridge.ios.TIDeviceTool;
+import org.cloud.sonic.agent.interfaces.DeviceStatus;
+import org.cloud.sonic.agent.tests.ios.IOSTestTaskBootThread;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.ITestContext;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author ZhouYiXun
+ * @des iOS测试执行类
+ * @date 2021/8/25 20:51
+ */
+public class IOSTests {
+ private final Logger logger = LoggerFactory.getLogger(IOSTests.class);
+
+ @DataProvider(name = "testData", parallel = true)
+ public Object[][] getTestData(ITestContext context) {
+ JSONObject dataInfo = JSON.parseObject(context.getCurrentXmlTest().getParameter("dataInfo"));
+ List dataProvider = new ArrayList<>();
+ for (JSONObject device : dataInfo.getJSONArray("device").toJavaList(JSONObject.class)) {
+ String udId = device.getString("udId");
+ if (!TIDeviceTool.getDeviceList().contains(udId)) {
+ continue;
+ }
+ JSONObject deviceTestData = new JSONObject();
+ deviceTestData.put("steps", dataInfo.getJSONArray("steps"));
+ deviceTestData.put("rid", dataInfo.getInteger("rid"));
+ deviceTestData.put("cid", dataInfo.getInteger("cid"));
+ deviceTestData.put("gp", dataInfo.getJSONObject("gp"));
+ deviceTestData.put("device", device);
+ dataProvider.add(deviceTestData);
+ }
+ Object[][] testDataProvider = new Object[dataProvider.size()][];
+ for (int i = 0; i < dataProvider.size(); i++) {
+ testDataProvider[i] = new Object[]{dataProvider.get(i)};
+ }
+ return testDataProvider;
+ }
+
+ @Test(dataProvider = "testData")
+ public void run(JSONObject jsonObject) throws IOException {
+ IOSStepHandler iosStepHandler = new IOSStepHandler();
+ int rid = jsonObject.getInteger("rid");
+ int cid = jsonObject.getInteger("cid");
+ String udId = jsonObject.getJSONObject("device").getString("udId");
+ JSONObject gp = jsonObject.getJSONObject("gp");
+ iosStepHandler.setGlobalParams(gp);
+ iosStepHandler.setTestMode(cid, rid, udId, DeviceStatus.TESTING, "");
+
+ // 启动任务
+ IOSTestTaskBootThread bootThread = new IOSTestTaskBootThread(jsonObject, iosStepHandler);
+ TaskManager.startBootThread(bootThread);
+ }
+}
diff --git a/src/main/java/com/sonic/agent/tests/TaskManager.java b/src/main/java/org/cloud/sonic/agent/tests/TaskManager.java
similarity index 96%
rename from src/main/java/com/sonic/agent/tests/TaskManager.java
rename to src/main/java/org/cloud/sonic/agent/tests/TaskManager.java
index e24eee4d..bce08587 100644
--- a/src/main/java/com/sonic/agent/tests/TaskManager.java
+++ b/src/main/java/org/cloud/sonic/agent/tests/TaskManager.java
@@ -1,8 +1,8 @@
-package com.sonic.agent.tests;
+package org.cloud.sonic.agent.tests;
-import com.sonic.agent.interfaces.PlatformType;
-import com.sonic.agent.tests.android.AndroidTestTaskBootThread;
-import com.sonic.agent.tests.ios.IOSTestTaskBootThread;
+import org.cloud.sonic.agent.interfaces.PlatformType;
+import org.cloud.sonic.agent.tests.android.AndroidTestTaskBootThread;
+import org.cloud.sonic.agent.tests.ios.IOSTestTaskBootThread;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.CollectionUtils;
diff --git a/src/main/java/com/sonic/agent/tests/android/AndroidPerfDataThread.java b/src/main/java/org/cloud/sonic/agent/tests/android/AndroidPerfDataThread.java
similarity index 94%
rename from src/main/java/com/sonic/agent/tests/android/AndroidPerfDataThread.java
rename to src/main/java/org/cloud/sonic/agent/tests/android/AndroidPerfDataThread.java
index 63b59903..ce31b880 100644
--- a/src/main/java/com/sonic/agent/tests/android/AndroidPerfDataThread.java
+++ b/src/main/java/org/cloud/sonic/agent/tests/android/AndroidPerfDataThread.java
@@ -1,6 +1,6 @@
-package com.sonic.agent.tests.android;
+package org.cloud.sonic.agent.tests.android;
-import com.sonic.agent.automation.AndroidStepHandler;
+import org.cloud.sonic.agent.automation.AndroidStepHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
diff --git a/src/main/java/com/sonic/agent/tests/android/AndroidRecordThread.java b/src/main/java/org/cloud/sonic/agent/tests/android/AndroidRecordThread.java
similarity index 94%
rename from src/main/java/com/sonic/agent/tests/android/AndroidRecordThread.java
rename to src/main/java/org/cloud/sonic/agent/tests/android/AndroidRecordThread.java
index 18e10622..e188bc7b 100644
--- a/src/main/java/com/sonic/agent/tests/android/AndroidRecordThread.java
+++ b/src/main/java/org/cloud/sonic/agent/tests/android/AndroidRecordThread.java
@@ -1,10 +1,10 @@
-package com.sonic.agent.tests.android;
+package org.cloud.sonic.agent.tests.android;
import com.android.ddmlib.IDevice;
-import com.sonic.agent.automation.AndroidStepHandler;
-import com.sonic.agent.bridge.android.AndroidDeviceBridgeTool;
-import com.sonic.agent.tools.RecordHandler;
-import com.sonic.agent.tools.MiniCapTool;
+import org.cloud.sonic.agent.automation.AndroidStepHandler;
+import org.cloud.sonic.agent.bridge.android.AndroidDeviceBridgeTool;
+import org.cloud.sonic.agent.tools.RecordHandler;
+import org.cloud.sonic.agent.tools.MiniCapTool;
import org.bytedeco.javacv.FrameRecorder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
diff --git a/src/main/java/com/sonic/agent/tests/android/AndroidRunStepThread.java b/src/main/java/org/cloud/sonic/agent/tests/android/AndroidRunStepThread.java
similarity index 93%
rename from src/main/java/com/sonic/agent/tests/android/AndroidRunStepThread.java
rename to src/main/java/org/cloud/sonic/agent/tests/android/AndroidRunStepThread.java
index 76415c82..3d53cb85 100644
--- a/src/main/java/com/sonic/agent/tests/android/AndroidRunStepThread.java
+++ b/src/main/java/org/cloud/sonic/agent/tests/android/AndroidRunStepThread.java
@@ -1,7 +1,7 @@
-package com.sonic.agent.tests.android;
+package org.cloud.sonic.agent.tests.android;
import com.alibaba.fastjson.JSONObject;
-import com.sonic.agent.automation.AndroidStepHandler;
+import org.cloud.sonic.agent.automation.AndroidStepHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
diff --git a/src/main/java/com/sonic/agent/tests/android/AndroidTemperThread.java b/src/main/java/org/cloud/sonic/agent/tests/android/AndroidTemperThread.java
similarity index 88%
rename from src/main/java/com/sonic/agent/tests/android/AndroidTemperThread.java
rename to src/main/java/org/cloud/sonic/agent/tests/android/AndroidTemperThread.java
index 8e287fd6..1e41d45f 100644
--- a/src/main/java/com/sonic/agent/tests/android/AndroidTemperThread.java
+++ b/src/main/java/org/cloud/sonic/agent/tests/android/AndroidTemperThread.java
@@ -1,10 +1,10 @@
-package com.sonic.agent.tests.android;
+package org.cloud.sonic.agent.tests.android;
import com.alibaba.fastjson.JSONObject;
import com.android.ddmlib.IDevice;
-import com.sonic.agent.bridge.android.AndroidDeviceBridgeTool;
-import com.sonic.agent.netty.NettyClientHandler;
-import com.sonic.agent.netty.NettyThreadPool;
+import org.cloud.sonic.agent.bridge.android.AndroidDeviceBridgeTool;
+import org.cloud.sonic.agent.netty.NettyClientHandler;
+import org.cloud.sonic.agent.netty.NettyThreadPool;
import org.springframework.util.StringUtils;
import java.util.ArrayList;
diff --git a/src/main/java/com/sonic/agent/tests/android/AndroidTestTaskBootThread.java b/src/main/java/org/cloud/sonic/agent/tests/android/AndroidTestTaskBootThread.java
similarity index 95%
rename from src/main/java/com/sonic/agent/tests/android/AndroidTestTaskBootThread.java
rename to src/main/java/org/cloud/sonic/agent/tests/android/AndroidTestTaskBootThread.java
index fc919f0b..c81d3438 100644
--- a/src/main/java/com/sonic/agent/tests/android/AndroidTestTaskBootThread.java
+++ b/src/main/java/org/cloud/sonic/agent/tests/android/AndroidTestTaskBootThread.java
@@ -1,10 +1,10 @@
-package com.sonic.agent.tests.android;
+package org.cloud.sonic.agent.tests.android;
import com.alibaba.fastjson.JSONObject;
-import com.sonic.agent.automation.AndroidStepHandler;
-import com.sonic.agent.bridge.android.AndroidDeviceLocalStatus;
-import com.sonic.agent.interfaces.ResultDetailStatus;
-import com.sonic.agent.tests.TaskManager;
+import org.cloud.sonic.agent.automation.AndroidStepHandler;
+import org.cloud.sonic.agent.bridge.android.AndroidDeviceLocalStatus;
+import org.cloud.sonic.agent.interfaces.ResultDetailStatus;
+import org.cloud.sonic.agent.tests.TaskManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
diff --git a/src/main/java/com/sonic/agent/tests/android/InputSocketThread.java b/src/main/java/org/cloud/sonic/agent/tests/android/InputSocketThread.java
similarity index 93%
rename from src/main/java/com/sonic/agent/tests/android/InputSocketThread.java
rename to src/main/java/org/cloud/sonic/agent/tests/android/InputSocketThread.java
index 4cde3f9e..d55b5982 100644
--- a/src/main/java/com/sonic/agent/tests/android/InputSocketThread.java
+++ b/src/main/java/org/cloud/sonic/agent/tests/android/InputSocketThread.java
@@ -1,9 +1,9 @@
-package com.sonic.agent.tests.android;
+package org.cloud.sonic.agent.tests.android;
import com.android.ddmlib.IDevice;
-import com.sonic.agent.bridge.android.AndroidDeviceBridgeTool;
-import com.sonic.agent.maps.MiniCapMap;
-import com.sonic.agent.tools.PortTool;
+import org.cloud.sonic.agent.bridge.android.AndroidDeviceBridgeTool;
+import org.cloud.sonic.agent.maps.MiniCapMap;
+import org.cloud.sonic.agent.tools.PortTool;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -11,10 +11,9 @@
import java.io.IOException;
import java.io.InputStream;
import java.net.Socket;
-import java.util.Queue;
import java.util.concurrent.BlockingQueue;
-import static com.sonic.agent.tools.AgentTool.subByteArray;
+import static org.cloud.sonic.agent.tools.AgentTool.subByteArray;
/**
* minicap socket线程
diff --git a/src/main/java/com/sonic/agent/tests/android/OutputSocketThread.java b/src/main/java/org/cloud/sonic/agent/tests/android/OutputSocketThread.java
similarity index 86%
rename from src/main/java/com/sonic/agent/tests/android/OutputSocketThread.java
rename to src/main/java/org/cloud/sonic/agent/tests/android/OutputSocketThread.java
index c0016c1e..907e8f12 100644
--- a/src/main/java/com/sonic/agent/tests/android/OutputSocketThread.java
+++ b/src/main/java/org/cloud/sonic/agent/tests/android/OutputSocketThread.java
@@ -1,18 +1,16 @@
-package com.sonic.agent.tests.android;
+package org.cloud.sonic.agent.tests.android;
import com.alibaba.fastjson.JSONObject;
+import org.cloud.sonic.agent.tools.AgentTool;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.websocket.Session;
import java.util.Arrays;
import java.util.List;
-import java.util.Queue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.atomic.AtomicReference;
-import static com.sonic.agent.tools.AgentTool.*;
-
/**
* 视频流输出线程
*
@@ -101,31 +99,31 @@ public void run() {
case 3:
case 4:
case 5:
- banner.get()[5] = bytesToLong(buffer, 2) + "";
+ banner.get()[5] = AgentTool.bytesToLong(buffer, 2) + "";
break;
case 6:
case 7:
case 8:
case 9:
- banner.get()[9] = bytesToLong(buffer, 6) + "";
+ banner.get()[9] = AgentTool.bytesToLong(buffer, 6) + "";
break;
case 10:
case 11:
case 12:
case 13:
- banner.get()[13] = bytesToLong(buffer, 10) + "";
+ banner.get()[13] = AgentTool.bytesToLong(buffer, 10) + "";
break;
case 14:
case 15:
case 16:
case 17:
- banner.get()[17] = bytesToLong(buffer, 14) + "";
+ banner.get()[17] = AgentTool.bytesToLong(buffer, 14) + "";
break;
case 18:
case 19:
case 20:
case 21:
- banner.get()[21] = bytesToLong(buffer, 18) + "";
+ banner.get()[21] = AgentTool.bytesToLong(buffer, 18) + "";
break;
case 22:
banner.get()[22] += buffer[cursor] * 90;
@@ -144,7 +142,7 @@ public void run() {
size.put("msg", "size");
size.put("width", banner.get()[9]);
size.put("height", banner.get()[13]);
- sendText(session, size.toJSONString());
+ AgentTool.sendText(session, size.toJSONString());
}
}
} else if (readFrameBytes < 4) {//读取并设置图片的大小
@@ -153,13 +151,13 @@ public void run() {
readFrameBytes += 1;
} else {
if (len - cursor >= frameBodyLength) {
- byte[] subByte = subByteArray(buffer, cursor,
+ byte[] subByte = AgentTool.subByteArray(buffer, cursor,
cursor + frameBodyLength);
- frameBody = addBytes(frameBody, subByte);
+ frameBody = AgentTool.addBytes(frameBody, subByte);
if ((frameBody[0] != -1) || frameBody[1] != -40) {
return;
}
- final byte[] finalBytes = subByteArray(frameBody,
+ final byte[] finalBytes = AgentTool.subByteArray(frameBody,
0, frameBody.length);
if (sessionOpen()) {
if (!Arrays.equals(oldBytes, finalBytes)) {
@@ -177,7 +175,7 @@ public void run() {
if (count % 4 == 0) {
count = 0;
oldBytes = finalBytes;
- sendByte(session, finalBytes);
+ AgentTool.sendByte(session, finalBytes);
}
}
}
@@ -189,8 +187,8 @@ public void run() {
readFrameBytes = 0;
frameBody = new byte[0];
} else {
- byte[] subByte = subByteArray(buffer, cursor, len);
- frameBody = addBytes(frameBody, subByte);
+ byte[] subByte = AgentTool.subByteArray(buffer, cursor, len);
+ frameBody = AgentTool.addBytes(frameBody, subByte);
frameBodyLength -= (len - cursor);
readFrameBytes += (len - cursor);
cursor = len;
diff --git a/src/main/java/com/sonic/agent/tests/android/SonicLocalThread.java b/src/main/java/org/cloud/sonic/agent/tests/android/SonicLocalThread.java
similarity index 96%
rename from src/main/java/com/sonic/agent/tests/android/SonicLocalThread.java
rename to src/main/java/org/cloud/sonic/agent/tests/android/SonicLocalThread.java
index af2be4b2..bf77bda4 100644
--- a/src/main/java/com/sonic/agent/tests/android/SonicLocalThread.java
+++ b/src/main/java/org/cloud/sonic/agent/tests/android/SonicLocalThread.java
@@ -1,9 +1,10 @@
-package com.sonic.agent.tests.android;
+package org.cloud.sonic.agent.tests.android;
import com.alibaba.fastjson.JSONObject;
import com.android.ddmlib.IDevice;
import com.android.ddmlib.IShellOutputReceiver;
-import com.sonic.agent.bridge.android.AndroidDeviceBridgeTool;
+import org.cloud.sonic.agent.bridge.android.AndroidDeviceBridgeTool;
+import org.cloud.sonic.agent.tools.AgentTool;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -13,8 +14,6 @@
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
-import static com.sonic.agent.tools.AgentTool.sendText;
-
/**
* 启动minicap等服务的线程
*
@@ -178,7 +177,7 @@ public void run() {
JSONObject support = new JSONObject();
support.put("msg", "support");
support.put("text", "该设备不兼容MiniCap投屏!");
- sendText(session, support.toJSONString());
+ AgentTool.sendText(session, support.toJSONString());
}
}
diff --git a/src/main/java/com/sonic/agent/tests/ios/IOSPerfDataThread.java b/src/main/java/org/cloud/sonic/agent/tests/ios/IOSPerfDataThread.java
similarity index 78%
rename from src/main/java/com/sonic/agent/tests/ios/IOSPerfDataThread.java
rename to src/main/java/org/cloud/sonic/agent/tests/ios/IOSPerfDataThread.java
index b3993396..6bbe667b 100644
--- a/src/main/java/com/sonic/agent/tests/ios/IOSPerfDataThread.java
+++ b/src/main/java/org/cloud/sonic/agent/tests/ios/IOSPerfDataThread.java
@@ -1,8 +1,5 @@
-package com.sonic.agent.tests.ios;
+package org.cloud.sonic.agent.tests.ios;
-import com.sonic.agent.automation.AndroidStepHandler;
-import com.sonic.agent.tests.android.AndroidRunStepThread;
-import com.sonic.agent.tests.android.AndroidTestTaskBootThread;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
diff --git a/src/main/java/com/sonic/agent/tests/ios/IOSRecordThread.java b/src/main/java/org/cloud/sonic/agent/tests/ios/IOSRecordThread.java
similarity index 93%
rename from src/main/java/com/sonic/agent/tests/ios/IOSRecordThread.java
rename to src/main/java/org/cloud/sonic/agent/tests/ios/IOSRecordThread.java
index 2cbc640b..39fcb142 100644
--- a/src/main/java/com/sonic/agent/tests/ios/IOSRecordThread.java
+++ b/src/main/java/org/cloud/sonic/agent/tests/ios/IOSRecordThread.java
@@ -1,7 +1,6 @@
-package com.sonic.agent.tests.ios;
+package org.cloud.sonic.agent.tests.ios;
-import com.sonic.agent.automation.IOSStepHandler;
-import org.bytedeco.javacv.FrameRecorder;
+import org.cloud.sonic.agent.automation.IOSStepHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
diff --git a/src/main/java/com/sonic/agent/tests/ios/IOSRunStepThread.java b/src/main/java/org/cloud/sonic/agent/tests/ios/IOSRunStepThread.java
similarity index 86%
rename from src/main/java/com/sonic/agent/tests/ios/IOSRunStepThread.java
rename to src/main/java/org/cloud/sonic/agent/tests/ios/IOSRunStepThread.java
index 976563f1..4b84bdeb 100644
--- a/src/main/java/com/sonic/agent/tests/ios/IOSRunStepThread.java
+++ b/src/main/java/org/cloud/sonic/agent/tests/ios/IOSRunStepThread.java
@@ -1,9 +1,7 @@
-package com.sonic.agent.tests.ios;
+package org.cloud.sonic.agent.tests.ios;
import com.alibaba.fastjson.JSONObject;
-import com.sonic.agent.automation.AndroidStepHandler;
-import com.sonic.agent.automation.IOSStepHandler;
-import com.sonic.agent.tests.android.AndroidTestTaskBootThread;
+import org.cloud.sonic.agent.automation.IOSStepHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
diff --git a/src/main/java/com/sonic/agent/tests/ios/IOSTestTaskBootThread.java b/src/main/java/org/cloud/sonic/agent/tests/ios/IOSTestTaskBootThread.java
similarity index 94%
rename from src/main/java/com/sonic/agent/tests/ios/IOSTestTaskBootThread.java
rename to src/main/java/org/cloud/sonic/agent/tests/ios/IOSTestTaskBootThread.java
index 5861e17e..f6946b44 100644
--- a/src/main/java/com/sonic/agent/tests/ios/IOSTestTaskBootThread.java
+++ b/src/main/java/org/cloud/sonic/agent/tests/ios/IOSTestTaskBootThread.java
@@ -1,11 +1,11 @@
-package com.sonic.agent.tests.ios;
+package org.cloud.sonic.agent.tests.ios;
import com.alibaba.fastjson.JSONObject;
-import com.sonic.agent.automation.IOSStepHandler;
-import com.sonic.agent.bridge.ios.IOSDeviceLocalStatus;
-import com.sonic.agent.bridge.ios.TIDeviceTool;
-import com.sonic.agent.interfaces.ResultDetailStatus;
-import com.sonic.agent.tests.TaskManager;
+import org.cloud.sonic.agent.automation.IOSStepHandler;
+import org.cloud.sonic.agent.bridge.ios.IOSDeviceLocalStatus;
+import org.cloud.sonic.agent.bridge.ios.TIDeviceTool;
+import org.cloud.sonic.agent.interfaces.ResultDetailStatus;
+import org.cloud.sonic.agent.tests.TaskManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
diff --git a/src/main/java/com/sonic/agent/tools/AgentTool.java b/src/main/java/org/cloud/sonic/agent/tools/AgentTool.java
similarity index 95%
rename from src/main/java/com/sonic/agent/tools/AgentTool.java
rename to src/main/java/org/cloud/sonic/agent/tools/AgentTool.java
index bd158c88..b721b373 100644
--- a/src/main/java/com/sonic/agent/tools/AgentTool.java
+++ b/src/main/java/org/cloud/sonic/agent/tools/AgentTool.java
@@ -1,62 +1,62 @@
-package com.sonic.agent.tools;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import javax.websocket.Session;
-import java.io.IOException;
-import java.nio.ByteBuffer;
-
-/**
- * @author ZhouYiXun
- * @des 获取id
- * @date 2021/8/26 22:23
- */
-public class AgentTool {
- private static final Logger log = LoggerFactory.getLogger(AgentTool.class);
-
- public static int agentId = 0;
-
- public static byte[] subByteArray(byte[] byte1, int start, int end) {
- byte[] byte2;
- byte2 = new byte[end - start];
- System.arraycopy(byte1, start, byte2, 0, end - start);
- return byte2;
- }
-
- public static long bytesToLong(byte[] src, int offset) {
- long value;
- value = ((src[offset] & 0xFF) | ((src[offset + 1] & 0xFF) << 8) | ((src[offset + 2] & 0xFF) << 16)
- | ((src[offset + 3] & 0xFF) << 24));
- return value;
- }
-
- // java合并两个byte数组
- public static byte[] addBytes(byte[] data1, byte[] data2) {
- byte[] data3 = new byte[data1.length + data2.length];
- System.arraycopy(data1, 0, data3, 0, data1.length);
- System.arraycopy(data2, 0, data3, data1.length, data2.length);
- return data3;
- }
-
- public static void sendByte(Session session, byte[] message) {
- synchronized (session) {
- try {
- session.getBasicRemote().sendBinary(ByteBuffer.wrap(message));
- } catch (IllegalStateException | IOException e) {
- log.error("WebSocket发送失败!连接已关闭!");
- }
- }
- }
-
- public static void sendText(Session session, String message) {
- synchronized (session) {
- try {
- session.getBasicRemote().sendText(message);
- } catch (IllegalStateException | IOException e) {
- log.error("WebSocket发送失败!连接已关闭!");
- }
- }
- }
-
-}
+package org.cloud.sonic.agent.tools;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.websocket.Session;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+/**
+ * @author ZhouYiXun
+ * @des 获取id
+ * @date 2021/8/26 22:23
+ */
+public class AgentTool {
+ private static final Logger log = LoggerFactory.getLogger(AgentTool.class);
+
+ public static int agentId = 0;
+
+ public static byte[] subByteArray(byte[] byte1, int start, int end) {
+ byte[] byte2;
+ byte2 = new byte[end - start];
+ System.arraycopy(byte1, start, byte2, 0, end - start);
+ return byte2;
+ }
+
+ public static long bytesToLong(byte[] src, int offset) {
+ long value;
+ value = ((src[offset] & 0xFF) | ((src[offset + 1] & 0xFF) << 8) | ((src[offset + 2] & 0xFF) << 16)
+ | ((src[offset + 3] & 0xFF) << 24));
+ return value;
+ }
+
+ // java合并两个byte数组
+ public static byte[] addBytes(byte[] data1, byte[] data2) {
+ byte[] data3 = new byte[data1.length + data2.length];
+ System.arraycopy(data1, 0, data3, 0, data1.length);
+ System.arraycopy(data2, 0, data3, data1.length, data2.length);
+ return data3;
+ }
+
+ public static void sendByte(Session session, byte[] message) {
+ synchronized (session) {
+ try {
+ session.getBasicRemote().sendBinary(ByteBuffer.wrap(message));
+ } catch (IllegalStateException | IOException e) {
+ log.error("WebSocket发送失败!连接已关闭!");
+ }
+ }
+ }
+
+ public static void sendText(Session session, String message) {
+ synchronized (session) {
+ try {
+ session.getBasicRemote().sendText(message);
+ } catch (IllegalStateException | IOException e) {
+ log.error("WebSocket发送失败!连接已关闭!");
+ }
+ }
+ }
+
+}
diff --git a/src/main/java/com/sonic/agent/tools/DownImageTool.java b/src/main/java/org/cloud/sonic/agent/tools/DownImageTool.java
similarity index 94%
rename from src/main/java/com/sonic/agent/tools/DownImageTool.java
rename to src/main/java/org/cloud/sonic/agent/tools/DownImageTool.java
index 80689c8b..e031240f 100644
--- a/src/main/java/com/sonic/agent/tools/DownImageTool.java
+++ b/src/main/java/org/cloud/sonic/agent/tools/DownImageTool.java
@@ -1,49 +1,49 @@
-package com.sonic.agent.tools;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URL;
-import java.net.URLConnection;
-import java.util.Calendar;
-
-public class DownImageTool {
- public static File download(String urlString) throws IOException {
- URL url = new URL(urlString);
- URLConnection con = url.openConnection();
- InputStream is = con.getInputStream();
- byte[] bs = new byte[1024];
- int len;
-
- long time = Calendar.getInstance().getTimeInMillis();
- String tail = "";
- if (urlString.lastIndexOf(".") != -1) {
- tail = urlString.substring(urlString.lastIndexOf(".") + 1);
- }
- String filename = "test-output" + File.separator + "download-" + time + "." + tail;
- File file = new File(filename);
- FileOutputStream os = null;
- try {
- os = new FileOutputStream(file, true);
- while ((len = is.read(bs)) != -1) {
- os.write(bs, 0, len);
- }
- } catch (Exception e) {
- e.printStackTrace();
- throw e;
- } finally {
- try {
- os.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- try {
- is.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- return file;
- }
-}
+package org.cloud.sonic.agent.tools;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.Calendar;
+
+public class DownImageTool {
+ public static File download(String urlString) throws IOException {
+ URL url = new URL(urlString);
+ URLConnection con = url.openConnection();
+ InputStream is = con.getInputStream();
+ byte[] bs = new byte[1024];
+ int len;
+
+ long time = Calendar.getInstance().getTimeInMillis();
+ String tail = "";
+ if (urlString.lastIndexOf(".") != -1) {
+ tail = urlString.substring(urlString.lastIndexOf(".") + 1);
+ }
+ String filename = "test-output" + File.separator + "download-" + time + "." + tail;
+ File file = new File(filename);
+ FileOutputStream os = null;
+ try {
+ os = new FileOutputStream(file, true);
+ while ((len = is.read(bs)) != -1) {
+ os.write(bs, 0, len);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw e;
+ } finally {
+ try {
+ os.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ try {
+ is.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ return file;
+ }
+}
diff --git a/src/main/java/com/sonic/agent/tools/EnvCheckTool.java b/src/main/java/org/cloud/sonic/agent/tools/EnvCheckTool.java
similarity index 99%
rename from src/main/java/com/sonic/agent/tools/EnvCheckTool.java
rename to src/main/java/org/cloud/sonic/agent/tools/EnvCheckTool.java
index 83b1665e..6f9391b9 100644
--- a/src/main/java/com/sonic/agent/tools/EnvCheckTool.java
+++ b/src/main/java/org/cloud/sonic/agent/tools/EnvCheckTool.java
@@ -1,4 +1,4 @@
-package com.sonic.agent.tools;
+package org.cloud.sonic.agent.tools;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ConfigurableApplicationContext;
diff --git a/src/main/java/com/sonic/agent/tools/LaunchTool.java b/src/main/java/org/cloud/sonic/agent/tools/LaunchTool.java
similarity index 85%
rename from src/main/java/com/sonic/agent/tools/LaunchTool.java
rename to src/main/java/org/cloud/sonic/agent/tools/LaunchTool.java
index 35531291..81635b2b 100644
--- a/src/main/java/com/sonic/agent/tools/LaunchTool.java
+++ b/src/main/java/org/cloud/sonic/agent/tools/LaunchTool.java
@@ -1,47 +1,47 @@
-package com.sonic.agent.tools;
-
-import com.sonic.agent.automation.AppiumServer;
-import com.sonic.agent.automation.RemoteDebugDriver;
-import com.sonic.agent.maps.GlobalProcessMap;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.boot.ApplicationArguments;
-import org.springframework.boot.ApplicationRunner;
-import org.springframework.context.annotation.DependsOn;
-import org.springframework.stereotype.Component;
-
-import javax.annotation.PreDestroy;
-import java.io.File;
-
-@Component
-@DependsOn("nettyMsgInit")
-public class LaunchTool implements ApplicationRunner {
- private final Logger logger = LoggerFactory.getLogger(LaunchTool.class);
-
- @Override
- public void run(ApplicationArguments args) {
- File testFile = new File("test-output");
- if (!testFile.exists()) {
- testFile.mkdirs();
- }
- AppiumServer.start();
- }
-
- @PreDestroy
- public void destroy() throws InterruptedException {
- RemoteDebugDriver.close();
- for (String key : GlobalProcessMap.getMap().keySet()) {
- Process ps = GlobalProcessMap.getMap().get(key);
- ps.children().forEach(ProcessHandle::destroy);
- ps.destroy();
- }
- AppiumServer.close();
- while (AppiumServer.service != null) {
- if (!AppiumServer.service.isRunning()) {
- break;
- } else {
- Thread.sleep(1000);
- }
- }
- }
-}
+package org.cloud.sonic.agent.tools;
+
+import org.cloud.sonic.agent.automation.AppiumServer;
+import org.cloud.sonic.agent.automation.RemoteDebugDriver;
+import org.cloud.sonic.agent.maps.GlobalProcessMap;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.boot.ApplicationArguments;
+import org.springframework.boot.ApplicationRunner;
+import org.springframework.context.annotation.DependsOn;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.PreDestroy;
+import java.io.File;
+
+@Component
+@DependsOn("nettyMsgInit")
+public class LaunchTool implements ApplicationRunner {
+ private final Logger logger = LoggerFactory.getLogger(LaunchTool.class);
+
+ @Override
+ public void run(ApplicationArguments args) {
+ File testFile = new File("test-output");
+ if (!testFile.exists()) {
+ testFile.mkdirs();
+ }
+ AppiumServer.start();
+ }
+
+ @PreDestroy
+ public void destroy() throws InterruptedException {
+ RemoteDebugDriver.close();
+ for (String key : GlobalProcessMap.getMap().keySet()) {
+ Process ps = GlobalProcessMap.getMap().get(key);
+ ps.children().forEach(ProcessHandle::destroy);
+ ps.destroy();
+ }
+ AppiumServer.close();
+ while (AppiumServer.service != null) {
+ if (!AppiumServer.service.isRunning()) {
+ break;
+ } else {
+ Thread.sleep(1000);
+ }
+ }
+ }
+}
diff --git a/src/main/java/com/sonic/agent/tools/LogTool.java b/src/main/java/org/cloud/sonic/agent/tools/LogTool.java
similarity index 93%
rename from src/main/java/com/sonic/agent/tools/LogTool.java
rename to src/main/java/org/cloud/sonic/agent/tools/LogTool.java
index 577f58f1..c9a3be13 100644
--- a/src/main/java/com/sonic/agent/tools/LogTool.java
+++ b/src/main/java/org/cloud/sonic/agent/tools/LogTool.java
@@ -1,217 +1,217 @@
-package com.sonic.agent.tools;
-
-import com.alibaba.fastjson.JSONObject;
-import com.sonic.agent.interfaces.DeviceStatus;
-import com.sonic.agent.interfaces.StepType;
-import com.sonic.agent.maps.WebSocketSessionMap;
-import com.sonic.agent.netty.NettyThreadPool;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import javax.websocket.Session;
-import java.io.IOException;
-import java.text.SimpleDateFormat;
-import java.util.Date;
-
-/**
- * @author ZhouYiXun
- * @des log工具类,会发送到服务端入库
- * @date 2021/8/16 19:54
- */
-public class LogTool {
- private final Logger logger = LoggerFactory.getLogger(LogTool.class);
- public String sessionId = "";
- public String type;
- public int caseId = 0;
- public int resultId = 0;
- public String udId = "";
-
- /**
- * @param message
- * @return void
- * @author ZhouYiXun
- * @des 判断发送到哪个地方
- * @date 2021/8/16 19:57
- */
- public void send(JSONObject message) {
- //先加上消息附带信息
- message.put("cid", caseId);
- message.put("rid", resultId);
- message.put("udId", udId);
- if (type.equals(DeviceStatus.DEBUGGING)) {
- sendToWebSocket(WebSocketSessionMap.getSession(sessionId), message);
- }
- if (type.equals(DeviceStatus.TESTING)) {
- sendToServer(message);
- }
- logger.info(message.toJSONString());
- }
-
- /**
- * @param message
- * @return void
- * @author ZhouYiXun
- * @des 发送到服务端
- * @date 2021/8/16 19:57
- */
- private void sendToServer(JSONObject message) {
- message.put("time", new Date());
- NettyThreadPool.send(message);
- }
-
- /**
- * @param session
- * @param message
- * @return void
- * @author ZhouYiXun
- * @des 通过session发送给前端
- * @date 2021/8/16 19:57
- */
- private void sendToWebSocket(Session session, JSONObject message) {
- synchronized (session) {
- try {
- message.put("time", getDateToString());
- session.getBasicRemote().sendText(message.toJSONString());
- } catch (IllegalStateException | IOException e) {
- logger.error(e.getMessage());
- }
- }
- }
-
- /**
- * @return java.lang.String
- * @author ZhouYiXun
- * @des format一下时间
- * @date 2021/8/16 19:58
- */
- public String getDateToString() {
- SimpleDateFormat sf = new SimpleDateFormat("HH:mm:ss");
- return sf.format(new Date());
- }
-
- /**
- * @param totalTime
- * @param platform
- * @param version
- * @return void
- * @author ZhouYiXun
- * @des 发送运行时长
- * @date 2021/8/16 19:58
- */
- public void sendElapsed(int totalTime, int platform, String version) {
- JSONObject log = new JSONObject();
- log.put("msg", "elapsed");
- log.put("pf", platform);
- log.put("ver", version);
- log.put("run", totalTime);
- send(log);
- }
-
- /**
- * @param status
- * @param des
- * @param detail
- * @return void
- * @author ZhouYiXun
- * @des 发送普通步骤log
- * @date 2021/8/16 19:58
- */
- public void sendStepLog(int status, String des, String detail) {
- JSONObject log = new JSONObject();
- log.put("msg", "step");
- log.put("des", des);
- log.put("status", status);
- log.put("log", detail);
- send(log);
- }
-
- /**
- * @param type
- * @param detail
- * @return void
- * @author ZhouYiXun
- * @des 发送性能数据
- * @date 2021/8/16 19:58
- */
- public void sendPerLog(String packageName, int type, JSONObject detail) {
- JSONObject log = new JSONObject();
- log.put("msg", "perform");
- log.put("des", packageName);
- log.put("log", detail.toJSONString());
- log.put("status", type);
- send(log);
- }
-
- /**
- * @param isSupport 是否支持录像
- * @param url
- * @return void
- * @author ZhouYiXun
- * @des 发送录像数据
- * @date 2021/8/16 19:58
- */
- public void sendRecordLog(boolean isSupport, String fileName, String url) {
- JSONObject log = new JSONObject();
- log.put("msg", "record");
- log.put("status", isSupport ? 1 : 0);
- log.put("des", fileName);
- log.put("log", url);
- send(log);
- }
-
- /**
- * @param url
- * @return void
- * @author ZhouYiXun
- * @des 发送日志数据
- * @date 2021/8/26 19:58
- */
-// public void sendSelfLog(String fileName, String url) {
-// JSONObject log = new JSONObject();
-// log.put("msg", "log");
-// log.put("name", fileName);
-// log.put("url", url);
-// send(log);
-// }
-
- /**
- * @param status
- * @return void
- * @author ZhouYiXun
- * @des 发送测试状态
- * @date 2021/8/16 19:58
- */
- public void sendStatusLog(int status) {
- JSONObject log = new JSONObject();
- log.put("msg", "status");
- log.put("des", "");
- log.put("log", "");
- log.put("status", status);
- send(log);
- }
-
- /**
- * @param platform
- * @param version
- * @param udId
- * @param manufacturer
- * @param model
- * @param api
- * @param size
- * @return void
- * @author ZhouYiXun
- * @des 发送安卓Info
- * @date 2021/8/16 19:59
- */
- public void androidInfo(String platform, String version, String udId, String manufacturer, String model, String api, String size) {
- sendStepLog(StepType.INFO, "",
- "设备操作系统:" + platform
- + "
操作系统版本:" + version
- + "
设备序列号:" + udId
- + "
设备制造商:" + manufacturer
- + "
设备型号:" + model
- + "
安卓API等级:" + api
- + "
设备分辨率:" + size
- );
- }
+package org.cloud.sonic.agent.tools;
+
+import com.alibaba.fastjson.JSONObject;
+import org.cloud.sonic.agent.interfaces.DeviceStatus;
+import org.cloud.sonic.agent.interfaces.StepType;
+import org.cloud.sonic.agent.maps.WebSocketSessionMap;
+import org.cloud.sonic.agent.netty.NettyThreadPool;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.websocket.Session;
+import java.io.IOException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+/**
+ * @author ZhouYiXun
+ * @des log工具类,会发送到服务端入库
+ * @date 2021/8/16 19:54
+ */
+public class LogTool {
+ private final Logger logger = LoggerFactory.getLogger(LogTool.class);
+ public String sessionId = "";
+ public String type;
+ public int caseId = 0;
+ public int resultId = 0;
+ public String udId = "";
+
+ /**
+ * @param message
+ * @return void
+ * @author ZhouYiXun
+ * @des 判断发送到哪个地方
+ * @date 2021/8/16 19:57
+ */
+ public void send(JSONObject message) {
+ //先加上消息附带信息
+ message.put("cid", caseId);
+ message.put("rid", resultId);
+ message.put("udId", udId);
+ if (type.equals(DeviceStatus.DEBUGGING)) {
+ sendToWebSocket(WebSocketSessionMap.getSession(sessionId), message);
+ }
+ if (type.equals(DeviceStatus.TESTING)) {
+ sendToServer(message);
+ }
+ logger.info(message.toJSONString());
+ }
+
+ /**
+ * @param message
+ * @return void
+ * @author ZhouYiXun
+ * @des 发送到服务端
+ * @date 2021/8/16 19:57
+ */
+ private void sendToServer(JSONObject message) {
+ message.put("time", new Date());
+ NettyThreadPool.send(message);
+ }
+
+ /**
+ * @param session
+ * @param message
+ * @return void
+ * @author ZhouYiXun
+ * @des 通过session发送给前端
+ * @date 2021/8/16 19:57
+ */
+ private void sendToWebSocket(Session session, JSONObject message) {
+ synchronized (session) {
+ try {
+ message.put("time", getDateToString());
+ session.getBasicRemote().sendText(message.toJSONString());
+ } catch (IllegalStateException | IOException e) {
+ logger.error(e.getMessage());
+ }
+ }
+ }
+
+ /**
+ * @return java.lang.String
+ * @author ZhouYiXun
+ * @des format一下时间
+ * @date 2021/8/16 19:58
+ */
+ public String getDateToString() {
+ SimpleDateFormat sf = new SimpleDateFormat("HH:mm:ss");
+ return sf.format(new Date());
+ }
+
+ /**
+ * @param totalTime
+ * @param platform
+ * @param version
+ * @return void
+ * @author ZhouYiXun
+ * @des 发送运行时长
+ * @date 2021/8/16 19:58
+ */
+ public void sendElapsed(int totalTime, int platform, String version) {
+ JSONObject log = new JSONObject();
+ log.put("msg", "elapsed");
+ log.put("pf", platform);
+ log.put("ver", version);
+ log.put("run", totalTime);
+ send(log);
+ }
+
+ /**
+ * @param status
+ * @param des
+ * @param detail
+ * @return void
+ * @author ZhouYiXun
+ * @des 发送普通步骤log
+ * @date 2021/8/16 19:58
+ */
+ public void sendStepLog(int status, String des, String detail) {
+ JSONObject log = new JSONObject();
+ log.put("msg", "step");
+ log.put("des", des);
+ log.put("status", status);
+ log.put("log", detail);
+ send(log);
+ }
+
+ /**
+ * @param type
+ * @param detail
+ * @return void
+ * @author ZhouYiXun
+ * @des 发送性能数据
+ * @date 2021/8/16 19:58
+ */
+ public void sendPerLog(String packageName, int type, JSONObject detail) {
+ JSONObject log = new JSONObject();
+ log.put("msg", "perform");
+ log.put("des", packageName);
+ log.put("log", detail.toJSONString());
+ log.put("status", type);
+ send(log);
+ }
+
+ /**
+ * @param isSupport 是否支持录像
+ * @param url
+ * @return void
+ * @author ZhouYiXun
+ * @des 发送录像数据
+ * @date 2021/8/16 19:58
+ */
+ public void sendRecordLog(boolean isSupport, String fileName, String url) {
+ JSONObject log = new JSONObject();
+ log.put("msg", "record");
+ log.put("status", isSupport ? 1 : 0);
+ log.put("des", fileName);
+ log.put("log", url);
+ send(log);
+ }
+
+ /**
+ * @param url
+ * @return void
+ * @author ZhouYiXun
+ * @des 发送日志数据
+ * @date 2021/8/26 19:58
+ */
+// public void sendSelfLog(String fileName, String url) {
+// JSONObject log = new JSONObject();
+// log.put("msg", "log");
+// log.put("name", fileName);
+// log.put("url", url);
+// send(log);
+// }
+
+ /**
+ * @param status
+ * @return void
+ * @author ZhouYiXun
+ * @des 发送测试状态
+ * @date 2021/8/16 19:58
+ */
+ public void sendStatusLog(int status) {
+ JSONObject log = new JSONObject();
+ log.put("msg", "status");
+ log.put("des", "");
+ log.put("log", "");
+ log.put("status", status);
+ send(log);
+ }
+
+ /**
+ * @param platform
+ * @param version
+ * @param udId
+ * @param manufacturer
+ * @param model
+ * @param api
+ * @param size
+ * @return void
+ * @author ZhouYiXun
+ * @des 发送安卓Info
+ * @date 2021/8/16 19:59
+ */
+ public void androidInfo(String platform, String version, String udId, String manufacturer, String model, String api, String size) {
+ sendStepLog(StepType.INFO, "",
+ "设备操作系统:" + platform
+ + "
操作系统版本:" + version
+ + "
设备序列号:" + udId
+ + "
设备制造商:" + manufacturer
+ + "
设备型号:" + model
+ + "
安卓API等级:" + api
+ + "
设备分辨率:" + size
+ );
+ }
}
\ No newline at end of file
diff --git a/src/main/java/com/sonic/agent/tools/MiniCapTool.java b/src/main/java/org/cloud/sonic/agent/tools/MiniCapTool.java
similarity index 82%
rename from src/main/java/com/sonic/agent/tools/MiniCapTool.java
rename to src/main/java/org/cloud/sonic/agent/tools/MiniCapTool.java
index 26e8ae8e..899caf65 100644
--- a/src/main/java/com/sonic/agent/tools/MiniCapTool.java
+++ b/src/main/java/org/cloud/sonic/agent/tools/MiniCapTool.java
@@ -1,91 +1,91 @@
-package com.sonic.agent.tools;
-
-import com.android.ddmlib.IDevice;
-import com.sonic.agent.bridge.android.AndroidDeviceBridgeTool;
-import com.sonic.agent.tests.TaskManager;
-import com.sonic.agent.tests.android.AndroidTestTaskBootThread;
-import com.sonic.agent.tests.android.InputSocketThread;
-import com.sonic.agent.tests.android.OutputSocketThread;
-import com.sonic.agent.tests.android.SonicLocalThread;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import javax.websocket.Session;
-import java.util.List;
-import java.util.concurrent.LinkedBlockingQueue;
-import java.util.concurrent.atomic.AtomicReference;
-
-import static com.sonic.agent.tests.android.AndroidTestTaskBootThread.ANDROID_TEST_TASK_BOOT_PRE;
-
-/**
- * @author ZhouYiXun
- * @des
- * @date 2021/8/26 9:20
- */
-public class MiniCapTool {
- private final Logger logger = LoggerFactory.getLogger(MiniCapTool.class);
-
- public Thread start(
- String udId,
- AtomicReference banner,
- AtomicReference> imgList,
- String pic,
- int tor,
- Session session
- ) {
- // 这里的AndroidTestTaskBootThread仅作为data bean使用,不会启动
- return start(udId, banner, imgList, pic, tor, session, new AndroidTestTaskBootThread().setUdId(udId));
- }
-
-
- public Thread start(
- String udId,
- AtomicReference banner,
- AtomicReference> imgList,
- String pic,
- int tor,
- Session session,
- AndroidTestTaskBootThread androidTestTaskBootThread
- ) {
- IDevice iDevice = AndroidDeviceBridgeTool.getIDeviceByUdId(udId);
- String key = androidTestTaskBootThread.formatThreadName(ANDROID_TEST_TASK_BOOT_PRE);
- int s;
- if (tor == -1) {
- s = AndroidDeviceBridgeTool.getScreen(AndroidDeviceBridgeTool.getIDeviceByUdId(udId));
- } else {
- s = tor;
- }
- // 启动minicap服务
- SonicLocalThread miniCapPro = new SonicLocalThread(iDevice, pic, s * 90, session, androidTestTaskBootThread);
- TaskManager.startChildThread(key, miniCapPro);
-
- // 等待启动
- int wait = 0;
- while (!miniCapPro.getIsFinish().tryAcquire()) {
- wait++;
- try {
- Thread.sleep(500);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- // 启动失败了,强行跳过,保证其它服务可用
- if (wait > 8) {
- break;
- }
- }
-
- // 启动输入流
- InputSocketThread sendImg = new InputSocketThread(
- iDevice, new LinkedBlockingQueue<>(), miniCapPro, session
- );
- // 启动输出流
- OutputSocketThread outputSocketThread = new OutputSocketThread(
- sendImg, banner, imgList, session, pic
- );
-
- TaskManager.startChildThread(key, sendImg, outputSocketThread);
-
- return miniCapPro; // server线程
- }
-
-}
+package org.cloud.sonic.agent.tools;
+
+import com.android.ddmlib.IDevice;
+import org.cloud.sonic.agent.bridge.android.AndroidDeviceBridgeTool;
+import org.cloud.sonic.agent.tests.TaskManager;
+import org.cloud.sonic.agent.tests.android.AndroidTestTaskBootThread;
+import org.cloud.sonic.agent.tests.android.InputSocketThread;
+import org.cloud.sonic.agent.tests.android.OutputSocketThread;
+import org.cloud.sonic.agent.tests.android.SonicLocalThread;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.websocket.Session;
+import java.util.List;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.atomic.AtomicReference;
+
+import static org.cloud.sonic.agent.tests.android.AndroidTestTaskBootThread.ANDROID_TEST_TASK_BOOT_PRE;
+
+/**
+ * @author ZhouYiXun
+ * @des
+ * @date 2021/8/26 9:20
+ */
+public class MiniCapTool {
+ private final Logger logger = LoggerFactory.getLogger(MiniCapTool.class);
+
+ public Thread start(
+ String udId,
+ AtomicReference banner,
+ AtomicReference> imgList,
+ String pic,
+ int tor,
+ Session session
+ ) {
+ // 这里的AndroidTestTaskBootThread仅作为data bean使用,不会启动
+ return start(udId, banner, imgList, pic, tor, session, new AndroidTestTaskBootThread().setUdId(udId));
+ }
+
+
+ public Thread start(
+ String udId,
+ AtomicReference banner,
+ AtomicReference> imgList,
+ String pic,
+ int tor,
+ Session session,
+ AndroidTestTaskBootThread androidTestTaskBootThread
+ ) {
+ IDevice iDevice = AndroidDeviceBridgeTool.getIDeviceByUdId(udId);
+ String key = androidTestTaskBootThread.formatThreadName(ANDROID_TEST_TASK_BOOT_PRE);
+ int s;
+ if (tor == -1) {
+ s = AndroidDeviceBridgeTool.getScreen(AndroidDeviceBridgeTool.getIDeviceByUdId(udId));
+ } else {
+ s = tor;
+ }
+ // 启动minicap服务
+ SonicLocalThread miniCapPro = new SonicLocalThread(iDevice, pic, s * 90, session, androidTestTaskBootThread);
+ TaskManager.startChildThread(key, miniCapPro);
+
+ // 等待启动
+ int wait = 0;
+ while (!miniCapPro.getIsFinish().tryAcquire()) {
+ wait++;
+ try {
+ Thread.sleep(500);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ // 启动失败了,强行跳过,保证其它服务可用
+ if (wait > 8) {
+ break;
+ }
+ }
+
+ // 启动输入流
+ InputSocketThread sendImg = new InputSocketThread(
+ iDevice, new LinkedBlockingQueue<>(), miniCapPro, session
+ );
+ // 启动输出流
+ OutputSocketThread outputSocketThread = new OutputSocketThread(
+ sendImg, banner, imgList, session, pic
+ );
+
+ TaskManager.startChildThread(key, sendImg, outputSocketThread);
+
+ return miniCapPro; // server线程
+ }
+
+}
diff --git a/src/main/java/com/sonic/agent/tools/PortTool.java b/src/main/java/org/cloud/sonic/agent/tools/PortTool.java
similarity index 89%
rename from src/main/java/com/sonic/agent/tools/PortTool.java
rename to src/main/java/org/cloud/sonic/agent/tools/PortTool.java
index f4b536e3..77f08b10 100644
--- a/src/main/java/com/sonic/agent/tools/PortTool.java
+++ b/src/main/java/org/cloud/sonic/agent/tools/PortTool.java
@@ -1,19 +1,19 @@
-package com.sonic.agent.tools;
-
-import java.io.IOException;
-import java.net.ServerSocket;
-
-public class PortTool {
- public static Integer getPort() {
- ServerSocket serverSocket;
- int port = 0;
- try {
- serverSocket = new ServerSocket(0);
- port = serverSocket.getLocalPort();
- serverSocket.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- return port;
- }
+package org.cloud.sonic.agent.tools;
+
+import java.io.IOException;
+import java.net.ServerSocket;
+
+public class PortTool {
+ public static Integer getPort() {
+ ServerSocket serverSocket;
+ int port = 0;
+ try {
+ serverSocket = new ServerSocket(0);
+ port = serverSocket.getLocalPort();
+ serverSocket.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return port;
+ }
}
\ No newline at end of file
diff --git a/src/main/java/com/sonic/agent/tools/ProcessCommandTool.java b/src/main/java/org/cloud/sonic/agent/tools/ProcessCommandTool.java
similarity index 96%
rename from src/main/java/com/sonic/agent/tools/ProcessCommandTool.java
rename to src/main/java/org/cloud/sonic/agent/tools/ProcessCommandTool.java
index c39ae265..c36f5814 100644
--- a/src/main/java/com/sonic/agent/tools/ProcessCommandTool.java
+++ b/src/main/java/org/cloud/sonic/agent/tools/ProcessCommandTool.java
@@ -1,63 +1,63 @@
-package com.sonic.agent.tools;
-
-import java.io.InputStreamReader;
-import java.io.LineNumberReader;
-import java.util.ArrayList;
-import java.util.List;
-
-public class ProcessCommandTool {
- public static List getProcessLocalCommand(String commandLine) {
- Process process = null;
- InputStreamReader inputStreamReader = null;
- InputStreamReader errorStreamReader;
- LineNumberReader consoleInput = null;
- LineNumberReader consoleError = null;
- String consoleInputLine;
- String consoleErrorLine;
- List sdrResult = new ArrayList();
- List sdrErrorResult = new ArrayList();
- try {
- String system = System.getProperty("os.name").toLowerCase();
- if (system.contains("win")) {
- process = Runtime.getRuntime().exec(new String[]{"cmd", "/c", commandLine});
- } else {
- process = Runtime.getRuntime().exec(new String[]{"sh", "-c", commandLine});
- }
- inputStreamReader = new InputStreamReader(process.getInputStream());
- consoleInput = new LineNumberReader(inputStreamReader);
- while ((consoleInputLine = consoleInput.readLine()) != null) {
- sdrResult.add(consoleInputLine);
- }
- errorStreamReader = new InputStreamReader(process.getErrorStream());
- consoleError = new LineNumberReader(errorStreamReader);
- while ((consoleErrorLine = consoleError.readLine()) != null) {
- sdrErrorResult.add(consoleErrorLine);
- }
-
- int resultCode = process.waitFor();
- if (resultCode > 0 && sdrErrorResult.size() > 0) {
- return sdrErrorResult;
- } else {
- return sdrResult;
- }
- } catch (Exception e) {
- return new ArrayList();
- } finally {
- try {
- if (null != consoleInput) {
- consoleInput.close();
- }
- if (null != consoleError) {
- consoleError.close();
- }
- if (null != inputStreamReader) {
- inputStreamReader.close();
- }
- if (null != process) {
- process.destroy();
- }
- } catch (Exception e) {
- }
- }
- }
-}
+package org.cloud.sonic.agent.tools;
+
+import java.io.InputStreamReader;
+import java.io.LineNumberReader;
+import java.util.ArrayList;
+import java.util.List;
+
+public class ProcessCommandTool {
+ public static List getProcessLocalCommand(String commandLine) {
+ Process process = null;
+ InputStreamReader inputStreamReader = null;
+ InputStreamReader errorStreamReader;
+ LineNumberReader consoleInput = null;
+ LineNumberReader consoleError = null;
+ String consoleInputLine;
+ String consoleErrorLine;
+ List sdrResult = new ArrayList();
+ List sdrErrorResult = new ArrayList();
+ try {
+ String system = System.getProperty("os.name").toLowerCase();
+ if (system.contains("win")) {
+ process = Runtime.getRuntime().exec(new String[]{"cmd", "/c", commandLine});
+ } else {
+ process = Runtime.getRuntime().exec(new String[]{"sh", "-c", commandLine});
+ }
+ inputStreamReader = new InputStreamReader(process.getInputStream());
+ consoleInput = new LineNumberReader(inputStreamReader);
+ while ((consoleInputLine = consoleInput.readLine()) != null) {
+ sdrResult.add(consoleInputLine);
+ }
+ errorStreamReader = new InputStreamReader(process.getErrorStream());
+ consoleError = new LineNumberReader(errorStreamReader);
+ while ((consoleErrorLine = consoleError.readLine()) != null) {
+ sdrErrorResult.add(consoleErrorLine);
+ }
+
+ int resultCode = process.waitFor();
+ if (resultCode > 0 && sdrErrorResult.size() > 0) {
+ return sdrErrorResult;
+ } else {
+ return sdrResult;
+ }
+ } catch (Exception e) {
+ return new ArrayList();
+ } finally {
+ try {
+ if (null != consoleInput) {
+ consoleInput.close();
+ }
+ if (null != consoleError) {
+ consoleError.close();
+ }
+ if (null != inputStreamReader) {
+ inputStreamReader.close();
+ }
+ if (null != process) {
+ process.destroy();
+ }
+ } catch (Exception e) {
+ }
+ }
+ }
+}
diff --git a/src/main/java/com/sonic/agent/tools/RecordHandler.java b/src/main/java/org/cloud/sonic/agent/tools/RecordHandler.java
similarity index 95%
rename from src/main/java/com/sonic/agent/tools/RecordHandler.java
rename to src/main/java/org/cloud/sonic/agent/tools/RecordHandler.java
index a827d2c7..d89c5c16 100644
--- a/src/main/java/com/sonic/agent/tools/RecordHandler.java
+++ b/src/main/java/org/cloud/sonic/agent/tools/RecordHandler.java
@@ -1,6 +1,5 @@
-package com.sonic.agent.tools;
+package org.cloud.sonic.agent.tools;
-import com.sonic.agent.tools.UploadTools;
import org.bytedeco.ffmpeg.global.avcodec;
import org.bytedeco.ffmpeg.global.avutil;
import org.bytedeco.javacv.FFmpegFrameRecorder;
diff --git a/src/main/java/com/sonic/agent/tools/ScrcpyTool.java b/src/main/java/org/cloud/sonic/agent/tools/ScrcpyTool.java
similarity index 98%
rename from src/main/java/com/sonic/agent/tools/ScrcpyTool.java
rename to src/main/java/org/cloud/sonic/agent/tools/ScrcpyTool.java
index 84b07da5..844e966f 100644
--- a/src/main/java/com/sonic/agent/tools/ScrcpyTool.java
+++ b/src/main/java/org/cloud/sonic/agent/tools/ScrcpyTool.java
@@ -1,4 +1,4 @@
-package com.sonic.agent.tools;
+package org.cloud.sonic.agent.tools;
import java.io.IOException;
import java.io.InputStream;
diff --git a/src/main/java/com/sonic/agent/tools/SpringTool.java b/src/main/java/org/cloud/sonic/agent/tools/SpringTool.java
similarity index 95%
rename from src/main/java/com/sonic/agent/tools/SpringTool.java
rename to src/main/java/org/cloud/sonic/agent/tools/SpringTool.java
index 9b0a44fe..43f8d8c4 100644
--- a/src/main/java/com/sonic/agent/tools/SpringTool.java
+++ b/src/main/java/org/cloud/sonic/agent/tools/SpringTool.java
@@ -1,4 +1,4 @@
-package com.sonic.agent.tools;
+package org.cloud.sonic.agent.tools;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
diff --git a/src/main/java/com/sonic/agent/tools/UploadTools.java b/src/main/java/org/cloud/sonic/agent/tools/UploadTools.java
similarity index 96%
rename from src/main/java/com/sonic/agent/tools/UploadTools.java
rename to src/main/java/org/cloud/sonic/agent/tools/UploadTools.java
index 38f63360..6a5ebccc 100644
--- a/src/main/java/com/sonic/agent/tools/UploadTools.java
+++ b/src/main/java/org/cloud/sonic/agent/tools/UploadTools.java
@@ -1,147 +1,145 @@
-package com.sonic.agent.tools;
-
-import com.alibaba.fastjson.JSONObject;
-import net.coobird.thumbnailator.Thumbnails;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.core.io.FileSystemResource;
-import org.springframework.http.ResponseEntity;
-import org.springframework.stereotype.Component;
-import org.springframework.util.LinkedMultiValueMap;
-import org.springframework.util.MultiValueMap;
-import org.springframework.web.client.RestTemplate;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.RandomAccessFile;
-import java.util.ArrayList;
-import java.util.Calendar;
-import java.util.List;
-import java.util.UUID;
-
-/**
- * @author ZhouYiXun
- * @des 所有上传方法在这里
- * @date 2021/8/17 23:38
- */
-@Component
-public class UploadTools {
- private final static Logger logger = LoggerFactory.getLogger(UploadTools.class);
- @Value("${sonic.server.host}")
- private String host;
- @Value("${sonic.server.folder-port}")
- private String port;
- private static String baseUrl;
-
- private static RestTemplate restTemplate;
-
- @Autowired
- public void setRestTemplate(RestTemplate restTemplate) {
- UploadTools.restTemplate = restTemplate;
- baseUrl = "http://" + host + ":" + port + "/api/folder";
- }
-
- public static String upload(File uploadFile, String type) {
- File folder = new File("test-output");
- if (!folder.exists()) {//判断文件目录是否存在
- folder.mkdirs();
- }
- File transfer;
- if (type.equals("keepFiles") || type.equals("imageFiles")) {
- long timeMillis = Calendar.getInstance().getTimeInMillis();
- try {
- Thumbnails.of(uploadFile)
- .scale(1f)
- .outputQuality(0.25f).toFile(folder + File.separator + timeMillis + "transfer.jpg");
- } catch (IOException e) {
- logger.error(e.getMessage());
- }
- transfer = new File(folder + File.separator + timeMillis + "transfer.jpg");
- } else {
- transfer = uploadFile;
- }
- FileSystemResource resource = new FileSystemResource(transfer);
- MultiValueMap param = new LinkedMultiValueMap<>();
- param.add("file", resource);
- param.add("type", type);
- ResponseEntity responseEntity =
- restTemplate.postForEntity(baseUrl + "/upload", param, JSONObject.class);
- if (responseEntity.getBody().getInteger("code") == 2000) {
- transfer.delete();
- } else {
- logger.info("发送失败!" + responseEntity.getBody());
- }
- return responseEntity.getBody().getString("data");
- }
-
- public static String uploadPatchRecord(File uploadFile) {
- if (uploadFile.length() == 0) {
- uploadFile.delete();
- return null;
- }
- String url = "";
- long size = 1024 * 1024;
- int num = (int) (Math.ceil(uploadFile.length() * 1.0 / size));
- String uuid = UUID.randomUUID().toString();
- File file = new File("test-output/record" + File.separator + uuid);
- if (!file.exists()) {
- file.mkdirs();
- }
- try {
- RandomAccessFile before = new RandomAccessFile(uploadFile, "r");
- long beforeSize = uploadFile.length();
- byte[] bytes = new byte[1024];
- int len;
- int successNum = 0;
- for (int i = 0; i < num; i++) {
- File branchFile = new File(file.getPath() + File.separator + uploadFile.getName());
- RandomAccessFile branch = new RandomAccessFile(branchFile, "rw");
- while ((len = before.read(bytes)) != -1) {
- if (beforeSize > len) {
- branch.write(bytes, 0, len);
- beforeSize -= len;
- } else {
- branch.write(bytes, 0, (int) beforeSize);
- }
- if (branch.length() >= size)
- break;
- }
- branch.close();
- FileSystemResource resource = new FileSystemResource(uploadFile);
- MultiValueMap param = new LinkedMultiValueMap<>();
- param.add("file", resource);
- param.add("uuid", uuid);
- param.add("index", i + "");
- param.add("total", num + "");
- ResponseEntity responseEntity = restTemplate.postForEntity(baseUrl + "/upload/recordFiles", param, JSONObject.class);
- if (responseEntity.getBody().getInteger("code") == 2000) {
- successNum++;
- }
- if (responseEntity.getBody().getString("data") != null) {
- url = responseEntity.getBody().getString("data");
- }
- branchFile.delete();
- try {
- Thread.sleep(1000);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- before.close();
- file.delete();
- if (successNum == num) {
- uploadFile.delete();
- } else {
- logger.info("上传缺失!");
- }
- } catch (FileNotFoundException e) {
- e.printStackTrace();
- } catch (IOException e) {
- e.printStackTrace();
- }
- return url;
- }
-}
+package org.cloud.sonic.agent.tools;
+
+import com.alibaba.fastjson.JSONObject;
+import net.coobird.thumbnailator.Thumbnails;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.core.io.FileSystemResource;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Component;
+import org.springframework.util.LinkedMultiValueMap;
+import org.springframework.util.MultiValueMap;
+import org.springframework.web.client.RestTemplate;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+import java.util.Calendar;
+import java.util.UUID;
+
+/**
+ * @author ZhouYiXun
+ * @des 所有上传方法在这里
+ * @date 2021/8/17 23:38
+ */
+@Component
+public class UploadTools {
+ private final static Logger logger = LoggerFactory.getLogger(UploadTools.class);
+ @Value("${sonic.server.host}")
+ private String host;
+ @Value("${sonic.server.folder-port}")
+ private String port;
+ private static String baseUrl;
+
+ private static RestTemplate restTemplate;
+
+ @Autowired
+ public void setRestTemplate(RestTemplate restTemplate) {
+ UploadTools.restTemplate = restTemplate;
+ baseUrl = "http://" + host + ":" + port + "/api/folder";
+ }
+
+ public static String upload(File uploadFile, String type) {
+ File folder = new File("test-output");
+ if (!folder.exists()) {//判断文件目录是否存在
+ folder.mkdirs();
+ }
+ File transfer;
+ if (type.equals("keepFiles") || type.equals("imageFiles")) {
+ long timeMillis = Calendar.getInstance().getTimeInMillis();
+ try {
+ Thumbnails.of(uploadFile)
+ .scale(1f)
+ .outputQuality(0.25f).toFile(folder + File.separator + timeMillis + "transfer.jpg");
+ } catch (IOException e) {
+ logger.error(e.getMessage());
+ }
+ transfer = new File(folder + File.separator + timeMillis + "transfer.jpg");
+ } else {
+ transfer = uploadFile;
+ }
+ FileSystemResource resource = new FileSystemResource(transfer);
+ MultiValueMap param = new LinkedMultiValueMap<>();
+ param.add("file", resource);
+ param.add("type", type);
+ ResponseEntity responseEntity =
+ restTemplate.postForEntity(baseUrl + "/upload", param, JSONObject.class);
+ if (responseEntity.getBody().getInteger("code") == 2000) {
+ transfer.delete();
+ } else {
+ logger.info("发送失败!" + responseEntity.getBody());
+ }
+ return responseEntity.getBody().getString("data");
+ }
+
+ public static String uploadPatchRecord(File uploadFile) {
+ if (uploadFile.length() == 0) {
+ uploadFile.delete();
+ return null;
+ }
+ String url = "";
+ long size = 1024 * 1024;
+ int num = (int) (Math.ceil(uploadFile.length() * 1.0 / size));
+ String uuid = UUID.randomUUID().toString();
+ File file = new File("test-output/record" + File.separator + uuid);
+ if (!file.exists()) {
+ file.mkdirs();
+ }
+ try {
+ RandomAccessFile before = new RandomAccessFile(uploadFile, "r");
+ long beforeSize = uploadFile.length();
+ byte[] bytes = new byte[1024];
+ int len;
+ int successNum = 0;
+ for (int i = 0; i < num; i++) {
+ File branchFile = new File(file.getPath() + File.separator + uploadFile.getName());
+ RandomAccessFile branch = new RandomAccessFile(branchFile, "rw");
+ while ((len = before.read(bytes)) != -1) {
+ if (beforeSize > len) {
+ branch.write(bytes, 0, len);
+ beforeSize -= len;
+ } else {
+ branch.write(bytes, 0, (int) beforeSize);
+ }
+ if (branch.length() >= size)
+ break;
+ }
+ branch.close();
+ FileSystemResource resource = new FileSystemResource(uploadFile);
+ MultiValueMap param = new LinkedMultiValueMap<>();
+ param.add("file", resource);
+ param.add("uuid", uuid);
+ param.add("index", i + "");
+ param.add("total", num + "");
+ ResponseEntity responseEntity = restTemplate.postForEntity(baseUrl + "/upload/recordFiles", param, JSONObject.class);
+ if (responseEntity.getBody().getInteger("code") == 2000) {
+ successNum++;
+ }
+ if (responseEntity.getBody().getString("data") != null) {
+ url = responseEntity.getBody().getString("data");
+ }
+ branchFile.delete();
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+ before.close();
+ file.delete();
+ if (successNum == num) {
+ uploadFile.delete();
+ } else {
+ logger.info("上传缺失!");
+ }
+ } catch (FileNotFoundException e) {
+ e.printStackTrace();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return url;
+ }
+}
diff --git a/src/main/java/com/sonic/agent/websockets/AndroidWSServer.java b/src/main/java/org/cloud/sonic/agent/websockets/AndroidWSServer.java
similarity index 93%
rename from src/main/java/com/sonic/agent/websockets/AndroidWSServer.java
rename to src/main/java/org/cloud/sonic/agent/websockets/AndroidWSServer.java
index 0d1ca276..78cddde9 100644
--- a/src/main/java/com/sonic/agent/websockets/AndroidWSServer.java
+++ b/src/main/java/org/cloud/sonic/agent/websockets/AndroidWSServer.java
@@ -1,625 +1,625 @@
-package com.sonic.agent.websockets;
-
-import com.alibaba.fastjson.JSON;
-import com.alibaba.fastjson.JSONArray;
-import com.alibaba.fastjson.JSONObject;
-import com.android.ddmlib.IDevice;
-import com.android.ddmlib.IShellOutputReceiver;
-import com.android.ddmlib.InstallException;
-import com.sonic.agent.automation.AndroidStepHandler;
-import com.sonic.agent.automation.HandleDes;
-import com.sonic.agent.automation.RemoteDebugDriver;
-import com.sonic.agent.bridge.android.AndroidDeviceBridgeTool;
-import com.sonic.agent.bridge.android.AndroidDeviceLocalStatus;
-import com.sonic.agent.bridge.android.AndroidDeviceThreadPool;
-import com.sonic.agent.interfaces.DeviceStatus;
-import com.sonic.agent.maps.*;
-import com.sonic.agent.netty.NettyThreadPool;
-import com.sonic.agent.tools.*;
-import org.openqa.selenium.OutputType;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.http.*;
-import org.springframework.stereotype.Component;
-import org.springframework.web.client.RestTemplate;
-
-import javax.websocket.*;
-import javax.websocket.server.PathParam;
-import javax.websocket.server.ServerEndpoint;
-import java.io.File;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.net.Socket;
-import java.util.*;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.Semaphore;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicReference;
-
-import static com.sonic.agent.tools.AgentTool.sendText;
-
-@Component
-@ServerEndpoint(value = "/websockets/android/{key}/{udId}/{token}", configurator = MyEndpointConfigure.class)
-public class AndroidWSServer {
-
- private final Logger logger = LoggerFactory.getLogger(AndroidWSServer.class);
- @Value("${sonic.agent.key}")
- private String key;
- @Value("${modules.android.use-adbkit}")
- private boolean isEnableAdbKit;
- private Map udIdMap = new ConcurrentHashMap<>();
- private Map> webViewForwardMap = new ConcurrentHashMap<>();
- private Map outputMap = new ConcurrentHashMap<>();
- private Map rotationMap = new ConcurrentHashMap<>();
- private Map rotationStatusMap = new ConcurrentHashMap<>();
- private Map picMap = new ConcurrentHashMap<>();
- @Autowired
- private RestTemplate restTemplate;
-
- @OnOpen
- public void onOpen(Session session, @PathParam("key") String secretKey,
- @PathParam("udId") String udId, @PathParam("token") String token) throws Exception {
- if (secretKey.length() == 0 || (!secretKey.equals(key)) || token.length() == 0) {
- logger.info("拦截访问!");
- return;
- }
-
- session.getUserProperties().put("udId", udId);
- boolean lockSuccess = DevicesLockMap.lockByUdId(udId, 30L, TimeUnit.SECONDS);
- if (!lockSuccess) {
- logger.info("30s内获取设备锁失败,请确保设备无人使用");
- return;
- }
- logger.info("android上锁udId:{}", udId);
- AndroidDeviceLocalStatus.startDebug(udId);
- JSONObject jsonDebug = new JSONObject();
- jsonDebug.put("msg", "debugUser");
- jsonDebug.put("token", token);
- jsonDebug.put("udId", udId);
- NettyThreadPool.send(jsonDebug);
- WebSocketSessionMap.addSession(session);
- IDevice iDevice = AndroidDeviceBridgeTool.getIDeviceByUdId(udId);
- if (iDevice == null) {
- logger.info("设备未连接,请检查!");
- return;
- }
- AndroidDeviceBridgeTool.screen(iDevice, "abort");
- AndroidDeviceBridgeTool.pressKey(iDevice, 3);
- udIdMap.put(session, iDevice);
-
- String path = AndroidDeviceBridgeTool.executeCommand(iDevice, "pm path com.sonic.plugins.assist").trim()
- .replaceAll("package:", "")
- .replaceAll("\n", "")
- .replaceAll("\t", "");
- if (path.length() > 0) {
- logger.info("已安装Sonic插件");
- } else {
- try {
- iDevice.installPackage("plugins/sonic-plugin.apk", true, "-t");
- } catch (InstallException e) {
- e.printStackTrace();
- logger.info("Sonic插件安装失败!");
- return;
- }
- path = AndroidDeviceBridgeTool.executeCommand(iDevice, "pm path com.sonic.plugins.assist").trim()
- .replaceAll("package:", "")
- .replaceAll("\n", "")
- .replaceAll("\t", "");
- }
-
- Semaphore isTouchFinish = new Semaphore(0);
- String finalPath = path;
- Thread rotationPro = new Thread(() -> {
- try {
- //开始启动
- iDevice.executeShellCommand(String.format("CLASSPATH=%s exec app_process /system/bin com.sonic.plugins.assist.RotationMonitorService", finalPath)
- , new IShellOutputReceiver() {
- @Override
- public void addOutput(byte[] bytes, int i, int i1) {
- String res = new String(bytes, i, i1).replaceAll("\n", "").replaceAll("\r", "");
- logger.info(udId + "旋转到:" + res);
- rotationStatusMap.put(session, Integer.parseInt(res));
- JSONObject rotationJson = new JSONObject();
- rotationJson.put("msg", "rotation");
- rotationJson.put("value", Integer.parseInt(res) * 90);
- sendText(session, rotationJson.toJSONString());
- Thread old = MiniCapMap.getMap().get(session);
- if (old != null) {
- old.interrupt();
- do {
- try {
- Thread.sleep(1000);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- while (MiniCapMap.getMap().get(session) != null);
- }
- MiniCapTool miniCapTool = new MiniCapTool();
- AtomicReference banner = new AtomicReference<>(new String[24]);
- Thread miniCapThread = miniCapTool.start(
- udIdMap.get(session).getSerialNumber(), banner, null,
- picMap.get(session) == null ? "high" : picMap.get(session),
- Integer.parseInt(res), session
- );
- MiniCapMap.getMap().put(session, miniCapThread);
- JSONObject picFinish = new JSONObject();
- picFinish.put("msg", "picFinish");
- sendText(session, picFinish.toJSONString());
- }
-
- @Override
- public void flush() {
- }
-
- @Override
- public boolean isCancelled() {
- return false;
- }
- }, 0, TimeUnit.MILLISECONDS);
- } catch (Exception e) {
- logger.info("{} 设备方向监听启动异常!"
- , iDevice.getSerialNumber());
- logger.error(e.getMessage());
- }
- });
- rotationPro.start();
- rotationMap.put(session, rotationPro);
-
- Thread touchPro = new Thread(() -> {
- try {
- //开始启动
- iDevice.executeShellCommand(String.format("CLASSPATH=%s exec app_process /system/bin com.sonic.plugins.assist.SonicTouchService", finalPath)
- , 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("Server start")) {
- isTouchFinish.release();
- }
- }
-
- @Override
- public void flush() {
- }
-
- @Override
- public boolean isCancelled() {
- return false;
- }
- }, 0, TimeUnit.MILLISECONDS);
- } catch (Exception e) {
- logger.info("{} 设备touch服务启动异常!"
- , iDevice.getSerialNumber());
- logger.error(e.getMessage());
- }
- });
- touchPro.start();
-
- int finalTouchPort = PortTool.getPort();
- AndroidDeviceThreadPool.cachedThreadPool.execute(() -> {
- int wait = 0;
- while (!isTouchFinish.tryAcquire()) {
- wait++;
- try {
- Thread.sleep(500);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- // 超时就不继续等了,保证其它服务可运行
- if (wait > 20) {
- return;
- }
- }
- AndroidDeviceBridgeTool.forward(iDevice, finalTouchPort, "sonictouchservice");
- Socket touchSocket = null;
- OutputStream outputStream = null;
- try {
- touchSocket = new Socket("localhost", finalTouchPort);
- outputStream = touchSocket.getOutputStream();
- outputMap.put(session, outputStream);
- while (outputMap.get(session) != null && (touchPro.isAlive())) {
- Thread.sleep(1000);
- }
- } catch (IOException | InterruptedException e) {
- e.printStackTrace();
- } finally {
- if (touchPro.isAlive()) {
- touchPro.interrupt();
- logger.info("touch thread已关闭");
- }
- if (touchSocket != null && touchSocket.isConnected()) {
- try {
- touchSocket.close();
- logger.info("touch socket已关闭");
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- if (outputStream != null) {
- try {
- outputStream.close();
- logger.info("touch output流已关闭");
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
- AndroidDeviceBridgeTool.removeForward(iDevice, finalTouchPort, "sonictouchservice");
- });
-
- AndroidDeviceThreadPool.cachedThreadPool.execute(() -> AndroidDeviceBridgeTool.pushYadb(udIdMap.get(session)));
-
- if (isEnableAdbKit) {
- String processName = String.format("process-%s-adbkit", udId);
- if (GlobalProcessMap.getMap().get(processName) != null) {
- Process ps = GlobalProcessMap.getMap().get(processName);
- ps.children().forEach(ProcessHandle::destroy);
- ps.destroy();
- }
- try {
- String system = System.getProperty("os.name").toLowerCase();
- Process ps = null;
- int port = PortTool.getPort();
- String command = String.format("adbkit usb-device-to-tcp -p %d %s", port, udId);
- if (system.contains("win")) {
- ps = Runtime.getRuntime().exec(new String[]{"cmd", "/c", command});
- } else if (system.contains("linux") || system.contains("mac")) {
- ps = Runtime.getRuntime().exec(new String[]{"sh", "-c", command});
- }
- GlobalProcessMap.getMap().put(processName, ps);
- JSONObject adbkit = new JSONObject();
- adbkit.put("msg", "adbkit");
- adbkit.put("isEnable", true);
- adbkit.put("port", port);
- sendText(session, adbkit.toJSONString());
- } catch (IOException e) {
- e.printStackTrace();
- }
- } else {
- JSONObject adbkit = new JSONObject();
- adbkit.put("msg", "adbkit");
- adbkit.put("isEnable", false);
- sendText(session, adbkit.toJSONString());
- }
-
- AndroidDeviceThreadPool.cachedThreadPool.execute(() -> {
- AndroidStepHandler androidStepHandler = new AndroidStepHandler();
- androidStepHandler.setTestMode(0, 0, udId, DeviceStatus.DEBUGGING, session.getId());
- JSONObject result = new JSONObject();
- try {
- androidStepHandler.startAndroidDriver(udId);
- result.put("status", "success");
- result.put("detail", "初始化Driver完成!");
- HandlerMap.getAndroidMap().put(session.getId(), androidStepHandler);
- } catch (Exception e) {
- logger.error(e.getMessage());
- result.put("status", "error");
- result.put("detail", "初始化Driver失败!部分功能不可用!请联系管理员");
- } finally {
- result.put("msg", "openDriver");
- sendText(session, result.toJSONString());
- }
- });
- }
-
- @OnClose
- public void onClose(Session session) {
- String udId = (String) session.getUserProperties().get("udId");
- try {
- exit(session);
- } finally {
- DevicesLockMap.unlockAndRemoveByUdId(udId);
- logger.info("android解锁udId:{}", udId);
- }
- }
-
- @OnError
- public void onError(Session session, Throwable error) {
- logger.error(error.getMessage());
- JSONObject errMsg = new JSONObject();
- errMsg.put("msg", "error");
- sendText(session, errMsg.toJSONString());
- }
-
- @OnMessage
- public void onMessage(String message, Session session) throws InterruptedException {
- JSONObject msg = JSON.parseObject(message);
- logger.info(session.getId() + " 发送 " + msg);
- switch (msg.getString("type")) {
- case "forwardView": {
- JSONObject forwardView = new JSONObject();
- IDevice iDevice = udIdMap.get(session);
- List wList = Arrays.asList("webview", "WebView", "chrome_devtools_remote", "Terrace_devtools_remote");
- 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()) {
- webSet.add(w.substring(w.indexOf("@") + 1));
- }
- }
- List has = webViewForwardMap.get(iDevice);
- if (has != null && has.size() > 0) {
- for (JSONObject j : has) {
- AndroidDeviceBridgeTool.removeForward(iDevice, j.getInteger("port"), j.getString("name"));
- }
- }
- has = new ArrayList<>();
- List result = new ArrayList<>();
- if (webViewList.size() > 0) {
- HttpHeaders headers = new HttpHeaders();
- headers.add("Content-Type", "application/json");
- for (String ws : webSet) {
- int port = PortTool.getPort();
- AndroidDeviceBridgeTool.forward(iDevice, port, ws);
- JSONObject j = new JSONObject();
- j.put("port", port);
- j.put("name", ws);
- has.add(j);
- JSONObject r = new JSONObject();
- r.put("port", port);
- 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);
- if (responseEntity.getStatusCode() == HttpStatus.OK) {
- List child = new ArrayList<>();
- for (Object e : responseEntity.getBody()) {
- LinkedHashMap objE = (LinkedHashMap) e;
- JSONObject c = new JSONObject();
- c.put("favicon", objE.get("faviconUrl"));
- c.put("title", objE.get("title"));
- c.put("url", objE.get("url"));
- c.put("id", objE.get("id"));
- child.add(c);
- }
- r.put("children", child);
- result.add(r);
- }
- }
- webViewForwardMap.put(iDevice, has);
- }
- forwardView.put("msg", "forwardView");
- if (RemoteDebugDriver.webDriver == null) {
- RemoteDebugDriver.startChromeDriver();
- }
- forwardView.put("chromePort", RemoteDebugDriver.chromePort);
- forwardView.put("detail", result);
- sendText(session, forwardView.toJSONString());
- break;
- }
- case "find":
- AndroidDeviceBridgeTool.searchDevice(udIdMap.get(session));
- break;
- case "battery":
- AndroidDeviceBridgeTool.controlBattery(udIdMap.get(session), msg.getInteger("detail"));
- break;
- case "scan":
- AndroidDeviceBridgeTool.pushToCamera(udIdMap.get(session), msg.getString("url"));
- break;
- case "text":
- ProcessCommandTool.getProcessLocalCommand("adb -s " + udIdMap.get(session).getSerialNumber()
- + " shell app_process -Djava.class.path=/data/local/tmp/yadb /data/local/tmp com.ysbing.yadb.Main -keyboard " + msg.getString("detail"));
- break;
- case "pic": {
- Thread old = MiniCapMap.getMap().get(session);
- old.interrupt();
- do {
- try {
- Thread.sleep(1000);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- while (MiniCapMap.getMap().get(session) != null);
- MiniCapTool miniCapTool = new MiniCapTool();
- AtomicReference banner = new AtomicReference<>(new String[24]);
- Thread miniCapThread = miniCapTool.start(
- udIdMap.get(session).getSerialNumber(), banner, null, msg.getString("detail"),
- rotationStatusMap.get(session), session
- );
- MiniCapMap.getMap().put(session, miniCapThread);
- JSONObject picFinish = new JSONObject();
- picFinish.put("msg", "picFinish");
- sendText(session, picFinish.toJSONString());
- break;
- }
- case "touch":
- OutputStream outputStream = outputMap.get(session);
- if (outputStream != null) {
- try {
- outputStream.write(msg.getString("detail").getBytes());
- outputStream.flush();
- outputStream.write("c\n".getBytes());
- outputStream.flush();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- break;
- case "keyEvent":
- AndroidDeviceBridgeTool.pressKey(udIdMap.get(session), msg.getInteger("detail"));
- break;
- case "debug":
- if (msg.getString("detail").equals("runStep")) {
- JSONObject jsonDebug = new JSONObject();
- jsonDebug.put("msg", "findSteps");
- jsonDebug.put("key", key);
- jsonDebug.put("udId", udIdMap.get(session).getSerialNumber());
- jsonDebug.put("pwd", msg.getString("pwd"));
- jsonDebug.put("sessionId", session.getId());
- jsonDebug.put("caseId", msg.getInteger("caseId"));
- NettyThreadPool.send(jsonDebug);
- } else {
- AndroidStepHandler androidStepHandler = HandlerMap.getAndroidMap().get(session.getId());
- if (androidStepHandler == null || androidStepHandler.getAndroidDriver() == null) {
- if (msg.getString("detail").equals("openDriver")) {
- androidStepHandler = new AndroidStepHandler();
- androidStepHandler.setTestMode(0, 0, udIdMap.get(session).getSerialNumber(), DeviceStatus.DEBUGGING, session.getId());
- JSONObject result = new JSONObject();
- AndroidStepHandler finalAndroidStepHandler1 = androidStepHandler;
- AndroidDeviceThreadPool.cachedThreadPool.execute(() -> {
- try {
- AndroidDeviceLocalStatus.startDebug(udIdMap.get(session).getSerialNumber());
- finalAndroidStepHandler1.startAndroidDriver(udIdMap.get(session).getSerialNumber());
- result.put("status", "success");
- result.put("detail", "初始化Driver完成!");
- HandlerMap.getAndroidMap().put(session.getId(), finalAndroidStepHandler1);
- } catch (Exception e) {
- logger.error(e.getMessage());
- result.put("status", "error");
- result.put("detail", "初始化Driver失败!部分功能不可用!请联系管理员");
- } finally {
- result.put("msg", "openDriver");
- sendText(session, result.toJSONString());
- }
- });
- }
- break;
- }
- try {
- if (msg.getString("detail").equals("tap")) {
- String xy = msg.getString("point");
- int x = Integer.parseInt(xy.substring(0, xy.indexOf(",")));
- int y = Integer.parseInt(xy.substring(xy.indexOf(",") + 1));
- AndroidDeviceBridgeTool.executeCommand(udIdMap.get(session), "input tap " + x + " " + y);
- }
- if (msg.getString("detail").equals("longPress")) {
- String xy = msg.getString("point");
- int x = Integer.parseInt(xy.substring(0, xy.indexOf(",")));
- int y = Integer.parseInt(xy.substring(xy.indexOf(",") + 1));
- AndroidDeviceBridgeTool.executeCommand(udIdMap.get(session), "input swipe " + x + " " + y + " " + x + " " + y + " 1500");
- }
- if (msg.getString("detail").equals("swipe")) {
- String xy1 = msg.getString("pointA");
- String xy2 = msg.getString("pointB");
- int x1 = Integer.parseInt(xy1.substring(0, xy1.indexOf(",")));
- 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 + " 200");
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- if (msg.getString("detail").equals("install")) {
- AndroidDeviceThreadPool.cachedThreadPool.execute(() -> {
- JSONObject result = new JSONObject();
- result.put("msg", "installFinish");
- try {
- File localFile = DownImageTool.download(msg.getString("apk"));
- udIdMap.get(session).installPackage(localFile.getAbsolutePath(), true, "-t");
- result.put("status", "success");
- } catch (IOException | InstallException e) {
- result.put("status", "fail");
- e.printStackTrace();
- }
- sendText(session, result.toJSONString());
- });
- }
- if (msg.getString("detail").equals("tree")) {
- AndroidStepHandler finalAndroidStepHandler = androidStepHandler;
- AndroidDeviceThreadPool.cachedThreadPool.execute(() -> {
- try {
- JSONObject result = new JSONObject();
- result.put("msg", "tree");
- result.put("detail", finalAndroidStepHandler.getResource());
- HandleDes handleDes = new HandleDes();
- if (!msg.getBoolean("hasScreen")) {
- result.put("img", finalAndroidStepHandler.stepScreen(handleDes));
- }
- if (handleDes.getE() != null) {
- logger.error(handleDes.getE().getMessage());
- JSONObject resultFail = new JSONObject();
- resultFail.put("msg", "treeFail");
- sendText(session, resultFail.toJSONString());
- } else {
- result.put("webView", finalAndroidStepHandler.getWebView());
- result.put("activity", finalAndroidStepHandler.getCurrentActivity());
- sendText(session, result.toJSONString());
- }
- } catch (Throwable e) {
- logger.error(e.getMessage());
- JSONObject result = new JSONObject();
- result.put("msg", "treeFail");
- sendText(session, result.toJSONString());
- }
- });
- }
- if (msg.getString("detail").equals("eleScreen")) {
- AndroidStepHandler finalAndroidStepHandler = androidStepHandler;
- AndroidDeviceThreadPool.cachedThreadPool.execute(() -> {
- JSONObject result = new JSONObject();
- result.put("msg", "eleScreen");
- try {
- result.put("img", UploadTools.upload(finalAndroidStepHandler.findEle("xpath", msg.getString("xpath")).getScreenshotAs(OutputType.FILE), "keepFiles"));
- } catch (Exception e) {
- result.put("errMsg", "获取元素截图失败!");
- }
- sendText(session, result.toJSONString());
- });
- }
- }
- break;
- }
- }
-
- private void exit(Session session) {
- AndroidDeviceLocalStatus.finish(session.getUserProperties().get("udId") + "");
- try {
- HandlerMap.getAndroidMap().get(session.getId()).closeAndroidDriver();
- } catch (Exception e) {
- logger.info("关闭driver异常!");
- } finally {
- HandlerMap.getAndroidMap().remove(session.getId());
- }
- if (udIdMap.get(session) != null) {
- List has = webViewForwardMap.get(udIdMap.get(session));
- if (has != null && has.size() > 0) {
- for (JSONObject j : has) {
- AndroidDeviceBridgeTool.removeForward(udIdMap.get(session), j.getInteger("port"), j.getString("name"));
- }
- }
- webViewForwardMap.remove(udIdMap.get(session));
- if (isEnableAdbKit) {
- String processName = String.format("process-%s-adbkit", udIdMap.get(session).getSerialNumber());
- if (GlobalProcessMap.getMap().get(processName) != null) {
- Process ps = GlobalProcessMap.getMap().get(processName);
- ps.children().forEach(ProcessHandle::destroy);
- ps.destroy();
- }
- }
- }
- outputMap.remove(session);
- udIdMap.remove(session);
- if (rotationMap.get(session) != null) {
- rotationMap.get(session).interrupt();
- }
- rotationMap.remove(session);
- if (MiniCapMap.getMap().get(session) != null) {
- MiniCapMap.getMap().get(session).interrupt();
- }
- WebSocketSessionMap.removeSession(session);
- try {
- session.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- logger.info(session.getId() + "退出");
- }
-}
+package org.cloud.sonic.agent.websockets;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.android.ddmlib.IDevice;
+import com.android.ddmlib.IShellOutputReceiver;
+import com.android.ddmlib.InstallException;
+import org.cloud.sonic.agent.automation.AndroidStepHandler;
+import org.cloud.sonic.agent.automation.HandleDes;
+import org.cloud.sonic.agent.automation.RemoteDebugDriver;
+import org.cloud.sonic.agent.bridge.android.AndroidDeviceBridgeTool;
+import org.cloud.sonic.agent.bridge.android.AndroidDeviceLocalStatus;
+import org.cloud.sonic.agent.bridge.android.AndroidDeviceThreadPool;
+import org.cloud.sonic.agent.interfaces.DeviceStatus;
+import org.cloud.sonic.agent.maps.*;
+import org.cloud.sonic.agent.maps.*;
+import org.cloud.sonic.agent.netty.NettyThreadPool;
+import org.cloud.sonic.agent.tools.*;
+import org.cloud.sonic.agent.tools.*;
+import org.openqa.selenium.OutputType;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.http.*;
+import org.springframework.stereotype.Component;
+import org.springframework.web.client.RestTemplate;
+
+import javax.websocket.*;
+import javax.websocket.server.PathParam;
+import javax.websocket.server.ServerEndpoint;
+import java.io.File;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.Socket;
+import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicReference;
+
+@Component
+@ServerEndpoint(value = "/websockets/android/{key}/{udId}/{token}", configurator = MyEndpointConfigure.class)
+public class AndroidWSServer {
+
+ private final Logger logger = LoggerFactory.getLogger(AndroidWSServer.class);
+ @Value("${sonic.agent.key}")
+ private String key;
+ @Value("${modules.android.use-adbkit}")
+ private boolean isEnableAdbKit;
+ private Map udIdMap = new ConcurrentHashMap<>();
+ private Map> webViewForwardMap = new ConcurrentHashMap<>();
+ private Map outputMap = new ConcurrentHashMap<>();
+ private Map rotationMap = new ConcurrentHashMap<>();
+ private Map rotationStatusMap = new ConcurrentHashMap<>();
+ private Map picMap = new ConcurrentHashMap<>();
+ @Autowired
+ private RestTemplate restTemplate;
+
+ @OnOpen
+ public void onOpen(Session session, @PathParam("key") String secretKey,
+ @PathParam("udId") String udId, @PathParam("token") String token) throws Exception {
+ if (secretKey.length() == 0 || (!secretKey.equals(key)) || token.length() == 0) {
+ logger.info("拦截访问!");
+ return;
+ }
+
+ session.getUserProperties().put("udId", udId);
+ boolean lockSuccess = DevicesLockMap.lockByUdId(udId, 30L, TimeUnit.SECONDS);
+ if (!lockSuccess) {
+ logger.info("30s内获取设备锁失败,请确保设备无人使用");
+ return;
+ }
+ logger.info("android上锁udId:{}", udId);
+ AndroidDeviceLocalStatus.startDebug(udId);
+ JSONObject jsonDebug = new JSONObject();
+ jsonDebug.put("msg", "debugUser");
+ jsonDebug.put("token", token);
+ jsonDebug.put("udId", udId);
+ NettyThreadPool.send(jsonDebug);
+ WebSocketSessionMap.addSession(session);
+ IDevice iDevice = AndroidDeviceBridgeTool.getIDeviceByUdId(udId);
+ if (iDevice == null) {
+ logger.info("设备未连接,请检查!");
+ return;
+ }
+ AndroidDeviceBridgeTool.screen(iDevice, "abort");
+ AndroidDeviceBridgeTool.pressKey(iDevice, 3);
+ udIdMap.put(session, iDevice);
+
+ String path = AndroidDeviceBridgeTool.executeCommand(iDevice, "pm path org.cloud.sonic.plugins.assist").trim()
+ .replaceAll("package:", "")
+ .replaceAll("\n", "")
+ .replaceAll("\t", "");
+ if (path.length() > 0) {
+ logger.info("已安装Sonic插件");
+ } else {
+ try {
+ iDevice.installPackage("plugins/sonic-plugin.apk", true, "-t");
+ } catch (InstallException e) {
+ e.printStackTrace();
+ logger.info("Sonic插件安装失败!");
+ return;
+ }
+ path = AndroidDeviceBridgeTool.executeCommand(iDevice, "pm path com.sonic.plugins.assist").trim()
+ .replaceAll("package:", "")
+ .replaceAll("\n", "")
+ .replaceAll("\t", "");
+ }
+
+ Semaphore isTouchFinish = new Semaphore(0);
+ String finalPath = path;
+ Thread rotationPro = new Thread(() -> {
+ try {
+ //开始启动
+ iDevice.executeShellCommand(String.format("CLASSPATH=%s exec app_process /system/bin com.sonic.plugins.assist.RotationMonitorService", finalPath)
+ , new IShellOutputReceiver() {
+ @Override
+ public void addOutput(byte[] bytes, int i, int i1) {
+ String res = new String(bytes, i, i1).replaceAll("\n", "").replaceAll("\r", "");
+ logger.info(udId + "旋转到:" + res);
+ rotationStatusMap.put(session, Integer.parseInt(res));
+ JSONObject rotationJson = new JSONObject();
+ rotationJson.put("msg", "rotation");
+ rotationJson.put("value", Integer.parseInt(res) * 90);
+ AgentTool.sendText(session, rotationJson.toJSONString());
+ Thread old = MiniCapMap.getMap().get(session);
+ if (old != null) {
+ old.interrupt();
+ do {
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+ while (MiniCapMap.getMap().get(session) != null);
+ }
+ MiniCapTool miniCapTool = new MiniCapTool();
+ AtomicReference banner = new AtomicReference<>(new String[24]);
+ Thread miniCapThread = miniCapTool.start(
+ udIdMap.get(session).getSerialNumber(), banner, null,
+ picMap.get(session) == null ? "high" : picMap.get(session),
+ Integer.parseInt(res), session
+ );
+ MiniCapMap.getMap().put(session, miniCapThread);
+ JSONObject picFinish = new JSONObject();
+ picFinish.put("msg", "picFinish");
+ AgentTool.sendText(session, picFinish.toJSONString());
+ }
+
+ @Override
+ public void flush() {
+ }
+
+ @Override
+ public boolean isCancelled() {
+ return false;
+ }
+ }, 0, TimeUnit.MILLISECONDS);
+ } catch (Exception e) {
+ logger.info("{} 设备方向监听启动异常!"
+ , iDevice.getSerialNumber());
+ logger.error(e.getMessage());
+ }
+ });
+ rotationPro.start();
+ rotationMap.put(session, rotationPro);
+
+ Thread touchPro = new Thread(() -> {
+ try {
+ //开始启动
+ iDevice.executeShellCommand(String.format("CLASSPATH=%s exec app_process /system/bin com.sonic.plugins.assist.SonicTouchService", finalPath)
+ , 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("Server start")) {
+ isTouchFinish.release();
+ }
+ }
+
+ @Override
+ public void flush() {
+ }
+
+ @Override
+ public boolean isCancelled() {
+ return false;
+ }
+ }, 0, TimeUnit.MILLISECONDS);
+ } catch (Exception e) {
+ logger.info("{} 设备touch服务启动异常!"
+ , iDevice.getSerialNumber());
+ logger.error(e.getMessage());
+ }
+ });
+ touchPro.start();
+
+ int finalTouchPort = PortTool.getPort();
+ AndroidDeviceThreadPool.cachedThreadPool.execute(() -> {
+ int wait = 0;
+ while (!isTouchFinish.tryAcquire()) {
+ wait++;
+ try {
+ Thread.sleep(500);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ // 超时就不继续等了,保证其它服务可运行
+ if (wait > 20) {
+ return;
+ }
+ }
+ AndroidDeviceBridgeTool.forward(iDevice, finalTouchPort, "sonictouchservice");
+ Socket touchSocket = null;
+ OutputStream outputStream = null;
+ try {
+ touchSocket = new Socket("localhost", finalTouchPort);
+ outputStream = touchSocket.getOutputStream();
+ outputMap.put(session, outputStream);
+ while (outputMap.get(session) != null && (touchPro.isAlive())) {
+ Thread.sleep(1000);
+ }
+ } catch (IOException | InterruptedException e) {
+ e.printStackTrace();
+ } finally {
+ if (touchPro.isAlive()) {
+ touchPro.interrupt();
+ logger.info("touch thread已关闭");
+ }
+ if (touchSocket != null && touchSocket.isConnected()) {
+ try {
+ touchSocket.close();
+ logger.info("touch socket已关闭");
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ if (outputStream != null) {
+ try {
+ outputStream.close();
+ logger.info("touch output流已关闭");
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ AndroidDeviceBridgeTool.removeForward(iDevice, finalTouchPort, "sonictouchservice");
+ });
+
+ AndroidDeviceThreadPool.cachedThreadPool.execute(() -> AndroidDeviceBridgeTool.pushYadb(udIdMap.get(session)));
+
+ if (isEnableAdbKit) {
+ String processName = String.format("process-%s-adbkit", udId);
+ if (GlobalProcessMap.getMap().get(processName) != null) {
+ Process ps = GlobalProcessMap.getMap().get(processName);
+ ps.children().forEach(ProcessHandle::destroy);
+ ps.destroy();
+ }
+ try {
+ String system = System.getProperty("os.name").toLowerCase();
+ Process ps = null;
+ int port = PortTool.getPort();
+ String command = String.format("adbkit usb-device-to-tcp -p %d %s", port, udId);
+ if (system.contains("win")) {
+ ps = Runtime.getRuntime().exec(new String[]{"cmd", "/c", command});
+ } else if (system.contains("linux") || system.contains("mac")) {
+ ps = Runtime.getRuntime().exec(new String[]{"sh", "-c", command});
+ }
+ GlobalProcessMap.getMap().put(processName, ps);
+ JSONObject adbkit = new JSONObject();
+ adbkit.put("msg", "adbkit");
+ adbkit.put("isEnable", true);
+ adbkit.put("port", port);
+ AgentTool.sendText(session, adbkit.toJSONString());
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ } else {
+ JSONObject adbkit = new JSONObject();
+ adbkit.put("msg", "adbkit");
+ adbkit.put("isEnable", false);
+ AgentTool.sendText(session, adbkit.toJSONString());
+ }
+
+ AndroidDeviceThreadPool.cachedThreadPool.execute(() -> {
+ AndroidStepHandler androidStepHandler = new AndroidStepHandler();
+ androidStepHandler.setTestMode(0, 0, udId, DeviceStatus.DEBUGGING, session.getId());
+ JSONObject result = new JSONObject();
+ try {
+ androidStepHandler.startAndroidDriver(udId);
+ result.put("status", "success");
+ result.put("detail", "初始化Driver完成!");
+ HandlerMap.getAndroidMap().put(session.getId(), androidStepHandler);
+ } catch (Exception e) {
+ logger.error(e.getMessage());
+ result.put("status", "error");
+ result.put("detail", "初始化Driver失败!部分功能不可用!请联系管理员");
+ } finally {
+ result.put("msg", "openDriver");
+ AgentTool.sendText(session, result.toJSONString());
+ }
+ });
+ }
+
+ @OnClose
+ public void onClose(Session session) {
+ String udId = (String) session.getUserProperties().get("udId");
+ try {
+ exit(session);
+ } finally {
+ DevicesLockMap.unlockAndRemoveByUdId(udId);
+ logger.info("android解锁udId:{}", udId);
+ }
+ }
+
+ @OnError
+ public void onError(Session session, Throwable error) {
+ logger.error(error.getMessage());
+ JSONObject errMsg = new JSONObject();
+ errMsg.put("msg", "error");
+ AgentTool.sendText(session, errMsg.toJSONString());
+ }
+
+ @OnMessage
+ public void onMessage(String message, Session session) throws InterruptedException {
+ JSONObject msg = JSON.parseObject(message);
+ logger.info(session.getId() + " 发送 " + msg);
+ switch (msg.getString("type")) {
+ case "forwardView": {
+ JSONObject forwardView = new JSONObject();
+ IDevice iDevice = udIdMap.get(session);
+ List wList = Arrays.asList("webview", "WebView", "chrome_devtools_remote", "Terrace_devtools_remote");
+ 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()) {
+ webSet.add(w.substring(w.indexOf("@") + 1));
+ }
+ }
+ List has = webViewForwardMap.get(iDevice);
+ if (has != null && has.size() > 0) {
+ for (JSONObject j : has) {
+ AndroidDeviceBridgeTool.removeForward(iDevice, j.getInteger("port"), j.getString("name"));
+ }
+ }
+ has = new ArrayList<>();
+ List result = new ArrayList<>();
+ if (webViewList.size() > 0) {
+ HttpHeaders headers = new HttpHeaders();
+ headers.add("Content-Type", "application/json");
+ for (String ws : webSet) {
+ int port = PortTool.getPort();
+ AndroidDeviceBridgeTool.forward(iDevice, port, ws);
+ JSONObject j = new JSONObject();
+ j.put("port", port);
+ j.put("name", ws);
+ has.add(j);
+ JSONObject r = new JSONObject();
+ r.put("port", port);
+ 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);
+ if (responseEntity.getStatusCode() == HttpStatus.OK) {
+ List child = new ArrayList<>();
+ for (Object e : responseEntity.getBody()) {
+ LinkedHashMap objE = (LinkedHashMap) e;
+ JSONObject c = new JSONObject();
+ c.put("favicon", objE.get("faviconUrl"));
+ c.put("title", objE.get("title"));
+ c.put("url", objE.get("url"));
+ c.put("id", objE.get("id"));
+ child.add(c);
+ }
+ r.put("children", child);
+ result.add(r);
+ }
+ }
+ webViewForwardMap.put(iDevice, has);
+ }
+ forwardView.put("msg", "forwardView");
+ if (RemoteDebugDriver.webDriver == null) {
+ RemoteDebugDriver.startChromeDriver();
+ }
+ forwardView.put("chromePort", RemoteDebugDriver.chromePort);
+ forwardView.put("detail", result);
+ AgentTool.sendText(session, forwardView.toJSONString());
+ break;
+ }
+ case "find":
+ AndroidDeviceBridgeTool.searchDevice(udIdMap.get(session));
+ break;
+ case "battery":
+ AndroidDeviceBridgeTool.controlBattery(udIdMap.get(session), msg.getInteger("detail"));
+ break;
+ case "scan":
+ AndroidDeviceBridgeTool.pushToCamera(udIdMap.get(session), msg.getString("url"));
+ break;
+ case "text":
+ ProcessCommandTool.getProcessLocalCommand("adb -s " + udIdMap.get(session).getSerialNumber()
+ + " shell app_process -Djava.class.path=/data/local/tmp/yadb /data/local/tmp com.ysbing.yadb.Main -keyboard " + msg.getString("detail"));
+ break;
+ case "pic": {
+ Thread old = MiniCapMap.getMap().get(session);
+ old.interrupt();
+ do {
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+ while (MiniCapMap.getMap().get(session) != null);
+ MiniCapTool miniCapTool = new MiniCapTool();
+ AtomicReference banner = new AtomicReference<>(new String[24]);
+ Thread miniCapThread = miniCapTool.start(
+ udIdMap.get(session).getSerialNumber(), banner, null, msg.getString("detail"),
+ rotationStatusMap.get(session), session
+ );
+ MiniCapMap.getMap().put(session, miniCapThread);
+ JSONObject picFinish = new JSONObject();
+ picFinish.put("msg", "picFinish");
+ AgentTool.sendText(session, picFinish.toJSONString());
+ break;
+ }
+ case "touch":
+ OutputStream outputStream = outputMap.get(session);
+ if (outputStream != null) {
+ try {
+ outputStream.write(msg.getString("detail").getBytes());
+ outputStream.flush();
+ outputStream.write("c\n".getBytes());
+ outputStream.flush();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ break;
+ case "keyEvent":
+ AndroidDeviceBridgeTool.pressKey(udIdMap.get(session), msg.getInteger("detail"));
+ break;
+ case "debug":
+ if (msg.getString("detail").equals("runStep")) {
+ JSONObject jsonDebug = new JSONObject();
+ jsonDebug.put("msg", "findSteps");
+ jsonDebug.put("key", key);
+ jsonDebug.put("udId", udIdMap.get(session).getSerialNumber());
+ jsonDebug.put("pwd", msg.getString("pwd"));
+ jsonDebug.put("sessionId", session.getId());
+ jsonDebug.put("caseId", msg.getInteger("caseId"));
+ NettyThreadPool.send(jsonDebug);
+ } else {
+ AndroidStepHandler androidStepHandler = HandlerMap.getAndroidMap().get(session.getId());
+ if (androidStepHandler == null || androidStepHandler.getAndroidDriver() == null) {
+ if (msg.getString("detail").equals("openDriver")) {
+ androidStepHandler = new AndroidStepHandler();
+ androidStepHandler.setTestMode(0, 0, udIdMap.get(session).getSerialNumber(), DeviceStatus.DEBUGGING, session.getId());
+ JSONObject result = new JSONObject();
+ AndroidStepHandler finalAndroidStepHandler1 = androidStepHandler;
+ AndroidDeviceThreadPool.cachedThreadPool.execute(() -> {
+ try {
+ AndroidDeviceLocalStatus.startDebug(udIdMap.get(session).getSerialNumber());
+ finalAndroidStepHandler1.startAndroidDriver(udIdMap.get(session).getSerialNumber());
+ result.put("status", "success");
+ result.put("detail", "初始化Driver完成!");
+ HandlerMap.getAndroidMap().put(session.getId(), finalAndroidStepHandler1);
+ } catch (Exception e) {
+ logger.error(e.getMessage());
+ result.put("status", "error");
+ result.put("detail", "初始化Driver失败!部分功能不可用!请联系管理员");
+ } finally {
+ result.put("msg", "openDriver");
+ AgentTool.sendText(session, result.toJSONString());
+ }
+ });
+ }
+ break;
+ }
+ try {
+ if (msg.getString("detail").equals("tap")) {
+ String xy = msg.getString("point");
+ int x = Integer.parseInt(xy.substring(0, xy.indexOf(",")));
+ int y = Integer.parseInt(xy.substring(xy.indexOf(",") + 1));
+ AndroidDeviceBridgeTool.executeCommand(udIdMap.get(session), "input tap " + x + " " + y);
+ }
+ if (msg.getString("detail").equals("longPress")) {
+ String xy = msg.getString("point");
+ int x = Integer.parseInt(xy.substring(0, xy.indexOf(",")));
+ int y = Integer.parseInt(xy.substring(xy.indexOf(",") + 1));
+ AndroidDeviceBridgeTool.executeCommand(udIdMap.get(session), "input swipe " + x + " " + y + " " + x + " " + y + " 1500");
+ }
+ if (msg.getString("detail").equals("swipe")) {
+ String xy1 = msg.getString("pointA");
+ String xy2 = msg.getString("pointB");
+ int x1 = Integer.parseInt(xy1.substring(0, xy1.indexOf(",")));
+ 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 + " 200");
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ if (msg.getString("detail").equals("install")) {
+ AndroidDeviceThreadPool.cachedThreadPool.execute(() -> {
+ JSONObject result = new JSONObject();
+ result.put("msg", "installFinish");
+ try {
+ File localFile = DownImageTool.download(msg.getString("apk"));
+ udIdMap.get(session).installPackage(localFile.getAbsolutePath(), true, "-t");
+ result.put("status", "success");
+ } catch (IOException | InstallException e) {
+ result.put("status", "fail");
+ e.printStackTrace();
+ }
+ AgentTool.sendText(session, result.toJSONString());
+ });
+ }
+ if (msg.getString("detail").equals("tree")) {
+ AndroidStepHandler finalAndroidStepHandler = androidStepHandler;
+ AndroidDeviceThreadPool.cachedThreadPool.execute(() -> {
+ try {
+ JSONObject result = new JSONObject();
+ result.put("msg", "tree");
+ result.put("detail", finalAndroidStepHandler.getResource());
+ HandleDes handleDes = new HandleDes();
+ if (!msg.getBoolean("hasScreen")) {
+ result.put("img", finalAndroidStepHandler.stepScreen(handleDes));
+ }
+ if (handleDes.getE() != null) {
+ logger.error(handleDes.getE().getMessage());
+ JSONObject resultFail = new JSONObject();
+ resultFail.put("msg", "treeFail");
+ AgentTool.sendText(session, resultFail.toJSONString());
+ } else {
+ result.put("webView", finalAndroidStepHandler.getWebView());
+ result.put("activity", finalAndroidStepHandler.getCurrentActivity());
+ AgentTool.sendText(session, result.toJSONString());
+ }
+ } catch (Throwable e) {
+ logger.error(e.getMessage());
+ JSONObject result = new JSONObject();
+ result.put("msg", "treeFail");
+ AgentTool.sendText(session, result.toJSONString());
+ }
+ });
+ }
+ if (msg.getString("detail").equals("eleScreen")) {
+ AndroidStepHandler finalAndroidStepHandler = androidStepHandler;
+ AndroidDeviceThreadPool.cachedThreadPool.execute(() -> {
+ JSONObject result = new JSONObject();
+ result.put("msg", "eleScreen");
+ try {
+ result.put("img", UploadTools.upload(finalAndroidStepHandler.findEle("xpath", msg.getString("xpath")).getScreenshotAs(OutputType.FILE), "keepFiles"));
+ } catch (Exception e) {
+ result.put("errMsg", "获取元素截图失败!");
+ }
+ AgentTool.sendText(session, result.toJSONString());
+ });
+ }
+ }
+ break;
+ }
+ }
+
+ private void exit(Session session) {
+ AndroidDeviceLocalStatus.finish(session.getUserProperties().get("udId") + "");
+ try {
+ HandlerMap.getAndroidMap().get(session.getId()).closeAndroidDriver();
+ } catch (Exception e) {
+ logger.info("关闭driver异常!");
+ } finally {
+ HandlerMap.getAndroidMap().remove(session.getId());
+ }
+ if (udIdMap.get(session) != null) {
+ List has = webViewForwardMap.get(udIdMap.get(session));
+ if (has != null && has.size() > 0) {
+ for (JSONObject j : has) {
+ AndroidDeviceBridgeTool.removeForward(udIdMap.get(session), j.getInteger("port"), j.getString("name"));
+ }
+ }
+ webViewForwardMap.remove(udIdMap.get(session));
+ if (isEnableAdbKit) {
+ String processName = String.format("process-%s-adbkit", udIdMap.get(session).getSerialNumber());
+ if (GlobalProcessMap.getMap().get(processName) != null) {
+ Process ps = GlobalProcessMap.getMap().get(processName);
+ ps.children().forEach(ProcessHandle::destroy);
+ ps.destroy();
+ }
+ }
+ }
+ outputMap.remove(session);
+ udIdMap.remove(session);
+ if (rotationMap.get(session) != null) {
+ rotationMap.get(session).interrupt();
+ }
+ rotationMap.remove(session);
+ if (MiniCapMap.getMap().get(session) != null) {
+ MiniCapMap.getMap().get(session).interrupt();
+ }
+ WebSocketSessionMap.removeSession(session);
+ try {
+ session.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ logger.info(session.getId() + "退出");
+ }
+}
diff --git a/src/main/java/com/sonic/agent/websockets/IOSWSServer.java b/src/main/java/org/cloud/sonic/agent/websockets/IOSWSServer.java
similarity index 95%
rename from src/main/java/com/sonic/agent/websockets/IOSWSServer.java
rename to src/main/java/org/cloud/sonic/agent/websockets/IOSWSServer.java
index efc65b0b..10ff47a0 100644
--- a/src/main/java/com/sonic/agent/websockets/IOSWSServer.java
+++ b/src/main/java/org/cloud/sonic/agent/websockets/IOSWSServer.java
@@ -1,20 +1,19 @@
-package com.sonic.agent.websockets;
+package org.cloud.sonic.agent.websockets;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
-import com.android.ddmlib.InstallException;
-import com.sonic.agent.automation.HandleDes;
-import com.sonic.agent.automation.IOSStepHandler;
-import com.sonic.agent.bridge.ios.IOSDeviceLocalStatus;
-import com.sonic.agent.bridge.ios.IOSDeviceThreadPool;
-import com.sonic.agent.bridge.ios.TIDeviceTool;
-import com.sonic.agent.interfaces.DeviceStatus;
-import com.sonic.agent.maps.DevicesLockMap;
-import com.sonic.agent.maps.HandlerMap;
-import com.sonic.agent.maps.WebSocketSessionMap;
-import com.sonic.agent.netty.NettyThreadPool;
-import com.sonic.agent.tools.DownImageTool;
-import com.sonic.agent.tools.UploadTools;
+import org.cloud.sonic.agent.automation.HandleDes;
+import org.cloud.sonic.agent.automation.IOSStepHandler;
+import org.cloud.sonic.agent.bridge.ios.IOSDeviceLocalStatus;
+import org.cloud.sonic.agent.bridge.ios.IOSDeviceThreadPool;
+import org.cloud.sonic.agent.bridge.ios.TIDeviceTool;
+import org.cloud.sonic.agent.interfaces.DeviceStatus;
+import org.cloud.sonic.agent.maps.DevicesLockMap;
+import org.cloud.sonic.agent.maps.HandlerMap;
+import org.cloud.sonic.agent.maps.WebSocketSessionMap;
+import org.cloud.sonic.agent.netty.NettyThreadPool;
+import org.cloud.sonic.agent.tools.DownImageTool;
+import org.cloud.sonic.agent.tools.UploadTools;
import io.appium.java_client.TouchAction;
import io.appium.java_client.touch.WaitOptions;
import io.appium.java_client.touch.offset.PointOption;
@@ -34,8 +33,6 @@
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
-import static com.sonic.agent.tools.AgentTool.sendText;
-
@Component
@ServerEndpoint(value = "/websockets/ios/{key}/{udId}/{token}", configurator = MyEndpointConfigure.class)
public class IOSWSServer {
diff --git a/src/main/java/com/sonic/agent/websockets/MyEndpointConfigure.java b/src/main/java/org/cloud/sonic/agent/websockets/MyEndpointConfigure.java
similarity index 92%
rename from src/main/java/com/sonic/agent/websockets/MyEndpointConfigure.java
rename to src/main/java/org/cloud/sonic/agent/websockets/MyEndpointConfigure.java
index 18f5d433..ed7ebc3d 100644
--- a/src/main/java/com/sonic/agent/websockets/MyEndpointConfigure.java
+++ b/src/main/java/org/cloud/sonic/agent/websockets/MyEndpointConfigure.java
@@ -1,23 +1,23 @@
-package com.sonic.agent.websockets;
-
-import org.springframework.beans.BeansException;
-import org.springframework.beans.factory.BeanFactory;
-import org.springframework.context.ApplicationContext;
-import org.springframework.context.ApplicationContextAware;
-
-import javax.websocket.server.ServerEndpointConfig;
-
-public class MyEndpointConfigure extends ServerEndpointConfig.Configurator implements ApplicationContextAware {
-
- private static volatile BeanFactory context;
-
- @Override
- public T getEndpointInstance(Class clazz){
- return context.getBean(clazz);
- }
-
- @Override
- public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
- MyEndpointConfigure.context = applicationContext;
- }
+package org.cloud.sonic.agent.websockets;
+
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.BeanFactory;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+
+import javax.websocket.server.ServerEndpointConfig;
+
+public class MyEndpointConfigure extends ServerEndpointConfig.Configurator implements ApplicationContextAware {
+
+ private static volatile BeanFactory context;
+
+ @Override
+ public T getEndpointInstance(Class clazz){
+ return context.getBean(clazz);
+ }
+
+ @Override
+ public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
+ MyEndpointConfigure.context = applicationContext;
+ }
}
\ No newline at end of file
diff --git a/src/main/java/com/sonic/agent/websockets/TerminalWSServer.java b/src/main/java/org/cloud/sonic/agent/websockets/TerminalWSServer.java
similarity index 95%
rename from src/main/java/com/sonic/agent/websockets/TerminalWSServer.java
rename to src/main/java/org/cloud/sonic/agent/websockets/TerminalWSServer.java
index b2bc2ad7..96a2327f 100644
--- a/src/main/java/com/sonic/agent/websockets/TerminalWSServer.java
+++ b/src/main/java/org/cloud/sonic/agent/websockets/TerminalWSServer.java
@@ -1,220 +1,220 @@
-package com.sonic.agent.websockets;
-
-import com.alibaba.fastjson.JSON;
-import com.alibaba.fastjson.JSONObject;
-import com.android.ddmlib.*;
-import com.sonic.agent.bridge.android.AndroidDeviceBridgeTool;
-import com.sonic.agent.bridge.android.AndroidDeviceThreadPool;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.stereotype.Component;
-
-import javax.websocket.*;
-import javax.websocket.server.PathParam;
-import javax.websocket.server.ServerEndpoint;
-import java.io.IOException;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.Future;
-import java.util.concurrent.TimeUnit;
-
-/**
- * @author ZhouYiXun
- * @des
- * @date 2021/10/30 23:35
- */
-@Component
-@ServerEndpoint(value = "/websockets/terminal/{key}/{udId}", configurator = MyEndpointConfigure.class)
-public class TerminalWSServer {
- private final Logger logger = LoggerFactory.getLogger(TerminalWSServer.class);
- @Value("${sonic.agent.key}")
- private String key;
- private Map udIdMap = new ConcurrentHashMap<>();
- private Map> terminalMap = new ConcurrentHashMap<>();
- private Map> logcatMap = new ConcurrentHashMap<>();
-
- @OnOpen
- public void onOpen(Session session, @PathParam("key") String secretKey, @PathParam("udId") String udId) throws Exception {
- if (secretKey.length() == 0 || (!secretKey.equals(key))) {
- logger.info("拦截访问!");
- return;
- }
- IDevice iDevice = AndroidDeviceBridgeTool.getIDeviceByUdId(udId);
- udIdMap.put(session, iDevice);
- String username = iDevice.getProperty("ro.product.device");
- Future> terminal = AndroidDeviceThreadPool.cachedThreadPool.submit(() -> {
- logger.info(udId + "开启terminal");
- JSONObject ter = new JSONObject();
- ter.put("msg", "terminal");
- ter.put("user", username);
- sendText(session, ter.toJSONString());
- });
- Future> logcat = AndroidDeviceThreadPool.cachedThreadPool.submit(() -> {
- logger.info(udId + "开启logcat");
- JSONObject ter = new JSONObject();
- ter.put("msg", "logcat");
- sendText(session, ter.toJSONString());
- });
- terminalMap.put(session, terminal);
- logcatMap.put(session, logcat);
- }
-
- @OnMessage
- public void onMessage(String message, Session session) {
- JSONObject msg = JSON.parseObject(message);
- logger.info(session.getId() + " 发送 " + msg);
- switch (msg.getString("type")) {
- case "stopCmd":
- Future> ter = terminalMap.get(session);
- if (!ter.isDone() || !ter.isCancelled()) {
- try {
- ter.cancel(true);
- } catch (Exception e) {
- logger.error(e.getMessage());
- }
- }
- break;
- case "command":
- if (msg.getString("detail").contains("reboot")
- || msg.getString("detail").contains("rm")
- || msg.getString("detail").contains("su ")) {
- JSONObject done = new JSONObject();
- done.put("msg", "terDone");
- sendText(session, done.toJSONString());
- return;
- }
- ter = AndroidDeviceThreadPool.cachedThreadPool.submit(() -> {
- try {
- udIdMap.get(session).executeShellCommand(msg.getString("detail"), new IShellOutputReceiver() {
- @Override
- public void addOutput(byte[] bytes, int i, int i1) {
- String res = new String(bytes, i, i1);
- JSONObject resp = new JSONObject();
- resp.put("msg", "terResp");
- resp.put("detail", res);
- sendText(session, resp.toJSONString());
- }
-
- @Override
- public void flush() {
- }
-
- @Override
- public boolean isCancelled() {
- return false;
- }
- }, 0, TimeUnit.MILLISECONDS);
- } catch (Throwable e) {
- return;
- }
- JSONObject done = new JSONObject();
- done.put("msg", "terDone");
- sendText(session, done.toJSONString());
- });
- terminalMap.put(session, ter);
- break;
- case "stopLogcat": {
- Future> logcat = logcatMap.get(session);
- if (!logcat.isDone() || !logcat.isCancelled()) {
- try {
- logcat.cancel(true);
- } catch (Exception e) {
- logger.error(e.getMessage());
- }
- }
- break;
- }
- case "logcat": {
- Future> logcat = logcatMap.get(session);
- if (!logcat.isDone() || !logcat.isCancelled()) {
- try {
- logcat.cancel(true);
- } catch (Exception e) {
- logger.error(e.getMessage());
- }
- }
- logcat = AndroidDeviceThreadPool.cachedThreadPool.submit(() -> {
- try {
- udIdMap.get(session).executeShellCommand("logcat *:"
- + msg.getString("level") +
- (msg.getString("filter").length() > 0 ?
- " | grep " + msg.getString("filter") : ""), new IShellOutputReceiver() {
- @Override
- public void addOutput(byte[] bytes, int i, int i1) {
- String res = new String(bytes, i, i1);
- JSONObject resp = new JSONObject();
- resp.put("msg", "logcatResp");
- resp.put("detail", res);
- sendText(session, resp.toJSONString());
- }
-
- @Override
- public void flush() {
- }
-
- @Override
- public boolean isCancelled() {
- return false;
- }
- }, 0, TimeUnit.MILLISECONDS);
- } catch (Throwable e) {
- return;
- }
- });
- logcatMap.put(session, logcat);
- break;
- }
- }
- }
-
- @OnClose
- public void onClose(Session session) {
- exit(session);
- }
-
- @OnError
- public void onError(Session session, Throwable error) {
- logger.error(error.getMessage());
- JSONObject errMsg = new JSONObject();
- errMsg.put("msg", "error");
- sendText(session, errMsg.toJSONString());
- }
-
- private void exit(Session session) {
- Future> cmd = terminalMap.get(session);
- if (!cmd.isDone() || !cmd.isCancelled()) {
- try {
- cmd.cancel(true);
- } catch (Exception e) {
- logger.error(e.getMessage());
- }
- }
- terminalMap.remove(session);
- Future> logcat = logcatMap.get(session);
- if (!logcat.isDone() || !logcat.isCancelled()) {
- try {
- logcat.cancel(true);
- } catch (Exception e) {
- logger.error(e.getMessage());
- }
- }
- logcatMap.remove(session);
- try {
- session.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- logger.info(session.getId() + "退出");
- }
-
- private void sendText(Session session, String message) {
- synchronized (session) {
- try {
- session.getBasicRemote().sendText(message);
- } catch (IllegalStateException | IOException e) {
- logger.error("webSocket发送失败!连接已关闭!");
- }
- }
- }
-}
+package org.cloud.sonic.agent.websockets;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import com.android.ddmlib.*;
+import org.cloud.sonic.agent.bridge.android.AndroidDeviceBridgeTool;
+import org.cloud.sonic.agent.bridge.android.AndroidDeviceThreadPool;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
+import javax.websocket.*;
+import javax.websocket.server.PathParam;
+import javax.websocket.server.ServerEndpoint;
+import java.io.IOException;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * @author ZhouYiXun
+ * @des
+ * @date 2021/10/30 23:35
+ */
+@Component
+@ServerEndpoint(value = "/websockets/terminal/{key}/{udId}", configurator = MyEndpointConfigure.class)
+public class TerminalWSServer {
+ private final Logger logger = LoggerFactory.getLogger(TerminalWSServer.class);
+ @Value("${sonic.agent.key}")
+ private String key;
+ private Map udIdMap = new ConcurrentHashMap<>();
+ private Map> terminalMap = new ConcurrentHashMap<>();
+ private Map> logcatMap = new ConcurrentHashMap<>();
+
+ @OnOpen
+ public void onOpen(Session session, @PathParam("key") String secretKey, @PathParam("udId") String udId) throws Exception {
+ if (secretKey.length() == 0 || (!secretKey.equals(key))) {
+ logger.info("拦截访问!");
+ return;
+ }
+ IDevice iDevice = AndroidDeviceBridgeTool.getIDeviceByUdId(udId);
+ udIdMap.put(session, iDevice);
+ String username = iDevice.getProperty("ro.product.device");
+ Future> terminal = AndroidDeviceThreadPool.cachedThreadPool.submit(() -> {
+ logger.info(udId + "开启terminal");
+ JSONObject ter = new JSONObject();
+ ter.put("msg", "terminal");
+ ter.put("user", username);
+ sendText(session, ter.toJSONString());
+ });
+ Future> logcat = AndroidDeviceThreadPool.cachedThreadPool.submit(() -> {
+ logger.info(udId + "开启logcat");
+ JSONObject ter = new JSONObject();
+ ter.put("msg", "logcat");
+ sendText(session, ter.toJSONString());
+ });
+ terminalMap.put(session, terminal);
+ logcatMap.put(session, logcat);
+ }
+
+ @OnMessage
+ public void onMessage(String message, Session session) {
+ JSONObject msg = JSON.parseObject(message);
+ logger.info(session.getId() + " 发送 " + msg);
+ switch (msg.getString("type")) {
+ case "stopCmd":
+ Future> ter = terminalMap.get(session);
+ if (!ter.isDone() || !ter.isCancelled()) {
+ try {
+ ter.cancel(true);
+ } catch (Exception e) {
+ logger.error(e.getMessage());
+ }
+ }
+ break;
+ case "command":
+ if (msg.getString("detail").contains("reboot")
+ || msg.getString("detail").contains("rm")
+ || msg.getString("detail").contains("su ")) {
+ JSONObject done = new JSONObject();
+ done.put("msg", "terDone");
+ sendText(session, done.toJSONString());
+ return;
+ }
+ ter = AndroidDeviceThreadPool.cachedThreadPool.submit(() -> {
+ try {
+ udIdMap.get(session).executeShellCommand(msg.getString("detail"), new IShellOutputReceiver() {
+ @Override
+ public void addOutput(byte[] bytes, int i, int i1) {
+ String res = new String(bytes, i, i1);
+ JSONObject resp = new JSONObject();
+ resp.put("msg", "terResp");
+ resp.put("detail", res);
+ sendText(session, resp.toJSONString());
+ }
+
+ @Override
+ public void flush() {
+ }
+
+ @Override
+ public boolean isCancelled() {
+ return false;
+ }
+ }, 0, TimeUnit.MILLISECONDS);
+ } catch (Throwable e) {
+ return;
+ }
+ JSONObject done = new JSONObject();
+ done.put("msg", "terDone");
+ sendText(session, done.toJSONString());
+ });
+ terminalMap.put(session, ter);
+ break;
+ case "stopLogcat": {
+ Future> logcat = logcatMap.get(session);
+ if (!logcat.isDone() || !logcat.isCancelled()) {
+ try {
+ logcat.cancel(true);
+ } catch (Exception e) {
+ logger.error(e.getMessage());
+ }
+ }
+ break;
+ }
+ case "logcat": {
+ Future> logcat = logcatMap.get(session);
+ if (!logcat.isDone() || !logcat.isCancelled()) {
+ try {
+ logcat.cancel(true);
+ } catch (Exception e) {
+ logger.error(e.getMessage());
+ }
+ }
+ logcat = AndroidDeviceThreadPool.cachedThreadPool.submit(() -> {
+ try {
+ udIdMap.get(session).executeShellCommand("logcat *:"
+ + msg.getString("level") +
+ (msg.getString("filter").length() > 0 ?
+ " | grep " + msg.getString("filter") : ""), new IShellOutputReceiver() {
+ @Override
+ public void addOutput(byte[] bytes, int i, int i1) {
+ String res = new String(bytes, i, i1);
+ JSONObject resp = new JSONObject();
+ resp.put("msg", "logcatResp");
+ resp.put("detail", res);
+ sendText(session, resp.toJSONString());
+ }
+
+ @Override
+ public void flush() {
+ }
+
+ @Override
+ public boolean isCancelled() {
+ return false;
+ }
+ }, 0, TimeUnit.MILLISECONDS);
+ } catch (Throwable e) {
+ return;
+ }
+ });
+ logcatMap.put(session, logcat);
+ break;
+ }
+ }
+ }
+
+ @OnClose
+ public void onClose(Session session) {
+ exit(session);
+ }
+
+ @OnError
+ public void onError(Session session, Throwable error) {
+ logger.error(error.getMessage());
+ JSONObject errMsg = new JSONObject();
+ errMsg.put("msg", "error");
+ sendText(session, errMsg.toJSONString());
+ }
+
+ private void exit(Session session) {
+ Future> cmd = terminalMap.get(session);
+ if (!cmd.isDone() || !cmd.isCancelled()) {
+ try {
+ cmd.cancel(true);
+ } catch (Exception e) {
+ logger.error(e.getMessage());
+ }
+ }
+ terminalMap.remove(session);
+ Future> logcat = logcatMap.get(session);
+ if (!logcat.isDone() || !logcat.isCancelled()) {
+ try {
+ logcat.cancel(true);
+ } catch (Exception e) {
+ logger.error(e.getMessage());
+ }
+ }
+ logcatMap.remove(session);
+ try {
+ session.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ logger.info(session.getId() + "退出");
+ }
+
+ private void sendText(Session session, String message) {
+ synchronized (session) {
+ try {
+ session.getBasicRemote().sendText(message);
+ } catch (IllegalStateException | IOException e) {
+ logger.error("webSocket发送失败!连接已关闭!");
+ }
+ }
+ }
+}
diff --git a/src/main/java/com/sonic/agent/websockets/WebSocketConfig.java b/src/main/java/org/cloud/sonic/agent/websockets/WebSocketConfig.java
similarity index 90%
rename from src/main/java/com/sonic/agent/websockets/WebSocketConfig.java
rename to src/main/java/org/cloud/sonic/agent/websockets/WebSocketConfig.java
index 150d715a..e7b4e519 100644
--- a/src/main/java/com/sonic/agent/websockets/WebSocketConfig.java
+++ b/src/main/java/org/cloud/sonic/agent/websockets/WebSocketConfig.java
@@ -1,18 +1,18 @@
-package com.sonic.agent.websockets;
-
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.web.socket.server.standard.ServerEndpointExporter;
-
-@Configuration
-public class WebSocketConfig {
- @Bean
- public ServerEndpointExporter serverEndpointExporter() {
- return new ServerEndpointExporter();
- }
-
- @Bean
- public MyEndpointConfigure newMyEndpointConfigure (){
- return new MyEndpointConfigure ();
- }
+package org.cloud.sonic.agent.websockets;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.socket.server.standard.ServerEndpointExporter;
+
+@Configuration
+public class WebSocketConfig {
+ @Bean
+ public ServerEndpointExporter serverEndpointExporter() {
+ return new ServerEndpointExporter();
+ }
+
+ @Bean
+ public MyEndpointConfigure newMyEndpointConfigure (){
+ return new MyEndpointConfigure ();
+ }
}
\ No newline at end of file
diff --git a/src/main/java/com/sonic/agent/websockets/WebViewWSServer.java b/src/main/java/org/cloud/sonic/agent/websockets/WebViewWSServer.java
similarity index 94%
rename from src/main/java/com/sonic/agent/websockets/WebViewWSServer.java
rename to src/main/java/org/cloud/sonic/agent/websockets/WebViewWSServer.java
index 5fd1abdc..68cfaa70 100644
--- a/src/main/java/com/sonic/agent/websockets/WebViewWSServer.java
+++ b/src/main/java/org/cloud/sonic/agent/websockets/WebViewWSServer.java
@@ -1,95 +1,94 @@
-package com.sonic.agent.websockets;
-
-import com.alibaba.fastjson.JSONObject;
-import org.java_websocket.client.WebSocketClient;
-import org.java_websocket.handshake.ServerHandshake;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.stereotype.Component;
-
-import javax.websocket.*;
-import javax.websocket.server.PathParam;
-import javax.websocket.server.ServerEndpoint;
-import java.io.IOException;
-import java.net.URI;
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * @author ZhouYiXun
- * @des
- * @date 2021/10/25 23:03
- */
-@Component
-@ServerEndpoint(value = "/websockets/webView/{key}/{port}/{id}", configurator = MyEndpointConfigure.class)
-public class WebViewWSServer {
- private final Logger logger = LoggerFactory.getLogger(WebViewWSServer.class);
- @Value("${sonic.agent.key}")
- private String key;
- private Map sessionWebSocketClientMap = new HashMap<>();
-
- @OnOpen
- public void onOpen(Session session, @PathParam("key") String secretKey, @PathParam("port") int port, @PathParam("id") String id) throws Exception {
- if (secretKey.length() == 0 || (!secretKey.equals(key))) {
- logger.info("拦截访问!");
- return;
- }
- URI uri = new URI("ws://localhost:" + port + "/devtools/page/" + id);
- WebSocketClient webSocketClient = new WebSocketClient(uri) {
- @Override
- public void onOpen(ServerHandshake serverHandshake) {
- logger.info("连接成功!");
- }
-
- @Override
- public void onMessage(String s) {
- sendText(session, s);
- }
-
- @Override
- public void onClose(int i, String s, boolean b) {
- logger.info("连接断开!");
- }
-
- @Override
- public void onError(Exception e) {
-
- }
- };
- webSocketClient.connect();
- sessionWebSocketClientMap.put(session, webSocketClient);
- }
-
- @OnMessage
- public void onMessage(String message, Session session) throws InterruptedException {
- if (sessionWebSocketClientMap.get(session) != null) {
- try {
- sessionWebSocketClientMap.get(session).send(message);
- } catch (Exception e) {
-
- }
- }
- }
-
- @OnClose
- public void onClose(Session session) {
- sessionWebSocketClientMap.get(session).close();
- sessionWebSocketClientMap.remove(session);
- }
-
- @OnError
- public void onError(Session session, Throwable error) {
- logger.error(error.getMessage());
- }
-
- private void sendText(Session session, String message) {
- synchronized (session) {
- try {
- session.getBasicRemote().sendText(message);
- } catch (IllegalStateException | IOException e) {
- logger.error("webSocket发送失败!连接已关闭!");
- }
- }
- }
-}
+package org.cloud.sonic.agent.websockets;
+
+import org.java_websocket.client.WebSocketClient;
+import org.java_websocket.handshake.ServerHandshake;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
+import javax.websocket.*;
+import javax.websocket.server.PathParam;
+import javax.websocket.server.ServerEndpoint;
+import java.io.IOException;
+import java.net.URI;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author ZhouYiXun
+ * @des
+ * @date 2021/10/25 23:03
+ */
+@Component
+@ServerEndpoint(value = "/websockets/webView/{key}/{port}/{id}", configurator = MyEndpointConfigure.class)
+public class WebViewWSServer {
+ private final Logger logger = LoggerFactory.getLogger(WebViewWSServer.class);
+ @Value("${sonic.agent.key}")
+ private String key;
+ private Map sessionWebSocketClientMap = new HashMap<>();
+
+ @OnOpen
+ public void onOpen(Session session, @PathParam("key") String secretKey, @PathParam("port") int port, @PathParam("id") String id) throws Exception {
+ if (secretKey.length() == 0 || (!secretKey.equals(key))) {
+ logger.info("拦截访问!");
+ return;
+ }
+ URI uri = new URI("ws://localhost:" + port + "/devtools/page/" + id);
+ WebSocketClient webSocketClient = new WebSocketClient(uri) {
+ @Override
+ public void onOpen(ServerHandshake serverHandshake) {
+ logger.info("连接成功!");
+ }
+
+ @Override
+ public void onMessage(String s) {
+ sendText(session, s);
+ }
+
+ @Override
+ public void onClose(int i, String s, boolean b) {
+ logger.info("连接断开!");
+ }
+
+ @Override
+ public void onError(Exception e) {
+
+ }
+ };
+ webSocketClient.connect();
+ sessionWebSocketClientMap.put(session, webSocketClient);
+ }
+
+ @OnMessage
+ public void onMessage(String message, Session session) throws InterruptedException {
+ if (sessionWebSocketClientMap.get(session) != null) {
+ try {
+ sessionWebSocketClientMap.get(session).send(message);
+ } catch (Exception e) {
+
+ }
+ }
+ }
+
+ @OnClose
+ public void onClose(Session session) {
+ sessionWebSocketClientMap.get(session).close();
+ sessionWebSocketClientMap.remove(session);
+ }
+
+ @OnError
+ public void onError(Session session, Throwable error) {
+ logger.error(error.getMessage());
+ }
+
+ private void sendText(Session session, String message) {
+ synchronized (session) {
+ try {
+ session.getBasicRemote().sendText(message);
+ } catch (IllegalStateException | IOException e) {
+ logger.error("webSocket发送失败!连接已关闭!");
+ }
+ }
+ }
+}