【Python】基于ADB和thinker的Android宏录制工具
想法:现在很多手游都太肝,作为科研狗没那么多空闲时间,想找个方法自动化代肝,首先想到的肯定是ADB,但是ADB还需要一个一个调试触点的坐标,太麻烦了,于是一直想找个可视化的方法
思路:
1,使用ADB的截图功能获取当前屏幕
2,使用thinker绘制图形界面,显示屏幕截图
3,使用thinker抓取鼠标点击和拖动的事件并记录下坐标
4,使用ADB命令将记录好的行为重新播放出来
遇到的问题:
1,本来想直接在Android系统上进行操作,在电脑端使用adb shell getevent直接获取十六进制格式的事件,然后再用adb shell sendevent命令发送回去,但是报错显示权限不足,查了一下似乎是新版本的Android禁止了ADB直接将事件发送至Android端,只能使用adb shell input命令模拟按键执行
2,坐标问题,ADB中,事件的坐标并不是直接对应于手机屏幕的物理位置的,而是对应着屏幕旋转后的显示方向,左上角为(0,0),同时,截图生成的图像也满足这个规律
3,分辨率问题:手机的分辨率比电脑还高(lll¬ω¬),需要进行缩放,缩放后获取的坐标要再缩放回去
4,延时问题:截图从手机上传输到电脑上需要时间,如果不等传输完成就读取图片会直接报错,这时候只能在截图完成后sleep等待传输完成,由此产生的时延使得录制宏的过程中记录时间失去了意义,不过ADB模拟按键本来就时延挺长的么,所以只要在一些关键位置,比如加载阶段,手动加个timeout命令就行了
效果图:
代码:
#recorder.py import tkinter as tk from PIL import Image,ImageTk import os import time from matplotlib.pyplot import title scale=0.25 imagefilename = '1.png' recordfilename= "record.txt" file=open(recordfilename,"w",buffering=1) global lastdist def RefreshImage(): os.system("adb shell screencap -p /sdcard/"+imagefilename) os.system("adb pull /sdcard/"+imagefilename) os.system("adb shell rm /sdcard/"+imagefilename) time.sleep(0.5) img = Image.open(imagefilename) img=img.resize((int(img.size[0]*scale),int(img.size[1]*scale))) photo = ImageTk.PhotoImage(img) return photo def PressCallBack(event): dist=[int(event.x/scale),int(event.y/scale)] #print("当前位置:",dist[0],dist[1]) global lastdist lastdist=dist def ReleaseCallBack(event): dist=[int(event.x/scale),int(event.y/scale)] global lastdist if(lastdist[0]==dist[0] and lastdist[1]==dist[1]): #print(event) os.system("adb shell input tap "+str(dist[0])+" "+str(dist[1])) print("tap at "+str(dist[0])+" "+str(dist[1])) file.write("adb shell input tap "+str(dist[0])+" "+str(dist[1])+"\n") else: os.system("adb shell input swipe "+str(lastdist[0])+" "+str(lastdist[1])+" "+str(dist[0])+" "+str(dist[1])) print("swipe from "+str(lastdist[0])+" "+str(lastdist[1])+" to "+str(dist[0])+" "+str(dist[1])) file.write("adb shell input swipe "+str(lastdist[0])+" "+str(lastdist[1])+" "+str(dist[0])+" "+str(dist[1])+"\n") img=RefreshImage() label.configure(image=img) label.image=img root = tk.Tk() #tk. photo=RefreshImage() #frame = tk.Frame(root, width = int(img.size[0]*scale), height = int(img.size[1]*scale),image=img) label = tk.Label(root,image=photo) label.bind("<Button-1>",PressCallBack) label.bind("<ButtonRelease-1>",ReleaseCallBack) label.pack() root.mainloop()
#player.py import os,time Loops=200 recordfilename="record.txt" file=open(recordfilename,"r") command=file.readlines() file.close() for t in range(Loops): for i in command: os.system(i) #time.sleep(0.5)