自动化工具 Java 和 Websocket 实现安卓真机操控

王勇 · November 26, 2019 · Last by Blanke replied at December 30, 2019 · 1237 hits

demo效果预览:

原理简介:
1、使用反射截图,压缩为webp格式图片,把图片编码为base64格式,通过websocket服务发送给前端,前端绘制出图片。
2、websocket服务器使用websocket库:Java-WebSocket-1.4.0-with-dependencies.jar。
3、事件转发也是走websocket,发送事件类型和相关参数,websocket服务做出对应动作。

ScreenCaptor反射截图关键方法:

public static Bitmap getScreencap(int screenWidth, int screenHeight) {
Bitmap bitmap = null;
String surfaceClassName;
ServiceManager serviceManager = new ServiceManager();

if (screenHeight == 0 || screenWidth ==0){
screenWidth = serviceManager.getDisplayManager().getDisplayInfo().getSize().getWidth();
screenHeight = serviceManager.getDisplayManager().getDisplayInfo().getSize().getHeight();
}


if (Build.VERSION.SDK_INT <= 17) {
surfaceClassName = "android.view.Surface";
} else {
surfaceClassName = "android.view.SurfaceControl";
}

try {
// api_level >= 27,截图方法:public static Bitmap screenshot(int width, int height) {}
if (Build.VERSION.SDK_INT <= 27) {

bitmap = (Bitmap) Class.forName(surfaceClassName).getDeclaredMethod("screenshot", new Class[]{Integer.TYPE, Integer.TYPE})
.invoke(null, new Object[]{screenWidth, screenHeight});

} else {
// 参考这里https://medium.com/@punpun/android-surfacecontrol-screenshot-changed-in-android-pie-9-0-8baf2c91a068
// api_level大于27,截图方法变为:public static Bitmap screenshot(Rect sourceCrop, int width, int height, int rotation) {}
Rect rect = new Rect(0, 0, 0, 0);
int rotation = serviceManager.getDisplayManager().getDisplayInfo().getRotation();

bitmap = (Bitmap) Class.forName(surfaceClassName).getDeclaredMethod("screenshot", new Class[]{Rect.class, Integer.TYPE, Integer.TYPE, Integer.TYPE})
.invoke(null, new Object[]{rect, screenWidth, screenHeight, rotation});
}
} catch (Throwable e) {
e.printStackTrace();
}
return bitmap;
}

websocket服务器,关键方法onMessage:

@Override
public void onMessage(WebSocket webSocket, String s) {

if (s.equals( "help")) {
String help = "screencap, keyevent, mouseevent";
webSocket.send(help);
}
else if(s.equals("screencap")){
String screencap = ScreenCaptor.getBase64Screencap();

webSocket.send(screencap);
}
else if(s.equals("keyevent")){
webSocket.send("keyevent cmd.");
}
else if(s.contains("mouseevent")) {

String[] cmds = s.split("#");

Input input = new Input();
int inputSource = InputDevice.SOURCE_TOUCHSCREEN;
input.sendTap(inputSource, Float.parseFloat(cmds[2]),
Float.parseFloat(cmds[3]));
webSocket.send("mouseevent success.");
} else{
webSocket.send("Unknown cmd: " + s);
}
}

前端js关键代码:

var screen = document.getElementById('screen');
var websocket = '';

var x = 0;
var y = 0;

var downTimestamp = 0;
var upTimestamp = 0;

if (window.WebSocket) {
websocket = new WebSocket(encodeURI('ws://localhost:8888'));
websocket.onopen = function() {
console.log('已连接');
};
websocket.onerror = function() {
console.log('连接发生错误');
alert("websocket连接失败")
};
websocket.onclose = function() {
console.log('已经断开连接');
};
// 消息接收
websocket.onmessage = function(message) {
websocket.send("screencap");
screen.src = message.data;

};
} else {
alert("该浏览器不支持websocket。<br/>建议使用高版本的浏览器,<br/>如 IE10、火狐 、谷歌 、搜狗等");
}
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
共收到 1 条回复 时间 点赞

感谢分享,demo开源吗?谢谢

需要 Sign In 后方可回复, 如果你还没有账号请点击这里 Sign Up