2323import android .view .IWindowManager ;
2424import android .view .KeyCharacterMap ;
2525import android .view .KeyEvent ;
26+ import android .view .MotionEvent ;
2627
2728/**
2829 * Command that sends key events to the device, either by their keycode, or by
2930 * desired character output.
3031 */
3132
3233public class Input {
34+ private static final String TAG = "Input" ;
35+
36+ private IWindowManager mWindowManager ;
3337
3438 /**
3539 * Command-line entry point.
@@ -40,6 +44,13 @@ public static void main(String[] args) {
4044 (new Input ()).run (args );
4145 }
4246
47+ private IWindowManager getWindowManager () {
48+ if (mWindowManager == null ) {
49+ mWindowManager = (IWindowManager .Stub .asInterface (ServiceManager .getService ("window" )));
50+ }
51+ return mWindowManager ;
52+ }
53+
4354 private void run (String [] args ) {
4455 if (args .length < 1 ) {
4556 showUsage ();
@@ -48,19 +59,37 @@ private void run(String[] args) {
4859
4960 String command = args [0 ];
5061
51- if (command .equals ("text" )) {
52- sendText (args [1 ]);
53- } else if (command .equals ("keyevent" )) {
54- sendKeyEvent (args [1 ]);
55- } else if (command .equals ("motionevent" )) {
56- System .err .println ("Error: motionevent not yet supported." );
57- return ;
58- }
59- else {
60- System .err .println ("Error: Unknown command: " + command );
61- showUsage ();
62- return ;
62+ try {
63+ if (command .equals ("text" )) {
64+ if (args .length == 2 ) {
65+ sendText (args [1 ]);
66+ return ;
67+ }
68+ } else if (command .equals ("keyevent" )) {
69+ if (args .length == 2 ) {
70+ sendKeyEvent (Integer .parseInt (args [1 ]));
71+ return ;
72+ }
73+ } else if (command .equals ("tap" )) {
74+ if (args .length == 3 ) {
75+ sendTap (Float .parseFloat (args [1 ]), Float .parseFloat (args [2 ]));
76+ return ;
77+ }
78+ } else if (command .equals ("swipe" )) {
79+ if (args .length == 5 ) {
80+ sendSwipe (Float .parseFloat (args [1 ]), Float .parseFloat (args [2 ]),
81+ Float .parseFloat (args [3 ]), Float .parseFloat (args [4 ]));
82+ return ;
83+ }
84+ } else {
85+ System .err .println ("Error: Unknown command: " + command );
86+ showUsage ();
87+ return ;
88+ }
89+ } catch (NumberFormatException ex ) {
6390 }
91+ System .err .println ("Error: Invalid arguments for command: " + command );
92+ showUsage ();
6493 }
6594
6695 /**
@@ -69,7 +98,6 @@ private void run(String[] args) {
6998 *
7099 * @param text is a string of characters you want to input to the device.
71100 */
72-
73101 private void sendText (String text ) {
74102
75103 StringBuffer buff = new StringBuffer (text );
@@ -90,55 +118,66 @@ private void sendText(String text) {
90118
91119 char [] chars = buff .toString ().toCharArray ();
92120
93- KeyCharacterMap mKeyCharacterMap = KeyCharacterMap .
94- load (KeyCharacterMap .VIRTUAL_KEYBOARD );
95-
96- KeyEvent [] events = mKeyCharacterMap .getEvents (chars );
97-
121+ KeyCharacterMap kcm = KeyCharacterMap .load (KeyCharacterMap .VIRTUAL_KEYBOARD );
122+ KeyEvent [] events = kcm .getEvents (chars );
98123 for (int i = 0 ; i < events .length ; i ++) {
99- KeyEvent event = events [i ];
100- Log .i ("SendKeyEvent" , Integer .toString (event .getKeyCode ()));
101- try {
102- (IWindowManager .Stub
103- .asInterface (ServiceManager .getService ("window" )))
104- .injectKeyEvent (event , true );
105- } catch (RemoteException e ) {
106- Log .i ("Input" , "DeadOjbectException" );
107- }
124+ injectKeyEvent (events [i ]);
108125 }
109126 }
110127
111- /**
112- * Send a single key event.
113- *
114- * @param event is a string representing the keycode of the key event you
115- * want to execute.
116- */
117- private void sendKeyEvent (String event ) {
118- int eventCode = Integer .parseInt (event );
128+ private void sendKeyEvent (int keyCode ) {
119129 long now = SystemClock .uptimeMillis ();
120- Log .i ("SendKeyEvent" , event );
130+ injectKeyEvent (new KeyEvent (now , now , KeyEvent .ACTION_DOWN , keyCode , 0 ));
131+ injectKeyEvent (new KeyEvent (now , now , KeyEvent .ACTION_UP , keyCode , 0 ));
132+ }
133+
134+ private void sendTap (float x , float y ) {
135+ long now = SystemClock .uptimeMillis ();
136+ injectPointerEvent (MotionEvent .obtain (now , now , MotionEvent .ACTION_DOWN , x , y , 0 ));
137+ injectPointerEvent (MotionEvent .obtain (now , now , MotionEvent .ACTION_UP , x , y , 0 ));
138+ }
139+
140+ private void sendSwipe (float x1 , float y1 , float x2 , float y2 ) {
141+ final int NUM_STEPS = 11 ;
142+ long now = SystemClock .uptimeMillis ();
143+ injectPointerEvent (MotionEvent .obtain (now , now , MotionEvent .ACTION_DOWN , x1 , y1 , 0 ));
144+ for (int i = 1 ; i < NUM_STEPS ; i ++) {
145+ float alpha = (float )i / NUM_STEPS ;
146+ injectPointerEvent (MotionEvent .obtain (now , now , MotionEvent .ACTION_MOVE ,
147+ lerp (x1 , x2 , alpha ), lerp (y1 , y2 , alpha ), 0 ));
148+ }
149+ injectPointerEvent (MotionEvent .obtain (now , now , MotionEvent .ACTION_UP , x2 , y2 , 0 ));
150+ }
151+
152+ private void injectKeyEvent (KeyEvent event ) {
153+ try {
154+ Log .i (TAG , "InjectKeyEvent: " + event );
155+ getWindowManager ().injectKeyEvent (event , true );
156+ } catch (RemoteException ex ) {
157+ Log .i (TAG , "RemoteException" , ex );
158+ }
159+ }
160+
161+ private void injectPointerEvent (MotionEvent event ) {
121162 try {
122- KeyEvent down = new KeyEvent (now , now , KeyEvent .ACTION_DOWN , eventCode , 0 );
123- KeyEvent up = new KeyEvent (now , now , KeyEvent .ACTION_UP , eventCode , 0 );
124- (IWindowManager .Stub
125- .asInterface (ServiceManager .getService ("window" )))
126- .injectKeyEvent (down , true );
127- (IWindowManager .Stub
128- .asInterface (ServiceManager .getService ("window" )))
129- .injectKeyEvent (up , true );
130- } catch (RemoteException e ) {
131- Log .i ("Input" , "DeadOjbectException" );
163+ Log .i ("Input" , "InjectPointerEvent: " + event );
164+ getWindowManager ().injectPointerEvent (event , true );
165+ } catch (RemoteException ex ) {
166+ Log .i (TAG , "RemoteException" , ex );
167+ } finally {
168+ event .recycle ();
132169 }
133170 }
134171
135- private void sendMotionEvent ( long downTime , int action , float x , float y ,
136- float pressure , float size ) {
172+ private static final float lerp ( float a , float b , float alpha ) {
173+ return ( b - a ) * alpha + a ;
137174 }
138175
139176 private void showUsage () {
140177 System .err .println ("usage: input [text|keyevent]" );
141178 System .err .println (" input text <string>" );
142- System .err .println (" input keyevent <event_code>" );
179+ System .err .println (" input keyevent <key code>" );
180+ System .err .println (" input tap <x> <y>" );
181+ System .err .println (" input swipe <x1> <y1> <x2> <y2>" );
143182 }
144183}
0 commit comments