no message

This commit is contained in:
wanjian
2017-04-08 13:48:54 +08:00
parent 526f478996
commit 8a27373aeb

134
README.md
View File

@@ -1,4 +1,3 @@
# androidScreenShareAndControl
### 免root兼容所有Android版本屏幕共享及远程控制。
@@ -45,6 +44,138 @@ MGJwanjian:~ wanjian$ adb forward tcp:8888 localabstract:puppet-ver1
### 屏幕共享原理
原理和Vysor相同Android提供了两个截屏方法Surface. screenshot和SurfaceControl. screenshot
这两个API是隐藏的客户端没有权限调用即使通过反射也得不到bitmap我们可以使用adb命令
启动一个进程让该进程调用该API就可以得到bitmap了然后通过socket把数据发送到PC即可。
关键代码如下:
```java
public class Main{
public static void main(String[]args){
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)});
}
}
```
* 然后按照如下操作:
* 把这个类编译成class文件
* 使用dx --dex --output=Main.dex Main.class打包成dex文件
* 把dex文件发送到手机adb push Main.dex /sdcard/Main.dex
* 执行adb shell进入shell
* 设置类路径 export CLASSPATH=/sdcard/Main.dex
* 运行代码 exec app_process /sdcard Main
这样就可以调用到Main.main方法
### 远程控制原理
* PC端获取点击位置相对于当前显示窗口的比例
* 把该比例发送给手机端
* 手机端根据手机屏幕大小把比例转换成绝对位置并调用如下代码既可以实现远程控制x和y是点击的绝对位置action是动作如按下滑动抬起等
```java
InputManager im = (InputManager) InputManager.class.getDeclaredMethod("getInstance", new Class[0]).invoke(null, new Object[0]);
MotionEvent.class.getDeclaredMethod("obtain", new Class[0]).setAccessible(true);
Method injectInputEventMethod = InputManager.class.getMethod("injectInputEvent", new Class[]{InputEvent.class, Integer.TYPE});
MotionEvent event = MotionEvent.obtain(downTime, eventTime, action, x, y, pressure, 1.0f, 0, 1.0f, 1.0f, 0, 0);
event.setSource(InputDeviceCompat.SOURCE_TOUCHSCREEN);
injectInputEventMethod.invoke(im, new Object[]{event, Integer.valueOf(0)});
```
##### 注意:
获取屏幕大小时会用到几个特殊的APIAndroid sdk没有提供这几个API但Android运行时却可以调用
为了保证编译不报错我们可以自己手写这几个API保证包名方法签名和系统中的相同即可方法若有
返回值直接返回null即可。例如
```java
package android.view;
import android.graphics.Point;
import android.os.IBinder;
/**
* Created by wanjian on 2017/4/4.
*/
public interface IWindowManager {
void getInitialDisplaySize(int i, Point displaySize);
int getRotation();
void getRealDisplaySize(Point displaySize);
abstract class Stub {
public static IWindowManager asInterface(IBinder invoke) {
return null;
}
}
}
```
```java
package android.view;
/**
* Created by wanjian on 2017/4/4.
*/
public interface DisplayInfo {
}
```
```java
package android.view;
/**
* Created by wanjian on 2017/4/4.
*/
public interface IRotationWatcher {
}
```
由于Android的双亲委派类加载机制Android会从系统路径下加载这几个类并不会使用我们编写的类我们编
写的这几个类只是为了编译不报错所以返回null也不会出现空指针
### 简易版
[http://blog.csdn.net/qingchunweiliang/article/details/69210431](http://blog.csdn.net/qingchunweiliang/article/details/69210431)
@@ -53,4 +184,3 @@ MGJwanjian:~ wanjian$ adb forward tcp:8888 localabstract:puppet-ver1