这里简单的给个思路和已经实现点击的Demo    

明确两者:控制方 和 被控制方;

实现思路:控制方获得被控制方的屏幕共享

                  控制方获得点击屏幕的X轴,Y轴坐标

                  通过服务器把坐标指令发送给被控制方

                  被控制方采用adb命令模拟点击;

模拟操作都是用 input 来完成

我们用adb shell来简单的看一下该指令的使用帮助


    tap     =   点按<X坐标> <y坐标>(默认触摸屏)
    swipe =   滑动<x1> <y1> <x2> <y2> [持续时间(毫秒)](默认值:触摸屏)

由此可见,我们可以通过这个命令来实现模拟人操作从而达成远程操作功能

adb命令:input tap X Y

该命令在Window,cmd shell下不用root可以执行。

java代码调用时需要ROOT权限;

(本文Demo没有实现屏幕共享,所以点击时看着被控方的屏幕需要点击的大概位置点击控制方屏幕测试效果

    屏幕共享功能可通过API21的录屏+MediaCode编码器实现

    adb命令下似乎还有个截屏的API 也可以实现屏幕共享,不过该API是隐藏的,即使用系统反射也调不起来。但可以用adb命令来获得,Vysor
这个软件就是通过adb调起这个截屏API不断的截屏发送数据来实现屏幕共享的)

本文Demo采用的是UDP通讯 在同一wifi局域网下实现通讯进行控制交互

发送坐标的控制方:用 dispatchtouchEvent();方法取得X,Y坐标
@Override public boolean dispatchTouchEvent(MotionEvent ev) {
msgShow.setText("点击位置的X坐标" + ev.getX() + "点击位置的Y坐标" + ev.getY()); switch
(ev.getAction()) { // 点击的开始位置 case MotionEvent.ACTION_DOWN:
msgShow.setText("起始位置:(" + ev.getX() + "," + ev.getY()); break; //触屏实时位置 case
MotionEvent.ACTION_MOVE: msgShow.setText("实时位置:(" + ev.getX() + "," +
ev.getY()); break; //离开屏幕的位置 case MotionEvent.ACTION_UP:
msgShow.setText("结束位置:(" + ev.getX() + "," + ev.getY()); sendMsg(ev.getX(),
ev.getY()); break; default: break; } // 注意返回值 // true:view继续响应Touch操作; //
false:view不再响应Touch操作,故此处若为false,只能显示起始位置,不能显示实时位置和结束位置 return
super.dispatchTouchEvent(ev); }
通过UDP发送JSON坐标数据  Data实体类就X,Y两个变量;这里的JSON我是用GSON插件生成的
private Gson gson = new Gson(); private DatagramSocket sendSocket = null;
private int sendPort = 8856;//发送端口 private void sendMsg(float x, float y) { try
{ if (sendSocket == null) { sendSocket = new DatagramSocket(sendPort); }
//发送到的IP InetAddress inetAddress = InetAddress.getByName("192.168.1.50");
String jsno = getJsonStr(x,y); byte[] bytes = jsno.getBytes(); DatagramPacket
datagramPacket = new DatagramPacket(bytes, bytes.length, inetAddress,
sendPort); sendSocket.send(datagramPacket); msgShow.setText("点击的坐标" + x + y); }
catch (SocketException e) { e.printStackTrace(); } catch (UnknownHostException
e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } }
public String getJsonStr(float x, float y) { Data p = new Data(); p.setX(x);
p.setY(y); return gson.toJson(p); }
接下来接收端:UDP监听帮助类
public class UdpReceive { private DatagramSocket receiveSocket = null; private
int receivePort = 8856; private DatagramPacket datagramPacket; private boolean
isRunning = true; private static UdpReceive udpReceive; public static
UdpReceive getUdpReceive() { if (udpReceive == null) { synchronized
(UdpReceive.class) { udpReceive = new UdpReceive(); } } return udpReceive; }
//初始化UDP监听 传入监听的端口号,回调 public void init(int port, Touch touch) { new Thread(()
-> { try { while (isRunning) { if (receiveSocket == null) { receiveSocket = new
DatagramSocket(port); } byte[] bytes = new byte[1024]; datagramPacket = new
DatagramPacket(bytes, 0, bytes.length); receiveSocket.receive(datagramPacket);
Log.e("接收成功 : " , new String(datagramPacket.getData()).trim()); if(touch!=null)
touch.move(datagramPacket.getData()); } } catch (SocketException e) {
e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }
}).start(); } }
UDP初始化   JSON数据用GSON解析
UdpReceive.getUdpReceive().init(8856, new Touch() { @Override public void
move(byte[] msg) { String data = new String(msg).trim(); Data json =
gson.fromJson(data,Data.class);
Log.e("",String.valueOf(json.getX()+json.getY()));
Log.e("X",String.valueOf(json.getX())); Log.e("Y",String.valueOf(json.getY()));
runOnUiThread (() -> { RootCmd.execRootCmd("input tap "+json.getX()+" "+
json.getY()); }); } @Override public void touch() { } });
 回调
public interface Touch { void move(byte[] msg); void touch(); }
 ADB命令执行方法
/** * 执行命令且得到结果 */ public static String inputRootCmd(String cmd) { String
result = ""; DataOutputStream dos = null; DataInputStream dis = null; try { //
经过Root的android系统即有su命令 Process p = Runtime.getRuntime().exec("su"); dos = new
DataOutputStream(p.getOutputStream()); dis = new
DataInputStream(p.getInputStream()); dos.writeBytes(cmd + "\n"); dos.flush();
dos.writeBytes("exit\n"); dos.flush(); String line = null; while ((line =
dis.readLine()) != null) { Log.d("result", line); result += line; }
p.waitFor(); } catch (Exception e) { e.printStackTrace(); } finally { if (dos
!= null) { try { dos.close(); } catch (IOException e) { e.printStackTrace(); }
} if (dis != null) { try { dis.close(); } catch (IOException e) {
e.printStackTrace(); } } } return result; }
被控制方需要ROOT权限才能通过java调用ADB命令来实现点击,滑动等操作 

Demo下载

GitHub地址:https://github.com/zhuangguangkang0013/udpSend.git
<https://github.com/zhuangguangkang0013/udpSend.git> 发送端(控制方)

                      https://github.com/zhuangguangkang0013/udpReceive.git
<https://github.com/zhuangguangkang0013/udpReceive.git> 接收端(被控制方)

限速云地址:https://pan.baidu.com/s/1x3_2YGtidTg3F9LsEmoeZA
<https://pan.baidu.com/s/1x3_2YGtidTg3F9LsEmoeZA>  提取码:6vm9

CSDN地址:   https://download.csdn.net/download/u011046184/11150664
<https://download.csdn.net/download/u011046184/11150664>

Demo效果图



新款加入了屏幕共享,滑动事件

 

友情链接
ioDraw流程图
API参考文档
OK工具箱
云服务器优惠
阿里云优惠券
腾讯云优惠券
华为云优惠券
站点信息
问题反馈
邮箱:ixiaoyang8@qq.com
QQ群:637538335
关注微信