截图阻塞的问题

master
yineng.huang 2024-07-31 14:34:54 +08:00
parent c05ca15444
commit 696d51ea04
5 changed files with 170 additions and 32 deletions

View File

@ -0,0 +1,42 @@
package net.northking.cctp.upperComputer.driver.agent;
import net.northking.cctp.upperComputer.driver.adb.Adb;
import net.northking.cctp.upperComputer.driver.adb.AdbDevice;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
/**
* Android Agent
*/
public class AndroidAgent{
private Logger logger = LoggerFactory.getLogger(AndroidAgent.class);
private final Adb adb;
private final AdbDevice adbDevice;
public AndroidAgent(Adb adb, AdbDevice adbDevice) {
this.adb = adb;
this.adbDevice = adbDevice;
}
public byte[] takeScreenshot() {
byte[] result = null;
StandaloneCommandRunner runner = new StandaloneCommandRunner(adb, adbDevice, "net.northking.product.cctpplus.command.ScreenShotCommand", "");
try {
result = runner.run();
} catch (StandaloneCommandTimeoutException e) {
logger.error("Android Agent执行超时", e);
} catch (StandaloneCommandException e) {
logger.error("Android Agent执行异常", e);
} catch (IOException e) {
logger.error("Android Agent执行IO异常", e);
}
return result;
}
}

View File

@ -0,0 +1,7 @@
package net.northking.cctp.upperComputer.driver.agent;
public class StandaloneCommandException extends Exception {
public StandaloneCommandException(String message) {
super(message);
}
}

View File

@ -0,0 +1,84 @@
package net.northking.cctp.upperComputer.driver.agent;
import net.northking.cctp.upperComputer.driver.adb.Adb;
import net.northking.cctp.upperComputer.driver.adb.AdbDevice;
import net.northking.cctp.upperComputer.driver.adb.AdbTransport;
import java.io.DataInputStream;
import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
public class StandaloneCommandRunner {
/**
*
*/
private static final int STATUS_CODE_OK = 0;
/**
*
*/
private static final int STATUS_CODE_TIMEOUT = -1;
/**
*
*/
private static final int STATUS_CODE_EXCEPTION = -2;
private final Adb adb;
private final AdbDevice adbDevice;
private final String className;
private String args = "";
public StandaloneCommandRunner(Adb adb, AdbDevice adbDevice, String className, String args) {
this.className = className;
this.adb = adb;
this.adbDevice = adbDevice;
this.args = args;
}
public byte[] run() throws StandaloneCommandException, StandaloneCommandTimeoutException, IOException {
try (AdbTransport transport = adb.shell(adbDevice, "export CLASSPATH=/data/local/tmp/agent.apk;app_process /system/bin " + className + " " + args)) {
DataInputStream dataInput = getDataInputStream(transport);
int status = dataInput.readInt();
switch (status) {
case STATUS_CODE_OK:
int dataLength = dataInput.readInt();
byte[] data = new byte[dataLength];
dataInput.readFully(data);
return data;
case STATUS_CODE_TIMEOUT:
throw new StandaloneCommandTimeoutException("Agent独立指令class:" + className + " args:" + args + " 超时");
case STATUS_CODE_EXCEPTION:
dataLength = dataInput.readInt();
data = new byte[dataLength];
dataInput.readFully(data);
throw new StandaloneCommandException(new String(data));
default:
throw new IOException("Agent独立指令class:" + className + " args:" + args + " 未知状态码:" + status);
}
}
}
private DataInputStream getDataInputStream(AdbTransport transport) throws IOException {
if (transport == null) {
throw new IOException("无法创建Shell");
}
InputStream inputStream = transport.getInputStream();
int bannerCount = 0;
while (bannerCount < 5) {
int b = inputStream.read();
if (b == -1) {
throw new EOFException("Agent独立指令class:" + className + " args:" + args + " 未能读取到banner");
}
if (b == (byte) 0x01) {
bannerCount++;
} else {
bannerCount = 0;
}
}
return new DataInputStream(inputStream);
}
}

View File

@ -0,0 +1,8 @@
package net.northking.cctp.upperComputer.driver.agent;
public class StandaloneCommandTimeoutException extends Exception {
public StandaloneCommandTimeoutException(String msg) {
super(msg);
}
}

View File

@ -13,6 +13,7 @@ import net.northking.cctp.upperComputer.deviceManager.thread.AndroidDeviceInitTh
import net.northking.cctp.upperComputer.driver.adb.Adb;
import net.northking.cctp.upperComputer.driver.adb.AdbDevice;
import net.northking.cctp.upperComputer.driver.adb.AdbTransport;
import net.northking.cctp.upperComputer.driver.agent.AndroidAgent;
import net.northking.cctp.upperComputer.driver.agent.AndroidAgentSession;
import net.northking.cctp.upperComputer.driver.agent.command.*;
import net.northking.cctp.upperComputer.enums.FileBusinessTypeEnum;
@ -36,6 +37,7 @@ import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import javax.annotation.PostConstruct;
import java.io.*;
@ -64,7 +66,7 @@ public class AndroidDebuggerServiceImpl extends AbstractDebuggerService {
private ConcurrentHashMap<String, AndroidDeviceAllInfoThread> queryDeviceInfoMap = new ConcurrentHashMap<>();
private ConcurrentHashMap<String, AndroidAgentSession> screenShotAgentSessionMap = new ConcurrentHashMap<>();
private ConcurrentHashMap<String, AndroidAgent> screenShotAgentMap = new ConcurrentHashMap<>();
private Adb adb;
@ -961,51 +963,46 @@ public class AndroidDebuggerServiceImpl extends AbstractDebuggerService {
private File getScreenShotInCommand(String deviceId) {
File tmpPicFile = null;
AndroidAgentSession agentSession = null;
try {
agentSession = screenShotAgentSessionMap.get(deviceId);
if (null == agentSession || !agentSession.isState()) {
AdbDevice currentDevice = AndroidDeviceManager.getInstance().getCurrentDevice(deviceId);
if (null == currentDevice) {
throw new ExecuteException("当前设备不在线");
}
agentSession = new AndroidAgentSession(currentDevice, false);
agentSession.start();
screenShotAgentSessionMap.put(deviceId, agentSession);
} else {
String send = agentSession.send(new EchoCommand("hello")); //检查
if (!"hello".equals(send)) {
logger.warn("设备【{}】当前使用的截图的session失效了重新创建一个。。。。。",deviceId);
AdbDevice currentDevice = AndroidDeviceManager.getInstance().getCurrentDevice(deviceId);
if (null == currentDevice) {
throw new ExecuteException("当前设备不在线");
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;
}
}
agentSession = new AndroidAgentSession(currentDevice, false);
agentSession.start();
screenShotAgentSessionMap.put(deviceId, agentSession);
} else {
logger.debug("设备【{}】当前使用的截图的session还能用继续使用。。。。。",deviceId);
}
if (null == currentDevice) {
logger.warn("设备【{}】不在线。。。。。",deviceId);
throw new ExecuteException("截图失败,当前设备不在线");
}
logger.warn("设备【{}】没有androidAgent创建一个。。。。。",deviceId);
androidAgent = new AndroidAgent(adb, currentDevice);
screenShotAgentMap.put(deviceId, androidAgent);
} else {
logger.warn("设备【{}】已经存在androidAgent。。。。。",deviceId);
}
byte[] screenShotData = agentSession.send(TakeScreenshotCommand.getInstance());
if (null != screenShotData && screenShotData.length > 0) { //截图
logger.debug("收到手机【{}】截图,大小:{}", deviceId, screenShotData.length);
byte[] screenShotData = androidAgent.takeScreenshot();
if (null != screenShotData && screenShotData.length > 0) {
logger.debug("收到手机【{}】截图,大小:{}",deviceId,screenShotData.length);
File tmpPicDir = new File(System.getProperty("user.dir")+"/tempPic");
if (!tmpPicDir.exists()) {
tmpPicDir.mkdir();
tmpPicDir.mkdirs();
}
String tmpPicPath = tmpPicDir.getAbsolutePath() + "/" + deviceId + "_" + System.currentTimeMillis() + ".png";
tmpPicFile = new File(tmpPicPath);
try (FileOutputStream fos = new FileOutputStream(tmpPicFile)){
try (FileOutputStream fos = new FileOutputStream(tmpPicFile)) {
fos.write(screenShotData);
}catch (Exception e) {
logger.error("截图写入临时文件异常:",e);
}
}
} catch (Exception e) {
logger.error("设备【"+deviceId+"】截图异常", e);
}finally {
logger.debug("设备【{}】写到本地的图片大小:{}", deviceId, tmpPicFile != null ? tmpPicFile.length() : 0);
}catch (Exception e) {
logger.error("设备【"+deviceId+"】截图异常",e);
}
return tmpPicFile;
}