Modern day smart-phones have already begun to migrate from the traditional "a-button-for-every-need" approach to the "huge-display-cum-touchscreen" form-factors. Android phones are no exception. But, traditional buttons are still reqd. for a few oft used functions (power,back,home,menu etc.) And smart-phones continue to have them alongwith the primary touch-based-UI.
Android-OS provides a very easy method to simulate key/button press/release events via software. You might ask why do we need a software to generate the events when a hardware button is already present on the device. Here's why:
- During development/testing of the button-drivers itself.
- To implement automated rigorous tests. ( MonkeyTest? )
- To implement/interface additional custom software keyboards.
- Just because we can!
The reason why i am doing it today is REASON NUMBER 4.
Now, the basic goal of this exercise is extremely simple:
Q. How to generate a hardware-button-press event
WITHOUT actually pressing any key on the device?
Let us first understand what happens when a hardware button is pressed. Here is what happens when you press a button on an Android device:
- The h/w button triggers an interrupt.
- The ISR of the corresponding driver gets called (in kernel).
- In the ISR, the driver generates an input-event.
- Android-framework (in userspace) gets the notification of the event.
- Android reads the input-event code & type.
- Compares it with the proper "keymap/keylayout" file.
- The proper button is identified.
To simulate button presses we enter this procedure at STEP3.
Instead of the regular driver generating the input-event, we generate an input-event ourselves using a pre-built userspace binary. This will then be notified to the Android-framework and the rest continues as above.
So now all depends on the the pre-built userspace binary, which is...
[ drum-roll... ]
[ drum-roll... ]
...Input. (How convenient!) The syntax of input is as follows:
input keyevent <event_code>
Now, before we try to send any keyevent, we need to find out the event-code that maps to the h/w key we want to simulate. The following table summarizes all the supported keycodes in Android:
Additionally we can look up the keylayout (.kl) file on the device. Personally, I find keylayout a misnomer, as we are not talking about different keyboards here, but different mappings of an input-event-value to its functionality.
Anyways you can always find the file in system/usr/keylayout/xyz.kl
NOTE: For each keyboard device xyz, the android.keylayout.xyz system property must be set. If a keylayout file is not specified, Android will default to /system/usr/keylayout/qwerty.kl
Now to generate a event of a specific keycode, we simply execute this on the terminal/serial console:
input keyevent <keycode>
The value of keycode can be any of the integer values from the above table. In case a serial-console is NOT available on your device, you can always run the command via adb as follows:
That's how a hardware-button-press is simulated in software!!
adb shell input keyevent <keycode>
That's how a hardware-button-press is simulated in software!!
Further Reading:
- More on keycodes, keymaps & Android-Input in general:
Android/development/pdk/docs/keymaps_keyboard_input.html - Android's Keyevent Class summary
http://developer.android.com/reference/android/view/KeyEvent.html
Awesome! Are there any way to detect foreground App to send accurate key events?
ReplyDeleteHave no problem using KEYCODE_CALL but no luck to hang-up with KEYCODE_ENDCALL.
ReplyDelete@sj314 KEYCODE_ENDCALL CANNOT be intercepted by apps. Also since it is handled lower than the input queue, injecting it via adb may not work as expected.
ReplyDeleteMore info here:
http://groups.google.com/group/android-platform/browse_thread/thread/c6e2de4b0cdbecd7/21b7cf4ee06a7005
Is there a way to send a key press event for long press (The one that generally opens a context menu)
ReplyDeletewhat about COLON key?
ReplyDelete@tagmaster Any character/string literals can be sent directly using "input text" command.
ReplyDeleteFor example to send a colon,
adb shell input text ":"
Hi,
ReplyDeletestill sending a text string with spaces is not supported.
Or at least not on my device
adb shell input text "a b c"
Will only print 'a' to the device screen
Workarounds are not so hard, just split the text on spaces and do 'adb shell input key SPACE' but it would be more convenient to have the adb to accept strings with spaces in them from the beginning
Cheers Johan
Can i simulate the power on event when the battery is off? I want my phone to power on as soon as a charger is connected . My specific requirement will not allow me to press power on button to start the android phone . Can any one has any idea whether this can be done? Iphone automatically starts itself if battery is drained off and put to charge . I want similar functionality in android phone. Please let me know if this is possible at all or not? Can we actually simulate power on button event when phone is off completely?Is it through alarm interrupt?if yes then details please.
ReplyDeleteThanks in advance.
Short answer: No.
DeleteLong answer: The technique described in the above post requires Android to be booted-up on the device and adb setup properly between the device and the host-machine. Powering-on the device when charger is connected depends on how the bootloader is configured on it. When powered-off and connected to a charger, most Android devices just start charging and do NOT power-on until the power button is explicitly pressed.
Autobooting a tablet is very possible in fact but it requires modifications inside the kernel initramfs to hotswap the charger binaries.
DeleteGenerally this means, compiling android from source (including a proper charging binary) and injecting that into the kernel as seen fit.
Have done it before. Worked fine.
If we have access to the source, then the simplest way to get this working is to modify the boot-loader code. During boot-up the boot-loader checks if the power button was pressed, and if not then just keeps charging (often displaying a rudimentary charging UI) and does not load the Linux kernel.
DeleteSimply commenting the check and loading the Linux kernel unconditionally all the time should produce the desired behaviour.
The keylayout table you listed is working fine, but I tried to search for it on the system and didn't find it under /system/usr/keylayout in any "*.kl" file their. For example in your able the power keycode is 26 which is working on my device, but the power keycode in all my "*.kl" files are 116. I am confused.
ReplyDeleteHere is the complete list of paths on the device where keylayout files can be stored.
DeleteAlso the various paths listed in the above link are in order of priority. i.e. the system starts scanning for a .kl file in the path at the top of the list and continues down the list.
The first relevant .kl file found is used by the device.
Multiple .kl files can exist on a device. This is usually done to handle different input-devices like external-keyboards & joysticks. The input-device can generally be identified by the names of the .kl files.
Irrelevant keycodes can be listed in some .kl files. For example a joystick's .kl file could contain a (possibly wrong) keymap for the "power" button. Such codes do NOT affect the system behaviour as long as that particular input-device never generates that keycode.
It also could be done intentionally to provide similar functionality from multiple interfaces. For example, a particular button on the joystick can be configured to act as a power button for the Android device.
One can verify any .kl file using the Validate Keymaps tool (available as part of Android source code).
This works great when I use terminal emulator, but when I log in via ssh or telnet and issue the same command (i.e. input keyevent 82), I get a "Segmentation Fault" error.
ReplyDeleteAnyway to run this with ssh and have the gui on the screen respond?
Thanks!
Not being able to run system commands is a common problem with various ssh servers on Android. It looks like its an issue with one or more environment vars not being setup properly which leads to missing lib and a seg-fault. You might want to run a trace on ssh from where you are trying to access the android device. Also the logs of the ssh-server on the Android device ought to be of help...
DeleteI did some more digging and found out that the version of su that I was using was causing the problem. It is the su that ships with the mk802 (which is what I am using). I downloaded Superuser from the market, and replaced the current su with it. Now it seems to be working, but it is a little slow. You don't happen to know of a way to speed it up do you?
DeleteSplendid job! :) Among other things, one way to speed-up ssh is switching to RSA keys which are almost 4times faster(for validation) than DSA.
DeleteHi erocm123,
DeleteHow did you replace "su"?
I have tried replacing the su file but executing su I do not get the su prompt.
Can you provide the steps?
Thanks!!
can anybody tell me that if i want to do any action on long click then it is possible using adb shell ? yes then how ? because i had try out to find out but get only by click event . please help me .
ReplyDeleteThank you , helped me a lot :)
ReplyDeleteis there a way to do the "opposite"
ReplyDeleteto hook a touch action to a hardware button, for instance
(I have first person shooters on tables because you cant aim and fire correctly)
in a game I press the screen to shoot which should be converted to a event, If I can attach that event to a button I'll be able to do the action with the button instead of the screen
the same way as if I attach a game controller to the tablet.
is that possible?
This works great! However , how can I use this to simuulate the screenshot capturing ? For capturing screenshot , *simultaneous* keypresses of volume down and power key are needed.
ReplyDeletei want to change the device date . changing date by 7 day ahead . i used intent function am start -a android.intent.action.MAIN -n com.android.settings/.DateTimeSettings
ReplyDeleteNow i can go ahead by 7 day by input keyevent to change the date .
*now i want to go ahead by 7 days by input keyevent to change the date
DeleteOne can use the keyevents 19/20/21/22 (up/down/left/right) and 66(enter) to navigate the UI elements. The following sequence of keyevents does the trick for me on my N1 running CyanogenMod7.2(gingerbread):-
Deleteadb shell
input keyevent 20
input keyevent 20
input keyevent 66
(down,down,enter to select "set-date" option)
input keyevent 22
input keyevent 19
(move focus to "+" over day)
input keyevent 66
input keyevent 19
input keyevent 66
input keyevent 19
input keyevent 66
input keyevent 19
input keyevent 66
input keyevent 19
input keyevent 66
input keyevent 19
input keyevent 66
input keyevent 19
input keyevent 66
(7 times "enter". "Up" to refocus onto "+")
input keyevent 20
input keyevent 20
input keyevent 20
input keyevent 66
(move focus "down" to "Set" button and "enter")
This might have to change depending on your device and any UI modifications based on the ROM you are running. For example if "Set Date" option is further down in the list, then additional "keyevent 20"s will be required to navigate all the way down.
A simpler method for rooted devices would be to run the following command to set the required time and date.
date -s yyyyMMdd.hhmmss
How do I delete say a list of characters for example.
ReplyDeleteThe quick brown fox.
I could from the end of sentence execute the following command 20 times. But that executes rather slowly and it also seems superflous. Is there a execute multiple times command to make it simpler ?
input keyevent 67
input keyevent 67
input keyevent 67
input keyevent 67
input keyevent 67
input keyevent 67
input keyevent 67
input keyevent 67
input keyevent 67
input keyevent 67
input keyevent 67
input keyevent 67
input keyevent 67
input keyevent 67
input keyevent 67
input keyevent 67
input keyevent 67
input keyevent 67
input keyevent 67
input keyevent 67
Use shell scripts! ;-)
ReplyDeleteEither enter the entire set of adb commands in a shell-script on the host-PC and run it.
OR
Create a shell-script on the Android-device with all the "input keyevent keycode" commands and run this script on the Android-device via "adb shell script-name".
Hi. I am creating a navigation bar alternative for Android and using these commands.
DeleteFor back key, the command is input keyevent 4
But after the command is fired on older devices, it takes some time (about a second or so) for the response. That is rather slow.
Writing a shell script also is not slow as after every command, it pauses for a small amount of time.
Is there any alternative to speed this up?
Thanks mate
ReplyDeletethis was useful
Hi ,
ReplyDeleteI want to simulate Recent Apps icon on my Android device, can u guys pls let me know how to do it ....
Thanks in Advance......
I get the following error-
ReplyDelete"Input cannot be resolved to a type"
Can anybody help??
What command did you run and where?...
DeleteI am a beginner and trying to write an android code to trigger the record button of the camera. I am launching the camera in video mode using intent and added -"Input keyevent 27" in my code to start recording but that produced an error "Input cannot be resolved to a type".
DeleteI then tried this-
KeyEvent kev = newKeyEvent(KeyEvent.ACTION_DOWN,KeyEvent.KEYCODE_CAMERA);
onKeyDown(KeyEvent.KEYCODE_CAMERA, kev);
but it didn't trigger the record button.
Please help. Thanks in advance.
Check out the tutorial to launch video recorder activity http://android-er.blogspot.tw/2011/04/start-video-recording-using.html
DeleteAlso the following link has examples describing how to capture video in your own activity http://stackoverflow.com/questions/1817742/how-can-i-capture-a-video-recording-on-android
Can you please tell how to use "input keyevent" in android code!
DeleteSending keyevents in java is accomplished by using dispatchKeyEvent().
DeleteThe documentation does go on to say that the keyevent is dispatched from the top of the view tree down to the currently focused view. If this view has focus, it will dispatch to itself. Otherwise it will dispatch the next node down the focus path. This method also fires any key listeners.
Great info. I can not get this to work because my ICS tablet does not have the input method on it. I tried pulling it from the emulator, but it seems to have dependencies that I am not getting correct. Have you seen any good info on the correct installation of input and its dependencies?
ReplyDeleteThe touchscreen driver is unaware of what is currently displayed on the screen. It just reports the X,Y co-ordinates.
ReplyDeleteIf you are trying to setup some sort of automation/monitoring on a particular device that you own, then one possible way to determine the key pressed would be have a look-up table with all the co-ordinate ranges for the on-screen soft-keyboard that you have on your device.
It will be really challenging to regenerate the look-up table if the orientation of the device changes OR if the on-screen soft-keyboard layout is changed.
Tools to record android keyboard input? Can you share any names/links to what you are referring to?
ReplyDeleteGreat!
ReplyDeleteso how could i type a german umlaut like öäü using "input keyevent"
ReplyDeleteusing input text ö
leads to a segmentation fault.
Hello. How did you fix input text for German umlaut?
DeletePlease send me your solution on oleh.prilepin@gmail.com
Thanks a lot
If you cannot use spaces with "text" is because a bug in /system/bin/input.
ReplyDeleteIn that script you can replace:
$*
by
"$*"
or run the commands manually
This comment has been removed by the author.
Delete"$*" is not working for me. But "$@" is working true.
DeleteHello,
ReplyDeleteI tried to use the keyevent 26 (KEYCODE_POWER) to shut down the screen by a java application. It's don't seem to work neither for the KEYCODE_HOME but it's work s fine for KEYCODE_BACK... Is theirs some known issues for this problem ? thanks
Exactly what commands are you running and how? On a PC connected to your Android device, does the following command from the console/command-line "adb shell input keyevent 26" work for you?...
DeleteWhen I use the adb shell input keyevent 26, it's works. But I would like to use it on a java file for the moment I tried :
DeleteProcess chmod = Runtime.getRuntime().exec("input keyevent 26"); //it's only works for back pressed
&
Instrumentation mInst = new Instrumentation(); mInst.sendKeyDownUpSync( KeyEvent.KEYCODE_POWER ); //it's only works for back pressed
The reason for the failure of "input keyevent" command launched using runtime.exec() is not clear to me as well. But i have NOT tried it and cannot vouch that it is supposed to work.
DeletesendKeyDownUpSync() sends the event to the currently focused "window". Hence only the back button event works as the events generated by the power and home buttons generally are not handled by the foreground activity and sending the activities those events does not produce the desired effect.
Any thought on how I use an external heat/motion sensor to trigger the camera on an android device?
ReplyDeleteHello,
ReplyDeleteIs there a way to simulate a long power button press? I need to turn off the device with a long power button press. I've tried with adb shell input 26 but it seems like a short button press and my phone goes to sleep.
The long-button press is not handled in the software stack. That is why it works even when the Android OS is not-responding.
DeleteThe power-button long-press event is generally implemented in hardware i.e as an interrupt to the PMIC (power-management chip). Upon receiving the interrupt, the PMIC momentarily cuts-off the power-supply to the main processor, effectively forcing a hard-reboot.
Use one of the following commands to shutdown/reboot your Android device :
adb shutdown -k or
adb reboot or
adb reboot -p
adb shutdown -k seems to be not working. Sadly, I need to do a shutdown instead a reboot. Is there another way to shutdown without using the pwr button?
ReplyDeleteFor your Query :
ReplyDeleteSergiu StratJun 11, 2013, 1:05:00 PM
Any idea how can I read Keyboard Inputs? For example I've pressed S key and I get X,Y coords for tap inputs and pressure in display area of that key... but nothing that could help me identify what key was pressed.
nevrax-McBkPr:~ nevrax$ adb shell getevent -lt
add device 1: /dev/input/event1
name: "lid_input"
add device 2: /dev/input/event0
name: "elan-touchscreen"
add device 3: /dev/input/event2
name: "gpio-keys"
[ 161550.717211] /dev/input/event0: EV_ABS ABS_MT_TRACKING_ID 000006ef
[ 161550.717228] /dev/input/event0: EV_ABS ABS_MT_TOUCH_MAJOR 00000006
[ 161550.717232] /dev/input/event0: EV_ABS ABS_MT_PRESSURE 0000000d
[ 161550.717237] /dev/input/event0: EV_ABS ABS_MT_POSITION_X 000000e3
[ 161550.717241] /dev/input/event0: EV_ABS ABS_MT_POSITION_Y 00000632
[ 161550.717247] /dev/input/event0: EV_SYN SYN_REPORT 00000000
[ 161550.862091] /dev/input/event0: EV_ABS ABS_MT_TRACKING_ID ffffffff
[ 161550.862104] /dev/input/event0: EV_SYN SYN_REPORT 00000
Now we can change these hexadecimal code into Binary format , which actually ur system can understand .Below is the code which converts into binary one :
$LOGFILE = "play.txt";
$FILE = "Sample.pl";
open (CHECKBOOK, $LOGFILE);
while ($record = ) {
chomp($record);
if($record eq "sleep"){
print "sleep 1;";
sleep 1;
#continue;
}
@values = split(' ', $record);
$value0 = substr($values[0],0,17);
$value1 = hex($values[1]);
$value2 = hex($values[2]);
$value3 = hex($values[3]);
#if($value1 eq 0)
print "adb shell sendevent $value0 $value1 $value2 $value3 \n" ;
{system( "adb shell sendevent $value0 $value1 $value2 $value3 "); }
# foreach my $val (@values) {
# print "$val\n";
# }
}
close(CHECKBOOK);
Thanks
Shubham Tomar
did you guys happen to get this to work?
ReplyDeleteI use RepetiToch but that is time based and if I set it up the only way I think it will soon be out of sink with my automagic flow.
I tried to enable debug mode an manually note each gesture and key input plus the time between actions but it does not seem to do anything I get this in my logs.
21.02.2014 01:19:58.894 [Flow1] Action 'Execute Root Command: input tap in ' stderr=sh: [1]: syntax error: '<' unexpected filed
nice article, just what I was lookin for.
ReplyDeletemaybe anyone of You come with such a problem (accept button in camera app):
ReplyDeletehttp://stackoverflow.com/a/23289891/2570350
m getting error when capturing KeyEvent_0.......KeyEvent_9. in receiver
ReplyDeleteThanks for the post! I was wondering if there is a way to press 2 keys at the same time. I am writing a command in tasker to help me login to to my wifi automatically. So far I have:
ReplyDeleteinput keyevent 61; input keyevent 61; input keyevent 61; input keyevent 61; input keyevent 61; input keyevent 61; input keyevent 61; input keyevent 61; input keyevent 66
Basically 61 is tab which cycles me through the links on the login page until it stops on the "accept" button. 66 is enter which activates the "accept" button. This takes some time to cycle through and since the "accept" button is the last link on the page I would prefer to simulate Shift+Tab and then Enter. It would be much quicker. Thanks !
Thanks for you'r nice explanation. It really helps me.
ReplyDeleteHas anyone tried sending the keyevent codes to the android via an arduino? I am using the arduino to determine if the screen needs to be dimmed or if the tablet should go to sleep. This is a car head unit.
ReplyDeleteThanks!
I have Honeywell ScanPal™ EDA50 (https://aidc.honeywell.com/en-GB/Pages/Product.aspx?category=hand-held-mobile-computer&cat=HSM&pid=scanpaleda50k)
ReplyDeleteHow can I emulate the hardware button "SCAN" with the KeyEvent is KeyEvent.KEYCODE_UNKNOWN and I only know the scanCode.
I have Honeywell ScanPal™ EDA50
ReplyDeleteHow can I emulate the hardware button "SCAN" with the KeyEvent is KeyEvent.KEYCODE_UNKNOWN if I only know the scanCode.