截图使用session,wda挂了之后重建nkAgent卡死
parent
f5dda0f46c
commit
e5d1e6e68b
|
@ -27,6 +27,14 @@ public abstract class IosDeviceInitThread extends Thread {
|
|||
|
||||
protected AppleDevice appleDevice;
|
||||
|
||||
/**
|
||||
* wda进程信息
|
||||
*/
|
||||
protected Process process;
|
||||
|
||||
protected boolean isFBServerReady = false;
|
||||
|
||||
|
||||
private int frame = 12;
|
||||
|
||||
public IosDeviceInitThread(PhoneEntity phone, AppleDevice appleDevice) {
|
||||
|
@ -36,22 +44,23 @@ public abstract class IosDeviceInitThread extends Thread {
|
|||
}
|
||||
|
||||
|
||||
protected void createNKAgent() {
|
||||
protected synchronized void createNKAgent(String tag) {
|
||||
logger.debug("createNKAgent:{}",tag);
|
||||
nkAgent = new NKAgent(this.appleDevice);
|
||||
nkAgent.setOnDisconnectListener(() -> {
|
||||
if(!isFBServerReady) return;
|
||||
logger.warn("设备【{}】的nkAgent失效了,需要重新创建...........", phone.getUdid());
|
||||
createNKAgent("回调重试");
|
||||
logger.warn("设备【{}】的nkAgent重新创建完成...........", phone.getUdid());
|
||||
});
|
||||
boolean nkAgentReady = false;
|
||||
int reTryTime = 1;
|
||||
do {
|
||||
while (!nkAgentReady && reTryTime <= 5 && isFBServerReady) {
|
||||
logger.debug("尝试第{}次连接设备【{}】的nkAgent", reTryTime, phone.getUdid());
|
||||
try {
|
||||
nkAgent.connect();
|
||||
nkAgentReady = nkAgent.getStatus();
|
||||
logger.debug("设备【{}】的nkAgent连接完成,结果:{}", phone.getUdid(), nkAgentReady);
|
||||
if (nkAgentReady) {
|
||||
logger.debug("设置设备【{}】的帧数为:{}", phone.getUdid(), frame);
|
||||
nkAgent.setMJPEGServerRate(frame);
|
||||
} else {
|
||||
logger.error("第{}次连接设备【{}】的agent不成功,等待下一次......",reTryTime, phone.getUdid());
|
||||
}
|
||||
} catch (IOException e) {
|
||||
logger.error("第{}次连接设备【{}】的agent出错", reTryTime, phone.getUdid(), e);
|
||||
try {
|
||||
|
@ -61,25 +70,23 @@ public abstract class IosDeviceInitThread extends Thread {
|
|||
}
|
||||
}
|
||||
reTryTime++;
|
||||
} while (!nkAgentReady && reTryTime <= 5);
|
||||
}
|
||||
if (!nkAgentReady) {
|
||||
nkAgent.setOnDisconnectListener(null);
|
||||
nkAgent = null;
|
||||
if (null != process) {
|
||||
process.destroy();
|
||||
}
|
||||
isFBServerReady = false;
|
||||
throw new ExecuteException(String.format("无法创建设备【%s】nkAgent", phone.getUdid()));
|
||||
}
|
||||
logger.debug("设置设备【{}】的nkAgent掉线之后的监听器................", phone.getUdid());
|
||||
nkAgent.setOnDisconnectListener(() -> {
|
||||
synchronized (nkAgent) {
|
||||
if (!nkAgent.getStatus()) {
|
||||
logger.warn("设备【{}】的nkAgent失效了,需要重新创建...........", phone.getUdid());
|
||||
IOSDeviceManager.getInstance().getIosInitThread(phone.getUdid()).createNKAgent();
|
||||
logger.warn("设备【{}】的nkAgent重新创建完成...........", phone.getUdid());
|
||||
}else{
|
||||
logger.warn("设备【{}】的nkAgent失效了,但是已经创建好了,不再创建了...........", phone.getUdid());
|
||||
logger.debug("设置设备【{}】的帧数为:{}", phone.getUdid(), frame);
|
||||
nkAgent.setMJPEGServerRate(frame);
|
||||
}
|
||||
}
|
||||
});
|
||||
logger.debug("设备【{}】的nkAgent连接完毕................", phone.getUdid());
|
||||
}
|
||||
|
||||
|
||||
public NKAgent getNkAgent() {
|
||||
return nkAgent;
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ import net.northking.cctp.upperComputer.driver.ios.NKAgent;
|
|||
import net.northking.cctp.upperComputer.driver.ios.command.data.ScreenInfoData;
|
||||
import net.northking.cctp.upperComputer.driver.usbmuxd.AppleDevice;
|
||||
import net.northking.cctp.upperComputer.entity.PhoneEntity;
|
||||
import net.northking.cctp.upperComputer.exception.ExecuteException;
|
||||
import net.northking.cctp.upperComputer.utils.SpringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
@ -31,11 +32,6 @@ public class MacIosDeviceInitThread extends IosDeviceInitThread {
|
|||
*/
|
||||
public static final int IOS_CORE_DEVICE_VERSION = 17;
|
||||
|
||||
/**
|
||||
* xcodebuild进程信息
|
||||
*/
|
||||
private Process process = null;
|
||||
|
||||
/**
|
||||
* xcodebuild的退出码
|
||||
*/
|
||||
|
@ -47,10 +43,6 @@ public class MacIosDeviceInitThread extends IosDeviceInitThread {
|
|||
|
||||
private OutputLineCallback outputLineCallback;
|
||||
|
||||
private boolean isFBServerReady = false;
|
||||
|
||||
private final Object waitFbServerReadyLock = new Object();
|
||||
|
||||
public MacIosDeviceInitThread(PhoneEntity phoneEntity, AppleDevice device) {
|
||||
super(phoneEntity, device);
|
||||
init();
|
||||
|
@ -112,17 +104,19 @@ public class MacIosDeviceInitThread extends IosDeviceInitThread {
|
|||
if (wdaConfig.isPrintWdaOutput()) {
|
||||
logger.debug("WDA-" + appleDevice.getConnectionDetail().serialNumber + "->" + line);
|
||||
}
|
||||
if (!isFBServerReady && line.contains("ServerURLHere")) {
|
||||
isFBServerReady = true;
|
||||
synchronized (waitFbServerReadyLock) {
|
||||
waitFbServerReadyLock.notifyAll();
|
||||
}
|
||||
createNKAgent();
|
||||
apiPortReady();
|
||||
}
|
||||
if (logOutput != null) {
|
||||
logOutput.write(line.getBytes());
|
||||
logOutput.write(10);
|
||||
if (!isFBServerReady && line.contains("ServerURLHere")) {
|
||||
logger.debug("发现WDA启动完成信号");
|
||||
isFBServerReady = true;
|
||||
try {
|
||||
createNKAgent("WDA启动");
|
||||
} catch (ExecuteException e) {
|
||||
logger.error("WDA启动后创建NKAgent失败", e);
|
||||
process.destroy();
|
||||
break;
|
||||
}
|
||||
apiPortReady();
|
||||
}
|
||||
if (outputLineCallback != null) {
|
||||
try {
|
||||
|
@ -150,20 +144,22 @@ public class MacIosDeviceInitThread extends IosDeviceInitThread {
|
|||
}
|
||||
}
|
||||
}
|
||||
isFBServerReady = false;
|
||||
if (nkAgent != null) {
|
||||
nkAgent.setOnDisconnectListener(null);
|
||||
}
|
||||
try {
|
||||
exitCode = process.waitFor();
|
||||
} catch (InterruptedException ignored) {
|
||||
break;
|
||||
}
|
||||
if (logOutput != null) {
|
||||
try {
|
||||
logOutput.close();
|
||||
} catch (IOException e) {
|
||||
logger.warn("关闭WDA独立日志流时发生IO异常,路径:{}", logFileName, e);
|
||||
}
|
||||
}
|
||||
IOSDeviceManager.getInstance().publishDeviceAgentDead(phone.getUdid());
|
||||
logger.debug("设备【{}】的wda退出了,重启一次......................", appleDevice.getConnectionDetail().serialNumber);
|
||||
isFBServerReady = false;
|
||||
}
|
||||
logger.debug("设备【{}】的wda退出了,不在重启了......................", appleDevice.getConnectionDetail().serialNumber);
|
||||
}
|
||||
|
|
|
@ -35,8 +35,6 @@ public class WindowsAndLinuxIosDeviceInitThread extends IosDeviceInitThread {
|
|||
super(phone,device);
|
||||
}
|
||||
|
||||
private Process wdaProcess;
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
logger.debug("不是mac作为上位机,用tidevice启动wda");
|
||||
|
@ -91,13 +89,12 @@ public class WindowsAndLinuxIosDeviceInitThread extends IosDeviceInitThread {
|
|||
FileOutputStream fileOutputStream = null;
|
||||
try {
|
||||
fileOutputStream = new FileOutputStream(wdaLogFile);
|
||||
this.wdaProcess = processBuilder.start();
|
||||
this.process = processBuilder.start();
|
||||
if (UpperComputerManager.getInstance().getOperatingSystem().startsWith("Windows")) {
|
||||
input = new LineNumberReader(new InputStreamReader(this.wdaProcess.getInputStream(),"GBK"));
|
||||
input = new LineNumberReader(new InputStreamReader(this.process.getInputStream(),"GBK"));
|
||||
} else if (UpperComputerManager.getInstance().getOperatingSystem().startsWith("Linux")) {
|
||||
input = new LineNumberReader(new InputStreamReader(this.wdaProcess.getInputStream(),"UTF-8"));
|
||||
input = new LineNumberReader(new InputStreamReader(this.process.getInputStream(),"UTF-8"));
|
||||
}
|
||||
input = new LineNumberReader(new InputStreamReader(this.wdaProcess.getInputStream()));
|
||||
String line = null;
|
||||
while (null != (line = input.readLine())) {
|
||||
if (line.contains("NKLog:")) {
|
||||
|
@ -106,7 +103,8 @@ public class WindowsAndLinuxIosDeviceInitThread extends IosDeviceInitThread {
|
|||
}
|
||||
if (line.contains(SUCCESS_FLAG)) {
|
||||
logger.info("设备【{}】的wda程序启动成功,开启nkAgent。。。。。。。。。", phone.getUdid());
|
||||
createNKAgent();
|
||||
isFBServerReady = true;
|
||||
createNKAgent("非macOS启动wda第一创建NKAgent");
|
||||
logger.info("设备【{}】即将启动8100端口代理。。。。。。。。。", phone.getUdid());
|
||||
apiProxyThread = new Device8100WatchThread(phone);
|
||||
apiProxyThread.start();
|
||||
|
@ -125,7 +123,7 @@ public class WindowsAndLinuxIosDeviceInitThread extends IosDeviceInitThread {
|
|||
}
|
||||
int code = 0;
|
||||
try {
|
||||
code = this.wdaProcess.waitFor();
|
||||
code = this.process.waitFor();
|
||||
} catch (InterruptedException e) {
|
||||
logger.warn("wda线程中断了。。。。");
|
||||
interrupt();
|
||||
|
@ -254,7 +252,7 @@ public class WindowsAndLinuxIosDeviceInitThread extends IosDeviceInitThread {
|
|||
}
|
||||
|
||||
public void exitWdaAndProxy() {
|
||||
this.wdaProcess.destroyForcibly();
|
||||
this.process.destroy();
|
||||
interrupt();
|
||||
}
|
||||
|
||||
|
|
|
@ -201,7 +201,8 @@ public class PacketTransfer {
|
|||
return connected;
|
||||
}
|
||||
|
||||
private void onDisconnected() {
|
||||
private synchronized void onDisconnected() {
|
||||
if (!connected) return;
|
||||
connected = false;
|
||||
sendHandler.stop();
|
||||
receiveHandler.stop();
|
||||
|
|
|
@ -50,7 +50,7 @@ import java.net.MalformedURLException;
|
|||
import java.net.URL;
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.*;
|
||||
|
||||
import static io.appium.java_client.remote.AndroidMobileCapabilityType.RESET_KEYBOARD;
|
||||
import static io.appium.java_client.remote.AndroidMobileCapabilityType.UNICODE_KEYBOARD;
|
||||
|
@ -74,6 +74,10 @@ public class AndroidDebuggerServiceImpl extends AbstractDebuggerService {
|
|||
|
||||
private ConcurrentHashMap<String, AndroidAgent> screenShotAgentMap = new ConcurrentHashMap<>();
|
||||
|
||||
private ConcurrentHashMap<String, AndroidAgentSession> screenShotAgentSessionMap = new ConcurrentHashMap<>();
|
||||
|
||||
private ExecutorService service = Executors.newFixedThreadPool(10);
|
||||
|
||||
private Adb adb;
|
||||
|
||||
@Autowired
|
||||
|
@ -1018,30 +1022,57 @@ public class AndroidDebuggerServiceImpl extends AbstractDebuggerService {
|
|||
|
||||
private File getScreenShotInCommand(String deviceId) {
|
||||
File tmpPicFile = null;
|
||||
try {
|
||||
AndroidAgent androidAgent = screenShotAgentMap.get(deviceId);
|
||||
if (null == androidAgent) {
|
||||
AdbDevice currentDevice = null;
|
||||
ArrayList<AdbDevice> adbDevices = adb.listDevices();
|
||||
if (!CollectionUtils.isEmpty(adbDevices)) {
|
||||
for (AdbDevice adbDevice : adbDevices) {
|
||||
if (deviceId.equals(adbDevice.getSerial())) {
|
||||
currentDevice = adbDevice;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
byte[] screenShotData = null;
|
||||
Future<byte[]> submit = service.submit(new Callable<byte[]>() {
|
||||
@Override
|
||||
public byte[] call() throws Exception {
|
||||
AndroidAgentSession agentSession = screenShotAgentSessionMap.get(deviceId);
|
||||
if (null == agentSession || !agentSession.isState()) {
|
||||
AdbDevice currentDevice = AndroidDeviceManager.getInstance().getCurrentDevice(deviceId);
|
||||
if (null == currentDevice) {
|
||||
logger.warn("设备【{}】不在线。。。。。",deviceId);
|
||||
throw new ExecuteException("截图失败,当前设备不在线");
|
||||
throw new ExecuteException("当前设备不在线");
|
||||
}
|
||||
logger.warn("设备【{}】没有androidAgent创建一个。。。。。",deviceId);
|
||||
androidAgent = new AndroidAgent(adb, currentDevice);
|
||||
screenShotAgentMap.put(deviceId, androidAgent);
|
||||
agentSession = new AndroidAgentSession(currentDevice, false);
|
||||
agentSession.start();
|
||||
screenShotAgentSessionMap.put(deviceId, agentSession);
|
||||
} else {
|
||||
logger.warn("设备【{}】已经存在androidAgent。。。。。",deviceId);
|
||||
String send = agentSession.send(new EchoCommand("hello")); //检查
|
||||
if (!"hello".equals(send)) {
|
||||
logger.warn("设备【{}】当前使用的截图的session失效了,重新创建一个。。。。。", deviceId);
|
||||
agentSession.closeSilence();
|
||||
AdbDevice currentDevice = AndroidDeviceManager.getInstance().getCurrentDevice(deviceId);
|
||||
if (null == currentDevice) {
|
||||
return null;
|
||||
}
|
||||
byte[] screenShotData = androidAgent.takeScreenshot();
|
||||
agentSession = new AndroidAgentSession(currentDevice, false);
|
||||
agentSession.start();
|
||||
screenShotAgentSessionMap.put(deviceId, agentSession);
|
||||
} else {
|
||||
logger.debug("设备【{}】当前使用的截图的session还能用,继续使用。。。。。", deviceId);
|
||||
}
|
||||
}
|
||||
byte[] temData = agentSession.send(TakeScreenshotCommand.getInstance());
|
||||
return temData;
|
||||
}
|
||||
});
|
||||
try {
|
||||
screenShotData = submit.get(5, TimeUnit.SECONDS);
|
||||
} catch (InterruptedException e) {
|
||||
logger.debug("设备【{}】截图的时候被中断了。。。。。", deviceId);
|
||||
return null;
|
||||
} catch (ExecutionException e) {
|
||||
logger.error("设备【{}】截图的时候报错了。。。。。", deviceId,e);
|
||||
return null;
|
||||
} catch (TimeoutException e) {
|
||||
logger.debug("设备【{}】截图的时候超时了。。。。。", deviceId,e);
|
||||
submit.cancel(true);
|
||||
AndroidAgentSession agentSession = screenShotAgentSessionMap.remove(deviceId);
|
||||
if (null != agentSession) {
|
||||
agentSession.closeSilence();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
if (null != screenShotData && screenShotData.length > 0) {
|
||||
logger.debug("收到手机【{}】截图,大小:{}",deviceId,screenShotData.length);
|
||||
File tmpPicDir = new File(System.getProperty("user.dir")+"/tempPic");
|
||||
|
|
Loading…
Reference in New Issue