截图阻塞的问题
parent
c05ca15444
commit
696d51ea04
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
package net.northking.cctp.upperComputer.driver.agent;
|
||||
|
||||
public class StandaloneCommandException extends Exception {
|
||||
public StandaloneCommandException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
package net.northking.cctp.upperComputer.driver.agent;
|
||||
|
||||
public class StandaloneCommandTimeoutException extends Exception {
|
||||
public StandaloneCommandTimeoutException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue