内容目录
背景
因为Scrcpy 目前版本不支持输入法,自己的协同工具为了方便自己使用,增加直接在windows用输入法,而不是直接Keycode方式,这样子体验好很多。
使用输入法
我这里直接用了网上开源 ADBKeyBoard 解决 不能支持uncode编码问题(因为adb input 不支持unicode,如果直接反射也是不可以使用的【这样子中文就有很大问题】),但这个实现用广播,原来scrcpy没有反射广播,于是我看 adb shell am broadcast -a 对应在android cmd 里面目录代码,看他用了broadcastIntent 方法
反射 Android12 broadcastIntent
public void sendBroadcast(Intent intent){
//IntentReceiver receiver = new IntentReceiver();
try {
Class cls = Class.forName("android.app.IApplicationThread");
// public int broadcastIntent(IApplicationThread caller,
//2352 Intent intent, String resolvedType, IIntentReceiver resultTo,
//2353 int resultCode, String resultData, Bundle map,
//2354 String requiredPermission, int appOp, boolean serialized,
//2355 boolean sticky, int userId)
Method method = manager.getClass().getMethod("broadcastIntent",cls, Intent.class, String.class, IIntentReceiver.class, int.class, String.class,
Bundle.class, String[].class, int.class, Bundle.class,boolean.class, boolean.class, int.class);
Object objString = method.invoke(manager, null,intent, null, null, 0, null, null, null, -1, null, true, false, android.os.Process.myUid()/100000);
Ln.i("调用完成:" + objString.toString() );
} catch (ClassNotFoundException e) {
Ln.e("notfound" + e.toString());
e.printStackTrace();
} catch (InvocationTargetException e) {
Ln.e("InvocationTargetException" + e.toString());
e.printStackTrace();
} catch (NoSuchMethodException e) {
Ln.e("NoSuchMethodException" + e.toString());
e.printStackTrace();
} catch (IllegalAccessException e) {
Ln.e("IllegalAccessException" + e.toString());
e.printStackTrace();
}
//manager.getClass().getMethod()
/*this.broadcastIntent(null, intent, null, null, 0, null, null, null, true, false,
Binder.getOrigCallingUser());*/
//receiver.waitForFinish();
}
这个参数挺多的,不能版本参数不一样,所以要看android的源代码,这样子我在windows 启动SDL 输入法
响应input
if (event.type == SDL_TEXTINPUT) {
HandleInput(event); //直接发送网络请求到android里面,然后调用反射发送广播
continue;
}
这样子就是简单实现app_process 反射广播
难点
- 一开始不不知道怎么弄,所以要看adb 里面发送广播的实现,scrcpy 实现本质也是看android adb源代码,所以协同工具本质就是自己实现一个adb在 app_process,同时app_process 启动进程使用shell权限,所以能反射一些高级命令,模拟点击就是具有adb权限,如果apk 具备这样子权限,那么也可以直接反射调用点击命令。
- 参数好多,如果不熟练很容易反射报错。今天我实现反射shellCommand 命令(高版本android 实现命令新代码),实例化带一个参数报错,结果我传入null,默认转换空参数数组,导致实例化失败。。
- 不同android版本反射参数有区别,我这里只是反射自己用的,所以要注意。
补充
后面可以说一下Scrcpy 开发思路,同时重点说一下服务怎么反射