adb shell input可以通过adb命令行发送input事件。包含keyevent和text两种。
对于安卓API KeyEvent定义的健值均可支持
https://developer.android.com/reference/android/view/KeyEvent
健值举例:
KEYCODE_0
Added in API level 1
public static final int KEYCODE_0
Key code constant: '0' key.
Constant Value: 7 (0x00000007)
KEYCODE_1
Added in API level 1
public static final int KEYCODE_1
Key code constant: '1' key.
Constant Value: 8 (0x00000008)
KEYCODE_11
Added in API level 21
public static final int KEYCODE_11
Key code constant: '11' key.
Constant Value: 227 (0x000000e3)
KEYCODE_12
Added in API level 21
public static final int KEYCODE_12
Key code constant: '12' key.
Constant Value: 228 (0x000000e4)
KEYCODE_2
Added in API level 1
public static final int KEYCODE_2
Key code constant: '2' key.
Constant Value: 9 (0x00000009)
KEYCODE_3
Added in API level 1
public static final int KEYCODE_3
Key code constant: '3' key.
Constant Value: 10 (0x0000000a)
KEYCODE_3D_MODE
public static final int KEYCODE_3D_MODE
Key code constant: 3D Mode key. Toggles the display between 2D and 3D mode. * @apiSince 14
Constant Value: 206 (0x000000ce)
KEYCODE_4
Added in API level 1
public static final int KEYCODE_4
Key code constant: '4' key.
Constant Value: 11 (0x0000000b)
KEYCODE_5
Added in API level 1
public static final int KEYCODE_5
Key code constant: '5' key.
Constant Value: 12 (0x0000000c)
例如,发送一个back键:
通过查询上述文档,我们发现back键值为4,所以连通adb调试后,命令行输入:
adb shell input keyevent 4
手机端就会响应back键(如果当前页面可以响应back)。
也可以支持直接的文本输入,例如,在手机端打开一个可以响应文本输入的界面,例如EditText控件,命令行输入:
adb shell input text 123
手机端EditText会填充文本123。
支持文本单引号和双引号:
adb shell input text "123"
adb shell input text '123'
都是可以的。
通过命令行调试一个back键值:adb shell input keyevent 4,看到手机端有如下log:
一部分是AndroidRuntime的log:
12-12 16:32:57.324 9375 9375 D AndroidRuntime: >>>>>> START com.android.internal.os.RuntimeInit uid 2000 <<<<<<
12-12 16:32:57.329 9375 9375 D AndroidRuntime: CheckJNI is OFF
12-12 16:32:57.445 9375 9375 D AndroidRuntime: Calling main entry com.android.commands.input.Input
12-12 16:32:57.509 9375 9375 D AndroidRuntime: Shutting down VM
另一部分,在start和shutting down中间,看到了keyevent相关:
12-12 16:14:30.277 8641 8641 I Input : injectKeyEvent: KeyEvent { action=ACTION_DOWN, keyCode=KEYCODE_BACK, scanCode=0, metaState=0, flags=0x0, repeatCount=0, eventTime=637379, downTime=637379, deviceId=-1, source=0x101 }
12-12 16:14:30.374 8641 8641 I Input : injectKeyEvent: KeyEvent { action=ACTION_UP, keyCode=KEYCODE_BACK, scanCode=0, metaState=0, flags=0x0, repeatCount=0, eventTime=637379, downTime=637379, deviceId=-1, source=0x101 }
再试一下文本:adb shell input text 12,AndroidRuntime的没区别,文本的处理:
12-12 16:40:19.753 9491 9491 I Input : injectKeyEvent: KeyEvent { action=ACTION_DOWN, keyCode=KEYCODE_1, scanCode=0, metaState=0, flags=0x0, repeatCount=0, eventTime=2186856, downTime=2186856, deviceId=-1, source=0x101 }
12-12 16:40:19.757 9491 9491 I Input : injectKeyEvent: KeyEvent { action=ACTION_UP, keyCode=KEYCODE_1, scanCode=0, metaState=0, flags=0x0, repeatCount=0, eventTime=2186856, downTime=2186856, deviceId=-1, source=0x101 }
12-12 16:40:19.763 9491 9491 I Input : injectKeyEvent: KeyEvent { action=ACTION_DOWN, keyCode=KEYCODE_2, scanCode=0, metaState=0, flags=0x0, repeatCount=0, eventTime=2186856, downTime=2186856, deviceId=-1, source=0x101 }
12-12 16:40:19.772 9491 9491 I Input : injectKeyEvent: KeyEvent { action=ACTION_UP, keyCode=KEYCODE_2, scanCode=0, metaState=0, flags=0x0, repeatCount=0, eventTime=2186856, downTime=2186856, deviceId=-1, source=0x101 }
再来一个大小写混合的:adb shell input text AbCd
12-12 16:41:43.986 9566 9566 I Input : injectKeyEvent: KeyEvent { action=ACTION_DOWN, keyCode=KEYCODE_SHIFT_LEFT, scanCode=0, metaState=META_SHIFT_ON|META_SHIFT_LEFT_ON, flags=0x0, repeatCount=0, eventTime=2271089, downTime=2271089, deviceId=-1, source=0x101 }
12-12 16:41:43.990 9566 9566 I Input : injectKeyEvent: KeyEvent { action=ACTION_DOWN, keyCode=KEYCODE_A, scanCode=0, metaState=META_SHIFT_ON|META_SHIFT_LEFT_ON, flags=0x0, repeatCount=0, eventTime=2271089, downTime=2271089, deviceId=-1, source=0x101 }
12-12 16:41:43.993 9566 9566 I Input : injectKeyEvent: KeyEvent { action=ACTION_UP, keyCode=KEYCODE_A, scanCode=0, metaState=META_SHIFT_ON|META_SHIFT_LEFT_ON, flags=0x0, repeatCount=0, eventTime=2271089, downTime=2271089, deviceId=-1, source=0x101 }
12-12 16:41:44.000 9566 9566 I Input : injectKeyEvent: KeyEvent { action=ACTION_UP, keyCode=KEYCODE_SHIFT_LEFT, scanCode=0, metaState=0, flags=0x0, repeatCount=0, eventTime=2271089, downTime=2271089, deviceId=-1, source=0x101 }
12-12 16:41:44.022 9566 9566 I Input : injectKeyEvent: KeyEvent { action=ACTION_DOWN, keyCode=KEYCODE_B, scanCode=0, metaState=0, flags=0x0, repeatCount=0, eventTime=2271089, downTime=2271089, deviceId=-1, source=0x101 }
12-12 16:41:44.027 9566 9566 I Input : injectKeyEvent: KeyEvent { action=ACTION_UP, keyCode=KEYCODE_B, scanCode=0, metaState=0, flags=0x0, repeatCount=0, eventTime=2271089, downTime=2271089, deviceId=-1, source=0x101 }
12-12 16:41:44.049 9566 9566 I Input : injectKeyEvent: KeyEvent { action=ACTION_DOWN, keyCode=KEYCODE_SHIFT_LEFT, scanCode=0, metaState=META_SHIFT_ON|META_SHIFT_LEFT_ON, flags=0x0, repeatCount=0, eventTime=2271089, downTime=2271089, deviceId=-1, source=0x101 }
12-12 16:41:44.052 9566 9566 I Input : injectKeyEvent: KeyEvent { action=ACTION_DOWN, keyCode=KEYCODE_C, scanCode=0, metaState=META_SHIFT_ON|META_SHIFT_LEFT_ON, flags=0x0, repeatCount=0, eventTime=2271089, downTime=2271089, deviceId=-1, source=0x101 }
12-12 16:41:44.055 9566 9566 I Input : injectKeyEvent: KeyEvent { action=ACTION_UP, keyCode=KEYCODE_C, scanCode=0, metaState=META_SHIFT_ON|META_SHIFT_LEFT_ON, flags=0x0, repeatCount=0, eventTime=2271089, downTime=2271089, deviceId=-1, source=0x101 }
12-12 16:41:44.075 9566 9566 I Input : injectKeyEvent: KeyEvent { action=ACTION_UP, keyCode=KEYCODE_SHIFT_LEFT, scanCode=0, metaState=0, flags=0x0, repeatCount=0, eventTime=2271089, downTime=2271089, deviceId=-1, source=0x101 }
12-12 16:41:44.078 9566 9566 I Input : injectKeyEvent: KeyEvent { action=ACTION_DOWN, keyCode=KEYCODE_D, scanCode=0, metaState=0, flags=0x0, repeatCount=0, eventTime=2271089, downTime=2271089, deviceId=-1, source=0x101 }
12-12 16:41:44.082 9566 9566 I Input : injectKeyEvent: KeyEvent { action=ACTION_UP, keyCode=KEYCODE_D, scanCode=0, metaState=0, flags=0x0, repeatCount=0, eventTime=2271089, downTime=2271089, deviceId=-1, source=0x101 }
从上面log基本上可以看出,对于text,实际上是拆分成每个字符,分别发了一个对应的KeyEvent Down&Up ,相当于一个字符两个KeyEvent。对于大写字母,前后再增加了KEYCODE_SHIFT_LEFT的Down和Up。
那么,中文文本呢?以上面的机制看,肯定是无法支持的。试验一下:adb shell input text 中文
手机端无反应,从log上看到了crash:
--------- beginning of crash
12-12 16:48:45.884 9749 9749 E AndroidRuntime: FATAL EXCEPTION: main
12-12 16:48:45.884 9749 9749 E AndroidRuntime: PID: 9749
12-12 16:48:45.884 9749 9749 E AndroidRuntime: java.lang.NullPointerException: Attempt to get length of null array
12-12 16:48:45.884 9749 9749 E AndroidRuntime: at com.android.commands.input.Input.sendText(Input.java:173)
12-12 16:48:45.884 9749 9749 E AndroidRuntime: at com.android.commands.input.Input.run(Input.java:82)
12-12 16:48:45.884 9749 9749 E AndroidRuntime: at com.android.commands.input.Input.main(Input.java:59)
12-12 16:48:45.884 9749 9749 E AndroidRuntime: at com.android.internal.os.RuntimeInit.nativeFinishInit(Native Method)
12-12 16:48:45.884 9749 9749 E AndroidRuntime: at com.android.internal.os.RuntimeInit.main(RuntimeInit.java:332)
--------- beginning of system
12-12 16:48:45.892 9749 9749 E MQSEventManagerDelegate: reportJEEvent error happened:java.lang.RuntimeException: Bad file descriptor
12-12 16:48:45.893 9749 9749 E AndroidRuntime: Error reporting crash
12-12 16:48:45.893 9749 9749 E AndroidRuntime: java.lang.RuntimeException: Bad file descriptor
12-12 16:48:45.893 9749 9749 E AndroidRuntime: at android.os.BinderProxy.transactNative(Native Method)
12-12 16:48:45.893 9749 9749 E AndroidRuntime: at android.os.BinderProxy.transact(Binder.java:510)
12-12 16:48:45.893 9749 9749 E AndroidRuntime: at android.os.ServiceManagerProxy.getService(ServiceManagerNative.java:123)
12-12 16:48:45.893 9749 9749 E AndroidRuntime: at android.os.ServiceManager.getService(ServiceManager.java:55)
12-12 16:48:45.893 9749 9749 E AndroidRuntime: at android.app.ActivityManagerNative$1.create(ActivityManagerNative.java:2778)
12-12 16:48:45.893 9749 9749 E AndroidRuntime: at android.app.ActivityManagerNative$1.create(ActivityManagerNative.java:2776)
12-12 16:48:45.893 9749 9749 E AndroidRuntime: at android.util.Singleton.get(Singleton.java:34)
12-12 16:48:45.893 9749 9749 E AndroidRuntime: at android.app.ActivityManagerNative.getDefault(ActivityManagerNative.java:87)
12-12 16:48:45.893 9749 9749 E AndroidRuntime: at com.android.internal.os.RuntimeInit$UncaughtHandler.uncaughtException(RuntimeInit.java:169)
12-12 16:48:45.893 9749 9749 E AndroidRuntime: at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:693)
12-12 16:48:45.893 9749 9749 E AndroidRuntime: at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:690)
12-12 16:48:45.901 9749 9749 E ProcessInjector: error while reportKillProcessEvent to system server!
12-12 16:48:45.901 9749 9749 E ProcessInjector: java.lang.reflect.InvocationTargetException
12-12 16:48:45.901 9749 9749 E ProcessInjector: at java.lang.reflect.Method.invoke(Native Method)
12-12 16:48:45.901 9749 9749 E ProcessInjector: at android.os.ProcessInjector.reportKillProcessEvent(ProcessInjector.java:20)
12-12 16:48:45.901 9749 9749 E ProcessInjector: at android.os.Process.killProcess(Process.java:1120)
12-12 16:48:45.901 9749 9749 E ProcessInjector: at com.android.internal.os.RuntimeInit$UncaughtHandler.uncaughtException(RuntimeInit.java:179)
12-12 16:48:45.901 9749 9749 E ProcessInjector: at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:693)
12-12 16:48:45.901 9749 9749 E ProcessInjector: at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:690)
12-12 16:48:45.901 9749 9749 E ProcessInjector: Caused by: java.lang.RuntimeException: Bad file descriptor
12-12 16:48:45.901 9749 9749 E ProcessInjector: at android.os.BinderProxy.transactNative(Native Method)
12-12 16:48:45.901 9749 9749 E ProcessInjector: at android.os.BinderProxy.transact(Binder.java:510)
12-12 16:48:45.901 9749 9749 E ProcessInjector: at android.os.ServiceManagerProxy.getService(ServiceManagerNative.java:123)
12-12 16:48:45.901 9749 9749 E ProcessInjector: at android.os.ServiceManager.getService(ServiceManager.java:55)
12-12 16:48:45.901 9749 9749 E ProcessInjector: at android.app.ActivityManagerNative$1.create(ActivityManagerNative.java:2778)
12-12 16:48:45.901 9749 9749 E ProcessInjector: at android.app.ActivityManagerNative$1.create(ActivityManagerNative.java:2776)
12-12 16:48:45.901 9749 9749 E ProcessInjector: at android.util.Singleton.get(Singleton.java:34)
12-12 16:48:45.901 9749 9749 E ProcessInjector: at android.app.ActivityManagerNative.getDefault(ActivityManagerNative.java:87)
12-12 16:48:45.901 9749 9749 E ProcessInjector: ... 6 more
接下来会结合安卓源代码,分析一下机制。