android屏幕共享及远程控制,android屏幕共享及远程控制原理
今天用了下Vysor,可以实现屏幕共享和远程控制,并且不需要root,而且可以兼容所有版本Android,功能很是强大,反编译了,下面是根据Vysor源码精简的功能。
import android.graphics.Bitmap;
import android.graphics.Point;
import android.hardware.input.InputManager;
import android.os.Build;
import android.os.Handler;
import android.os.SystemClock;
import android.support.v4.view.InputDeviceCompat;
import android.view.InputEvent;
import android.view.KeyEvent;
import android.view.MotionEvent;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* Created by wanjian on 2017/4/4.
*/
public class Main {
private static InputManager im;
private static Method injectInputEventMethod;
private static long downTime;
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, FileNotFoundException {
if ("screenshot".equals(args[0])) {
screenShot();
return;
}
initEvent();
if ("home".equals(args[0])) {
System.out.println("home");
pressHome();
return;
}
if ("touch".equals(args[0])) {
System.out.println("slide");
slideScreen();
return;
}
if ("back".equals(args[0])) {
System.out.println("back");
back();
return;
}
}
private static void screenShot() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, FileNotFoundException {
System.out.println("started screenshot");
Point size = new Point();
size.x = 1080;
size.y = 1920;
String surfaceClassName;
if (Build.VERSION.SDK_INT <= 17) {
surfaceClassName = "android.view.Surface";
} else {
surfaceClassName = "android.view.SurfaceControl";
}
Bitmap b = (Bitmap) Class.forName(surfaceClassName).getDeclaredMethod("screenshot", new Class[]{Integer.TYPE, Integer.TYPE}).invoke(null, new Object[]{Integer.valueOf(size.x), Integer.valueOf(size.y)});
System.out.println(b);
File file = new File("/sdcard/myscreenshot");
if (!file.exists()) {
file.mkdirs();
}
b.compress(Bitmap.CompressFormat.JPEG, 60, new FileOutputStream(new File(file, System.currentTimeMillis() + ".jpg")));
System.out.println("finished " + file.getAbsolutePath());
}
private static void back() throws InvocationTargetException, IllegalAccessException {
sendKeyEvent(im, injectInputEventMethod, InputDeviceCompat.SOURCE_KEYBOARD, 4, false);
}
private static void slideScreen() throws InvocationTargetException, IllegalAccessException {
final float clientX = 900;
final float clientY = 200;
touchDown(clientX, clientY);
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
int i = 0;
float mClientX = clientX;
@Override
public void run() {
if (i++ > 300) {
try {
touchUp(mClientX, clientY);
} catch (Exception e) {
e.printStackTrace();
}
return;
}
mClientX -= 3;
try {
touchMove(mClientX, clientY);
} catch (Exception e) {
e.printStackTrace();
}
handler.postDelayed(this, 10);
}
}, 10);
}
private static void touchUp(float clientX, float clientY) throws InvocationTargetException, IllegalAccessException {
injectMotionEvent(im, injectInputEventMethod, InputDeviceCompat.SOURCE_TOUCHSCREEN, 1, downTime, SystemClock.uptimeMillis() - downTime, clientX, clientY, 1.0f);
}
private static void touchMove(float clientX, float clientY) throws InvocationTargetException, IllegalAccessException {
injectMotionEvent(im, injectInputEventMethod, InputDeviceCompat.SOURCE_TOUCHSCREEN, 2, downTime, SystemClock.uptimeMillis() - downTime, clientX, clientY, 1.0f);
}
private static void touchDown(float clientX, float clientY) throws InvocationTargetException, IllegalAccessException {
downTime = SystemClock.uptimeMillis();
injectMotionEvent(im, injectInputEventMethod, InputDeviceCompat.SOURCE_TOUCHSCREEN, 0, downTime, downTime, clientX, clientY, 1.0f);
}
private static void pressHome() throws InvocationTargetException, IllegalAccessException {
//home键
sendKeyEvent(im, injectInputEventMethod, InputDeviceCompat.SOURCE_KEYBOARD, 3, false);
}
private static void initEvent() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
im = (InputManager) InputManager.class.getDeclaredMethod("getInstance", new Class[0]).invoke(null, new Object[0]);
MotionEvent.class.getDeclaredMethod("obtain", new Class[0]).setAccessible(true);
injectInputEventMethod = InputManager.class.getMethod("injectInputEvent", new Class[]{InputEvent.class, Integer.TYPE});
}
private static void injectMotionEvent(InputManager im, Method injectInputEventMethod, int inputSource, int action, long downTime, long eventTime, float x, float y, float pressure) throws InvocationTargetException, IllegalAccessException {
MotionEvent event = MotionEvent.obtain(downTime, eventTime, action, x, y, pressure, 1.0f, 0, 1.0f, 1.0f, 0, 0);
event.setSource(inputSource);
injectInputEventMethod.invoke(im, new Object[]{event, Integer.valueOf(0)});
}
private static void injectKeyEvent(InputManager im, Method injectInputEventMethod, KeyEvent event) throws InvocationTargetException, IllegalAccessException {
injectInputEventMethod.invoke(im, new Object[]{event, Integer.valueOf(0)});
}
private static void sendKeyEvent(InputManager im, Method injectInputEventMethod, int inputSource, int keyCode, boolean shift) throws InvocationTargetException, IllegalAccessException {
long now = SystemClock.uptimeMillis();
int meta = shift ? 1 : 0;
injectKeyEvent(im, injectInputEventMethod, new KeyEvent(now, now, 0, keyCode, 0, meta, -1, 0, 0, inputSource));
injectKeyEvent(im, injectInputEventMethod, new KeyEvent(now, now, 1, keyCode, 0, meta, -1, 0, 0, inputSource));
}
}
首先把这端代码编译成class文件,然后转成dex文件
dx --dex --output=Main.dex Main.class
把转换好的dex文件发送到手机上
adb push Main.dex /sdcard/Main.dex
进入shell
adb shell
执行命令
export CLASSPATH=/sdcard/Main.dex
执行截屏命令,执行后会放到/sdcard/myscreenshot文件夹下,vysor就是通过不停的截屏实现的屏幕共享
exec app_process /sdcard Main screenshot
执行按下home按键
exec app_process /sdcard Main home
执行按下返回按键
exec app_process /sdcard Main back
执行触屏事件
exec app_process /sdcard Main touch
完整命令如下:
MGJwanjian:sss wanjian$ dx --dex --output=Main.dex Main.class
MGJwanjian:sss wanjian$ adb push Main.dex /sdcard/Main.dex
[100%] /sdcard/Main.dex
MGJwanjian:sss wanjian$ adb shell
shell@mx5:/ $ export CLASSPATH=/sdcard/Main.dex
shell@mx5:/ $ exec app_process /sdcard Main screenshot
started screenshot
android.graphics.Bitmap@13c1ffa9
finished /sdcard/myscreenshot
MGJwanjian:sss wanjian$ adb shell
shell@mx5:/ $ export CLASSPATH=/sdcard/Main.dex
shell@mx5:/ $ exec app_process /sdcard Main home
home
MGJwanjian:sss wanjian$ adb shell
shell@mx5:/ $ export CLASSPATH=/sdcard/Main.dex
shell@mx5:/ $ exec app_process /sdcard Main back
back
MGJwanjian:sss wanjian$ adb shell
shell@mx5:/ $ export CLASSPATH=/sdcard/Main.dex
shell@mx5:/ $ exec app_process /sdcard Main touch
slide
MGJwanjian:sss wanjian$ adb shell
shell@mx5:/ $ export CLASSPATH=/sdcard/Main.dex
shell@mx5:/ $ exec app_process /sdcard Main touch
slide
补:关于如何把java文件打包成class文件
最简单的方式:
在android studio中右击com.wanjian.puppet.Main这个文件,选择 run Main.main(),编译后的class文件就会自动保存到
androidScreenShareAndControl/shareandcontrollib/build/intermediates/classes/debug 这个目录中
方式2:
把 android sdk目录下的android.jar和supportv4.jar拷贝到
androidScreenShareAndControl/shareandcontrollib/src/main/java
目录下,同时在这个目录下新建classes文件夹,用于保存编译后的class文件,并把命令行切换到这个目录
执行如下命令,其中android.jar和support-v4-23.4.0-sources.jar 是android sdk中的jar包,一个在platforms/android-xx文件夹下,一个在extras/android/m2repository/com/android/support/support-v4下
中间用:分割,windows的话需要用;分割
javac -cp android.jar:support-v4-23.4.0-sources.jar:./ com/wanjian/puppet/Main.java -d classes
这样就会在classes文件夹中生成class文件了(JDK版本不能太高,不然会提示 unsupported class file version 52.0)
android屏幕共享及远程控制,android屏幕共享及远程控制原理相关推荐
- PC远程控制android思路,PC 远程控制 android手机的方法之一VNC
1.VNC访问 a .在android手机中安装vnc 的服务端:androidvncserver http://code.google.com/p/android-vnc-server/ 本文下载了 ...
- Android屏幕共享及远程控制【免root】
Android屏幕共享及远程控制[免root] 使用方式 对于mac 笔记本用户: Android手机开启开发者选项 用数据线连接Android手机和mac 运行lib目录下的Client,用于显示和 ...
- macbook android 屏幕共享,苹果设备小技巧:iPhone,iPad,Mac进行屏幕共享和远程控制...
随着生活的发展,对视频通话和屏幕共享的需求已大大增加.有时,当您不在身边时,可以轻松地通过电话或短信进行故障排除,但通常可以在屏幕上看到发生了什么,并可以远程访问权限.接下来,我们将介绍如何与iPho ...
- qq android远程协助,Android 实现远程控制(类似QQ的远程协助)
Android 实现远程控制(类似QQ的远程协助) 发布时间:2019-04-29 10:18, 浏览次数:441 , 标签: Android QQ 这里简单的给个思路和已经实现点击的Demo 明确两 ...
- android studio远程控制,Android Studio远程登录控制台缺少“网络”和“窗口”命令?...
我成功地连接到本地主机:5554,在/Users/me/.emulator_console_auth_token发现令牌认证,并得到了名单可用的命令: $ telnet localhost 5554 ...
- SpyNote V5.0图形化工具远程控制Android手机教程(图文教程+演示视频)
*本文原创作者:艾登--皮尔斯,本文属FreeBuf原创奖励计划,未经许可禁止转载 前言 本篇文章主要以图文教程和视频演示详细地教你如何快速学会使用SpyNote 5.0图形化工具来穿透内网远程控制A ...
- 向日葵android比pc端慢很多,向日葵远程控制Android主控端9.5上线,交互流畅性全面升级...
近日,向日葵发布全新移动端版本--向日葵远程控制Android主控端9.5版本.该版本对界面模块进行了调整,新增会心攻略模块,优化交互模式,提升按键宽容度,打造远控游戏的完美体验. 新增会心攻略,提供 ...
- 【Android应用开发】 Android 崩溃日志 本地存储 与 远程保存
示例代码下载 : http://download.csdn.net/detail/han1202012/8638801; 一. 崩溃日志本地存储 1. 保存原理解析 崩溃信息本地保存步骤 : -- 1 ...
- android app通过Geth RPC接口实现远程调用
记录一下APP怎么通过以太坊的RPC接口实现远程调用.此过程的环境为Window7和Android studio2.2.3.以web3_clientVersion为例.更多用法参考Geth JSON- ...
- 编译Android VNC Server(pc远程控制android)
1.下载fastdroid-vnc 下载:https://download.csdn.net/download/u010164190/103466602.编译libjpeg.a for fastdro ...
最新文章
- java compareto方法怎么排序的_深入理解Java中Comparable和Comparator排序
- android 页面过渡动画,Activity过渡动画的实现方法
- C#中实现对象的深拷贝
- 常用crc查表法_CRC校验码简介及CRC16的计算方法
- python下绘制叠加区域图和叠加柱状图
- python从入门到实践答案第六章-《Python从入门到实践》第六章动手试一试
- 58. web 攻击技术(2)
- Atitit 函数调用的原理与本质attilax总结 stdcall cdecl区别
- 软著申请合作开发协议模板
- PLSQL下载、安装、配置、连接详细教程
- 爱心函数可视化 python
- 微信公众号之免登陆快速入门
- leetcode 904 水果成篮
- 仿真树叶飘落效果的实现
- influxdb java api使用_InfluxDB使用HTTP的API查询数据
- 猴子排序算法_猴子排序-有史以来最慢的排序算法?
- SQL 创建、更新、删除表、重命表名
- JavaScript给按钮绑定点击事件(onclick)的方法及js常见事件
- python入门之字符串索引,切片
- pcb板子开窗_PCB中 开窗 是什么意思?