ios和android录屏
parent
fd88ef376a
commit
509a7278fc
|
@ -689,9 +689,9 @@ public class MobileDeviceConnection extends AbstractDeviceConnection {
|
||||||
@Override
|
@Override
|
||||||
public void startRecord() {
|
public void startRecord() {
|
||||||
if ("0".equals(deviceInfo.getPlatform())) {
|
if ("0".equals(deviceInfo.getPlatform())) {
|
||||||
AndroidUtil.startRecord(this.remoteAddress, deviceInfo.getDeviceId(), deviceInfo.getOtherInfo().get("taskId"));
|
AndroidUtil.startRecord(this.remoteAddress, deviceInfo.getDeviceId(), deviceInfo.getOtherInfo().get("taskId"),deviceInfo.getOtherInfo().get("tenantId"));
|
||||||
} else {
|
} else {
|
||||||
IosUtil.startRecord(this.remoteAddress, deviceInfo.getDeviceId(), deviceInfo.getOtherInfo().get("taskId"), deviceInfo.getResolution());
|
IosUtil.startRecord(this.remoteAddress, deviceInfo.getDeviceId(), deviceInfo.getOtherInfo().get("taskId"), deviceInfo.getOtherInfo().get("tenantId"),deviceInfo.getResolution());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -589,6 +589,7 @@ public class DefaultExecThread implements AtuExecThread{
|
||||||
otherInfo = new HashMap<>();
|
otherInfo = new HashMap<>();
|
||||||
}
|
}
|
||||||
otherInfo.put("taskId",task.getTaskId());
|
otherInfo.put("taskId",task.getTaskId());
|
||||||
|
otherInfo.put("tenantId", task.getTenantId());
|
||||||
deviceConnection.getDeviceInfo().setOtherInfo(otherInfo);
|
deviceConnection.getDeviceInfo().setOtherInfo(otherInfo);
|
||||||
//开启录屏
|
//开启录屏
|
||||||
deviceConnection.startRecord();
|
deviceConnection.startRecord();
|
||||||
|
|
|
@ -55,10 +55,11 @@ public class AndroidUtil {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String startRecord(String remoteAddress,String deviceId,String taskId){
|
public static String startRecord(String remoteAddress,String deviceId,String taskId,String tenantId){
|
||||||
DebuggerDeviceInfo info = new DebuggerDeviceInfo();
|
DebuggerDeviceInfo info = new DebuggerDeviceInfo();
|
||||||
info.setDeviceId(deviceId);
|
info.setDeviceId(deviceId);
|
||||||
info.setPlatform("0");
|
info.setPlatform("0");
|
||||||
|
info.setTenantId(tenantId);
|
||||||
logger.info("移动任务开启录屏,任务id:"+taskId);
|
logger.info("移动任务开启录屏,任务id:"+taskId);
|
||||||
info.setTaskId(taskId);
|
info.setTaskId(taskId);
|
||||||
logger.info("录屏参数:{}", JSON.toJSONString(info));
|
logger.info("录屏参数:{}", JSON.toJSONString(info));
|
||||||
|
|
|
@ -122,10 +122,11 @@ public class IosUtil {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static String startRecord(String remoteAddress, String deviceId, String taskId, String resolution) {
|
public static String startRecord(String remoteAddress, String deviceId, String taskId, String tenantId,String resolution) {
|
||||||
DebuggerDeviceInfo info = new DebuggerDeviceInfo();
|
DebuggerDeviceInfo info = new DebuggerDeviceInfo();
|
||||||
info.setDeviceId(deviceId);
|
info.setDeviceId(deviceId);
|
||||||
info.setPlatform("1");
|
info.setPlatform("1");
|
||||||
|
info.setTenantId(tenantId);
|
||||||
logger.info("移动任务开启录屏,任务id:" + taskId);
|
logger.info("移动任务开启录屏,任务id:" + taskId);
|
||||||
info.setTaskId(taskId);
|
info.setTaskId(taskId);
|
||||||
info.setResolution(resolution);
|
info.setResolution(resolution);
|
||||||
|
|
|
@ -16,6 +16,7 @@ import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.http.HttpEntity;
|
import org.springframework.http.HttpEntity;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
import javax.websocket.Session;
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.math.RoundingMode;
|
import java.math.RoundingMode;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
|
@ -46,6 +47,7 @@ public abstract class AbstractDeviceManager extends Thread implements DeviceMana
|
||||||
SpringUtils.getBean(DeviceConnectionService.class).deviceAgentDead(serial);
|
SpringUtils.getBean(DeviceConnectionService.class).deviceAgentDead(serial);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected void publishDeviceOnlineToWebConnection(String deviceId) {
|
protected void publishDeviceOnlineToWebConnection(String deviceId) {
|
||||||
MessageHandler handleMessageThread = SpringUtils.getBean(DeviceConnectionService.class).getHandleMessageThread(deviceId);
|
MessageHandler handleMessageThread = SpringUtils.getBean(DeviceConnectionService.class).getHandleMessageThread(deviceId);
|
||||||
if (null != handleMessageThread) {
|
if (null != handleMessageThread) {
|
||||||
|
@ -176,4 +178,6 @@ public abstract class AbstractDeviceManager extends Thread implements DeviceMana
|
||||||
brand.setBrandName(manufacturer.toUpperCase());
|
brand.setBrandName(manufacturer.toUpperCase());
|
||||||
return brand;
|
return brand;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public abstract void stopWebScreen(String udid, Session session);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,15 +1,16 @@
|
||||||
package net.northking.cctp.upperComputer.deviceManager;
|
package net.northking.cctp.upperComputer.deviceManager;
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.JSON;
|
||||||
|
import net.northking.cctp.upperComputer.deviceManager.screen.AndroidScreenResponseThread;
|
||||||
import net.northking.cctp.upperComputer.deviceManager.thread.AndroidDeviceInitThread;
|
import net.northking.cctp.upperComputer.deviceManager.thread.AndroidDeviceInitThread;
|
||||||
import net.northking.cctp.upperComputer.driver.adb.Adb;
|
import net.northking.cctp.upperComputer.driver.adb.Adb;
|
||||||
import net.northking.cctp.upperComputer.driver.adb.AdbDevice;
|
import net.northking.cctp.upperComputer.driver.adb.AdbDevice;
|
||||||
import net.northking.cctp.upperComputer.driver.adb.AndroidDeviceListener;
|
import net.northking.cctp.upperComputer.driver.adb.AndroidDeviceListener;
|
||||||
import net.northking.cctp.upperComputer.webSocket.thread.AndroidScreenResponseThread;
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.util.CollectionUtils;
|
import org.springframework.util.CollectionUtils;
|
||||||
|
|
||||||
|
import javax.websocket.Session;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
@ -73,6 +74,11 @@ public class AndroidDeviceManager extends AbstractDeviceManager {
|
||||||
deviceSystemIsReady.put(serial, status);
|
deviceSystemIsReady.put(serial, status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean getDeviceSystemStatus(String serial) {
|
||||||
|
return deviceSystemIsReady.get(serial);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void shutdown() {
|
public void shutdown() {
|
||||||
clearAndShutdownDevices();
|
clearAndShutdownDevices();
|
||||||
|
@ -205,7 +211,7 @@ public class AndroidDeviceManager extends AbstractDeviceManager {
|
||||||
for (AndroidScreenResponseThread screenResponseThread : screenMap.values()) {
|
for (AndroidScreenResponseThread screenResponseThread : screenMap.values()) {
|
||||||
logger.debug("上位机重启,中断残余获取屏幕线程");
|
logger.debug("上位机重启,中断残余获取屏幕线程");
|
||||||
if (null != screenResponseThread && screenResponseThread.isAlive() && !screenResponseThread.isInterrupted()) {
|
if (null != screenResponseThread && screenResponseThread.isAlive() && !screenResponseThread.isInterrupted()) {
|
||||||
screenResponseThread.stopAndExit();
|
screenResponseThread.stopFetchPic();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
screenMap.clear();
|
screenMap.clear();
|
||||||
|
@ -226,4 +232,23 @@ public class AndroidDeviceManager extends AbstractDeviceManager {
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void offlineDevice(String serial) {
|
||||||
|
synchronized (onlineDeviceInitMap){
|
||||||
|
AndroidDeviceInitThread initThread = onlineDeviceInitMap.remove(serial);
|
||||||
|
if (null != initThread && initThread.isAlive() && !initThread.isInterrupted()) {
|
||||||
|
logger.info("设备【{}】初始化线程准备退出",serial);
|
||||||
|
initThread.exit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void stopWebScreen(String udid, Session session) {
|
||||||
|
AndroidScreenResponseThread androidScreenResponseThread = screenMap.get(udid);
|
||||||
|
if (null != androidScreenResponseThread) {
|
||||||
|
androidScreenResponseThread.stopWebSessionTransform(session);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ package net.northking.cctp.upperComputer.deviceManager;
|
||||||
|
|
||||||
import net.northking.cctp.upperComputer.config.BuildWdaConfig;
|
import net.northking.cctp.upperComputer.config.BuildWdaConfig;
|
||||||
import net.northking.cctp.upperComputer.deviceManager.common.PyMobileDevice;
|
import net.northking.cctp.upperComputer.deviceManager.common.PyMobileDevice;
|
||||||
|
import net.northking.cctp.upperComputer.deviceManager.screen.IosScreenResponseThread;
|
||||||
import net.northking.cctp.upperComputer.deviceManager.thread.IosDeviceInitThread;
|
import net.northking.cctp.upperComputer.deviceManager.thread.IosDeviceInitThread;
|
||||||
import net.northking.cctp.upperComputer.deviceManager.thread.MacIosDeviceInitThread;
|
import net.northking.cctp.upperComputer.deviceManager.thread.MacIosDeviceInitThread;
|
||||||
import net.northking.cctp.upperComputer.deviceManager.thread.WindowsAndLinuxIosDeviceInitThread;
|
import net.northking.cctp.upperComputer.deviceManager.thread.WindowsAndLinuxIosDeviceInitThread;
|
||||||
|
@ -13,10 +14,10 @@ import net.northking.cctp.upperComputer.driver.usbmuxd.UsbMuxd;
|
||||||
import net.northking.cctp.upperComputer.driver.usbmuxd.payload.usbmuxd.entity.DeviceConnectionDetail;
|
import net.northking.cctp.upperComputer.driver.usbmuxd.payload.usbmuxd.entity.DeviceConnectionDetail;
|
||||||
import net.northking.cctp.upperComputer.entity.PhoneEntity;
|
import net.northking.cctp.upperComputer.entity.PhoneEntity;
|
||||||
import net.northking.cctp.upperComputer.utils.SpringUtils;
|
import net.northking.cctp.upperComputer.utils.SpringUtils;
|
||||||
import net.northking.cctp.upperComputer.webSocket.thread.IosScreenResponseThread;
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import javax.websocket.Session;
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
@ -396,4 +397,12 @@ public class IOSDeviceManager extends AbstractDeviceManager {
|
||||||
public PyMobileDevice.SpecificAppleDeviceInfo getSpecificAppleDeviceInfo(String serial){
|
public PyMobileDevice.SpecificAppleDeviceInfo getSpecificAppleDeviceInfo(String serial){
|
||||||
return pyMobileDeviceMap.get(serial);
|
return pyMobileDeviceMap.get(serial);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void stopWebScreen(String udid, Session session) {
|
||||||
|
IosScreenResponseThread iosScreenResponseThread = screenMap.get(udid);
|
||||||
|
if (null != iosScreenResponseThread) {
|
||||||
|
iosScreenResponseThread.stopWebSessionTransform(session);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package net.northking.cctp.upperComputer.webSocket.thread;
|
package net.northking.cctp.upperComputer.deviceManager.screen;
|
||||||
|
|
||||||
import net.northking.cctp.upperComputer.constants.ResponseCmd;
|
import net.northking.cctp.upperComputer.constants.ResponseCmd;
|
||||||
import net.northking.cctp.upperComputer.deviceManager.AndroidDeviceManager;
|
import net.northking.cctp.upperComputer.deviceManager.AndroidDeviceManager;
|
||||||
|
@ -7,10 +7,9 @@ import net.northking.cctp.upperComputer.driver.agent.AndroidAgentSession;
|
||||||
import net.northking.cctp.upperComputer.driver.agent.command.ScreenStreamCommand;
|
import net.northking.cctp.upperComputer.driver.agent.command.ScreenStreamCommand;
|
||||||
import net.northking.cctp.upperComputer.driver.agent.command.WatchScreenStreamCommand;
|
import net.northking.cctp.upperComputer.driver.agent.command.WatchScreenStreamCommand;
|
||||||
import net.northking.cctp.upperComputer.utils.SessionUtils;
|
import net.northking.cctp.upperComputer.utils.SessionUtils;
|
||||||
import net.northking.cctp.upperComputer.webSocket.entity.CatchParam;
|
|
||||||
import net.northking.cctp.upperComputer.webSocket.entity.CmdRequest;
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.util.CollectionUtils;
|
||||||
|
|
||||||
import javax.websocket.Session;
|
import javax.websocket.Session;
|
||||||
import java.io.DataInput;
|
import java.io.DataInput;
|
||||||
|
@ -18,42 +17,35 @@ import java.io.IOException;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
public class AndroidScreenResponseThread extends Thread {
|
public class AndroidScreenResponseThread extends ImageScreenResponse {
|
||||||
|
|
||||||
private AndroidAgentSession asyncAgentSession;
|
private AndroidAgentSession asyncAgentSession;
|
||||||
|
|
||||||
private Session wsSession;
|
|
||||||
|
|
||||||
private AdbDevice adbDevice;
|
private AdbDevice adbDevice;
|
||||||
|
|
||||||
private CmdRequest screenOnRequest;
|
|
||||||
|
|
||||||
private CatchParam catchParam;
|
|
||||||
|
|
||||||
private byte[] lastData;
|
private byte[] lastData;
|
||||||
|
|
||||||
private boolean sendDeviceStatus = true;
|
|
||||||
|
|
||||||
private final Logger logger = LoggerFactory.getLogger(AndroidScreenResponseThread.class);
|
private final Logger logger = LoggerFactory.getLogger(AndroidScreenResponseThread.class);
|
||||||
|
|
||||||
public AndroidScreenResponseThread(Session wsSession, AdbDevice adbDevice, CatchParam catchParam) {
|
public AndroidScreenResponseThread(AdbDevice adbDevice) {
|
||||||
this.wsSession = wsSession;
|
|
||||||
this.adbDevice = adbDevice;
|
this.adbDevice = adbDevice;
|
||||||
this.catchParam = catchParam;
|
this.deviceId = adbDevice.getSerial();
|
||||||
setName("[" + adbDevice.getSerial() + "-response]");
|
setName("[" + adbDevice.getSerial() + "-response]");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setScreenOnRequest(CmdRequest screenOnRequest) {
|
|
||||||
this.screenOnRequest = screenOnRequest;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
while (!isInterrupted()) {
|
while (!isInterrupted()) {
|
||||||
|
if (!CollectionUtils.isEmpty(webSessions)) {
|
||||||
//通知前端开始连接
|
//通知前端开始连接
|
||||||
Map<String, Object> messageMap = new HashMap<>();
|
Map<String, Object> messageMap = new HashMap<>();
|
||||||
messageMap.put(ResponseCmd.DeviceStatus.STATUS, ResponseCmd.DeviceStatus.CONNECTING);
|
messageMap.put(ResponseCmd.DeviceStatus.STATUS, ResponseCmd.DeviceStatus.CONNECTING);
|
||||||
SessionUtils.sendMessageInitiative(wsSession, ResponseCmd.DEVICE_STATUS, adbDevice.getSerial(), messageMap, "设备掉线了");
|
for (Session webSession : webSessions) {
|
||||||
|
if (webSession.isOpen()) {
|
||||||
|
SessionUtils.sendMessageInitiative(webSession, ResponseCmd.DEVICE_STATUS, adbDevice.getSerial(), messageMap, "设备掉线了");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
AdbDevice currentDevice = AndroidDeviceManager.getInstance().getCurrentDevice(adbDevice.getSerial());
|
AdbDevice currentDevice = AndroidDeviceManager.getInstance().getCurrentDevice(adbDevice.getSerial());
|
||||||
if (null == currentDevice) {
|
if (null == currentDevice) {
|
||||||
logger.warn("设备【{}】掉线了,等待设备准备好再打开图片流........", adbDevice.getSerial());
|
logger.warn("设备【{}】掉线了,等待设备准备好再打开图片流........", adbDevice.getSerial());
|
||||||
|
@ -74,15 +66,24 @@ public class AndroidScreenResponseThread extends Thread {
|
||||||
this.asyncAgentSession.send(screenStreamCommand);
|
this.asyncAgentSession.send(screenStreamCommand);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
logger.error("创建设备【{}】agentSession出错。。。。。。", adbDevice.getSerial(), e);
|
logger.error("创建设备【{}】agentSession出错。。。。。。", adbDevice.getSerial(), e);
|
||||||
Thread.currentThread().interrupt();
|
interrupt();
|
||||||
|
if (!CollectionUtils.isEmpty(webSessions)) {
|
||||||
|
//通知前端断开
|
||||||
Map<String, Object> result = new HashMap<>();
|
Map<String, Object> result = new HashMap<>();
|
||||||
result.put(ResponseCmd.DeviceStatus.STATUS, ResponseCmd.DeviceStatus.DISCONNECT);
|
result.put(ResponseCmd.DeviceStatus.STATUS, ResponseCmd.DeviceStatus.DISCONNECT);
|
||||||
SessionUtils.sendMessageInitiative(wsSession, ResponseCmd.DEVICE_STATUS, adbDevice.getSerial(), result, "设备连接失败");
|
for (Session webSession : webSessions) {
|
||||||
|
if (webSession.isOpen()) {
|
||||||
|
SessionUtils.sendMessageInitiative(webSession, ResponseCmd.DEVICE_STATUS, adbDevice.getSerial(), result, "设备连接失败");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
this.asyncAgentSession.closeSilence();
|
this.asyncAgentSession.closeSilence();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
sendConnectInfo2Web();
|
// sendConnectInfo2Web();
|
||||||
DataInput dataInput = this.asyncAgentSession.getDataInput();
|
DataInput dataInput = this.asyncAgentSession.getDataInput();
|
||||||
|
int receive = 1;
|
||||||
|
int send = 1;
|
||||||
while (!isInterrupted()) {
|
while (!isInterrupted()) {
|
||||||
try {
|
try {
|
||||||
int commandId = dataInput.readInt();
|
int commandId = dataInput.readInt();
|
||||||
|
@ -94,23 +95,38 @@ public class AndroidScreenResponseThread extends Thread {
|
||||||
//将获取的最新帧进行缓存
|
//将获取的最新帧进行缓存
|
||||||
if (null != screenPicContent && screenPicContent.length > 0) {
|
if (null != screenPicContent && screenPicContent.length > 0) {
|
||||||
this.lastData = screenPicContent;
|
this.lastData = screenPicContent;
|
||||||
|
logger.info("设备【{}】收到图片:{}张,大小:{}",adbDevice.getSerial(),receive++,screenPicContent.length);
|
||||||
} else {
|
} else {
|
||||||
logger.warn("设备【{}】command读取最新帧为空!",adbDevice.getSerial());
|
logger.warn("设备【{}】command读取最新帧为空!",adbDevice.getSerial());
|
||||||
|
logger.info("设备【{}】收到图片:{}张,大小为零",adbDevice.getSerial(),receive++);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
logger.error("读取数据出错了", e);
|
logger.error("读取数据出错了", e);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
//录屏
|
||||||
|
if (null != screenRecorder) {
|
||||||
|
screenRecorder.addImgToVideo(screenPicContent);
|
||||||
|
}
|
||||||
//有后端会话则给后端推送屏幕图片
|
//有后端会话则给后端推送屏幕图片
|
||||||
if (wsSession != null && wsSession.isOpen()) {
|
if (!CollectionUtils.isEmpty(webSessions)) {
|
||||||
SessionUtils.sendBinary(wsSession, screenPicContent);
|
for (Session webSession : webSessions) {
|
||||||
|
if (webSession.isOpen()) {
|
||||||
if (sendDeviceStatus) {
|
if (sendDeviceStatus) {
|
||||||
Map<String, Object> result = new HashMap<>();
|
Map<String, Object> result = new HashMap<>();
|
||||||
result.put(ResponseCmd.DeviceStatus.STATUS, ResponseCmd.DeviceStatus.CONNECTED);
|
result.put(ResponseCmd.DeviceStatus.STATUS, ResponseCmd.DeviceStatus.CONNECTED);
|
||||||
SessionUtils.sendMessageInitiative(wsSession, ResponseCmd.DEVICE_STATUS, adbDevice.getSerial(), result, "设备连接失败");
|
SessionUtils.sendMessageInitiative(webSession, ResponseCmd.DEVICE_STATUS, adbDevice.getSerial(), result, "设备连接失败");
|
||||||
sendDeviceStatus = false;
|
sendDeviceStatus = false;
|
||||||
}
|
}
|
||||||
|
logger.info("设备【{}】发送图片到微服务:{}张",adbDevice.getSerial(),send++);
|
||||||
|
SessionUtils.sendBinary(webSession, screenPicContent);
|
||||||
|
logger.info("设备【{}】发送图片到微服务完成:{}张",adbDevice.getSerial(),send);
|
||||||
|
} else {
|
||||||
|
logger.warn("推送到web端的session已经断开,sessionId:{}",webSession.getId());
|
||||||
|
//todo:操作一下,去掉webSessions里面的无效session
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
|
@ -129,58 +145,36 @@ public class AndroidScreenResponseThread extends Thread {
|
||||||
logger.warn("设备【{}】响应到上位机的屏幕线程退出..........................", adbDevice.getSerial());
|
logger.warn("设备【{}】响应到上位机的屏幕线程退出..........................", adbDevice.getSerial());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sendConnectInfo2Web() {
|
// public void sendConnectInfo2Web() {
|
||||||
//新连接需要先发送状态
|
// //新连接需要先发送状态
|
||||||
if (null != screenOnRequest) { //只发第一次screen_on指令
|
// if (null != screenOnRequest) { //只发第一次screen_on指令
|
||||||
//向前端推送之前缓存的最新帧
|
// //向前端推送之前缓存的最新帧
|
||||||
if (null != adbDevice) {
|
// if (null != adbDevice) {
|
||||||
if (null != lastData && lastData.length > 0) {
|
// if (null != lastData && lastData.length > 0) {
|
||||||
SessionUtils.sendBinary(wsSession, lastData);
|
// SessionUtils.sendBinary(wsSession, lastData);
|
||||||
logger.debug("上位机发送缓存帧成功,大小:{}", lastData.length);
|
// logger.debug("上位机发送缓存帧成功,大小:{}", lastData.length);
|
||||||
Map<String, Object> result = new HashMap<>();
|
// Map<String, Object> result = new HashMap<>();
|
||||||
result.put(ResponseCmd.DeviceStatus.STATUS, ResponseCmd.DeviceStatus.CONNECTED);
|
// result.put(ResponseCmd.DeviceStatus.STATUS, ResponseCmd.DeviceStatus.CONNECTED);
|
||||||
SessionUtils.sendMessageInitiative(wsSession, ResponseCmd.DEVICE_STATUS, adbDevice.getSerial(), result, "设备连接失败");
|
// SessionUtils.sendMessageInitiative(wsSession, ResponseCmd.DEVICE_STATUS, adbDevice.getSerial(), result, "设备连接失败");
|
||||||
sendDeviceStatus = false;
|
// sendDeviceStatus = false;
|
||||||
} else {
|
// } else {
|
||||||
logger.warn("设备【{}】缓存帧获取为空...", adbDevice.getSerial());
|
// logger.warn("设备【{}】缓存帧获取为空...", adbDevice.getSerial());
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
//向前端推送之前缓存的最新帧后发screenOn回复
|
// //向前端推送之前缓存的最新帧后发screenOn回复
|
||||||
SessionUtils.sendSuccessData(wsSession, screenOnRequest, null, "开启屏幕成功");
|
// SessionUtils.sendSuccessData(wsSession, screenOnRequest, null, "开启屏幕成功");
|
||||||
setScreenOnRequest(null);
|
// setScreenOnRequest(null);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
public void stopAndExit() {
|
@Override
|
||||||
logger.warn("设备【{}】退出屏幕获取线程...", adbDevice.getSerial());
|
public void stopFetchPic() {
|
||||||
|
logger.warn("设备【{}】即将退出屏幕获取线程...", adbDevice.getSerial());
|
||||||
|
ScreenStreamCommand screenStreamCommand = new ScreenStreamCommand(false, catchParam.getRotation(), catchParam.getWidth(), catchParam.getHeight(), catchParam.getFrameRate(), catchParam.getQuality());
|
||||||
|
asyncAgentSession.send(screenStreamCommand);
|
||||||
asyncAgentSession.closeSilence();
|
asyncAgentSession.closeSilence();
|
||||||
this.lastData = null;
|
this.lastData = null;
|
||||||
AndroidDeviceManager.getInstance().removeScreenThread(adbDevice.getSerial());
|
AndroidDeviceManager.getInstance().removeScreenThread(adbDevice.getSerial());
|
||||||
interrupt();
|
interrupt();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 更新关联的后端会话和屏幕尺寸
|
|
||||||
*
|
|
||||||
* @param session
|
|
||||||
* @param catchParam
|
|
||||||
*/
|
|
||||||
public void startSendScreenToWeb(Session session, CatchParam catchParam) {
|
|
||||||
this.wsSession = session;
|
|
||||||
this.catchParam = catchParam;
|
|
||||||
// this.isNewConnect = true;
|
|
||||||
sendConnectInfo2Web();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 断开后端会话连接,保留接收最新帧数据
|
|
||||||
*/
|
|
||||||
public void stopSendPic2Web() {
|
|
||||||
this.wsSession = null;
|
|
||||||
// logger.debug("后端会话关联已置空!屏幕获取线程是否被中断:"+isInterrupted());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSendDeviceStatus(boolean sendDeviceStatus) {
|
|
||||||
this.sendDeviceStatus = sendDeviceStatus;
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
package net.northking.cctp.upperComputer.webSocket.thread;
|
package net.northking.cctp.upperComputer.deviceManager.screen;
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.JSON;
|
||||||
import net.northking.cctp.upperComputer.constants.ResponseCmd;
|
import net.northking.cctp.upperComputer.constants.ResponseCmd;
|
|
@ -0,0 +1,114 @@
|
||||||
|
package net.northking.cctp.upperComputer.deviceManager.screen;
|
||||||
|
|
||||||
|
import net.northking.cctp.upperComputer.constants.ResponseCmd;
|
||||||
|
import net.northking.cctp.upperComputer.utils.SessionUtils;
|
||||||
|
import net.northking.cctp.upperComputer.webSocket.entity.CatchParam;
|
||||||
|
import net.northking.cctp.upperComputer.webSocket.entity.CmdRequest;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.util.CollectionUtils;
|
||||||
|
|
||||||
|
import javax.websocket.Session;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author : yineng.huang
|
||||||
|
* @date : 2024/7/18 17:48
|
||||||
|
*/
|
||||||
|
public abstract class ImageScreenResponse extends Thread{
|
||||||
|
|
||||||
|
private Logger logger = LoggerFactory.getLogger(IosScreenResponseThread.class);
|
||||||
|
|
||||||
|
protected List<Session> webSessions = new ArrayList<>(3); //与微服务之间的连接session,传送屏幕的
|
||||||
|
|
||||||
|
protected ScreenRecorder screenRecorder;
|
||||||
|
|
||||||
|
protected boolean sendDeviceStatus = true;
|
||||||
|
|
||||||
|
protected Map<String,CmdRequest> allConnectionScreenOnRequestMap; //只是第一次连接需要,发送给前端代表连接成功
|
||||||
|
|
||||||
|
protected String deviceId;
|
||||||
|
|
||||||
|
protected CatchParam catchParam;
|
||||||
|
|
||||||
|
public void setCatchParam(CatchParam catchParam) {
|
||||||
|
this.catchParam = catchParam;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void startRecordScreen(String tenantId, int width, int height, String taskId) {
|
||||||
|
logger.info("收到设备【{}】的录屏请求,当前请求的taskId为:{}",deviceId,taskId);
|
||||||
|
if (null != screenRecorder) {
|
||||||
|
logger.warn("上一次设备【{}】的录频还在跑呢,上一次跑的taskId为:{}",deviceId,screenRecorder.getTaskId());
|
||||||
|
String previousRecordPath = screenRecorder.endRecord();
|
||||||
|
logger.warn("设备【{}】上一次的录频结束,taskId为:{},上传的地址为:{}",deviceId,screenRecorder.getTaskId(),previousRecordPath);
|
||||||
|
}
|
||||||
|
logger.info("开启设备【{}】的录屏请求,当前请求的taskId为:{}",deviceId,taskId);
|
||||||
|
SimpleDateFormat format = new SimpleDateFormat("yyyy_MM_dd_HH_mm_ss");
|
||||||
|
String dateFormat = format.format(new Date());
|
||||||
|
String videoName = deviceId + "_" + dateFormat + ".mp4";
|
||||||
|
screenRecorder = new ScreenRecorder(deviceId, videoName, tenantId,taskId, width, height);
|
||||||
|
screenRecorder.startRecordVideo();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String stopRecord() {
|
||||||
|
String result = null;
|
||||||
|
String taskId = null;
|
||||||
|
if (null != screenRecorder) {
|
||||||
|
result = screenRecorder.endRecord();
|
||||||
|
taskId = screenRecorder.getTaskId();
|
||||||
|
screenRecorder = null;
|
||||||
|
}
|
||||||
|
if (CollectionUtils.isEmpty(webSessions)) {
|
||||||
|
logger.info("设备【{}】在taskId:{}的录屏结束了,而且没有前端的连接,直接退出屏幕抓取的线程了.............", deviceId, taskId);
|
||||||
|
stopFetchPic();
|
||||||
|
} else {
|
||||||
|
logger.info("设备【{}】在taskId:{}的录屏结束了,但是还有前端的连接再用着,先不断开.............", deviceId, taskId);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void startSendScreenToWeb(Session session, CatchParam catchParam) {
|
||||||
|
logger.info("设备【{}】当前连接了{}个web客户端...............",deviceId,this.webSessions.size());
|
||||||
|
if (this.webSessions.size() > 3) {
|
||||||
|
//通知前端断开连接,最多只能连接三个
|
||||||
|
Map<String, Object> messageMap = new HashMap<>();
|
||||||
|
messageMap.put(ResponseCmd.DeviceStatus.STATUS, ResponseCmd.DeviceStatus.DISCONNECT);
|
||||||
|
SessionUtils.sendMessageInitiative(session, ResponseCmd.DEVICE_STATUS, deviceId, messageMap, "最多支持三个客户端同时浏览手机");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.catchParam = catchParam;
|
||||||
|
this.webSessions.add(session);
|
||||||
|
//通知前端开始连接
|
||||||
|
Map<String, Object> messageMap = new HashMap<>();
|
||||||
|
messageMap.put(ResponseCmd.DeviceStatus.STATUS, ResponseCmd.DeviceStatus.CONNECTING);
|
||||||
|
SessionUtils.sendMessageInitiative(session, ResponseCmd.DEVICE_STATUS, deviceId, messageMap, "设备掉线了");
|
||||||
|
this.sendDeviceStatus = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSendDeviceStatus(boolean sendDeviceStatus) {
|
||||||
|
this.sendDeviceStatus = sendDeviceStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void stopWebSessionTransform(Session session) {
|
||||||
|
logger.info("移除设备【{}】的web投屏连接,sessionId为:{}...............",deviceId,session.getId());
|
||||||
|
webSessions.remove(session);
|
||||||
|
logger.info("设备【{}】的web投屏连接数还剩下:{}...............",deviceId,webSessions.size());
|
||||||
|
if (webSessions.size() > 0) {
|
||||||
|
logger.info("设备【{}】还有其他人连着这个屏幕的,还保留一下这个线程............",deviceId);
|
||||||
|
} else {
|
||||||
|
if (null != screenRecorder) {
|
||||||
|
logger.info("设备【{}】还录着屏幕的,还保留一下这个线程............", deviceId);
|
||||||
|
} else {
|
||||||
|
logger.info("设备【{}】没有web端连接,也没有录频,退出............", deviceId);
|
||||||
|
stopFetchPic();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setScreenOnRequest(Session session, CmdRequest screenOnRequest) {
|
||||||
|
SessionUtils.sendSuccessData(session, screenOnRequest, null, "开启屏幕成功");
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract void stopFetchPic();
|
||||||
|
}
|
|
@ -1,27 +1,22 @@
|
||||||
package net.northking.cctp.upperComputer.webSocket.thread;
|
package net.northking.cctp.upperComputer.deviceManager.screen;
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSONObject;
|
|
||||||
import net.northking.cctp.upperComputer.constants.ResponseCmd;
|
import net.northking.cctp.upperComputer.constants.ResponseCmd;
|
||||||
import net.northking.cctp.upperComputer.deviceManager.IOSDeviceManager;
|
import net.northking.cctp.upperComputer.deviceManager.IOSDeviceManager;
|
||||||
import net.northking.cctp.upperComputer.deviceManager.thread.IosDeviceInitThread;
|
import net.northking.cctp.upperComputer.deviceManager.thread.IosDeviceInitThread;
|
||||||
import net.northking.cctp.upperComputer.driver.ios.NKAgent;
|
|
||||||
import net.northking.cctp.upperComputer.driver.usbmuxd.AppleDevice;
|
import net.northking.cctp.upperComputer.driver.usbmuxd.AppleDevice;
|
||||||
import net.northking.cctp.upperComputer.driver.usbmuxd.UsbMuxd;
|
import net.northking.cctp.upperComputer.driver.usbmuxd.UsbMuxd;
|
||||||
import net.northking.cctp.upperComputer.driver.usbmuxd.UsbMuxdConnectFailedException;
|
import net.northking.cctp.upperComputer.driver.usbmuxd.UsbMuxdConnectFailedException;
|
||||||
import net.northking.cctp.upperComputer.driver.usbmuxd.payload.usbmuxd.entity.DeviceConnectionDetail;
|
import net.northking.cctp.upperComputer.driver.usbmuxd.payload.usbmuxd.entity.DeviceConnectionDetail;
|
||||||
import net.northking.cctp.upperComputer.entity.PhoneEntity;
|
import net.northking.cctp.upperComputer.entity.PhoneEntity;
|
||||||
import net.northking.cctp.upperComputer.utils.SessionUtils;
|
import net.northking.cctp.upperComputer.utils.SessionUtils;
|
||||||
import net.northking.cctp.upperComputer.webSocket.entity.CatchParam;
|
|
||||||
import net.northking.cctp.upperComputer.webSocket.entity.CmdRequest;
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.util.CollectionUtils;
|
||||||
|
|
||||||
import javax.websocket.Session;
|
import javax.websocket.Session;
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.text.SimpleDateFormat;
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
@ -30,7 +25,7 @@ import java.util.Map;
|
||||||
* @author : yineng.huang
|
* @author : yineng.huang
|
||||||
* @date : 2023/10/17 16:41
|
* @date : 2023/10/17 16:41
|
||||||
*/
|
*/
|
||||||
public class IosScreenResponseThread extends Thread {
|
public class IosScreenResponseThread extends ImageScreenResponse {
|
||||||
|
|
||||||
private Logger logger = LoggerFactory.getLogger(IosScreenResponseThread.class);
|
private Logger logger = LoggerFactory.getLogger(IosScreenResponseThread.class);
|
||||||
|
|
||||||
|
@ -53,32 +48,24 @@ public class IosScreenResponseThread extends Thread {
|
||||||
|
|
||||||
private PhoneEntity phone;
|
private PhoneEntity phone;
|
||||||
|
|
||||||
private Session webSession;
|
|
||||||
|
|
||||||
private long num = 1;
|
private long num = 1;
|
||||||
|
|
||||||
private CmdRequest screenOnRequest; //只是第一次连接需要,发送给前端代表连接成功
|
|
||||||
|
|
||||||
private UsbMuxd.ConnectOperator connectOperator;
|
private UsbMuxd.ConnectOperator connectOperator;
|
||||||
|
|
||||||
private IosScreenRecordThread screenRecordThread;
|
|
||||||
|
|
||||||
private String recordingType = "0"; //录屏类型0-未录,1-真机录屏,2-自动化执行任务录屏
|
|
||||||
|
|
||||||
private boolean sendDeviceStatus = true;
|
|
||||||
|
|
||||||
private String currentTaskId;
|
|
||||||
|
|
||||||
// private IosScreenCompressHandleThread screenCompressHandle;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
logger.info("即将开始拉取设备【{}】图片................................", phone.getUdid());
|
logger.info("即将开始拉取设备【{}】图片................................", phone.getUdid());
|
||||||
while (!isInterrupted()) {
|
while (!isInterrupted()) {
|
||||||
|
if (!CollectionUtils.isEmpty(webSessions)) {
|
||||||
//通知前端开始连接
|
//通知前端开始连接
|
||||||
Map<String, Object> messageMap = new HashMap<>();
|
Map<String, Object> messageMap = new HashMap<>();
|
||||||
messageMap.put(ResponseCmd.DeviceStatus.STATUS, ResponseCmd.DeviceStatus.CONNECTING);
|
messageMap.put(ResponseCmd.DeviceStatus.STATUS, ResponseCmd.DeviceStatus.CONNECTING);
|
||||||
|
for (Session webSession : webSessions) {
|
||||||
|
if (webSession.isOpen()) {
|
||||||
SessionUtils.sendMessageInitiative(webSession, ResponseCmd.DEVICE_STATUS, phone.getUdid(), messageMap, "设备掉线了");
|
SessionUtils.sendMessageInitiative(webSession, ResponseCmd.DEVICE_STATUS, phone.getUdid(), messageMap, "设备掉线了");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
UsbMuxd usbmuxd = new UsbMuxd();
|
UsbMuxd usbmuxd = new UsbMuxd();
|
||||||
connectOperator = getDeviceConnectOperator(usbmuxd);
|
connectOperator = getDeviceConnectOperator(usbmuxd);
|
||||||
if (connectOperator == null) {
|
if (connectOperator == null) {
|
||||||
|
@ -97,7 +84,7 @@ public class IosScreenResponseThread extends Thread {
|
||||||
try {
|
try {
|
||||||
sleep(500);
|
sleep(500);
|
||||||
} catch (InterruptedException ignored) {
|
} catch (InterruptedException ignored) {
|
||||||
Thread.currentThread().interrupt();
|
interrupt();
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -151,8 +138,8 @@ public class IosScreenResponseThread extends Thread {
|
||||||
}
|
}
|
||||||
byte[] rawImageFileByteArray = chunkBuffer.toByteArray();
|
byte[] rawImageFileByteArray = chunkBuffer.toByteArray();
|
||||||
//这里是录屏
|
//这里是录屏
|
||||||
if (null != screenRecordThread && screenRecordThread.isAlive()) {
|
if (null != screenRecorder) {
|
||||||
screenRecordThread.addImgToVideo(rawImageFileByteArray);
|
screenRecorder.addImgToVideo(rawImageFileByteArray);
|
||||||
}
|
}
|
||||||
// if (compressQuality != 1f) {
|
// if (compressQuality != 1f) {
|
||||||
//
|
//
|
||||||
|
@ -174,17 +161,23 @@ public class IosScreenResponseThread extends Thread {
|
||||||
// lastRawChunkSize = rawImageFileByteArray.length;
|
// lastRawChunkSize = rawImageFileByteArray.length;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
if (null != this.webSession && this.webSession.isOpen()) {
|
//有后端会话则给后端推送屏幕图片
|
||||||
SessionUtils.sendBinary(this.webSession, rawImageFileByteArray);
|
if (!CollectionUtils.isEmpty(webSessions)) {
|
||||||
|
for (Session webSession : webSessions) {
|
||||||
|
if (webSession.isOpen()) {
|
||||||
if (sendDeviceStatus) {
|
if (sendDeviceStatus) {
|
||||||
Map<String, Object> result = new HashMap<>();
|
Map<String, Object> result = new HashMap<>();
|
||||||
result.put(ResponseCmd.DeviceStatus.STATUS, ResponseCmd.DeviceStatus.CONNECTED);
|
result.put(ResponseCmd.DeviceStatus.STATUS, ResponseCmd.DeviceStatus.CONNECTED);
|
||||||
SessionUtils.sendMessageInitiative(webSession, ResponseCmd.DEVICE_STATUS, phone.getUdid(), result, "设备连接失败");
|
SessionUtils.sendMessageInitiative(webSession, ResponseCmd.DEVICE_STATUS, phone.getUdid(), result, "设备连接失败");
|
||||||
sendDeviceStatus = false;
|
sendDeviceStatus = false;
|
||||||
}
|
}
|
||||||
|
SessionUtils.sendBinary(webSession, rawImageFileByteArray);
|
||||||
|
} else {
|
||||||
|
logger.warn("推送到web端的session已经断开,sessionId:{}",webSession.getId());
|
||||||
|
//todo:操作一下,去掉webSessions里面的无效session
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// if (null != screenCompressHandle && screenCompressHandle.isAlive() && !screenCompressHandle.isInterrupted()) {
|
// if (null != screenCompressHandle && screenCompressHandle.isAlive() && !screenCompressHandle.isInterrupted()) {
|
||||||
// screenCompressHandle.addData(rawImageFileByteArray);
|
// screenCompressHandle.addData(rawImageFileByteArray);
|
||||||
// }
|
// }
|
||||||
|
@ -227,10 +220,12 @@ public class IosScreenResponseThread extends Thread {
|
||||||
/**
|
/**
|
||||||
* @param phone
|
* @param phone
|
||||||
*/
|
*/
|
||||||
public IosScreenResponseThread(PhoneEntity phone, String currentTaskId) {
|
public IosScreenResponseThread(PhoneEntity phone) {
|
||||||
|
// screenCompressHandle = new IosScreenCompressHandleThread(phone.getUdid());
|
||||||
|
// screenCompressHandle.start();
|
||||||
this.phone = phone;
|
this.phone = phone;
|
||||||
|
this.deviceId = phone.getUdid();
|
||||||
setName(phone.getUdid() + "拉取屏幕");
|
setName(phone.getUdid() + "拉取屏幕");
|
||||||
this.currentTaskId = currentTaskId;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private UsbMuxd.ConnectOperator getDeviceConnectOperator(UsbMuxd usbMuxd) {
|
private UsbMuxd.ConnectOperator getDeviceConnectOperator(UsbMuxd usbMuxd) {
|
||||||
|
@ -254,12 +249,6 @@ public class IosScreenResponseThread extends Thread {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setScreenOnRequest(CmdRequest screenOnRequest) {
|
|
||||||
if (!isInterrupted() && null != this.webSession && this.webSession.isOpen()) { //只发第一次screen_on指令
|
|
||||||
SessionUtils.sendSuccessData(this.webSession, screenOnRequest, null, "开启屏幕成功");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void changeSize(int width, int height) {
|
public void changeSize(int width, int height) {
|
||||||
// if (this.screenCompressHandle != null && this.screenCompressHandle.isAlive() && !this.screenCompressHandle.isInterrupted()) {
|
// if (this.screenCompressHandle != null && this.screenCompressHandle.isAlive() && !this.screenCompressHandle.isInterrupted()) {
|
||||||
// this.screenCompressHandle.setScreenSize(width,height);
|
// this.screenCompressHandle.setScreenSize(width,height);
|
||||||
|
@ -272,30 +261,14 @@ public class IosScreenResponseThread extends Thread {
|
||||||
IosDeviceInitThread iosInitThread = IOSDeviceManager.getInstance().getIosInitThread(phone.getUdid());
|
IosDeviceInitThread iosInitThread = IOSDeviceManager.getInstance().getIosInitThread(phone.getUdid());
|
||||||
if (null != iosInitThread && !iosInitThread.isInterrupted() && iosInitThread.isAlive()) {
|
if (null != iosInitThread && !iosInitThread.isInterrupted() && iosInitThread.isAlive()) {
|
||||||
logger.warn("设置手机【{}】推送图片的帧率:{}",phone.getUdid(),frameRate);
|
logger.warn("设置手机【{}】推送图片的帧率:{}",phone.getUdid(),frameRate);
|
||||||
NKAgent nkAgent = iosInitThread.getNkAgent();
|
iosInitThread.setMJPEGServerRate(frameRate);
|
||||||
nkAgent.setMJPEGServerRate(frameRate);
|
|
||||||
} else {
|
} else {
|
||||||
logger.warn("设备【{}】已经不在线了............................");
|
logger.warn("设备【{}】已经不在线了............................");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 1.判断是否处于自动化任务录屏中,若是,保留该线程,等待自动化录屏完成之后再退出
|
|
||||||
* 2.若不处于自动化任务录屏中,判断是否真机录屏中,是则先退出真机的录屏,将录屏地址发送到服务端,若没有真机录屏,直接关闭
|
|
||||||
*/
|
|
||||||
public void stopFetchPic() {
|
public void stopFetchPic() {
|
||||||
if (recordingType.equals("2")) { //直播退出
|
logger.warn("设备【{}】即将退出屏幕的抓取。。。。。。", phone.getUdid());
|
||||||
logger.warn("该设备【{}】处于自动化的录屏阶段,稍后自动化录屏完成之后再退出手机屏幕的获取。。。。。。", phone.getUdid());
|
|
||||||
this.webSession = null;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
logger.warn("该设备【{}】未处于自动化的录屏阶段,现在退出屏幕抓取。。。。。。", phone.getUdid());
|
|
||||||
String videoUrl = stopRecord();
|
|
||||||
if (null != videoUrl) {
|
|
||||||
Map<String, Object> result = new HashMap<>();
|
|
||||||
result.put("videoInfo", videoUrl);
|
|
||||||
SessionUtils.sendMessageInitiative(webSession, ResponseCmd.RECORD_FINISH, this.phone.getUdid(), result, "结束录屏成功");
|
|
||||||
}
|
|
||||||
if (null != connectOperator) {
|
if (null != connectOperator) {
|
||||||
try {
|
try {
|
||||||
connectOperator.close();
|
connectOperator.close();
|
||||||
|
@ -304,63 +277,8 @@ public class IosScreenResponseThread extends Thread {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
IOSDeviceManager.getInstance().removeScreenThread(phone.getUdid());
|
IOSDeviceManager.getInstance().removeScreenThread(phone.getUdid());
|
||||||
this.webSession = null;
|
|
||||||
interrupt();
|
interrupt();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void startRecordScreen(String tenantId, int width, int height,String recordType, String currentTaskId){
|
|
||||||
this.recordingType = recordType;
|
|
||||||
if (null != screenRecordThread && screenRecordThread.isAlive()) {
|
|
||||||
screenRecordThread.killRecord();
|
|
||||||
}
|
|
||||||
SimpleDateFormat format = new SimpleDateFormat("yyyy_MM_dd_HH_mm_ss");
|
|
||||||
String dateFormat = format.format(new Date());
|
|
||||||
String videoName = this.phone.getUdid() + "_" + dateFormat + ".mp4";
|
|
||||||
screenRecordThread = new IosScreenRecordThread(this.phone.getUdid(), videoName, tenantId,width, height, currentTaskId);
|
|
||||||
screenRecordThread.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
//真机结束录屏
|
|
||||||
public String stopRecord() {
|
|
||||||
this.recordingType = "0";
|
|
||||||
if (null == screenRecordThread || screenRecordThread.isInterrupted() || !screenRecordThread.isAlive()) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
String result = screenRecordThread.endRecord();
|
|
||||||
screenRecordThread = null;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
//自动化结束录屏
|
|
||||||
public String stopRecord(String tenantId,boolean isSave) {
|
|
||||||
this.recordingType = "0";
|
|
||||||
if (null == screenRecordThread || screenRecordThread.isInterrupted() || !screenRecordThread.isAlive()) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
String result = screenRecordThread.endRecord(tenantId,isSave);
|
|
||||||
JSONObject object = JSONObject.parseObject(result, JSONObject.class);
|
|
||||||
screenRecordThread = null;
|
|
||||||
String videoUrl = object.getString("videoUrl");
|
|
||||||
logger.debug("上传录屏的地址:{}", videoUrl);
|
|
||||||
if (this.webSession == null) {
|
|
||||||
logger.info("设备【{}】自动化录屏退出,同时退出设备的屏幕获取", phone.getUdid());
|
|
||||||
stopFetchPic();
|
|
||||||
} else {
|
|
||||||
logger.info("设备【{}】正链接前端的屏幕,稍后退出", phone.getUdid());
|
|
||||||
}
|
|
||||||
return videoUrl;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void startSendScreenToWeb(Session session, CatchParam catchParam) {
|
|
||||||
this.webSession = session;
|
|
||||||
//通知前端开始连接
|
|
||||||
Map<String, Object> messageMap = new HashMap<>();
|
|
||||||
messageMap.put(ResponseCmd.DeviceStatus.STATUS, ResponseCmd.DeviceStatus.CONNECTING);
|
|
||||||
SessionUtils.sendMessageInitiative(webSession, ResponseCmd.DEVICE_STATUS, phone.getUdid(), messageMap, "设备掉线了");
|
|
||||||
this.sendDeviceStatus = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSendDeviceStatus(boolean sendDeviceStatus) {
|
|
||||||
this.sendDeviceStatus = sendDeviceStatus;
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -1,8 +1,7 @@
|
||||||
package net.northking.cctp.upperComputer.webSocket.thread;
|
package net.northking.cctp.upperComputer.deviceManager.screen;
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.JSON;
|
||||||
import net.northking.cctp.upperComputer.deviceManager.UpperComputerManager;
|
import net.northking.cctp.upperComputer.deviceManager.UpperComputerManager;
|
||||||
import net.northking.cctp.upperComputer.enums.FileBusinessTypeEnum;
|
|
||||||
import net.northking.cctp.upperComputer.entity.Attachment;
|
import net.northking.cctp.upperComputer.entity.Attachment;
|
||||||
import net.northking.cctp.upperComputer.utils.HttpUtils;
|
import net.northking.cctp.upperComputer.utils.HttpUtils;
|
||||||
import net.northking.cctp.upperComputer.utils.SpringUtils;
|
import net.northking.cctp.upperComputer.utils.SpringUtils;
|
||||||
|
@ -26,9 +25,9 @@ import java.util.Map;
|
||||||
* @author : yineng.huang
|
* @author : yineng.huang
|
||||||
* @date : 2023/10/25 16:30
|
* @date : 2023/10/25 16:30
|
||||||
*/
|
*/
|
||||||
public class IosScreenRecordThread extends Thread{
|
public class ScreenRecorder {
|
||||||
|
|
||||||
private Logger logger = LoggerFactory.getLogger(IosScreenRecordThread.class);
|
private Logger logger = LoggerFactory.getLogger(ScreenRecorder.class);
|
||||||
|
|
||||||
private FFmpegFrameRecorder recorder;
|
private FFmpegFrameRecorder recorder;
|
||||||
|
|
||||||
|
@ -48,12 +47,13 @@ public class IosScreenRecordThread extends Thread{
|
||||||
|
|
||||||
private int videoHeight;
|
private int videoHeight;
|
||||||
|
|
||||||
private String currentTaskId;
|
private String taskId;
|
||||||
|
|
||||||
public IosScreenRecordThread(String udid, String videoName, String tenantId, int videoWidth, int videoHeight, String currentTaskId) {
|
public ScreenRecorder(String udid, String videoName, String tenantId,String taskId, int videoWidth, int videoHeight) {
|
||||||
this.udid = udid;
|
this.udid = udid;
|
||||||
this.videoName = videoName;
|
this.videoName = videoName;
|
||||||
this.tenantId = tenantId;
|
this.tenantId = tenantId;
|
||||||
|
this.taskId = taskId;
|
||||||
this.videoWidth = videoWidth;
|
this.videoWidth = videoWidth;
|
||||||
this.videoHeight = videoHeight;
|
this.videoHeight = videoHeight;
|
||||||
this.filePath = UpperComputerManager.getInstance().getApplicationPath() + "/screenRecordTmp/";
|
this.filePath = UpperComputerManager.getInstance().getApplicationPath() + "/screenRecordTmp/";
|
||||||
|
@ -63,40 +63,35 @@ public class IosScreenRecordThread extends Thread{
|
||||||
}
|
}
|
||||||
//todo:这里注意改正linux的配置参数,写文件
|
//todo:这里注意改正linux的配置参数,写文件
|
||||||
recorder = new FFmpegFrameRecorder(filePath + videoName, videoWidth, videoHeight);
|
recorder = new FFmpegFrameRecorder(filePath + videoName, videoWidth, videoHeight);
|
||||||
|
// recorder.setFormat("mp4");
|
||||||
recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264);
|
recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264);
|
||||||
|
// recorder.setVideoCodec(opencv_cudacodec.MPEG4);
|
||||||
recorder.setFrameRate(FRAME_RATE);
|
recorder.setFrameRate(FRAME_RATE);
|
||||||
recorder.setPixelFormat(avutil.AV_PIX_FMT_YUV420P);
|
recorder.setPixelFormat(avutil.AV_PIX_FMT_YUV420P);
|
||||||
this.currentTaskId = currentTaskId;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public void startRecordVideo() {
|
||||||
public void run() {
|
|
||||||
try {
|
try {
|
||||||
recorder.start();
|
recorder.start();
|
||||||
} catch (FFmpegFrameRecorder.Exception e) {
|
} catch (FFmpegFrameRecorder.Exception e) {
|
||||||
logger.warn("录屏启动失败。。。。。。。", e);
|
logger.warn("录屏启动失败。。。。。。。", e);
|
||||||
}
|
}
|
||||||
while (!isInterrupted()) {
|
logger.info("设备【{}】已开启录屏.............................",udid);
|
||||||
logger.info("ios设备【{}】录屏中。。。。。。。。。。。。。", udid);
|
|
||||||
try {
|
|
||||||
Thread.sleep(5000);
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
logger.info("结束ios设备【{}】任务【{}】的录屏。。。。。。。", udid, videoName);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addImgToVideo(byte[] imgData) {
|
public void addImgToVideo(byte[] imgData) {
|
||||||
try {
|
try {
|
||||||
BufferedImage read = ImageIO.read(new ByteArrayInputStream(imgData));
|
BufferedImage read = ImageIO.read(new ByteArrayInputStream(imgData));
|
||||||
|
if (!recorder.isCloseOutputStream()) {
|
||||||
recorder.record(converter.getFrame(read));
|
recorder.record(converter.getFrame(read));
|
||||||
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
logger.warn("添加图片文件出现错误。。。。。",e);
|
logger.warn("添加图片文件出现错误。。。。。",e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public String endRecord() {
|
public String endRecord() {
|
||||||
|
logger.info("准备结束设备【{}】在taskId:{}的视频录制.............",udid,taskId);
|
||||||
try {
|
try {
|
||||||
recorder.stop();
|
recorder.stop();
|
||||||
} catch (FFmpegFrameRecorder.Exception e) {
|
} catch (FFmpegFrameRecorder.Exception e) {
|
||||||
|
@ -108,37 +103,10 @@ public class IosScreenRecordThread extends Thread{
|
||||||
logger.warn("释放录屏失败。。。。。。", e);
|
logger.warn("释放录屏失败。。。。。。", e);
|
||||||
}
|
}
|
||||||
String result = uploadVideoToServer();
|
String result = uploadVideoToServer();
|
||||||
this.interrupt();
|
logger.info("设备【{}】在taskId:{}的视频录制已经结束,得到的视频地址为:{}.............",udid,taskId,result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String endRecord(Boolean save) {
|
|
||||||
try {
|
|
||||||
recorder.stop();
|
|
||||||
} catch (FFmpegFrameRecorder.Exception e) {
|
|
||||||
logger.warn("结束录屏失败。。。。。。", e);
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
recorder.release();
|
|
||||||
} catch (FFmpegFrameRecorder.Exception e) {
|
|
||||||
logger.warn("释放录屏失败。。。。。。", e);
|
|
||||||
}
|
|
||||||
String result = null;
|
|
||||||
if (null != save && save) {
|
|
||||||
result = uploadVideoToServer();
|
|
||||||
}else {
|
|
||||||
logger.debug("录屏文件不保存!");
|
|
||||||
}
|
|
||||||
this.interrupt();
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String endRecord(String tenantId,Boolean save) {
|
|
||||||
this.tenantId = tenantId;
|
|
||||||
return endRecord(save);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private String uploadVideoToServer() {
|
private String uploadVideoToServer() {
|
||||||
Map<String, String> resultMap = new HashMap<>();
|
Map<String, String> resultMap = new HashMap<>();
|
||||||
try {
|
try {
|
||||||
|
@ -146,36 +114,22 @@ public class IosScreenRecordThread extends Thread{
|
||||||
logger.debug("[" +udid+ "]录屏停止,开始上传视屏文件");
|
logger.debug("[" +udid+ "]录屏停止,开始上传视屏文件");
|
||||||
String serverAddress = SpringUtils.getProperties("nk.mobile-computer.serverAddr");
|
String serverAddress = SpringUtils.getProperties("nk.mobile-computer.serverAddr");
|
||||||
String pubUploadPath = SpringUtils.getProperties("nk.mobile-computer.publicUploadAddr");
|
String pubUploadPath = SpringUtils.getProperties("nk.mobile-computer.publicUploadAddr");
|
||||||
logger.info("开始上传ios视频文件");
|
Attachment upload = HttpUtils.upload(serverAddress + pubUploadPath, filePath + videoName, tenantId);
|
||||||
Attachment upload = HttpUtils.upload(serverAddress + pubUploadPath, filePath + videoName, tenantId, currentTaskId, FileBusinessTypeEnum.MOBILE_TASK_VIDEO.getCode());
|
|
||||||
if (null != upload && StringUtils.isNotBlank(upload.getId())) {
|
if (null != upload && StringUtils.isNotBlank(upload.getId())) {
|
||||||
logger.info("文件上传成功,返回id:{}", upload.getId());
|
logger.debug("文件上传成功,返回id:{}", upload.getId());
|
||||||
resultMap.put("videoUrl", upload.getUrlPath());
|
resultMap.put("videoUrl", upload.getUrlPath());
|
||||||
resultMap.put("videoRef", videoWidth + "x" + videoHeight);
|
resultMap.put("videoRef", videoWidth + "x" + videoHeight);
|
||||||
return JSON.toJSONString(resultMap);
|
return JSON.toJSONString(resultMap);
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logger.warn("上传视频文件失败。。。。。。。。", e);
|
logger.warn("上传视频文件失败。。。。。。。。", e);
|
||||||
|
}finally {
|
||||||
|
|
||||||
}
|
}
|
||||||
//todo:上传完之后要删除
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void killRecord() {
|
public String getTaskId() {
|
||||||
try {
|
return taskId;
|
||||||
recorder.stop();
|
|
||||||
} catch (FFmpegFrameRecorder.Exception e) {
|
|
||||||
logger.warn("结束录屏失败。。。。。。", e);
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
recorder.release();
|
|
||||||
} catch (FFmpegFrameRecorder.Exception e) {
|
|
||||||
logger.warn("释放录屏失败。。。。。。", e);
|
|
||||||
}
|
|
||||||
File file = new File(filePath + videoName);
|
|
||||||
if (file.exists()) {
|
|
||||||
file.delete();
|
|
||||||
}
|
|
||||||
interrupt();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -431,6 +431,7 @@ public class AndroidDeviceInitThread extends Thread {
|
||||||
Map<String, Integer> sizeMap = new HashMap<>();
|
Map<String, Integer> sizeMap = new HashMap<>();
|
||||||
sizeMap.put("width", displayData.getWidth());
|
sizeMap.put("width", displayData.getWidth());
|
||||||
sizeMap.put("height", displayData.getHeight());
|
sizeMap.put("height", displayData.getHeight());
|
||||||
|
sizeMap.put("rotation", displayData.getRotation());
|
||||||
return sizeMap;
|
return sizeMap;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -27,6 +27,8 @@ public abstract class IosDeviceInitThread extends Thread {
|
||||||
|
|
||||||
protected AppleDevice appleDevice;
|
protected AppleDevice appleDevice;
|
||||||
|
|
||||||
|
private int frame = 12;
|
||||||
|
|
||||||
public IosDeviceInitThread(PhoneEntity phone, AppleDevice appleDevice) {
|
public IosDeviceInitThread(PhoneEntity phone, AppleDevice appleDevice) {
|
||||||
this.phone = phone;
|
this.phone = phone;
|
||||||
this.appleDevice = appleDevice;
|
this.appleDevice = appleDevice;
|
||||||
|
@ -45,8 +47,8 @@ public abstract class IosDeviceInitThread extends Thread {
|
||||||
nkAgentReady = nkAgent.getStatus();
|
nkAgentReady = nkAgent.getStatus();
|
||||||
logger.debug("设备【{}】的nkAgent连接完成,结果:{}", phone.getUdid(),nkAgentReady);
|
logger.debug("设备【{}】的nkAgent连接完成,结果:{}", phone.getUdid(),nkAgentReady);
|
||||||
if (nkAgentReady) {
|
if (nkAgentReady) {
|
||||||
logger.debug("设置设备【{}】的帧数为:{}", phone.getUdid(), 25);
|
logger.debug("设置设备【{}】的帧数为:{}", phone.getUdid(), frame);
|
||||||
nkAgent.setMJPEGServerRate(25);
|
nkAgent.setMJPEGServerRate(frame);
|
||||||
} else {
|
} else {
|
||||||
logger.error("第{}次连接设备【{}】的agent不成功,等待下一次......",reTryTime, phone.getUdid());
|
logger.error("第{}次连接设备【{}】的agent不成功,等待下一次......",reTryTime, phone.getUdid());
|
||||||
}
|
}
|
||||||
|
@ -91,5 +93,9 @@ public abstract class IosDeviceInitThread extends Thread {
|
||||||
return String.format("%s%d%d_%d-%d-%d", calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), calendar.get(Calendar.DAY_OF_MONTH), calendar.get(Calendar.HOUR_OF_DAY), calendar.get(Calendar.MINUTE), calendar.get(Calendar.SECOND));
|
return String.format("%s%d%d_%d-%d-%d", calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), calendar.get(Calendar.DAY_OF_MONTH), calendar.get(Calendar.HOUR_OF_DAY), calendar.get(Calendar.MINUTE), calendar.get(Calendar.SECOND));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setMJPEGServerRate(int frameRate){
|
||||||
|
this.frame = frameRate;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,8 @@ import io.appium.java_client.AppiumDriver;
|
||||||
import io.appium.java_client.android.AndroidDriver;
|
import io.appium.java_client.android.AndroidDriver;
|
||||||
import io.appium.java_client.ios.IOSDriver;
|
import io.appium.java_client.ios.IOSDriver;
|
||||||
import net.northking.cctp.upperComputer.config.MobileProperty;
|
import net.northking.cctp.upperComputer.config.MobileProperty;
|
||||||
|
import net.northking.cctp.upperComputer.deviceManager.screen.AndroidScreenResponseThread;
|
||||||
|
import net.northking.cctp.upperComputer.deviceManager.thread.AndroidDeviceInitThread;
|
||||||
import net.northking.cctp.upperComputer.driver.adb.Adb;
|
import net.northking.cctp.upperComputer.driver.adb.Adb;
|
||||||
import net.northking.cctp.upperComputer.driver.adb.AdbDevice;
|
import net.northking.cctp.upperComputer.driver.adb.AdbDevice;
|
||||||
import net.northking.cctp.upperComputer.driver.adb.AdbTransport;
|
import net.northking.cctp.upperComputer.driver.adb.AdbTransport;
|
||||||
|
@ -18,9 +20,11 @@ import net.northking.cctp.upperComputer.entity.DebuggerDeviceInfo;
|
||||||
import net.northking.cctp.upperComputer.exception.AppiumException;
|
import net.northking.cctp.upperComputer.exception.AppiumException;
|
||||||
import net.northking.cctp.upperComputer.exception.ExecuteException;
|
import net.northking.cctp.upperComputer.exception.ExecuteException;
|
||||||
import net.northking.cctp.upperComputer.deviceManager.AndroidDeviceManager;
|
import net.northking.cctp.upperComputer.deviceManager.AndroidDeviceManager;
|
||||||
|
import net.northking.cctp.upperComputer.exception.ParamMistakeException;
|
||||||
import net.northking.cctp.upperComputer.service.thread.AndroidDeviceAllInfoThread;
|
import net.northking.cctp.upperComputer.service.thread.AndroidDeviceAllInfoThread;
|
||||||
import net.northking.cctp.upperComputer.service.thread.AndroidDeviceInfoByPackageThread;
|
import net.northking.cctp.upperComputer.service.thread.AndroidDeviceInfoByPackageThread;
|
||||||
import net.northking.cctp.upperComputer.utils.*;
|
import net.northking.cctp.upperComputer.utils.*;
|
||||||
|
import net.northking.cctp.upperComputer.webSocket.entity.CatchParam;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.openqa.selenium.WebElement;
|
import org.openqa.selenium.WebElement;
|
||||||
import org.openqa.selenium.remote.DesiredCapabilities;
|
import org.openqa.selenium.remote.DesiredCapabilities;
|
||||||
|
@ -705,111 +709,172 @@ public class AndroidDebuggerServiceImpl extends AbstractDebuggerService {
|
||||||
|
|
||||||
private Map<String, Process> processMap = new HashMap<>();
|
private Map<String, Process> processMap = new HashMap<>();
|
||||||
|
|
||||||
|
// @Override
|
||||||
|
// public boolean startRecord(DebuggerDeviceInfo info) {
|
||||||
|
// logger.info("开启录屏");
|
||||||
|
// String taskId = info.getTaskId();
|
||||||
|
// if (StringUtils.isBlank(taskId)) {
|
||||||
|
// logger.warn("任务id必填");
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
// String videoPath = mobileProperty.getStfPath() + "/temp";
|
||||||
|
// Thread thread = new Thread(() -> {
|
||||||
|
// File file = new File(videoPath);
|
||||||
|
// if (!file.isDirectory()) {
|
||||||
|
// file.mkdirs();
|
||||||
|
// }
|
||||||
|
// logger.info("录屏前先kill掉所有scrcpy进程");
|
||||||
|
// String pullCmd = String.format("ps -ef|grep 'scrcpy -s %s -b 2M -Nr %s' |grep -v grep |awk '{print $2}' |xargs --no-run-if-empty kill -9", info.getDeviceId(), videoPath + "/" + taskId + ".mp4");
|
||||||
|
// String[] delCmd = {"/bin/sh", "-c", pullCmd};
|
||||||
|
// try {
|
||||||
|
// Process delProcess = Runtime.getRuntime().exec(delCmd, null, null);
|
||||||
|
// delProcess.waitFor();
|
||||||
|
// logger.info("录屏开启命令:" + pullCmd);
|
||||||
|
// delProcess.destroy();
|
||||||
|
// } catch (Exception e) {
|
||||||
|
// logger.error("删除scrcpy进程失败:", e);
|
||||||
|
// }
|
||||||
|
// String cmd = String.format("scrcpy -s %s -b 2M -Nr %s ", info.getDeviceId(), videoPath + "/" + taskId + ".mp4");
|
||||||
|
// logger.info(cmd);
|
||||||
|
//// if(props.getProperty("os.name").contains("Linux")){
|
||||||
|
//// }
|
||||||
|
// try {
|
||||||
|
// Process process = Runtime.getRuntime().exec(cmd);
|
||||||
|
// processMap.put(taskId, process);
|
||||||
|
// logger.info("开启scrcpy进程");
|
||||||
|
// } catch (IOException e) {
|
||||||
|
// logger.error("开启录屏异常:", e);
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
// thread.start();
|
||||||
|
// try {
|
||||||
|
// Thread.sleep(2000);
|
||||||
|
// } catch (InterruptedException e) {
|
||||||
|
// logger.warn("线程终止。。。。。。", e);
|
||||||
|
// Thread.currentThread().interrupt();
|
||||||
|
// }
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean startRecord(DebuggerDeviceInfo info) {
|
public boolean startRecord(DebuggerDeviceInfo info) {
|
||||||
logger.info("开启录屏");
|
|
||||||
String taskId = info.getTaskId();
|
String taskId = info.getTaskId();
|
||||||
|
logger.info("收到设备【{}】在任务【{}】开启录屏的请求............",info.getDeviceId(),taskId);
|
||||||
if (StringUtils.isBlank(taskId)) {
|
if (StringUtils.isBlank(taskId)) {
|
||||||
logger.warn("任务id必填");
|
logger.error("设备【{}】在录屏的时候任务id不存在",info.getDeviceId());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
String videoPath = mobileProperty.getStfPath() + "/temp";
|
AdbDevice currentDevice = AndroidDeviceManager.getInstance().getCurrentDevice(info.getDeviceId());
|
||||||
Thread thread = new Thread(() -> {
|
if (null == currentDevice) {
|
||||||
File file = new File(videoPath);
|
logger.error("设备【{}】当前不在线,无法录视频..........",info.getDeviceId());
|
||||||
if (!file.isDirectory()) {
|
return false;
|
||||||
file.mkdirs();
|
|
||||||
}
|
}
|
||||||
logger.info("录屏前先kill掉所有scrcpy进程");
|
logger.info("获取手机【{}】的实际宽高............................",info.getDeviceId());
|
||||||
String pullCmd = String.format("ps -ef|grep 'scrcpy -s %s -b 2M -Nr %s' |grep -v grep |awk '{print $2}' |xargs --no-run-if-empty kill -9", info.getDeviceId(), videoPath + "/" + taskId + ".mp4");
|
AndroidDeviceInitThread androidInitThread = AndroidDeviceManager.getInstance().getAndroidInitThread(info.getDeviceId());
|
||||||
String[] delCmd = {"/bin/sh", "-c", pullCmd};
|
if (null == androidInitThread) {
|
||||||
try {
|
throw new ParamMistakeException(String.format("手机【%s】已离线,请稍后再试!", info.getDeviceId()));
|
||||||
Process delProcess = Runtime.getRuntime().exec(delCmd, null, null);
|
}
|
||||||
delProcess.waitFor();
|
Map<String, Integer> screenSizeMap = androidInitThread.getRealScreenSize();
|
||||||
logger.info("录屏开启命令:" + pullCmd);
|
if (null == screenSizeMap) {
|
||||||
delProcess.destroy();
|
throw new ParamMistakeException(String.format("获取手机【%s】实际宽高失败,请稍后再试!", info.getDeviceId()));
|
||||||
} catch (Exception e) {
|
}
|
||||||
logger.error("删除scrcpy进程失败:", e);
|
CatchParam catchParam = new CatchParam();
|
||||||
|
catchParam.setRealHeight(screenSizeMap.get("height"));
|
||||||
|
catchParam.setRealWidth(screenSizeMap.get("width"));
|
||||||
|
catchParam.setWidth(screenSizeMap.get("width")/2);
|
||||||
|
catchParam.setHeight(screenSizeMap.get("width")/2);
|
||||||
|
catchParam.setFrameRate(30);
|
||||||
|
catchParam.setQuality(75);
|
||||||
|
catchParam.setRotation(screenSizeMap.get("rotation"));
|
||||||
|
logger.info("手机【{}】的实际宽:{}高:{}............................",info.getDeviceId() ,catchParam.getRealWidth(), catchParam.getRealHeight());
|
||||||
|
AndroidScreenResponseThread screenThread = AndroidDeviceManager.getInstance().getScreenThread(info.getDeviceId());
|
||||||
|
if (null == screenThread || screenThread.isInterrupted() || !screenThread.isAlive()) { //没人连手机
|
||||||
|
screenThread = new AndroidScreenResponseThread(currentDevice);
|
||||||
|
screenThread.setCatchParam(catchParam);
|
||||||
|
screenThread.start();
|
||||||
|
AndroidDeviceManager.getInstance().saveDeviceScreenThread(info.getDeviceId(),screenThread);
|
||||||
|
}
|
||||||
|
screenThread.startRecordScreen(info.getTenantId(), catchParam.getRealWidth(), catchParam.getRealHeight(),taskId);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
String cmd = String.format("scrcpy -s %s -b 2M -Nr %s ", info.getDeviceId(), videoPath + "/" + taskId + ".mp4");
|
|
||||||
logger.info(cmd);
|
|
||||||
|
|
||||||
try {
|
// @Override
|
||||||
Process process = Runtime.getRuntime().exec(cmd);
|
// public String endRecord(DebuggerDeviceInfo info) {
|
||||||
processMap.put(taskId, process);
|
// String taskId = info.getTaskId();
|
||||||
logger.info("开启scrcpy进程");
|
// if (StringUtils.isBlank(taskId)) {
|
||||||
} catch (IOException e) {
|
// logger.warn("任务id必填");
|
||||||
logger.error("开启录屏异常:", e);
|
// return null;
|
||||||
}
|
// }
|
||||||
});
|
// String videoPath = null;
|
||||||
thread.start();
|
// String filePath = mobileProperty.getStfPath() + "/temp";
|
||||||
try {
|
// logger.info("关闭scrcpy进程");
|
||||||
Thread.sleep(2000);
|
// try {
|
||||||
} catch (InterruptedException e) {
|
// Process process = processMap.remove(taskId);
|
||||||
logger.warn("线程终止。。。。。。", e);
|
// if (process != null) {
|
||||||
Thread.currentThread().interrupt();
|
// process.destroy();
|
||||||
}
|
// process = null;
|
||||||
return false;
|
// }
|
||||||
}
|
// Thread.sleep(2000);
|
||||||
|
// } catch (Exception e) {
|
||||||
|
// logger.error("关闭录屏异常", e);
|
||||||
|
// return videoPath;
|
||||||
|
// }
|
||||||
|
// Boolean save = info.getSave();
|
||||||
|
// logger.info("上传视频文件");
|
||||||
|
// String fileName = filePath + "/" + taskId + ".mp4";
|
||||||
|
// File temp = new File(fileName);
|
||||||
|
// if (save) {
|
||||||
|
// try {
|
||||||
|
// //等待文件生成
|
||||||
|
// Thread.sleep(3000);
|
||||||
|
// } catch (InterruptedException e) {
|
||||||
|
// logger.warn("线程终止。。。。。。", e);
|
||||||
|
// Thread.currentThread().interrupt();
|
||||||
|
// }
|
||||||
|
// if (!temp.exists()) {
|
||||||
|
// logger.warn("结束录屏失败:视频文件不存在,文件路径:{}", fileName);
|
||||||
|
// return videoPath;
|
||||||
|
// }
|
||||||
|
// try {
|
||||||
|
// //租户id
|
||||||
|
// String tenantId = info.getTenantId();
|
||||||
|
//// NKFile nkFile = simpleStorageService.upload(tenantId, temp);
|
||||||
|
//// if (nkFile != null && StringUtils.isNotBlank(nkFile.getId())) {
|
||||||
|
//// logger.debug("文件上传成功,返回id:{}", nkFile.getId());
|
||||||
|
//// String fileId = nkFile.getId();
|
||||||
|
//// videoPath = pathToId(tenantId,fileId);
|
||||||
|
//// }
|
||||||
|
// Attachment upload = HttpUtils.upload(mobileProperty.getServerAddr() + mobileProperty.getPublicUploadAddr(), temp.getAbsolutePath(), tenantId);
|
||||||
|
// if (null != upload && StringUtils.isNotBlank(upload.getId())) {
|
||||||
|
// logger.debug("文件上传成功,返回id:{}", upload.getId());
|
||||||
|
// videoPath = upload.getUrlPath();
|
||||||
|
// }
|
||||||
|
// } catch (Exception e) {
|
||||||
|
// logger.error("结束录屏失败,文件上传未成功:", e);
|
||||||
|
// return videoPath;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// try {
|
||||||
|
// temp.deleteOnExit();
|
||||||
|
// } catch (Exception e) {
|
||||||
|
// logger.error("删除文件失败:", e);
|
||||||
|
// }
|
||||||
|
// return videoPath;
|
||||||
|
// }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String endRecord(DebuggerDeviceInfo info) {
|
public String endRecord(DebuggerDeviceInfo info) {
|
||||||
String taskId = info.getTaskId();
|
String result = null;
|
||||||
if (StringUtils.isBlank(taskId)) {
|
logger.info("收到设备【{}】在任务【{}】关闭录屏的请求............",info.getDeviceId(),info.getTaskId());
|
||||||
logger.warn("任务id必填");
|
AndroidScreenResponseThread screenThread = AndroidDeviceManager.getInstance().getScreenThread(info.getDeviceId());
|
||||||
return null;
|
if (null != screenThread && screenThread.isAlive() && !screenThread.isInterrupted()) {
|
||||||
|
result = screenThread.stopRecord();
|
||||||
|
return result;
|
||||||
|
} else {
|
||||||
|
logger.info("设备【{}】在任务【{}】录屏不存在............",info.getDeviceId(),info.getTaskId());
|
||||||
}
|
}
|
||||||
String videoPath = null;
|
logger.info("设备【{}】在任务【{}】录屏保存的地址:{}............",info.getDeviceId(),info.getTaskId(),result);
|
||||||
String filePath = mobileProperty.getStfPath() + "/temp";
|
return result;
|
||||||
logger.info("关闭scrcpy进程");
|
|
||||||
try {
|
|
||||||
Process process = processMap.remove(taskId);
|
|
||||||
if (process != null) {
|
|
||||||
process.destroy();
|
|
||||||
process = null;
|
|
||||||
}
|
|
||||||
Thread.sleep(2000);
|
|
||||||
} catch (Exception e) {
|
|
||||||
logger.error("关闭录屏异常", e);
|
|
||||||
return videoPath;
|
|
||||||
}
|
|
||||||
Boolean save = info.getSave();
|
|
||||||
logger.info("上传视频文件");
|
|
||||||
String fileName = filePath + "/" + taskId + ".mp4";
|
|
||||||
File temp = new File(fileName);
|
|
||||||
if (save) {
|
|
||||||
try {
|
|
||||||
//等待文件生成
|
|
||||||
Thread.sleep(3000);
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
logger.warn("线程终止。。。。。。", e);
|
|
||||||
Thread.currentThread().interrupt();
|
|
||||||
}
|
|
||||||
if (!temp.exists()) {
|
|
||||||
logger.warn("结束录屏失败:视频文件不存在,文件路径:{}", fileName);
|
|
||||||
return videoPath;
|
|
||||||
}
|
|
||||||
logger.info("视频文件路径:{},视频文件大小:{}", temp.getAbsolutePath(), temp.length());
|
|
||||||
try {
|
|
||||||
//租户id
|
|
||||||
String tenantId = info.getTenantId();
|
|
||||||
|
|
||||||
logger.info("开始上传视频文件,任务信息:{},android设备{}", JSON.toJSONString(info), info.getDeviceId());
|
|
||||||
Attachment upload = HttpUtils.upload(mobileProperty.getServerAddr() + mobileProperty.getPublicUploadAddr(), temp.getAbsolutePath(), tenantId, taskId, FileBusinessTypeEnum.MOBILE_TASK_VIDEO.getCode());
|
|
||||||
if (null != upload && StringUtils.isNotBlank(upload.getId())) {
|
|
||||||
logger.debug("文件上传成功,返回id:{}", upload.getId());
|
|
||||||
videoPath = upload.getUrlPath();
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
logger.error("结束录屏失败,文件上传未成功:", e);
|
|
||||||
return videoPath;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
temp.deleteOnExit();
|
|
||||||
} catch (Exception e) {
|
|
||||||
logger.error("删除文件失败:", e);
|
|
||||||
}
|
|
||||||
return videoPath;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -5,6 +5,7 @@ import com.alibaba.fastjson.JSON;
|
||||||
import com.alibaba.fastjson.JSONObject;
|
import com.alibaba.fastjson.JSONObject;
|
||||||
import io.appium.java_client.AppiumDriver;
|
import io.appium.java_client.AppiumDriver;
|
||||||
import net.northking.cctp.upperComputer.config.MobileProperty;
|
import net.northking.cctp.upperComputer.config.MobileProperty;
|
||||||
|
import net.northking.cctp.upperComputer.deviceManager.screen.IosScreenResponseThread;
|
||||||
import net.northking.cctp.upperComputer.entity.Attachment;
|
import net.northking.cctp.upperComputer.entity.Attachment;
|
||||||
import net.northking.cctp.upperComputer.entity.DebuggerDeviceInfo;
|
import net.northking.cctp.upperComputer.entity.DebuggerDeviceInfo;
|
||||||
import net.northking.cctp.upperComputer.entity.PhoneEntity;
|
import net.northking.cctp.upperComputer.entity.PhoneEntity;
|
||||||
|
@ -17,7 +18,6 @@ import net.northking.cctp.upperComputer.service.thread.IOSDeviceInfoByPackageThr
|
||||||
import net.northking.cctp.upperComputer.deviceManager.IOSDeviceManager;
|
import net.northking.cctp.upperComputer.deviceManager.IOSDeviceManager;
|
||||||
import net.northking.cctp.upperComputer.utils.HttpUtils;
|
import net.northking.cctp.upperComputer.utils.HttpUtils;
|
||||||
import net.northking.cctp.upperComputer.utils.ScreenShotUtils;
|
import net.northking.cctp.upperComputer.utils.ScreenShotUtils;
|
||||||
import net.northking.cctp.upperComputer.webSocket.thread.IosScreenResponseThread;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.openqa.selenium.WebElement;
|
import org.openqa.selenium.WebElement;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
@ -219,10 +219,13 @@ public class IosDebuggerServiceImpl extends AbstractDebuggerService {
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean startRecord(DebuggerDeviceInfo info) {
|
public boolean startRecord(DebuggerDeviceInfo info) {
|
||||||
IosScreenResponseThread screenThread = IOSDeviceManager.getInstance().getScreenThread(info.getDeviceId());
|
logger.info("收到设备【{}】在任务【{}】开启录屏的请求............",info.getDeviceId(),info.getTaskId());
|
||||||
|
net.northking.cctp.upperComputer.deviceManager.screen.IosScreenResponseThread screenThread = IOSDeviceManager.getInstance().getScreenThread(info.getDeviceId());
|
||||||
String taskId = info.getTaskId();
|
String taskId = info.getTaskId();
|
||||||
|
String tenantId = info.getTenantId();
|
||||||
String resolution = info.getResolution();
|
String resolution = info.getResolution();
|
||||||
String[] split = resolution.split("\\*");
|
String[] split = resolution.split("\\*");
|
||||||
int width = Integer.parseInt(split[0]);
|
int width = Integer.parseInt(split[0]);
|
||||||
|
@ -235,24 +238,27 @@ public class IosDebuggerServiceImpl extends AbstractDebuggerService {
|
||||||
}
|
}
|
||||||
if (null == screenThread || screenThread.isInterrupted() || !screenThread.isAlive()) { //没人连手机
|
if (null == screenThread || screenThread.isInterrupted() || !screenThread.isAlive()) { //没人连手机
|
||||||
PhoneEntity phoneEntity = IOSDeviceManager.getInstance().getPhoneEntity(info.getDeviceId());
|
PhoneEntity phoneEntity = IOSDeviceManager.getInstance().getPhoneEntity(info.getDeviceId());
|
||||||
screenThread = new IosScreenResponseThread(phoneEntity, taskId);
|
screenThread = new net.northking.cctp.upperComputer.deviceManager.screen.IosScreenResponseThread(phoneEntity);
|
||||||
screenThread.start();
|
screenThread.start();
|
||||||
IOSDeviceManager.getInstance().saveDeviceScreenThread(info.getDeviceId(),screenThread);
|
IOSDeviceManager.getInstance().saveDeviceScreenThread(info.getDeviceId(),screenThread);
|
||||||
}
|
}
|
||||||
screenThread.startRecordScreen("default", width, height,"2", taskId);
|
screenThread.startRecordScreen(tenantId, width, height,taskId);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String endRecord(DebuggerDeviceInfo info) {
|
public String endRecord(DebuggerDeviceInfo info) {
|
||||||
|
String result = null;
|
||||||
|
logger.info("收到设备【{}】在任务【{}】关闭录屏的请求............",info.getDeviceId(),info.getTaskId());
|
||||||
IosScreenResponseThread screenThread = IOSDeviceManager.getInstance().getScreenThread(info.getDeviceId());
|
IosScreenResponseThread screenThread = IOSDeviceManager.getInstance().getScreenThread(info.getDeviceId());
|
||||||
if (null != screenThread && screenThread.isAlive() && !screenThread.isInterrupted()) {
|
if (null != screenThread && screenThread.isAlive() && !screenThread.isInterrupted()) {
|
||||||
String tenantId = info.getTenantId();
|
result = screenThread.stopRecord();
|
||||||
//增加是否保存录屏文件的参数
|
|
||||||
String result = screenThread.stopRecord(tenantId,info.getSave());
|
|
||||||
return result;
|
return result;
|
||||||
|
} else {
|
||||||
|
logger.info("设备【{}】在任务【{}】录屏不存在............",info.getDeviceId(),info.getTaskId());
|
||||||
}
|
}
|
||||||
return null;
|
logger.info("设备【{}】在任务【{}】录屏保存的地址:{}............",info.getDeviceId(),info.getTaskId(),result);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -2,6 +2,7 @@ package net.northking.cctp.upperComputer.webSocket.thread;
|
||||||
|
|
||||||
import net.northking.cctp.upperComputer.constants.KeyBoardCodeEnum;
|
import net.northking.cctp.upperComputer.constants.KeyBoardCodeEnum;
|
||||||
import net.northking.cctp.upperComputer.deviceManager.IOSDeviceManager;
|
import net.northking.cctp.upperComputer.deviceManager.IOSDeviceManager;
|
||||||
|
import net.northking.cctp.upperComputer.deviceManager.screen.IosScreenResponseThread;
|
||||||
import net.northking.cctp.upperComputer.deviceManager.thread.IosDeviceInitThread;
|
import net.northking.cctp.upperComputer.deviceManager.thread.IosDeviceInitThread;
|
||||||
import net.northking.cctp.upperComputer.driver.ios.NKAgent;
|
import net.northking.cctp.upperComputer.driver.ios.NKAgent;
|
||||||
import net.northking.cctp.upperComputer.driver.ios.command.data.UiNodeData;
|
import net.northking.cctp.upperComputer.driver.ios.command.data.UiNodeData;
|
||||||
|
@ -34,8 +35,6 @@ public abstract class AbstractIosMessageHandlerThread extends AbstractMessageHan
|
||||||
|
|
||||||
protected IosFunctionByAgent function;
|
protected IosFunctionByAgent function;
|
||||||
|
|
||||||
protected IosScreenResponseThread screenResponseThread;
|
|
||||||
|
|
||||||
protected GetNodeTreeThread nodeTreeThread;
|
protected GetNodeTreeThread nodeTreeThread;
|
||||||
|
|
||||||
protected StopWatch handleWatch = new StopWatch();
|
protected StopWatch handleWatch = new StopWatch();
|
||||||
|
@ -160,7 +159,6 @@ public abstract class AbstractIosMessageHandlerThread extends AbstractMessageHan
|
||||||
SessionUtils.sendSuccessData(session, request, uiNodeData, "获取节点树成功");
|
SessionUtils.sendSuccessData(session, request, uiNodeData, "获取节点树成功");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void clearAndCloseDeviceAgentConnection() {
|
public void clearAndCloseDeviceAgentConnection() {
|
||||||
//通知前端设备现在处于掉线的状态,前端开始转圈
|
//通知前端设备现在处于掉线的状态,前端开始转圈
|
||||||
|
@ -170,8 +168,12 @@ public abstract class AbstractIosMessageHandlerThread extends AbstractMessageHan
|
||||||
@Override
|
@Override
|
||||||
public void reConnectDeviceAgent() {
|
public void reConnectDeviceAgent() {
|
||||||
notifyDeviceOnlineToWeb();
|
notifyDeviceOnlineToWeb();
|
||||||
|
//发送前端重连成功消息的标志
|
||||||
|
IosScreenResponseThread screenResponseThread = IOSDeviceManager.getInstance().getScreenThread(phoneEntity.getUdid());
|
||||||
|
if (null != screenResponseThread) {
|
||||||
screenResponseThread.setSendDeviceStatus(true); //发送连接成功消息
|
screenResponseThread.setSendDeviceStatus(true); //发送连接成功消息
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -551,35 +553,6 @@ public abstract class AbstractIosMessageHandlerThread extends AbstractMessageHan
|
||||||
return new Point(realX.floatValue(), realY.floatValue());
|
return new Point(realX.floatValue(), realY.floatValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void stopRecordScreen(CmdRequest request) {
|
|
||||||
String recordFileInfo = screenResponseThread.stopRecord();
|
|
||||||
if (recordFileInfo != null) {
|
|
||||||
Map<String, Object> result = new HashMap<>();
|
|
||||||
result.put("videoInfo", recordFileInfo);
|
|
||||||
SessionUtils.sendSuccessData(session, request, result, "结束录屏成功");
|
|
||||||
} else {
|
|
||||||
SessionUtils.sendFailureMessage(session, request, "该设备未开启录屏");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void startRecordScreen(CmdRequest request) {
|
|
||||||
Map<String, Object> data = request.getData();
|
|
||||||
ParamCheck tenantIdCheck = ParamCheck.build().name("tenantId").type("string").length(32);
|
|
||||||
Map<String, Object> params = null;
|
|
||||||
try {
|
|
||||||
params = checkParam(data, false, tenantIdCheck);
|
|
||||||
} catch (Exception e) {
|
|
||||||
logger.error("参数校验失败!", e);
|
|
||||||
if (e instanceof ParamMistakeException) {
|
|
||||||
SessionUtils.sendFailureMessage(session, request, e.getMessage());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
screenResponseThread.startRecordScreen((String) params.get("tenantId"), catchParam.getRealWidth(), catchParam.getRealHeight(), "1", null);
|
|
||||||
SessionUtils.sendSuccessData(session, request, null, "开启录屏成功");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void changeScreenQuality(CmdRequest request) {
|
public void changeScreenQuality(CmdRequest request) {
|
||||||
|
@ -601,6 +574,7 @@ public abstract class AbstractIosMessageHandlerThread extends AbstractMessageHan
|
||||||
int frameRateUse = (int) params.get("framerate");
|
int frameRateUse = (int) params.get("framerate");
|
||||||
catchParam.setFrameRate(frameRateUse);
|
catchParam.setFrameRate(frameRateUse);
|
||||||
logger.debug("改变屏幕质量=====>width:{} height:{} quality:{} frameRate:{}", catchParam.getWidth(), catchParam.getHeight(), qualityUse, frameRateUse);
|
logger.debug("改变屏幕质量=====>width:{} height:{} quality:{} frameRate:{}", catchParam.getWidth(), catchParam.getHeight(), qualityUse, frameRateUse);
|
||||||
|
IosScreenResponseThread screenResponseThread = IOSDeviceManager.getInstance().getScreenThread(phoneEntity.getUdid());
|
||||||
screenResponseThread.changeQuality(qualityUse / 100f,frameRateUse);
|
screenResponseThread.changeQuality(qualityUse / 100f,frameRateUse);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -624,6 +598,7 @@ public abstract class AbstractIosMessageHandlerThread extends AbstractMessageHan
|
||||||
int heightUse = (int) params.get("height");
|
int heightUse = (int) params.get("height");
|
||||||
catchParam.setHeight(heightUse);
|
catchParam.setHeight(heightUse);
|
||||||
logger.debug("改变宽高屏幕=====>width:{} height:{} quality:{} frameRate:{}", widthUse, heightUse, catchParam.getQuality(), catchParam.getFrameRate());
|
logger.debug("改变宽高屏幕=====>width:{} height:{} quality:{} frameRate:{}", widthUse, heightUse, catchParam.getQuality(), catchParam.getFrameRate());
|
||||||
|
IosScreenResponseThread screenResponseThread = IOSDeviceManager.getInstance().getScreenThread(phoneEntity.getUdid());
|
||||||
screenResponseThread.changeSize(widthUse, heightUse);
|
screenResponseThread.changeSize(widthUse, heightUse);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -657,25 +632,23 @@ public abstract class AbstractIosMessageHandlerThread extends AbstractMessageHan
|
||||||
int rotationUse = (int) params.get("rotation");
|
int rotationUse = (int) params.get("rotation");
|
||||||
catchParam.setRotation(rotationUse);
|
catchParam.setRotation(rotationUse);
|
||||||
logger.debug("开启屏幕=====>width:{} height:{} quality:{} frameRate:{},rotation:{}", widthUse, heightUse, qualityUse, frameRateUse, rotationUse);
|
logger.debug("开启屏幕=====>width:{} height:{} quality:{} frameRate:{},rotation:{}", widthUse, heightUse, qualityUse, frameRateUse, rotationUse);
|
||||||
screenResponseThread = IOSDeviceManager.getInstance().getScreenThread(phoneEntity.getUdid());
|
IosScreenResponseThread screenResponseThread = IOSDeviceManager.getInstance().getScreenThread(phoneEntity.getUdid());
|
||||||
if (null == screenResponseThread || screenResponseThread.isInterrupted() || !screenResponseThread.isAlive()) {
|
if (null == screenResponseThread || screenResponseThread.isInterrupted() || !screenResponseThread.isAlive()) {
|
||||||
//读取手机端响应线程
|
//读取手机端响应线程
|
||||||
screenResponseThread = new IosScreenResponseThread(phoneEntity, null);
|
screenResponseThread = new IosScreenResponseThread(phoneEntity);
|
||||||
screenResponseThread.start();
|
screenResponseThread.start();
|
||||||
screenResponseThread.startSendScreenToWeb(session, catchParam);
|
screenResponseThread.startSendScreenToWeb(session, catchParam);
|
||||||
screenResponseThread.setScreenOnRequest(request);
|
screenResponseThread.setScreenOnRequest(session,request);
|
||||||
IOSDeviceManager.getInstance().saveDeviceScreenThread(phoneEntity.getUdid(), screenResponseThread);
|
IOSDeviceManager.getInstance().saveDeviceScreenThread(phoneEntity.getUdid(), screenResponseThread);
|
||||||
} else {
|
} else {
|
||||||
screenResponseThread.startSendScreenToWeb(session, catchParam);
|
screenResponseThread.startSendScreenToWeb(session, catchParam);
|
||||||
screenResponseThread.setScreenOnRequest(request);
|
screenResponseThread.setScreenOnRequest(session,request);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void stopAndExit() {
|
public void stopAndExit() {
|
||||||
if (null != screenResponseThread) {
|
IOSDeviceManager.getInstance().stopWebScreen(phoneEntity.getUdid(),session);
|
||||||
screenResponseThread.stopFetchPic();
|
|
||||||
}
|
|
||||||
if (null != iosPerfThread) {
|
if (null != iosPerfThread) {
|
||||||
iosPerfThread.stopThread();
|
iosPerfThread.stopThread();
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,10 +60,6 @@ public abstract class AbstractMessageHandler extends Thread implements MessageHa
|
||||||
changeScreenSize(request);
|
changeScreenSize(request);
|
||||||
} else if (RequestCmd.SCREEN_QUALITY.equals(request.getCmd())) { //改变屏幕质量
|
} else if (RequestCmd.SCREEN_QUALITY.equals(request.getCmd())) { //改变屏幕质量
|
||||||
changeScreenQuality(request);
|
changeScreenQuality(request);
|
||||||
} else if (RequestCmd.SCREEN_RECORD_ON.equals(request.getCmd())) {//开启录屏
|
|
||||||
startRecordScreen(request);
|
|
||||||
} else if (RequestCmd.SCREEN_RECORD_OFF.equals(request.getCmd())) { //结束录屏
|
|
||||||
stopRecordScreen(request);
|
|
||||||
} else if (RequestCmd.SCREEN_CAPTURE.equals(request.getCmd())) {//截图
|
} else if (RequestCmd.SCREEN_CAPTURE.equals(request.getCmd())) {//截图
|
||||||
screenShot(request);
|
screenShot(request);
|
||||||
} else if (RequestCmd.INPUT_TOUCH_DOWN.equals(request.getCmd())) { //鼠标摁下
|
} else if (RequestCmd.INPUT_TOUCH_DOWN.equals(request.getCmd())) { //鼠标摁下
|
||||||
|
|
|
@ -6,6 +6,8 @@ import net.northking.cctp.upperComputer.constants.KeyBoardCodeEnum;
|
||||||
import net.northking.cctp.upperComputer.constants.ResponseCmd;
|
import net.northking.cctp.upperComputer.constants.ResponseCmd;
|
||||||
import net.northking.cctp.upperComputer.deviceManager.AndroidDeviceManager;
|
import net.northking.cctp.upperComputer.deviceManager.AndroidDeviceManager;
|
||||||
import net.northking.cctp.upperComputer.deviceManager.UpperComputerManager;
|
import net.northking.cctp.upperComputer.deviceManager.UpperComputerManager;
|
||||||
|
import net.northking.cctp.upperComputer.deviceManager.screen.AndroidScreenResponseThread;
|
||||||
|
import net.northking.cctp.upperComputer.deviceManager.screen.AndroidVideoScreenResponseThread;
|
||||||
import net.northking.cctp.upperComputer.deviceManager.thread.AndroidDeviceInitThread;
|
import net.northking.cctp.upperComputer.deviceManager.thread.AndroidDeviceInitThread;
|
||||||
import net.northking.cctp.upperComputer.driver.adb.AdbDevice;
|
import net.northking.cctp.upperComputer.driver.adb.AdbDevice;
|
||||||
import net.northking.cctp.upperComputer.driver.adb.AdbTransport;
|
import net.northking.cctp.upperComputer.driver.adb.AdbTransport;
|
||||||
|
@ -16,7 +18,6 @@ import net.northking.cctp.upperComputer.driver.agent.command.*;
|
||||||
import net.northking.cctp.upperComputer.driver.agent.command.data.PackageInfo;
|
import net.northking.cctp.upperComputer.driver.agent.command.data.PackageInfo;
|
||||||
import net.northking.cctp.upperComputer.driver.agent.command.protocol.ProtocolCommand;
|
import net.northking.cctp.upperComputer.driver.agent.command.protocol.ProtocolCommand;
|
||||||
import net.northking.cctp.upperComputer.entity.Attachment;
|
import net.northking.cctp.upperComputer.entity.Attachment;
|
||||||
import net.northking.cctp.upperComputer.enums.FileBusinessTypeEnum;
|
|
||||||
import net.northking.cctp.upperComputer.exception.ExecuteException;
|
import net.northking.cctp.upperComputer.exception.ExecuteException;
|
||||||
import net.northking.cctp.upperComputer.exception.ParamMistakeException;
|
import net.northking.cctp.upperComputer.exception.ParamMistakeException;
|
||||||
import net.northking.cctp.upperComputer.utils.HttpUtils;
|
import net.northking.cctp.upperComputer.utils.HttpUtils;
|
||||||
|
@ -50,8 +51,6 @@ public class AndroidMessageHandlerThread extends AbstractMessageHandler {
|
||||||
|
|
||||||
private String tenantId;
|
private String tenantId;
|
||||||
|
|
||||||
private AndroidScreenRecordThread screenRecordThread;
|
|
||||||
|
|
||||||
private AndroidLogThread androidLogThread;
|
private AndroidLogThread androidLogThread;
|
||||||
|
|
||||||
private AndroidPerfThread androidPerfThread;
|
private AndroidPerfThread androidPerfThread;
|
||||||
|
@ -68,8 +67,6 @@ public class AndroidMessageHandlerThread extends AbstractMessageHandler {
|
||||||
|
|
||||||
private boolean capsDown = false;
|
private boolean capsDown = false;
|
||||||
|
|
||||||
private AndroidScreenResponseThread responseThread;
|
|
||||||
|
|
||||||
private AndroidVideoScreenResponseThread videoScreenResponseThread;
|
private AndroidVideoScreenResponseThread videoScreenResponseThread;
|
||||||
|
|
||||||
private List<String> capsUpLetters = Arrays.asList("A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z");
|
private List<String> capsUpLetters = Arrays.asList("A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z");
|
||||||
|
@ -154,7 +151,7 @@ public class AndroidMessageHandlerThread extends AbstractMessageHandler {
|
||||||
//上传到服务器
|
//上传到服务器
|
||||||
String serverIp = SpringUtils.getProperties("nk.mobile-computer.serverAddr");
|
String serverIp = SpringUtils.getProperties("nk.mobile-computer.serverAddr");
|
||||||
String fileUploadPath = SpringUtils.getProperties("nk.mobile-computer.publicUploadAddr");
|
String fileUploadPath = SpringUtils.getProperties("nk.mobile-computer.publicUploadAddr");
|
||||||
String fileId = HttpUtils.doUpload(serverIp + fileUploadPath, tmpFile, tenantId,null, FileBusinessTypeEnum.MOBILE_TASK_SCREENSHOT.getCode());
|
String fileId = HttpUtils.doUpload(serverIp + fileUploadPath, tmpFile, tenantId);
|
||||||
logger.info("上传文件到服务器完成:{}", fileId);
|
logger.info("上传文件到服务器完成:{}", fileId);
|
||||||
Map<String, Object> result = new HashMap<>();
|
Map<String, Object> result = new HashMap<>();
|
||||||
result.put("fileName", fileName);
|
result.put("fileName", fileName);
|
||||||
|
@ -325,7 +322,6 @@ public class AndroidMessageHandlerThread extends AbstractMessageHandler {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void getNodeTreeOnce(CmdRequest request) {
|
public void getNodeTreeOnce(CmdRequest request) {
|
||||||
|
|
||||||
|
@ -365,8 +361,10 @@ public class AndroidMessageHandlerThread extends AbstractMessageHandler {
|
||||||
throw new ExecuteException("设备还未准备好,请稍后再试");
|
throw new ExecuteException("设备还未准备好,请稍后再试");
|
||||||
}
|
}
|
||||||
notifyDeviceOnlineToWeb();
|
notifyDeviceOnlineToWeb();
|
||||||
if(responseThread != null){
|
//发送前端重连成功消息的标志
|
||||||
responseThread.setSendDeviceStatus(true); //发送连接成功消息
|
AndroidScreenResponseThread screenThread = AndroidDeviceManager.getInstance().getScreenThread(adbDevice.getSerial());
|
||||||
|
if (null != screenThread) {
|
||||||
|
screenThread.setSendDeviceStatus(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1152,7 +1150,7 @@ public class AndroidMessageHandlerThread extends AbstractMessageHandler {
|
||||||
String pubUploadPath = SpringUtils.getProperties("nk.mobile-computer.publicUploadAddr");
|
String pubUploadPath = SpringUtils.getProperties("nk.mobile-computer.publicUploadAddr");
|
||||||
Attachment upload = null;
|
Attachment upload = null;
|
||||||
try {
|
try {
|
||||||
upload = HttpUtils.upload(serverAddress + pubUploadPath, screenShotData, tenantId,null,FileBusinessTypeEnum.MOBILE_TASK_SCREENSHOT.getCode());
|
upload = HttpUtils.upload(serverAddress + pubUploadPath, screenShotData, tenantId);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logger.debug("[{}]上传截图失败", adbDevice.getSerial(),e);
|
logger.debug("[{}]上传截图失败", adbDevice.getSerial(),e);
|
||||||
}
|
}
|
||||||
|
@ -1172,45 +1170,9 @@ public class AndroidMessageHandlerThread extends AbstractMessageHandler {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void stopRecordScreen(CmdRequest request) {
|
|
||||||
if (screenRecordThread != null && screenRecordThread.isAlive()) {
|
|
||||||
String recordFilePath = screenRecordThread.stopRecord();
|
|
||||||
if (recordFilePath != null) {
|
|
||||||
Map<String, Object> result = new HashMap<>();
|
|
||||||
result.put("videoInfo", recordFilePath);
|
|
||||||
SessionUtils.sendSuccessData(session, request, result, "结束录屏成功");
|
|
||||||
} else {
|
|
||||||
SessionUtils.sendFailureMessage(session, request, "上传录屏失败");
|
|
||||||
}
|
|
||||||
screenRecordThread = null;
|
|
||||||
} else {
|
|
||||||
SessionUtils.sendFailureMessage(session, request, "未找到开启录屏信息");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void startRecordScreen(CmdRequest request) {
|
|
||||||
Map<String, Object> data = request.getData();
|
|
||||||
ParamCheck tenantIdCheck = ParamCheck.build().name("tenantId").type("string").length(32);
|
|
||||||
Map<String, Object> params = null;
|
|
||||||
try {
|
|
||||||
params = checkParam(data, false, tenantIdCheck);
|
|
||||||
} catch (Exception e) {
|
|
||||||
logger.error("参数校验失败!", e);
|
|
||||||
if (e instanceof ParamMistakeException) {
|
|
||||||
SessionUtils.sendFailureMessage(session, request, e.getMessage());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (null == screenRecordThread || screenRecordThread.isInterrupted() || !screenRecordThread.isAlive()) {
|
|
||||||
screenRecordThread = new AndroidScreenRecordThread(adbDevice.getSerial(), (String) params.get("tenantId"), catchParam.getRealWidth(), catchParam.getRealHeight());
|
|
||||||
screenRecordThread.start();
|
|
||||||
} else {
|
|
||||||
logger.info("设备【{}】正在录屏。。。。。",serial);
|
|
||||||
}
|
|
||||||
SessionUtils.sendSuccessData(session, request, null, "开启录屏成功");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void changeScreenQuality(CmdRequest request) {
|
public void changeScreenQuality(CmdRequest request) {
|
||||||
|
@ -1232,6 +1194,7 @@ public class AndroidMessageHandlerThread extends AbstractMessageHandler {
|
||||||
int frameRateUse = (int) params.get("framerate");
|
int frameRateUse = (int) params.get("framerate");
|
||||||
catchParam.setFrameRate(frameRateUse);
|
catchParam.setFrameRate(frameRateUse);
|
||||||
logger.debug("改变屏幕质量=====>width:{} height:{} quality:{} frameRate:{}", catchParam.getWidth(), catchParam.getHeight(), qualityUse, frameRateUse);
|
logger.debug("改变屏幕质量=====>width:{} height:{} quality:{} frameRate:{}", catchParam.getWidth(), catchParam.getHeight(), qualityUse, frameRateUse);
|
||||||
|
AndroidScreenResponseThread responseThread = AndroidDeviceManager.getInstance().getScreenThread(adbDevice.getSerial());
|
||||||
if (null != responseThread) { //图片流
|
if (null != responseThread) { //图片流
|
||||||
ScreenStreamCommand screenStreamCommand = new ScreenStreamCommand(true, 0, catchParam.getWidth(), catchParam.getHeight(), frameRateUse, qualityUse);
|
ScreenStreamCommand screenStreamCommand = new ScreenStreamCommand(true, 0, catchParam.getWidth(), catchParam.getHeight(), frameRateUse, qualityUse);
|
||||||
asyncSendCommand(screenStreamCommand);
|
asyncSendCommand(screenStreamCommand);
|
||||||
|
@ -1264,6 +1227,7 @@ public class AndroidMessageHandlerThread extends AbstractMessageHandler {
|
||||||
int heightUse = (int) params.get("height");
|
int heightUse = (int) params.get("height");
|
||||||
catchParam.setHeight(heightUse);
|
catchParam.setHeight(heightUse);
|
||||||
logger.debug("改变宽高屏幕=====>width:{} height:{} quality:{} frameRate:{}", widthUse, heightUse, catchParam.getQuality(), catchParam.getFrameRate());
|
logger.debug("改变宽高屏幕=====>width:{} height:{} quality:{} frameRate:{}", widthUse, heightUse, catchParam.getQuality(), catchParam.getFrameRate());
|
||||||
|
AndroidScreenResponseThread responseThread = AndroidDeviceManager.getInstance().getScreenThread(adbDevice.getSerial());
|
||||||
if (null != responseThread) { //图片流
|
if (null != responseThread) { //图片流
|
||||||
ScreenStreamCommand screenStreamCommand = new ScreenStreamCommand(true, 0, widthUse, heightUse, catchParam.getFrameRate(), catchParam.getQuality());
|
ScreenStreamCommand screenStreamCommand = new ScreenStreamCommand(true, 0, widthUse, heightUse, catchParam.getFrameRate(), catchParam.getQuality());
|
||||||
asyncSendCommand(screenStreamCommand);
|
asyncSendCommand(screenStreamCommand);
|
||||||
|
@ -1313,19 +1277,20 @@ public class AndroidMessageHandlerThread extends AbstractMessageHandler {
|
||||||
catchParam.setRotation(rotationUse);
|
catchParam.setRotation(rotationUse);
|
||||||
if ("image".equals(type)) {
|
if ("image".equals(type)) {
|
||||||
logger.debug("接收到开启屏幕指令=====>width:{} height:{} quality:{} frameRate:{},rotation:{}", widthUse, heightUse, qualityUse, frameRateUse, rotationUse);
|
logger.debug("接收到开启屏幕指令=====>width:{} height:{} quality:{} frameRate:{},rotation:{}", widthUse, heightUse, qualityUse, frameRateUse, rotationUse);
|
||||||
responseThread = AndroidDeviceManager.getInstance().getScreenThread(adbDevice.getSerial());
|
AndroidScreenResponseThread responseThread = AndroidDeviceManager.getInstance().getScreenThread(adbDevice.getSerial());
|
||||||
if (null == responseThread || responseThread.isInterrupted() || !responseThread.isAlive()) {
|
if (null == responseThread || responseThread.isInterrupted() || !responseThread.isAlive()) {
|
||||||
//之前未开启过设备屏幕获取线程则新建
|
//之前未开启过设备屏幕获取线程则新建
|
||||||
logger.debug("设备【{}】新建屏幕获取线程------",serial);
|
logger.debug("设备【{}】新建屏幕获取线程------",serial);
|
||||||
responseThread = new AndroidScreenResponseThread(session, adbDevice, catchParam);
|
responseThread = new AndroidScreenResponseThread(adbDevice);
|
||||||
responseThread.setScreenOnRequest(request);
|
responseThread.startSendScreenToWeb(session,catchParam);
|
||||||
|
responseThread.setScreenOnRequest(session,request);
|
||||||
responseThread.start();
|
responseThread.start();
|
||||||
AndroidDeviceManager.getInstance().saveDeviceScreenThread(adbDevice.getSerial(), responseThread);
|
AndroidDeviceManager.getInstance().saveDeviceScreenThread(adbDevice.getSerial(), responseThread);
|
||||||
} else {
|
} else {
|
||||||
//之前开启过则复用原屏幕获取线程
|
//之前开启过则复用原屏幕获取线程
|
||||||
logger.debug("设备【{}】复用原屏幕获取线程=====",serial);
|
logger.debug("设备【{}】复用原屏幕获取线程=====",serial);
|
||||||
responseThread.setScreenOnRequest(request);
|
|
||||||
responseThread.startSendScreenToWeb(session,catchParam);
|
responseThread.startSendScreenToWeb(session,catchParam);
|
||||||
|
responseThread.setScreenOnRequest(session,request);
|
||||||
}
|
}
|
||||||
} else if ("video".equals(type)) {
|
} else if ("video".equals(type)) {
|
||||||
//视频流专属的参数
|
//视频流专属的参数
|
||||||
|
@ -1413,9 +1378,7 @@ public class AndroidMessageHandlerThread extends AbstractMessageHandler {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void stopAndExit() {
|
public void stopAndExit() {
|
||||||
if (null != responseThread) {
|
AndroidDeviceManager.getInstance().stopWebScreen(adbDevice.getSerial(),session);
|
||||||
responseThread.stopSendPic2Web();
|
|
||||||
}
|
|
||||||
if (null != videoScreenResponseThread) {
|
if (null != videoScreenResponseThread) {
|
||||||
videoScreenResponseThread.stopAndExit();
|
videoScreenResponseThread.stopAndExit();
|
||||||
}
|
}
|
||||||
|
@ -1425,9 +1388,6 @@ public class AndroidMessageHandlerThread extends AbstractMessageHandler {
|
||||||
if (null != syncAgentSession) {
|
if (null != syncAgentSession) {
|
||||||
syncAgentSession.closeSilence();
|
syncAgentSession.closeSilence();
|
||||||
}
|
}
|
||||||
if (null != screenRecordThread) {
|
|
||||||
screenRecordThread.stopRecord();
|
|
||||||
}
|
|
||||||
if (null != androidPerfThread) {
|
if (null != androidPerfThread) {
|
||||||
androidPerfThread.stopThread();
|
androidPerfThread.stopThread();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,131 +0,0 @@
|
||||||
package net.northking.cctp.upperComputer.webSocket.thread;
|
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSON;
|
|
||||||
import net.northking.cctp.upperComputer.deviceManager.UpperComputerManager;
|
|
||||||
import net.northking.cctp.upperComputer.enums.FileBusinessTypeEnum;
|
|
||||||
import net.northking.cctp.upperComputer.entity.Attachment;
|
|
||||||
import net.northking.cctp.upperComputer.utils.HttpUtils;
|
|
||||||
import net.northking.cctp.upperComputer.utils.ProcessCmdUtils;
|
|
||||||
import net.northking.cctp.upperComputer.utils.SpringUtils;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.InputStreamReader;
|
|
||||||
import java.io.LineNumberReader;
|
|
||||||
import java.text.SimpleDateFormat;
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 录屏线程
|
|
||||||
*/
|
|
||||||
public class AndroidScreenRecordThread extends Thread{
|
|
||||||
|
|
||||||
private Logger logger = LoggerFactory.getLogger(AndroidScreenRecordThread.class);
|
|
||||||
|
|
||||||
private String serial;
|
|
||||||
|
|
||||||
private Process process;
|
|
||||||
|
|
||||||
private String recordFileName;
|
|
||||||
|
|
||||||
private String tenantId;
|
|
||||||
|
|
||||||
private int videoWidth;
|
|
||||||
|
|
||||||
private int videoHeight;
|
|
||||||
|
|
||||||
public AndroidScreenRecordThread(String serial,String tenantId,int width,int height){
|
|
||||||
this.serial = serial;
|
|
||||||
this.tenantId = tenantId;
|
|
||||||
this.videoWidth = width;
|
|
||||||
this.videoHeight = height;
|
|
||||||
setName("[" + serial+"]-record");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
String applicationPath = UpperComputerManager.getInstance().getApplicationPath();
|
|
||||||
applicationPath = applicationPath.replace("\\","/");
|
|
||||||
File screenRecordPath = new File(applicationPath + "/screenRecordTmp/");
|
|
||||||
if (!screenRecordPath.exists()) {
|
|
||||||
screenRecordPath.mkdirs();
|
|
||||||
}
|
|
||||||
SimpleDateFormat format = new SimpleDateFormat("yyyy_MM_dd_HH_mm_ss");
|
|
||||||
String dateFormat = format.format(new Date());
|
|
||||||
String tmpPath = screenRecordPath.getAbsolutePath();
|
|
||||||
tmpPath = tmpPath.replace("\\","/");
|
|
||||||
recordFileName = tmpPath + "/" + serial + "_" + dateFormat + ".mp4";
|
|
||||||
List<String> cmdList = new ArrayList<>();
|
|
||||||
cmdList.add("scrcpy");
|
|
||||||
cmdList.add("-s");
|
|
||||||
cmdList.add(serial);
|
|
||||||
cmdList.add("-b");
|
|
||||||
cmdList.add("2M");
|
|
||||||
cmdList.add("-Nr");
|
|
||||||
cmdList.add(recordFileName);
|
|
||||||
logger.info("[" +serial+ "]录屏开启,时间:{}",new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
|
|
||||||
process = ProcessCmdUtils.execCmd(cmdList);
|
|
||||||
InputStreamReader ir = null;
|
|
||||||
LineNumberReader input = null;
|
|
||||||
try {
|
|
||||||
ir = new InputStreamReader(process.getInputStream(),"UTF-8");
|
|
||||||
input = new LineNumberReader(ir);
|
|
||||||
String line;
|
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
while ((line = input.readLine()) != null) {
|
|
||||||
logger.debug(line);
|
|
||||||
sb.append(line);
|
|
||||||
}
|
|
||||||
input.close();
|
|
||||||
} catch (Exception e) {
|
|
||||||
logger.warn("读取录屏输出失败",e);
|
|
||||||
}
|
|
||||||
logger.info("[" +serial+ "]录屏结束,时间:{}",new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
|
|
||||||
}
|
|
||||||
|
|
||||||
public String stopRecord(){
|
|
||||||
if (null != process) {
|
|
||||||
process.destroy();
|
|
||||||
logger.debug("录屏进程是否存活:{}",process.isAlive());
|
|
||||||
//上传文件
|
|
||||||
logger.debug("[" +serial+ "]录屏停止,开始上传视屏文件");
|
|
||||||
String serverAddress = SpringUtils.getProperties("nk.mobile-computer.serverAddr");
|
|
||||||
String pubUploadPath = SpringUtils.getProperties("nk.mobile-computer.publicUploadAddr");
|
|
||||||
try {
|
|
||||||
if (StringUtils.isNotBlank(recordFileName)) {
|
|
||||||
File file = new File(recordFileName);
|
|
||||||
//文件存在才上传
|
|
||||||
if (null != file && file.exists()) {
|
|
||||||
logger.info("开始上传安卓视频文件,设备Id:{}", serial);
|
|
||||||
Attachment upload = HttpUtils.upload(serverAddress + pubUploadPath, recordFileName, tenantId, null, FileBusinessTypeEnum.MOBILE_TASK_VIDEO.getCode());
|
|
||||||
if (null != upload && StringUtils.isNotBlank(upload.getId())) {
|
|
||||||
logger.debug("文件上传成功,返回id:{}", upload.getId());
|
|
||||||
Map<String, String> resultMap = new HashMap<>();
|
|
||||||
resultMap.put("videoUrl", upload.getUrlPath());
|
|
||||||
resultMap.put("videoRef", videoWidth + "x" + videoHeight);
|
|
||||||
return JSON.toJSONString(resultMap);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}else {
|
|
||||||
logger.warn("[" +serial+ "]录屏文件路径为空");
|
|
||||||
}
|
|
||||||
}catch (Exception e) {
|
|
||||||
logger.error("上传录像文件异常,",e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void killRecord(){
|
|
||||||
if (null != process) {
|
|
||||||
process.destroy();
|
|
||||||
logger.debug("原录屏进程是否存活:",process.isAlive());
|
|
||||||
File file = new File(recordFileName);
|
|
||||||
if (file.exists()) {
|
|
||||||
file.delete();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -2,7 +2,6 @@ package net.northking.cctp.upperComputer.webSocket.thread;
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.JSON;
|
||||||
import com.alibaba.fastjson.JSONObject;
|
import com.alibaba.fastjson.JSONObject;
|
||||||
import net.northking.cctp.upperComputer.constants.HandCommand;
|
|
||||||
import net.northking.cctp.upperComputer.constants.IosInputKeyBoardEnum;
|
import net.northking.cctp.upperComputer.constants.IosInputKeyBoardEnum;
|
||||||
import net.northking.cctp.upperComputer.constants.KeyBoardCodeEnum;
|
import net.northking.cctp.upperComputer.constants.KeyBoardCodeEnum;
|
||||||
import net.northking.cctp.upperComputer.deviceManager.IOSDeviceManager;
|
import net.northking.cctp.upperComputer.deviceManager.IOSDeviceManager;
|
||||||
|
@ -10,13 +9,8 @@ import net.northking.cctp.upperComputer.deviceManager.UpperComputerManager;
|
||||||
import net.northking.cctp.upperComputer.deviceManager.common.PyMobileDevice;
|
import net.northking.cctp.upperComputer.deviceManager.common.PyMobileDevice;
|
||||||
import net.northking.cctp.upperComputer.deviceManager.thread.IosDeviceInitThread;
|
import net.northking.cctp.upperComputer.deviceManager.thread.IosDeviceInitThread;
|
||||||
import net.northking.cctp.upperComputer.driver.ios.NKAgent;
|
import net.northking.cctp.upperComputer.driver.ios.NKAgent;
|
||||||
import net.northking.cctp.upperComputer.driver.ios.command.data.DragXYData;
|
|
||||||
import net.northking.cctp.upperComputer.driver.ios.command.data.ForceTapXYData;
|
|
||||||
import net.northking.cctp.upperComputer.driver.ios.command.data.TypeKeysUiNodeData;
|
|
||||||
import net.northking.cctp.upperComputer.driver.ios.packet.EmptyCommandData;
|
|
||||||
import net.northking.cctp.upperComputer.entity.Attachment;
|
import net.northking.cctp.upperComputer.entity.Attachment;
|
||||||
import net.northking.cctp.upperComputer.entity.PhoneEntity;
|
import net.northking.cctp.upperComputer.entity.PhoneEntity;
|
||||||
import net.northking.cctp.upperComputer.enums.FileBusinessTypeEnum;
|
|
||||||
import net.northking.cctp.upperComputer.exception.ExecuteException;
|
import net.northking.cctp.upperComputer.exception.ExecuteException;
|
||||||
import net.northking.cctp.upperComputer.exception.ParamMistakeException;
|
import net.northking.cctp.upperComputer.exception.ParamMistakeException;
|
||||||
import net.northking.cctp.upperComputer.utils.HttpUtils;
|
import net.northking.cctp.upperComputer.utils.HttpUtils;
|
||||||
|
@ -41,6 +35,7 @@ public class IosMacMessageHandlerThread extends AbstractIosMessageHandlerThread
|
||||||
|
|
||||||
private final Logger logger = LoggerFactory.getLogger(IosMacMessageHandlerThread.class);
|
private final Logger logger = LoggerFactory.getLogger(IosMacMessageHandlerThread.class);
|
||||||
|
|
||||||
|
|
||||||
public IosMacMessageHandlerThread(PhoneEntity phoneEntity, Session session) throws ParamMistakeException {
|
public IosMacMessageHandlerThread(PhoneEntity phoneEntity, Session session) throws ParamMistakeException {
|
||||||
super(phoneEntity, session);
|
super(phoneEntity, session);
|
||||||
}
|
}
|
||||||
|
@ -689,7 +684,7 @@ public class IosMacMessageHandlerThread extends AbstractIosMessageHandlerThread
|
||||||
String pubUploadPath = SpringUtils.getProperties("nk.mobile-computer.publicUploadAddr");
|
String pubUploadPath = SpringUtils.getProperties("nk.mobile-computer.publicUploadAddr");
|
||||||
Attachment upload = null;
|
Attachment upload = null;
|
||||||
try {
|
try {
|
||||||
upload = HttpUtils.upload(serverAddress + pubUploadPath, screenShotData, tenantId, null, FileBusinessTypeEnum.MOBILE_RECORD_SCREENSHOT.getCode());
|
upload = HttpUtils.upload(serverAddress + pubUploadPath, screenShotData, tenantId);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logger.debug("[{}]上传截图失败", phoneEntity.getUdid(), e);
|
logger.debug("[{}]上传截图失败", phoneEntity.getUdid(), e);
|
||||||
}
|
}
|
||||||
|
@ -712,9 +707,7 @@ public class IosMacMessageHandlerThread extends AbstractIosMessageHandlerThread
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void stopAndExit() {
|
public void stopAndExit() {
|
||||||
if (null != screenResponseThread) {
|
IOSDeviceManager.getInstance().stopWebScreen(phoneEntity.getUdid(),session);
|
||||||
screenResponseThread.stopFetchPic();
|
|
||||||
}
|
|
||||||
if (null != iosPerfThread) {
|
if (null != iosPerfThread) {
|
||||||
iosPerfThread.stopThread();
|
iosPerfThread.stopThread();
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,6 @@ import net.northking.cctp.upperComputer.deviceManager.thread.IosDeviceInitThread
|
||||||
import net.northking.cctp.upperComputer.driver.ios.NKAgent;
|
import net.northking.cctp.upperComputer.driver.ios.NKAgent;
|
||||||
import net.northking.cctp.upperComputer.entity.Attachment;
|
import net.northking.cctp.upperComputer.entity.Attachment;
|
||||||
import net.northking.cctp.upperComputer.entity.PhoneEntity;
|
import net.northking.cctp.upperComputer.entity.PhoneEntity;
|
||||||
import net.northking.cctp.upperComputer.enums.FileBusinessTypeEnum;
|
|
||||||
import net.northking.cctp.upperComputer.exception.ExecuteException;
|
import net.northking.cctp.upperComputer.exception.ExecuteException;
|
||||||
import net.northking.cctp.upperComputer.exception.ParamMistakeException;
|
import net.northking.cctp.upperComputer.exception.ParamMistakeException;
|
||||||
import net.northking.cctp.upperComputer.utils.HttpUtils;
|
import net.northking.cctp.upperComputer.utils.HttpUtils;
|
||||||
|
@ -20,7 +19,6 @@ import net.northking.cctp.upperComputer.utils.SpringUtils;
|
||||||
import net.northking.cctp.upperComputer.webSocket.entity.CmdRequest;
|
import net.northking.cctp.upperComputer.webSocket.entity.CmdRequest;
|
||||||
import net.northking.cctp.upperComputer.webSocket.entity.ParamCheck;
|
import net.northking.cctp.upperComputer.webSocket.entity.ParamCheck;
|
||||||
import net.northking.cctp.upperComputer.webSocket.entity.Point;
|
import net.northking.cctp.upperComputer.webSocket.entity.Point;
|
||||||
import net.northking.cctp.upperComputer.webSocket.function.IosFunction;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
@ -112,7 +110,6 @@ public class IosWindowsAndLinuxMessageHandlerThread extends AbstractIosMessageHa
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void stopLogcat(CmdRequest request) {
|
public void stopLogcat(CmdRequest request) {
|
||||||
Map<String, Object> data = request.getData();
|
Map<String, Object> data = request.getData();
|
||||||
|
@ -648,9 +645,7 @@ public class IosWindowsAndLinuxMessageHandlerThread extends AbstractIosMessageHa
|
||||||
function.swipe(startX, startY, endX, endY);
|
function.swipe(startX, startY, endX, endY);
|
||||||
} else { //点击
|
} else { //点击
|
||||||
if (time < 2000) {//点击
|
if (time < 2000) {//点击
|
||||||
logger.debug("设备【{}】准备请求点击坐标x:{},y:{}",phoneEntity.getUdid(),startX,startY);
|
|
||||||
function.click(startX, startY);
|
function.click(startX, startY);
|
||||||
logger.debug("设备【{}】点击完成",phoneEntity.getUdid(),startX,startY);
|
|
||||||
} else { //长按
|
} else { //长按
|
||||||
function.longPress(startX, startY);
|
function.longPress(startX, startY);
|
||||||
}
|
}
|
||||||
|
@ -718,7 +713,7 @@ public class IosWindowsAndLinuxMessageHandlerThread extends AbstractIosMessageHa
|
||||||
String pubUploadPath = SpringUtils.getProperties("nk.mobile-computer.publicUploadAddr");
|
String pubUploadPath = SpringUtils.getProperties("nk.mobile-computer.publicUploadAddr");
|
||||||
Attachment upload = null;
|
Attachment upload = null;
|
||||||
try {
|
try {
|
||||||
upload = HttpUtils.upload(serverAddress + pubUploadPath, screenShotData, tenantId, null, FileBusinessTypeEnum.MOBILE_TASK_SCREENSHOT.getCode());
|
upload = HttpUtils.upload(serverAddress + pubUploadPath, screenShotData, tenantId);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logger.debug("[{}]上传截图失败", phoneEntity.getUdid(), e);
|
logger.debug("[{}]上传截图失败", phoneEntity.getUdid(), e);
|
||||||
}
|
}
|
||||||
|
@ -740,9 +735,7 @@ public class IosWindowsAndLinuxMessageHandlerThread extends AbstractIosMessageHa
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void stopAndExit() {
|
public void stopAndExit() {
|
||||||
if (null != screenResponseThread) {
|
IOSDeviceManager.getInstance().stopWebScreen(phoneEntity.getUdid(),session);
|
||||||
screenResponseThread.stopFetchPic();
|
|
||||||
}
|
|
||||||
if (null != iosPerfThread) {
|
if (null != iosPerfThread) {
|
||||||
iosPerfThread.stopThread();
|
iosPerfThread.stopThread();
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,10 +23,6 @@ public interface MessageHandler {
|
||||||
|
|
||||||
public void changeScreenQuality(CmdRequest request);
|
public void changeScreenQuality(CmdRequest request);
|
||||||
|
|
||||||
public void startRecordScreen(CmdRequest request);
|
|
||||||
|
|
||||||
public void stopRecordScreen(CmdRequest request);
|
|
||||||
|
|
||||||
public void screenShot(CmdRequest request);
|
public void screenShot(CmdRequest request);
|
||||||
|
|
||||||
public void touchDown(CmdRequest request);
|
public void touchDown(CmdRequest request);
|
||||||
|
|
Loading…
Reference in New Issue