当前位置:   article > 正文

python GUI编程(tkinter)基于adb 编写安卓助手_python tk/ttk制作 安卓群控助手

python tk/ttk制作 安卓群控助手

源码地址:https://github.com/18713341733/PhoneAssistant

以前编写adb工具都是bat格式的,今天分享一下利用python tkinterGUI编程来写工具。

基于python+adb 编写的安卓助手工具。支持录屏、截图、日志抓取、性能数据查看等功能。目前的功能不是很完善,只是单纯的打个样儿。

这个工具是很久之前用python2写的,虽然有点老,但是可以自己手动改改成python3

链接手机界面:

连接成功后,功能如图:

截屏 录屏界面:

安装APK界面:

monkey界面:

LOG日志抓取界面:

性能数据查看界面:

一些其他功能:

这些功能的实现全部是基于adb命令实现。

具体的实现逻辑等就不讲了,上代码:

目录结构如下:

首先,编写首页,

  1. # -*- coding:utf-8 -*-
  2. #作者:张兴,陈帅
  3. #修改日期:2018.7.7
  4. #修改功能:链接手机时,增加了对是否安装adb的判断
  5. from tkinter import *
  6. from tkinter.messagebox import *
  7. import tkinter as tk
  8. from MainPage import *
  9. import os
  10. import re
  11. import subprocess
  12. class HomePage1(object):
  13. def __init__(self, master=None):
  14. self.root = master # 定义内部变量root
  15. self.root.geometry('%dx%d' % (300, 180)) # 设置窗口大小
  16. self.createPage()
  17. def createPage(self):
  18. self.page = Frame(self.root) # 创建Frame
  19. self.page.pack()
  20. Button(self.page, text='连接手机',width=12, command=self.loginCheck).grid(row=1, stick=W, pady=10,column=1)
  21. Button(self.page, text='退出',width=12, command=self.page.quit).grid(row=2, column=1, stick=E)
  22. def loginCheck(self):
  23. #点击后去连接手机,连接手机后,对是否连接成功做一些判断,
  24. # 如何获取控制台的内容,Python2 与Python3 处理是不一样的
  25. #Python2的处理方式为commands模块,但是Python3中废掉了commands模块,用subprocess代替,详情使用方法访问博客:
  26. #https://blog.csdn.net/qq_39208536/article/details/80894752
  27. out = subprocess.getstatusoutput('adb devices -l')
  28. out1 = subprocess.getstatusoutput('adb devices')
  29. #out是一个tuple,(0, 'List of devices attached \nc0cfe4a4 device product:PD1515A model:vivo_X6Plus_A device:PD1515A\n')
  30. #out[0]为状态码,0成功,1失败
  31. if out[0]==0:#命令成功之后,进行判断
  32. if 'device product' in out[1]:
  33. self.page.destroy()
  34. MainPage(self.root)
  35. #连接成功返回新的页面
  36. else:
  37. self.sayTry()
  38. #此时命令执行成功,但是手机没有连接上
  39. else:
  40. if out1[0]==0:
  41. if 'device' in out1[1]:
  42. self.page.destroy()
  43. MainPage(self.root)
  44. #连接成功返回新的页面
  45. else:
  46. self.sayTry()
  47. else:
  48. self.sayNoadb()#增加了对adb命令执行失败的判断。
  49. def connectPhone(self):
  50. self.page.destroy()
  51. def sayTry(self):
  52. tk.messagebox.showinfo("Message", "手机连接失败,请尝试重新连接") # 弹出消息窗口
  53. def sayFail(self):
  54. tk.messagebox.showinfo("Message", "手机连接失败,未知错误") # 弹出消息窗口
  55. #没有安装adb判断
  56. def sayNoadb(self):
  57. tk.messagebox.showinfo("Message", "没有安装adb或者未配置adb环境变量") # 弹出消息窗口

MainPage.py

  1. from tkinter import *
  2. from view import * # 菜单栏对应的各个子页面
  3. class MainPage(object):
  4. def __init__(self, master=None):
  5. self.root = master # 定义内部变量root
  6. self.root.geometry('%dx%d' % (600, 450)) # 设置窗口大小
  7. self.createPage()
  8. def createPage(self):
  9. self.inputPage = InputFrame(self.root) # 创建不同Frame
  10. self.installPage=InstallFrame(self.root)
  11. self.queryPage = QueryFrame(self.root)
  12. self.countPage = CountFrame(self.root)
  13. self.aboutPage = AboutFrame(self.root)
  14. # self.settingPage = SeetingFrame(self.root)
  15. self.seniorPage = SeniorFrame(self.root)#高级页面
  16. self.helpPage=HelpFrame(self.root)
  17. self.inputPage.pack() # 默认显示基础功能界面
  18. menubar = Menu(self.root)
  19. menubar.add_command(label='基础功能', command=self.inputData)
  20. menubar.add_command(label='安装apk', command=self.installData)
  21. menubar.add_command(label='monkey', command=self.queryData)
  22. menubar.add_command(label='log日志', command=self.countData)
  23. menubar.add_command(label='性能测试', command=self.aboutDisp)
  24. # menubar.add_command(label='设置', command=self.setting)
  25. menubar.add_command(label='高级', command=self.senior)
  26. menubar.add_command(label='帮助', command=self.helpMe)
  27. self.root['menu'] = menubar # 设置菜单栏
  28. def inputData(self):
  29. self.inputPage.pack()
  30. self.installPage.pack_forget()
  31. self.queryPage.pack_forget()
  32. self.countPage.pack_forget()
  33. self.aboutPage.pack_forget()
  34. # self.settingPage.pack_forget()
  35. self.helpPage.pack_forget()
  36. self.seniorPage.pack_forget()#不显示高级页面
  37. def installData(self):
  38. self.inputPage.pack_forget()
  39. self.installPage.pack()
  40. self.queryPage.pack_forget()
  41. self.countPage.pack_forget()
  42. self.aboutPage.pack_forget()
  43. # self.settingPage.pack_forget()
  44. self.helpPage.pack_forget()
  45. self.seniorPage.pack_forget() # 不显示高级页面
  46. def queryData(self):
  47. self.inputPage.pack_forget()
  48. self.queryPage.pack()
  49. self.countPage.pack_forget()
  50. self.aboutPage.pack_forget()
  51. # self.settingPage.pack_forget()
  52. self.helpPage.pack_forget()
  53. self.installPage.pack_forget()
  54. self.seniorPage.pack_forget() # 不显示高级页面
  55. def countData(self):
  56. self.inputPage.pack_forget()
  57. self.queryPage.pack_forget()
  58. self.countPage.pack()
  59. self.aboutPage.pack_forget()
  60. # self.settingPage.pack_forget()
  61. self.helpPage.pack_forget()
  62. self.installPage.pack_forget()
  63. self.seniorPage.pack_forget() # 不显示高级页面
  64. def aboutDisp(self):
  65. self.inputPage.pack_forget()
  66. self.queryPage.pack_forget()
  67. self.countPage.pack_forget()
  68. self.aboutPage.pack()
  69. # self.settingPage.pack_forget()
  70. self.helpPage.pack_forget()
  71. self.installPage.pack_forget()
  72. self.seniorPage.pack_forget() # 不显示高级页面
  73. # def setting(self):#设置页面
  74. # self.inputPage.pack_forget()
  75. # self.queryPage.pack_forget()
  76. # self.countPage.pack_forget()
  77. # self.aboutPage.pack_forget()
  78. # self.settingPage.pack()
  79. # self.helpPage.pack_forget()
  80. # self.installPage.pack_forget()
  81. # self.seniorPage.pack_forget() # 不显示高级页面
  82. def helpMe(self):#帮助页面
  83. self.inputPage.pack_forget()
  84. self.queryPage.pack_forget()
  85. self.countPage.pack_forget()
  86. self.aboutPage.pack_forget()
  87. # self.settingPage.pack_forget()
  88. self.helpPage.pack()
  89. self.installPage.pack_forget()
  90. self.seniorPage.pack_forget() # 不显示高级页面
  91. def senior(self):#高级页面
  92. self.inputPage.pack_forget()
  93. self.queryPage.pack_forget()
  94. self.countPage.pack_forget()
  95. self.aboutPage.pack_forget()
  96. # self.settingPage.pack_forget()
  97. self.helpPage.pack_forget()
  98. self.installPage.pack_forget()
  99. self.seniorPage.pack() # 显示高级页面

view.py

  1. from tkinter import *
  2. from tkinter import ttk
  3. from tkinter.messagebox import *
  4. import os
  5. import subprocess
  6. import datetime
  7. import tkinter as tk
  8. import threading
  9. import time
  10. #from PIL import Image, ImageTk
  11. import re
  12. import signal
  13. import tkinter.filedialog
  14. #基础功能
  15. class InputFrame(Frame): # 继承Frame类
  16. def __init__(self, master=None):
  17. Frame.__init__(self, master)
  18. self.root = master # 定义内部变量root
  19. self.itemName = StringVar()
  20. self.importPrice = StringVar()
  21. self.sellPrice = StringVar()
  22. self.deductPrice = StringVar()
  23. self.createPage()
  24. #基础功能页面展示
  25. def createPage(self):
  26. Label(self).grid(row=0, stick=W, pady=10)
  27. Button(self,text='截屏',width=25,height=5,command=self.screenshot).grid(row=1, stick=W, pady=10)
  28. # Button(self, text='录像',width=25,height=5,command=self.screenrecord).grid(row=2, stick=W, pady=10)
  29. self.switchscrBtn = Button(self, text='开始录像', width=25, height=5, command=self.switchscreenrecord)
  30. self.switchscrBtn.grid(row=2, stick=W, pady=10)
  31. # Button(self, text='安装APK', width=25, height=5, command=self.screenrecord).grid(row=3, stick=W, pady=10)
  32. # def screenrecord(self):
  33. # Label(self).grid(row=0, stick=W, pady=10)
  34. # Label(self, text='开始录屏请点击下方按钮').grid(row=3, stick=W, pady=10)
  35. # self.B = Button(self, text='开始', width=12, command=self.switch)
  36. # self.B.grid(row=6, stick=E, pady=10)
  37. def switchscreenrecord(self):
  38. if self.switchscrBtn['text'] == '开始录像':
  39. self.switchscrBtn['text'] = '结束录像'
  40. self.startrecord()
  41. else:
  42. self.switchscrBtn['text'] = '开始录像'
  43. self.endrecord()
  44. def startrecord(self):
  45. nowtime = datetime.datetime.now().strftime('%Y%m%d%H%M%S')
  46. self.name1 = nowtime + 'test.mp4'
  47. out = 'adb shell screenrecord /sdcard/test.mp4'
  48. self.pro = subprocess.Popen(out, stderr=subprocess.PIPE)
  49. # 结束进程
  50. def endrecord(self):
  51. self.pro.kill()
  52. out2 = subprocess.getstatusoutput('adb pull /sdcard/test.mp4 .\{}'.format(self.name1)) # .close()是关闭文件的 .kill()是杀掉进程
  53. #截图函数
  54. def screenshot(self):
  55. nowtime=datetime.datetime.now().strftime('%Y%m%d%H%M%S')
  56. name=nowtime+'.png'
  57. out = subprocess.getstatusoutput('adb shell screencap -p /sdcard/screen.png')
  58. out1 = subprocess.getstatusoutput('adb pull /sdcard/screen.png .\{}'.format(name))
  59. if out[0]==0 and out1[0]==0:
  60. pass
  61. else:
  62. tk.messagebox.showinfo("Message", "未知原因,截图失败") # 弹出消息窗口
  63. #安装APK
  64. class InstallFrame(Frame):
  65. def __init__(self, master=None):
  66. Frame.__init__(self, master)
  67. self.root = master # 定义内部变量root
  68. self.itemName = StringVar()
  69. self.importPrice = StringVar()
  70. self.sellPrice = StringVar()
  71. self.deductPrice = StringVar()
  72. self.number = StringVar()
  73. self.createPage()
  74. def createPage(self):
  75. Label(self).grid(row=0, stick=W, pady=10)
  76. Button(self, text='查找安装文件', width=25, height=5, command=self.search).grid(row=1, stick=W, pady=10)
  77. def search(self):
  78. default_dir = r"C:\Users\lenovo\Desktop" # 设置默认打开目录
  79. self.filename = tkinter.filedialog.askopenfilename(title=u"选择文件",initialdir=(os.path.expanduser(default_dir)),filetypes=[("apk格式", "apk")])
  80. Label(self,text='路径为:').grid(row=2,stick=W,pady=10)
  81. Label(self, text=self.filename).grid(row=3, pady=10, stick=W)
  82. self.B = Button(self, text='开始安装', width=12, command=self.switch)
  83. self.B.grid(row=6, stick=E, pady=10)
  84. def switch(self):
  85. print(self.B)
  86. if self.B['text'] == '开始安装':
  87. self.B['text'] = '结束安装'
  88. self.startinstall() # 调取安装APK函数
  89. else:
  90. self.B['text'] = '开始安装'
  91. self.endinstall() # 结束抓取日志函数
  92. def startinstall(self):
  93. tk.messagebox.showinfo("Message", "马上开始安装")
  94. out1=self.filename
  95. out = 'adb install -r '
  96. #adb install 为安装 adb install -r为覆盖安装
  97. out2=out+out1
  98. self.pro = subprocess.Popen(out2, stderr=subprocess.PIPE)
  99. def endinstall(self):
  100. self.pro.kill()
  101. #monkey压测
  102. class QueryFrame(Frame): # 继承Frame类
  103. def __init__(self, master=None):
  104. Frame.__init__(self, master)
  105. self.root = master # 定义内部变量root
  106. self.packageName=StringVar()#包名
  107. self.pressureNum=StringVar()#打压次数
  108. self.seedNum=StringVar()#标记
  109. self.logLevel=StringVar()#日志级别
  110. self.throttle=StringVar()#时间间隔
  111. self.ignoreCrash=StringVar()#忽略崩溃
  112. self.ignoreANR=StringVar()#忽略闪退
  113. self.ignoreTimeout=StringVar()#忽略超时
  114. self.createPage()
  115. def createPage(self):
  116. Label(self).grid(row=0, stick=W, pady=10)
  117. Label(self, text='包名: ').grid(row=1, stick=W, pady=10)
  118. Entry(self, textvariable=self.packageName).grid(row=1, column=1, stick=E)
  119. Label(self, text='压力: ').grid(row=2, stick=W, pady=10)
  120. Entry(self, textvariable=self.pressureNum).grid(row=2, column=1, stick=E)
  121. self.press = Entry(self, textvariable=self.pressureNum)
  122. self.press.insert(10, 1000)
  123. Label(self, text='标记: ').grid(row=3, stick=W, pady=10)
  124. Entry(self, textvariable=self.seedNum).grid(row=3, column=1, stick=E)
  125. self.seed =Entry(self, textvariable=self.seedNum)
  126. self.seed.insert(10, 1)
  127. # 创建一个下拉列表
  128. Label(self, text='日志级别: ').grid(row=4, stick=W, pady=10)
  129. numberChosen = ttk.Combobox(self, width=12, textvariable=self.logLevel, state='readonly')
  130. numberChosen['values'] = (1, 2, 3) # 设置下拉列表的值
  131. numberChosen.grid(column=1, row=4,stick=E) # 设置其在界面中出现的位置 column代表列 row 代表行
  132. numberChosen.current(2) # 设置下拉列表默认显示的值,1为 numberChosen['values'] 的下标值
  133. # 创建一个下拉列表,时间间隔throttle
  134. Label(self, text='throttle').grid(row=5, stick=W, pady=10)
  135. numberChosen = ttk.Combobox(self, width=12, textvariable=self.throttle, state='readonly')
  136. numberChosen['values'] = (100,150,200,250,300,350,400) # 设置下拉列表的值
  137. numberChosen.grid(column=1, row=5, stick=E) # 设置其在界面中出现的位置 column代表列 row 代表行
  138. numberChosen.current(0) # 设置下拉列表默认显示的值,1为 numberChosen['values'] 的下标值
  139. Checkbutton(self,text='忽略崩溃',onvalue=1,offvalue=0,variable =self.ignoreCrash).grid(row=6, column=1, stick=E)
  140. #offvalue #设置Off的值=0
  141. #onvalue #设置on的值=1
  142. Checkbutton(self, text='忽略超时',onvalue=1,offvalue=0,variable =self.ignoreTimeout).grid(row=7, column=1, stick=E)
  143. self.startBtn=Button(self, text='开始压测',command=self.switch)
  144. self.startBtn.grid(row=8, column=5, stick=E, pady=5)
  145. Button(self, text='报告分析').grid(row=9, column=5, stick=E, pady=5)
  146. # 制作中
  147. # 开始与结束之间的切换
  148. def switch(self):
  149. if self.startBtn['text'] == '开始压测':
  150. self.startBtn['text'] = '强行终止'
  151. self.monkey() # 开始跑monkey
  152. else:
  153. self.startBtn['text'] = '开始压测'
  154. self.killPro() # 结束monkey
  155. def monkey(self):
  156. packageName=self.packageName.get() # 包名
  157. print('包名{}'.format(packageName))
  158. pressureNum=int(self.pressureNum.get()) # 打压次数
  159. print('打压次数:{}'.format(pressureNum))
  160. seedNum=int(self.seedNum.get()) # 标记
  161. print('标记:{}'.format(seedNum))
  162. logLevel=int(self.logLevel.get()) # 日志级别
  163. print('日志级别:{}'.format(logLevel))
  164. ignoreCrash=self.ignoreCrash.get()
  165. print('忽略崩溃:{}'.format(ignoreCrash))
  166. ignoreTimeout=self.ignoreTimeout.get()
  167. throttle=int(self.throttle.get())
  168. print('时间间隔:{}'.format(throttle))
  169. print('忽略超时:{}'.format(ignoreTimeout))
  170. nowtime = datetime.datetime.now().strftime('%Y%m%d%H%M%S')
  171. filename = 'Monkey'+nowtime + ".txt"
  172. logcat_file = open(filename, 'w')
  173. logcmd = r'adb shell monkey -p {} -s {} -v -v -v --throttle {} --ignore-crashes --ignore-timeouts --ignore-security-exceptions --ignore-native-crashes --monitor-native-crashes {}'.format(packageName,seedNum,throttle,pressureNum)
  174. self.pro = subprocess.Popen(logcmd, stdout=logcat_file, stderr=subprocess.PIPE)
  175. # 结束进程
  176. def some_adb_cmd(self):
  177. p = subprocess.Popen('adb shell cd sdcard && cd Android && cd data && ps |grep monkey',stdout=subprocess.PIPE, stderr=subprocess.PIPE)
  178. return_code = p.poll()
  179. while return_code is None:
  180. line = p.stdout.readline()
  181. return_code = p.poll()
  182. line = line.strip()
  183. line1=str(line,"utf-8")
  184. pattern = re.compile(r'[^\d]+(\d+)[^\d]+')
  185. res = re.findall(pattern, line1)
  186. #os.kill(int(res), signal.SIGKILL)
  187. res1=res[0]
  188. a='adb shell cd sdcard && cd Android && cd data'
  189. a1='kill '+res1
  190. a2=a+" && "+a1
  191. p1 = subprocess.Popen(a2,stdout=subprocess.PIPE, stderr=subprocess.PIPE)
  192. break
  193. def killPro(self):
  194. self.some_adb_cmd()
  195. #log日志
  196. class CountFrame(Frame): # 继承Frame类
  197. def __init__(self, master=None):
  198. Frame.__init__(self, master)
  199. self.root = master # 定义内部变量root
  200. self.filterTag=StringVar() # 过滤标签
  201. self.filterStr=StringVar() # 过滤字符串
  202. self.filterRegular=StringVar() # 正则过滤
  203. self.logLevel = StringVar() # 日志级别
  204. self.filterFormat=StringVar()#过滤项格式
  205. self.createPage()
  206. def createPage(self):
  207. #Label(self, text='过滤标签: ').grid(row=1, stick=W, pady=10)
  208. #entry=Entry(self, textvariable=self.filterTag).grid(row=1, column=1, stick=E)
  209. Label(self, text='过滤字符串: ').grid(row=2, stick=W, pady=10)
  210. Entry(self, textvariable=self.filterStr).grid(row=2, column=1, stick=E)
  211. #Label(self, text='正则过滤: ').grid(row=3, stick=W, pady=10)
  212. #Entry(self, textvariable=self.filterRegular).grid(row=3, column=1, stick=E)
  213. #日志级别############################################################
  214. # 创建一个下拉列表
  215. # Label(self, text='日志级别: ').grid(row=4, stick=W, pady=10)
  216. # Label(self).grid(row=0, stick=W, pady=10)
  217. #numberChosen = ttk.Combobox(self, width=12, textvariable=self.logLevel, state='readonly')
  218. # numberChosen['values'] = (1, 2, 3) # 设置下拉列表的值
  219. # numberChosen.grid(column=1, row=4, stick=E) # 设置其在界面中出现的位置 column代表列 row 代表行
  220. # numberChosen.current(1) # 设置下拉列表默认显示的值,1为 numberChosen['values'] 的下标值
  221. #过滤格式############################################################
  222. Label(self, text='过滤项格式: ').grid(row=5, stick=W, pady=10)
  223. Label(self).grid(row=0, stick=W, pady=10)
  224. filterFormat = ttk.Combobox(self, width=12, textvariable=self.filterFormat, state='readonly')
  225. #-- V : Verbose (明细);
  226. #-- D : Debug (调试);
  227. #-- I : Info (信息);
  228. #-- W : Warn (警告);
  229. #-- E : Error (错误);
  230. #-- F : Fatal (严重错误);
  231. filterFormat['values'] = ('Verbose','Debug','Warn','Error','Fatal') # 设置下拉列表的值
  232. filterFormat.grid(column=1, row=5, stick=E) # 设置其在界面中出现的位置 column代表列 row 代表行
  233. filterFormat.current(1) # 设置下拉列表默认显示的值,1为 numberChosen['values'] 的下标值
  234. # Button(self, text='开始', width=12,command=self.switch).grid(row=6, stick=E, pady=10)
  235. self.B=Button(self, text='开始', width=12,command=self.switch)
  236. self.B.grid(row=6, stick=E, pady=10)
  237. # 开始与结束之间的切换
  238. def switch(self):
  239. print(self.B)
  240. if self.B['text'] == '开始':
  241. self.B['text'] = '结束'
  242. self.logCat()#调取抓取日志函数
  243. else:
  244. self.B['text'] = '开始'
  245. self.killPro()#结束抓取日志函数
  246. #def filterLog(self):
  247. def logCat(self):
  248. #packageName = self.packageName.get() # 包名
  249. #print('包名{}'.format(packageName))
  250. #过滤标签
  251. # filterTag=self.filterTag.get()
  252. # print('过滤标签:{}'.format(filterTag))
  253. # print('过滤字符串:{}'.format(self.filterStr.get()))
  254. #过滤字符串
  255. filterStr=self.filterStr.get()
  256. print('过滤字符串:{}'.format(filterStr))
  257. #正则过滤
  258. # filterRegular=self.filterRegular.get()
  259. # print('正则过滤:{}'.format(filterRegular))
  260. #日志级别
  261. # logLevel=self.logLevel.get()
  262. # print('日志级别:{}'.format(logLevel))
  263. #过滤格式项
  264. filterFormat=self.filterFormat.get()
  265. print('过滤格式项:{}'.format(filterFormat))
  266. #抓取日志
  267. #def logCat(self):
  268. nowtime = datetime.datetime.now().strftime('%Y%m%d%H%M%S')
  269. filename = nowtime + ".txt"
  270. logcat_file = open(filename, 'w')
  271. #logcmd = r'adb shell monkey -p {} -s {} -v -v -v --throttle {} --ignore-crashes --ignore-timeouts --ignore-security-exceptions --ignore-native-crashes --monitor-native-crashes {}'.format(
  272. # packageName, seedNum
  273. # p = subprocess.Popen('adb shell cd sdcard && cd Android && cd data && ps |grep monkey', stdout=subprocess.PIPE,stderr=subprocess.PIPE)
  274. if filterFormat!='' and filterStr!='':
  275. logcmd = r'adb shell cd sdcard && cd Android && cd data && logcat *:{} | grep {}'.format(filterFormat,filterStr)
  276. elif filterFormat!='' and filterStr=='':
  277. logcmd = r'adb shell cd sdcard && cd Android && cd data && logcat *:{}'.format(filterFormat)
  278. elif filterFormat=='' and filterStr !='':
  279. logcmd = r'adb shell cd sdcard && cd Android && cd data && logcat | grep {}'.format(filterStr)
  280. else:
  281. logcmd = 'adb logcat -v time'
  282. #logcmd = 'adb logcat -v time'
  283. self.pro = subprocess.Popen(logcmd, stdout=logcat_file, stderr=subprocess.PIPE)
  284. #结束进程
  285. def killPro(self):
  286. self.pro.kill() # .close()是关闭文件的 .kill()是杀掉进程
  287. #性能测试界面
  288. class AboutFrame(Frame): # 继承Frame类
  289. def __init__(self, master=None):
  290. Frame.__init__(self, master)
  291. self.root = master # 定义内部变量root
  292. self.createPage()
  293. def createPage(self):
  294. Button(self, text='内存监测', width=12, command=self.getMemory).grid(row=1, stick=E, pady=10, column=1)
  295. # Button(self, text='手机CPU监测', width=12, command=self.allCpu).grid(row=2, stick=E, pady=10, column=1)
  296. Button(self, text='当前应用CPU', width=12, command=self.myCpu).grid(row=2, stick=E, pady=10, column=1)
  297. Button(self, text='电量信息', width=12, command=self.charge).grid(row=3, stick=E, pady=10, column=1)
  298. Button(self, text='启动时间', width=12, command=self.startTime).grid(row=4, stick=E, pady=10, column=1)
  299. #电量信息
  300. def charge(self):
  301. print('电量信息')
  302. out = subprocess.getstatusoutput('adb shell dumpsys battery')
  303. top = tk.Toplevel()
  304. top.title('电量信息')
  305. top.geometry('%dx%d' % (600, 600)) # 设置窗口大小
  306. t = Text(top, width=600, height=600)
  307. t.insert('1.0', "{}".format(out[1]))
  308. t.pack()
  309. top.mainloop()
  310. #内存数据获取
  311. def getMemory(self):
  312. import re
  313. out = subprocess.getstatusoutput('adb shell dumpsys window | findstr mCurrentFocus ')
  314. str1 =out[1]
  315. pattern = re.compile(r'u0\s*(.+?)\/')
  316. res = re.findall(pattern, str1)
  317. self.package=res[0]#获取当前应用的包名
  318. nowtime = datetime.datetime.now().strftime('%Y%m%d%H%M%S')
  319. # filename = "startime"+nowtime+".txt"
  320. filename = "startime" + nowtime + ".xls"
  321. startime_file = open(filename, 'w')
  322. order = "adb shell dumpsys meminfo {}".format(self.package) # 获取内存的命令
  323. self.pro = subprocess.Popen(order, stdout=startime_file, stderr=subprocess.PIPE)
  324. #手机内当前前十位的应用cpu占用动态监测
  325. def allCpu(self):
  326. top = tk.Toplevel()
  327. top.title('内存监测')
  328. top.geometry('%dx%d' % (700, 1400)) # 设置窗口大小
  329. #Text文本框的定义和输出
  330. t = Text(top, width=700, height=100)
  331. t.pack(fill=tkinter.X, side=tkinter.BOTTOM)
  332. top.mainloop()
  333. # out = subprocess.getstatusoutput('adb shell&&top -m 10 -s cpu')
  334. logcmd='adb shell&&top -m 10 -s cpu'
  335. out=subprocess.Popen(logcmd,stderr=subprocess.PIPE)
  336. t.insert(tkinter.END,"{}".format(out[1]))
  337. t.see(tkinter.END)
  338. t.update()
  339. #当前应用占用CPU显示
  340. def myCpu(self):
  341. import re
  342. out = subprocess.getstatusoutput('adb shell dumpsys window | findstr mCurrentFocus ')
  343. str1 = out[1]
  344. pattern = re.compile(r'u0\s*(.+?)\/')
  345. res = re.findall(pattern, str1)
  346. self.packageName = res[0] # 获取当前应用的包名
  347. out = subprocess.getstatusoutput('adb shell dumpsys cpuinfo | find "{}"'.format(self.packageName))
  348. top = tk.Toplevel()
  349. top.title('当前应用')
  350. top.geometry('%dx%d' % (300, 100)) # 设置窗口大小
  351. t = Text(top, width=300, height=100)
  352. t.insert('1.0', "{}".format(out[1]))
  353. t.pack()
  354. top.mainloop()
  355. def startTime(self):
  356. pass
  357. #设置页面
  358. class SeetingFrame(Frame): # 继承Frame类
  359. def __init__(self, master=None):
  360. Frame.__init__(self, master)
  361. self.root = master # 定义内部变量root
  362. self.createPage()
  363. def createPage(self):
  364. Label(self, text='设置开发中').pack()
  365. #高级页面
  366. class SeniorFrame(Frame):
  367. def __init__(self, master=None):
  368. Frame.__init__(self, master)
  369. self.root = master # 定义内部变量root
  370. self.createPage()
  371. def createPage(self):
  372. # 查看手机上已经安装的所有的包名列表
  373. Label(self, text='当前应用包名: ').grid(row=1, stick=W, pady=10)
  374. Button(self, text='当前应用', width=12, command=self.currentPackage).grid(row=1, stick=E, pady=10, column=1)
  375. #查看手机上已经安装的所有的包名列表
  376. Label(self, text='包名列表: ').grid(row=2,stick=W, pady=10)
  377. Button(self, text='包名列表', width=12, command=self.listPackage).grid(row=2, stick=E, pady=10,column=1)
  378. # 查看当前手机屏幕分辨率
  379. Label(self, text='设备分辨率: ').grid(row=3, stick=W, pady=10)
  380. Button(self, text='分辨率', width=12, command=self.resolution).grid(row=3, stick=E, pady=10, column=1)
  381. #查看手机系统版本
  382. Label(self, text='当前手机版本: ').grid(row=4, stick=W, pady=10)
  383. Button(self, text='手机版本', width=12, command=self.systemversion).grid(row=4, stick=E, pady=10, column=1)
  384. Label(self, text='手机设备id: ').grid(row=5, stick=W, pady=10)
  385. Button(self, text='设备id', width=12, command=self.deviceid).grid(row=5, stick=E, pady=10, column=1)
  386. #当前应用的包名及activity
  387. def currentPackage(self):
  388. out =subprocess.getstatusoutput('adb shell dumpsys window | findstr mCurrentFocus ')
  389. top = tk.Toplevel()
  390. top.title('当前应用')
  391. top.geometry('%dx%d' % (700,100)) # 设置窗口大小
  392. t = Text(top, width=700, height=100)
  393. t.insert('1.0', "{}".format(out[1]))
  394. t.pack()
  395. top.mainloop()
  396. #所有的包名列表
  397. def listPackage(self):
  398. nowtime = datetime.datetime.now().strftime('%Y%m%d%H%M%S')
  399. filename = 'package'+nowtime + ".txt"
  400. logcat_file = open(filename, 'w')
  401. logcmd = 'adb shell pm list packages'
  402. self.pro = subprocess.Popen(logcmd, stdout=logcat_file, stderr=subprocess.PIPE)
  403. out = subprocess.getstatusoutput('adb shell pm list packages')
  404. top = tk.Toplevel()
  405. top.title('包名列表')
  406. top.geometry('%dx%d' % (400, 1200)) # 设置窗口大小
  407. t=Text(top,width=400,height=900)
  408. t.insert('1.0',"{}".format(out[1]))
  409. #插入文本,用引号引起来“1.0” 这个是插入文本的坐标,且1与0之间为点,而不是逗号,切记
  410. #wraplength: 指定多少单位后开始换行
  411. #justify: 指定多行的对齐方式
  412. #例子: Label(top, text='查看当前手机上所有包名: ',wraplength = 80,justify = 'left').grid(row=1,stick=W, pady=10)
  413. t.pack()
  414. top.mainloop()
  415. # 当前应用的包名及activity
  416. def resolution(self):
  417. out = subprocess.getstatusoutput('adb shell wm size')
  418. top = tk.Toplevel()
  419. top.title('分辨率')
  420. top.geometry('%dx%d' % (300, 100)) # 设置窗口大小
  421. t = Text(top, width=300, height=100)
  422. t.insert('1.0', "{}".format(out[1]))
  423. t.pack()
  424. top.mainloop()
  425. def systemversion(self):
  426. out = subprocess.getstatusoutput('adb shell getprop ro.build.version.release')
  427. top = tk.Toplevel()
  428. top.title('手机系统版本')
  429. top.geometry('%dx%d' % (300, 100)) # 设置窗口大小
  430. t = Text(top, width=300, height=100)
  431. t.insert('1.0', "{}".format(out[1]))
  432. t.pack()
  433. top.mainloop()
  434. def deviceid(self):
  435. out = subprocess.getstatusoutput('adb get-serialno')
  436. top = tk.Toplevel()
  437. top.title('手机设备id')
  438. top.geometry('%dx%d' % (600, 100)) # 设置窗口大小
  439. t = Text(top, width=600, height=100)
  440. t.insert('1.0', "{}".format(out[1]))
  441. t.pack()
  442. top.mainloop()
  443. #帮助页面
  444. class HelpFrame(Frame): # 继承Frame类
  445. def __init__(self, master=None):
  446. Frame.__init__(self, master)
  447. self.root = master # 定义内部变量root
  448. self.createPage()
  449. def createPage(self):
  450. a='''如有疑问,请联系...'''
  451. b='''Python2的处理方式为commands模块,但是Python3中废掉了commands模块,用subprocess代替'''
  452. c='''详情使用方法访问博客:'''
  453. d='''#https://blog.csdn.net/qq_39208536/article/details/80894752'''
  454. Label(self, text=a).grid(row=1, stick=W, pady=10)
  455. # Label(self, text=b).grid(row=2, stick=W, pady=10)
  456. # Label(self, text=c).grid(row=3, stick=W, pady=10)
  457. # Label(self, text=d).grid(row=4, stick=W, pady=10)

最后是main.py

  1. from tkinter import *
  2. from HomePage1 import *
  3. # from icon import img
  4. # import base64
  5. root = Tk()
  6. root.title('安卓助手')
  7. HomePage1(root)
  8. root.mainloop()

具体细节就不讲了,很简单。大家一定都会的

最后十分感谢张兴老师的努力。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Gausst松鼠会/article/detail/213663
推荐阅读
相关标签
  

闽ICP备14008679号