Python 使用 ADB 录制回放触摸事件

发布时间 2023-03-23 11:02:47作者: 可乐芬达
import re
import subprocess
from subprocess import PIPE
import sys
import os
import time

__version__ = '1.0.0'

TOUCH_EVENT_ABS = re.compile(r"\S+:\s+EV_ABS\s+ABS_MT_POSITION_(X|Y)\s+([A-Za-z0-9]+)")
TOUCH_COORDINATE = re.compile(r"(\S+) X ([0-9]+) Y ([0-9]+)")

class Colors:
    HEADER = '\033[95m'
    OKBLUE = '\033[94m'
    OKGREEN = '\033[92m'
    WARNING = '\033[93m'
    FAIL = '\033[91m'
    ENDC = '\033[0m'
    BOLD = '\033[1m'
    UNDERLINE = '\033[4m'

def dlog(msg):
    print(str(msg))

def ilog(msg):
    print(Colors.OKBLUE + str(msg) + Colors.ENDC)

def elog(msg):
    print(Colors.FAIL + str(msg) + Colors.ENDC)

class AdbEventRecorder(object):
    def __init__(self, adb):
        self.adb_command = adb
        self.adb_shell_command = adb + ' shell'

    def record(self, fpath):
        ilog('Start recording')
        eventlist = []
        eventnum = 0
        record_command = self.adb_shell_command + ' getevent -l'
        print(record_command)
        adb = subprocess.Popen(record_command,
                               stdin=PIPE, stdout=PIPE,
                               stderr=PIPE)

        outputFile = open(fpath, 'w')
        while adb.poll() is None:
            try:
                millis = int(round(time.time() * 1000))
                line = adb.stdout.readline().decode('utf-8', 'replace').strip()
                match = TOUCH_EVENT_ABS.match(line.strip())

                if match is not None:
                    if 'X' in match.group(1):
                        abs, absval = match.groups()
                        eventlist.append([abs, int(absval, 16)])
                    elif 'Y' in match.group(1):
                        abs, absval = match.groups()
                        eventlist.append([abs, int(absval, 16)])

                    ## Write to the file
                    if len(eventlist) % 2 == 0:
                        rline = "%s %s %s %s %s\n" % (millis, eventlist[eventnum+0][0], eventlist[eventnum+0][1], eventlist[eventnum+1][0], eventlist[eventnum+1][1])
                        dlog(rline)
                        outputFile.write(rline)
                        eventnum += 2
            except KeyboardInterrupt:
                break
            if len(line) == 0:
                break
        outputFile.close()
        ilog('End recording')

    def play(self, fpath, repeat=False):
        ilog('Start playing')
        while True:
            lastTs = None
            with open(fpath) as fp:
                for line in fp:
                    match = TOUCH_COORDINATE.match(line.strip())
                    ts, absx, absy = match.groups()
                    ts = float(ts)
                    if lastTs and (ts - lastTs) > 0:
                        delta_second = (ts - lastTs) / 1000
                        time.sleep(delta_second)

                    lastTs = ts
                    cmds = self.adb_shell_command + ' input tap {} {}'.format(absx, absy)
                    dlog(cmds)
                    if subprocess.call(cmds) != 0:
                        raise OSError('sendevent failed')

            if repeat == False:
                break
        ilog('End playing')

if __name__ == '__main__':
    adb_recorder = AdbEventRecorder('adb')
    # adb_recorder.record(fpath=r'C:\\Users\\Desktop\\r.txt')
    adb_recorder.play(fpath=r'C:\\Users\\Desktop\\r.txt')