android input命令 模拟按键
来源:互联网 发布:go并发编程实践 编辑:程序博客网 时间:2024/06/05 21:09
我们可以在手机adb shell中,使用input来模拟按键,和之前的sm类似,input也是一个进程,在framework/base/cmds目录下。
一、Input源码
下面我们先看下input的源码:
[cpp] view plain copy 在CODE上查看代码片派生到我的代码片
private void run(String[] args) {
if (args.length < 1) {
showUsage();
return;
}
int index = 0; String command = args[index]; int inputSource = InputDevice.SOURCE_UNKNOWN; if (SOURCES.containsKey(command)) { inputSource = SOURCES.get(command); index++; command = args[index]; } final int length = args.length - index; try { if (command.equals("text")) { if (length == 2) { inputSource = getSource(inputSource, InputDevice.SOURCE_KEYBOARD); sendText(inputSource, args[index+1]); return; } } else if (command.equals("keyevent")) { if (length >= 2) { final boolean longpress = "--longpress".equals(args[index + 1]); final int start = longpress ? index + 2 : index + 1; inputSource = getSource(inputSource, InputDevice.SOURCE_KEYBOARD); if (length > start) { for (int i = start; i < length; i++) { int keyCode = KeyEvent.keyCodeFromString(args[i]); if (keyCode == KeyEvent.KEYCODE_UNKNOWN) { keyCode = KeyEvent.keyCodeFromString("KEYCODE_" + args[i]); } sendKeyEvent(inputSource, keyCode, longpress); } return; } } }.............
我们再来看看sendKeyEvent函数
[cpp] view plain copy 在CODE上查看代码片派生到我的代码片
private void sendKeyEvent(int inputSource, int keyCode, boolean longpress) {
long now = SystemClock.uptimeMillis();
injectKeyEvent(new KeyEvent(now, now, KeyEvent.ACTION_DOWN, keyCode, 0, 0,
KeyCharacterMap.VIRTUAL_KEYBOARD, 0, 0, inputSource));
if (longpress) {
injectKeyEvent(new KeyEvent(now, now, KeyEvent.ACTION_DOWN, keyCode, 1, 0,
KeyCharacterMap.VIRTUAL_KEYBOARD, 0, KeyEvent.FLAG_LONG_PRESS,
inputSource));
}
injectKeyEvent(new KeyEvent(now, now, KeyEvent.ACTION_UP, keyCode, 0, 0,
KeyCharacterMap.VIRTUAL_KEYBOARD, 0, 0, inputSource));
}
最后再来看看injectKeyEvent函数,其主要还是调用了,InputManager中的injectInputEvent函数。
[cpp] view plain copy 在CODE上查看代码片派生到我的代码片
private void injectKeyEvent(KeyEvent event) {
Log.i(TAG, “injectKeyEvent: ” + event);
InputManager.getInstance().injectInputEvent(event,
InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH);
}
二、InputManager相关代码
我们再来看看InputManager的injectInputEvent函数,最后还是调用了InputManagerService的injectInputEvent函数。
[cpp] view plain copy 在CODE上查看代码片派生到我的代码片
public boolean injectInputEvent(InputEvent event, int mode) {
if (event == null) {
throw new IllegalArgumentException(“event must not be null”);
}
if (mode != INJECT_INPUT_EVENT_MODE_ASYNC
&& mode != INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH
&& mode != INJECT_INPUT_EVENT_MODE_WAIT_FOR_RESULT) {
throw new IllegalArgumentException(“mode is invalid”);
}
try { return mIm.injectInputEvent(event, mode);//调用了InputManagerService的injectInputEvent函数 } catch (RemoteException ex) { return false; }
}
我们再来看看InputManagerService的injectInputEvent函数
[cpp] view plain copy 在CODE上查看代码片派生到我的代码片
@Override // Binder call
public boolean injectInputEvent(InputEvent event, int mode) {
return injectInputEventInternal(event, Display.DEFAULT_DISPLAY, mode);
}
我们再来看injectInputEventInternal函数
[cpp] view plain copy 在CODE上查看代码片派生到我的代码片
private boolean injectInputEventInternal(InputEvent event, int displayId, int mode) {
if (event == null) {
throw new IllegalArgumentException(“event must not be null”);
}
if (mode != InputManager.INJECT_INPUT_EVENT_MODE_ASYNC
&& mode != InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH
&& mode != InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_RESULT) {
throw new IllegalArgumentException(“mode is invalid”);
}
final int pid = Binder.getCallingPid(); final int uid = Binder.getCallingUid(); final long ident = Binder.clearCallingIdentity(); final int result; try { result = nativeInjectInputEvent(mPtr, event, displayId, pid, uid, mode,//主要看这个jni函数 INJECTION_TIMEOUT_MILLIS, WindowManagerPolicy.FLAG_DISABLE_KEY_REPEAT); } finally { Binder.restoreCallingIdentity(ident); } switch (result) { case INPUT_EVENT_INJECTION_PERMISSION_DENIED: Slog.w(TAG, "Input event injection from pid " + pid + " permission denied."); throw new SecurityException( "Injecting to another application requires INJECT_EVENTS permission"); case INPUT_EVENT_INJECTION_SUCCEEDED: return true; case INPUT_EVENT_INJECTION_TIMED_OUT: Slog.w(TAG, "Input event injection from pid " + pid + " timed out."); return false; case INPUT_EVENT_INJECTION_FAILED: default: Slog.w(TAG, "Input event injection from pid " + pid + " failed."); return false; }
}
三、native层代码
上面这个函数主要调用了nativeInjectInputEvent这个native函数。
[cpp] view plain copy 在CODE上查看代码片派生到我的代码片
static jint nativeInjectInputEvent(JNIEnv* env, jclass /* clazz */,
jlong ptr, jobject inputEventObj, jint displayId, jint injectorPid, jint injectorUid,
jint syncMode, jint timeoutMillis, jint policyFlags) {
NativeInputManager* im = reinterpret_cast
- android input命令 模拟按键
- android input命令 模拟按键
- Android adb input命令模拟滑动 按键 点击事件
- 命令模拟android 按键
- android input进程(模拟按键)
- input 模拟按键
- 【android】android使用命令模拟按键
- [Android][adb]input笔记--模拟-按键-点击-滑动事件
- ADB命令模拟 按键
- android 软按键 模拟按键
- android 模拟按键
- android 应用模拟按键
- android 模拟按键
- Android模拟按键
- Android 模拟物理按键
- Android模拟按键
- android 按键模拟
- Android 模拟物理按键
- AMD公布2017财年第二季度财报:净亏损1600万美元,股价大幅上涨8%
- 2017网络安全生态峰会在京举办 360郑文彬演讲攻防新趋势
- jquery中$符号报错的问题
- 15-面向对象(匿名内部类-概述) 1 2
- android Fragment传递数据方法
- android input命令 模拟按键
- 16-面向对象(匿名内部类-应用) 1 2 3 4
- 现场:CV人才争夺有多热烈,AI医疗与驾驶市场的竞争就有多激烈 | CVPR 2017
- Matlab 学习笔记
- sql server 2012 中文软件和安装教程
- 华人科学家一人斩获三篇CVPR论文!曾主持天猫精灵开发,技术成果或将产品化
- 兵贵神速 雷军趁出货量新高发起线下攻防战
- 原滴滴高级副总裁付强加入ofo小黄车 软银新轮融资或已启动
- 二叉树遍历(层次、前中后序)递归与非递归python实现