安卓性能监控工具介绍(二)----工具介绍

前言

上一篇文章介绍了工具的数据采集部分,这段时间对工具页面进行了优化:

  • 增加清屏功能
  • 增加图表显示

新版本V1.1.0界面如下所示:


主界面.png

工具介绍

使用方法介绍

使用方法上一篇文章,已经大致介绍过了,主要步骤如下:
(电脑环境配置什么的就不在赘述了)

  • 连接手机,点击检查设备,正常获取返回设备SN号,获取失败,显示‘No device found’
  • 打开待测应用,点击获取,获取应用包名和activity
  • 下拉选择更新时间
  • 开始测试,结束
  • 点击图表,显示图表(这边暂时未做到实时显示图表,后续再优化)

主界面介绍

基于QT Designer工具,添加需要的pushbutton、textedit等控件,这个上一篇文章已经介绍过了,QT Designer的简单使用,就不再多说了。
这篇文章就重点说一下核心代码部分和遇到的问题及解决方法吧。
过程中主要遇到了两个问题:
1.数据采集过程中,需要在保留原有数据的基础上,不断添加新数据
2.图表的展示

流量的统计

数据采集部分,主要代码如下:
采用

adb shell cat /proc/net/xt_qtaguid/stats | findstr uid

命令获取到的流量是一个total值,而我们需要统计的是一段时间内的值,所以这边采用两个值相减的方法,即根据选择的更新时间,后一个减去前一个的结果,得到这段时间内的统计值

#获取流量
receive = []
sendflow = []
all = []
def flow():
    cmd = 'adb -s '+ get_devices() +' shell cat /proc/net/xt_qtaguid/stats | findstr '+ uid()
    print (cmd)
    flow_info = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).stdout.readlines()
    down = 0
    up = 0
    if len(flow_info)>= 1:
        for flow in flow_info:
            down =down + int(flow.split()[5])
            up = up+ int(flow.split()[7])
        receive.append(down)
        sendflow.append(up)
    print (receive,sendflow)
    return (receive,sendflow)

def getflow():
    (receive,sendflow) = flow()
    recev = []
    send = []
    allflow = []
    print(len(receive))
    for i in range(len(receive)-1):
        recev.append((int(receive[i+1]) - int(receive[i]))//1024)
        send.append((int(sendflow[i+1]) - int(sendflow[i]))//1024)
        allflow.append(recev[i]+send[i])
    print(recev,send,allflow)
    return recev,send,allflow

其他的相对简单,直接把获取到的值,最后一个append到textedit中即可以了

QTimer的使用

加入QTimer主要是为了解决,在写数据的过程中,不断往原有数据上append新采集到数据的问题,同时不至于是应用无响应。

初始化一个定时器,把定时器的timeout信号和slotadd()槽函数连接。

        self.timer = QTimer(self)
        self.timer.timeout.connect(self.slotadd)

slotadd()往五个textedit中写数据
由于返回的数据是一个列表,所以每次只需要取最新的即最后一个数据即可。

    def slotadd(self):
        '''
        往mem、cpu、flow写数据
        :return:
        '''
        memlist = adb.mem()
        mem = 'mem占用:'+ str(memlist[-1])
        cpulist = adb.cpu()
        cpu = 'cpu占用:'+ str(cpulist[-1])
        self.ui.mem.append(mem)
        self.ui.cpu.append(cpu)
        (recevice,send,allflow)=adb.getflow()
        receflow = '下载流量:' + str(int(recevice[-1]))
        sendflow = '上传流量:' + str(int(send[-1]))
        alladd = '总流量:' + str(int(allflow[-1]))
        self.ui.recv.append(receflow)
        self.ui.send.append(sendflow)
        self.ui.all.append(alladd)

点击开始按钮,启动定时器,并使开始按钮失效


    def startTimer(self):
        '''
        设置时间间隔并启动定时器
        :return:
        '''
        self.timer.start(self.wait_time())
        self.ui.start.setEnabled(False)
        self.ui.end.setEnabled(True)

点击结束按钮,停止定时器,并使开始按钮生效。

    def endTimer(self):
        self.timer.stop()
        self.ui.start.setEnabled(True)

Matplotlib的应用

Matplotlib是python常用的绘图模块,提供了一套与MATLAB 相似的命令API,用来交互式的绘图,非常方便。

设置绘图类

新增一个MatplotlibWidget.py文件,创建FigureCanvas类,在初始化过程中建立一个空白图像。

class MyMplCanvas(FigureCanvas):
    """FigureCanvas的最终的父类其实是QWidget。"""

    def __init__(self, parent=None, width=5, height=4, dpi=100):

        # 配置中文显示
        plt.rcParams['font.family'] = ['SimHei']  # 用来正常显示中文标签
        plt.rcParams['axes.unicode_minus'] = False  # 用来正常显示负号

        self.fig = plt.figure(figsize=(width, height), dpi=dpi)  # 新建一个figure

        self.axes = self.fig.add_subplot(111)  # 建立一个子图,如果要建立复合图,可以在这里修改

        self.axes.hold(False)  # 每次绘图的时候不保留上一次绘图的结果
        FigureCanvas.__init__(self, self.fig)
        self.setParent(parent)

        '''定义FigureCanvas的尺寸策略,这部分的意思是设置FigureCanvas,使之尽可能的向外填充空间。'''
        FigureCanvas.setSizePolicy(self,
                                   QSizePolicy.Expanding,
                                   QSizePolicy.Expanding)
        FigureCanvas.updateGeometry(self)

定义绘图函数,调用这个函数可以在上面所创建的空白图像中绘图。

    def start_static_plot(self):

        self.fig.suptitle('图表')
        a=[1,2,4,2,3,1,2,3,4,2]
        self.axes.plot(a)
        self.axes.set_ylabel('number')
        self.axes.grid(True)
封装绘图类

这部分主要把上面的绘图类和工具栏封装到MatplotlibWidget中,只需要调用MatplotlibWidget这个类就可以实现绘图功能;

class MatplotlibWidget(QWidget):
    def __init__(self, parent=None):
        super(MatplotlibWidget, self).__init__(parent)
        self.initUi()

    def initUi(self):
        self.layout = QVBoxLayout(self)
        self.mpl = MyMplCanvas(self, width=5, height=4, dpi=100)
        self.mpl.start_static_plot() 
        self.mpl_ntb = NavigationToolbar(self.mpl, self)  # 添加完整的 toolbar

        self.layout.addWidget(self.mpl)
        self.layout.addWidget(self.mpl_ntb)

测试程序:


if __name__ == '__main__':
    app = QApplication(sys.argv)
    ui = MatplotlibWidget()
    ui.mpl.start_static_plot()  # 测试静态图效果
    ui.show()
    sys.exit(app.exec_())

结果运行,如图所示:


图表.png

设置提升窗口控件

在QT Designer中右击提升窗口部件,新建一个QWidget类,名称和头文件均为 MatplotlibWidget


升级.png

在.ui文件中加入widget并升级


升级widget.png

MatplotlibWidget的使用

首先初始化模型:

class Main(QMainWindow,Ui_Form):

    def __init__(self,parent=None):
        super(Main,self).__init__(parent)
        self.ui = Ui_Form()
        self.ui.setupUi(self)
        self.setWindowTitle('Waiqin365-AATT-V1.1.0')
        self.ui.mem_plot.setVisible(False)

初始化中隐藏图像,设置按钮的出发操作,同时使得图像可见并出发绘图函数

    @pyqtSlot()
    def on_pushButton_clicked(self):
        self.ui.mem_plot.setVisible(True)
        self.ui.mem_plot.mpl.start_static_plot()

测试程序:

if __name__ == "__main__":
    import sys

    app = QApplication(sys.argv)
    ui = Main()
    ui.show()
    sys.exit(app.exec_())

运行结果如下所示:


页面.png

思考

虽然工具优化到V1.1.0版本,但是仍存在很多不足的情况,目前遇到的问题:
1.打包成exe文件后,无法使用
2.缺少对手机状态的监控,断开连接后,没有自动停止
3.还不能动态展示图表
后面有时间将一一攻破这些难题,欢迎有ideal的小伙伴多提提意见

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,117评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,963评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 107,897评论 0 240
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,805评论 0 203
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,208评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,535评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,797评论 2 311
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,493评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,215评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,477评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,988评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,325评论 2 252
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,971评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,055评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,807评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,544评论 2 271
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,455评论 2 266

推荐阅读更多精彩内容