Emulating touchscreen interaction with sendevent in Android

Android provides these two convenient tools for dealing with input events:

getevent

for dumping input events and providing information about input devices

sendevent - for injecting input events

Every sendevent command requires 4 parameters:
device_name (string)
event_type (decimal int)
event_code (decimal int)
value (decimal int)

First you need to find the name of touchscreen device.
in adb

getevent -p

get the event list
Let's assume it printed out "/dev/input/event0" - this would be the first parameter.

For touch events only 2 event types are used:
EV_ABS (3)
EV_SYN (0)

Touching the display (in case of Type A protocol) will result in an input report (sequence of input events) containing the following event codes:
ABS_MT_TRACKING_ID (57) - ID of the touch (important for multi-touch reports)
ABS_MT_POSITION_X (53) - x coordinate of the touch
ABS_MT_POSITION_Y (54) - y coordinate of the touch
ABS_MT_TOUCH_MAJOR (48) - basically width of your finger tip in pixels
ABS_MT_PRESSURE (58) - pressure of the touch
SYN_MT_REPORT (2) - end of separate touch data
SYN_REPORT (0) - end of report

Let's say we want to emulate a touch down event at the point with coordinates x=300, y=400. We will need to execute the following sendevent commands:

sendevent /dev/input/event0 3 57 0
sendevent /dev/input/event0 3 53 300
sendevent /dev/input/event0 3 54 400
sendevent /dev/input/event0 3 48 5
sendevent /dev/input/event0 3 58 50
sendevent /dev/input/event0 0 2 0
sendevent /dev/input/event0 0 0 0

I used arbitrary values of 5 for the ABS_MT_TOUCH_MAJOR (makes for very small finger tip for high precision) and 50 for the ABS_MT_PRESSURE (a slight tap) which work good enough for most applications.

For most touch screens on the market it takes 20 to 50 milliseconds to reliably register the touch. So I would recommend to wait at least 50 milliseconds before sending the release event report. If you want to emulate the long touch - then you wait longer. You can use busybox usleep command:

busybox usleep 50000

The release report is really simple. To let the input device know that all previous touches have been released - you just send the empty report with ABS_MT_TRACKING_ID = -1:

ABS_MT_TRACKING_ID (57)
SYN_MT_REPORT (2)
SYN_REPORT (0)

sendevent /dev/input/event0 3 57 -1 `
sendevent /dev/input/event0 0 2 0
sendevent /dev/input/event0 0 0 0

This is how injecting touch events could be implemented in python:

#!/usr/bin/python

import subprocess
import os

def adbshell(command, serial=None, adbpath='adb'):
    args = [adbpath]
    if serial is not None:
        args.append('-s')
        args.append(serial)
    args.append('shell')
    args.append(command)
    return os.linesep.join(subprocess.check_output(args).split('\r\n')[0:-1])

def adbdevices(adbpath='adb'):
return [dev.split('\t')[0] for dev in subprocess.check_output([adbpath, 'devices']).splitlines() if dev.endswith('\tdevice')]

def touchscreen_devices(serial=None, adbpath='adb'):
return [dev.splitlines()[0].split()[-1] for dev in adbshell('getevent -il', serial, adbpath).split('add device ') if dev.find('ABS_MT_POSITION_X') > -1]

def tap(devicename, x, y, serial=None, adbpath='adb'):
adbshell('S="sendevent {}";$S 3 57 0;$S 3 53 {};$S 3 54 {};$S 3 58 50;$S 3 50 5;$S 0 2 0;$S 0 0 0;'.format(devicename, x, y), serial, adbpath)
adbshell('S="sendevent {}";$S 3 57 -1;$S 0 2 0;$S 0 0 0;'.format(devicename), serial, adbpath)

serial = adbdevices()[0]
touchdev = touchscreen_devices(serial)[0]
tap(touchdev, 100, 100, serial)

view rawtouch_test.py hosted with ❤ by GitHub
Labels: adb, android, busybox, getevent, sendevent
2 comments:

NavigatorJuly 5, 2013 at 4:43 AM
At least on my Motorola Defy with CM7 (Android 2.3.7) things look a bit different.
It looks like
0 2 0
0 0 0
is NOT a release report, but some kind of activation of the previous sendevent commands.
To release you have to send an additional command (including activation):

sendevent /dev/input/event3 3 57 -1
sendevent /dev/input/event3 0 2 0
sendevent /dev/input/event3 0 0 0
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 从前是世界一片黑暗,宇宙中有一个大鸡蛋,大鸡蛋里面有个人,那就是盘古,他睡了1800年。突然有一天他醒来了,他什么...
    谢孟佳阅读 281评论 0 1
  • 今天下午刷微博的时候,看到漫画家陈缘风的微博,晒着各种跟女儿蓝蓝的腻歪又温馨的日常。突然,好想找个这样的蓝银结婚,...
    WHelen阅读 927评论 9 18
  • 今天周三对班有个同事休班,今天下午我们早班开完宾 然后准备下班的时候对班的队长去吃饭了 只剩下店长一个人了,担心店...
    kyle房成阅读 278评论 8 0
  • 好累。 每天装卸货,像劳务一样,赚着寥寥无几的薪水,手上磨了个水泡,胳膊被蹭出来好多伤痕,没有人关心,没有人心疼,...
    大白比小白白阅读 432评论 2 0