导语:在Android性能测试中,我们经常要对某个android应用进行流量监控测试,从而得出这个应用流量消耗情况。同时,我们也会时常收到用户抱怨,说手机管家流量监控不准 确,甚至有些手机的浮动窗口数值不会变化一直保持为0,但是当我们向开发人员反馈时他们会抱怨说是机型导致这个问题。那么android系统中的流量究竟是如何统计的呢?是不是真和机型相关?下面就让我们来看看android系统的流量统计数据是如何获取的。
(1)使用wireshark进行抓包:
Wireshark(前称Ethereal)是一个网络封包分析软件。网络封包分析软件的功能是撷取网络封包,并尽可能显示出最为详细的网络封包资料。目前,wireshark主要测试活动有K吧里面提到的手机QQ性能测试和管家流量监控准确性测试。虽然wireshark可以准确统计流量数据,但是如果数据量比较大时就难准确分析,同时据我所知wireshark无法通过命令行来获取某些数据包的流量统计(如果哪位同仁知道怎么处理希望能告诉我J)
(2)通过已有的工具,比如手机管家、360手机卫士或其他统计工具
使用现场工具是最为简便的方法,但并不是每个工具都可以做到100%的准确,比如手机管家是在有浮动窗口情况下3秒刷新一次,通知栏的流量统计是30秒刷新一次。
(1)读取linux本地文件
Android是基于linux的一个操作系统。在Android中,如果用Root Explorer去查看系统文件,与流量监控相关的会有这么几个文件:
① 系统总流量:/proc/net/dev,这个文件中记录的是整个系统的流量情况。
② 单个进程流量:/proc/uid_stat/%d" 和"/proc/uid_stat/%d" %d为进程的UID。这个文件里只有两项数据tcp_rcv和tcp_snd。从命名我们就能看出:tcp_rcv代表总的接收字节数,tcp_snd代表总的发送字节数。
但是,上面的两个流量统计数据都是开机之后累计的数据,也就是说重启手机之后相应的流量数据会自动清零。
对于系统总流量数据,有如下输出格式如图1所示:
图1 Android系统总流量数据
但上图是在WIFI开启的情况下,只有GPRS开启时显示如下图2所示:
图2 在GPRS开启时Android系统中总流量数据
相信大家看了上面的日志会得出eth0是WIFI网络使用的接口,而rmnet0是GPRS使用的接口。但这就是问题所在了,不是所有机器都是用eth0来表示WIFI接口,同样也不是所有rmnet0来表示GPRS, 这些字段的表示都与ROM相关,甚至有些ROM连/proc/net/dev这个文件都没有!如果我们使用的流量监控工具或者程序只适配了这种情况,那么在别的机器上就有可能获取不到流量数据了,从而就有可能导致用户反馈的手机流量数据一直为0的这种情况。
既然不同的ROM可能有不同的字段,那么有没有比较好的办法来做适配呢?据我了解暂时没有,目前比较好的办法是将能收集到的流量字段做成配置文件,然后在读取时去一一匹配,比如配置文件的格式可以如下:
(2)利用系统现有函数
在Android 2.1及以下版本是没有专门的流量统计系统函数,随后在2.2版及后续版本都加入了TrafficStats类,这样就可以轻松获取系统总流量或者单个进程的流量数据。其实,TrafficStats类本身也是读取Linux提供的文件对象系统类型的文本进行解析,其中有的方法也是读取别的文件。TrafficStats类中,提供了多种静态方法,比如getMobileRxByte()可以直接调用获取通过Mobile连接收到的字节总数,getUidRxBytes()返回的是某个进程流量数据,这两个函数返回值均为long型,如果返回等于-1代表 UNSUPPORTED 当前设备不支持统计。
但是需要注意的是,在没有wifi的情况下,各进程获得的getUidRxBytes之和与getMobileRxBytes所返回的值不相等,原因在于getUidRxBytes是读取上文提到的文件,而getMobileRxBytes读取的是sys/class/net/rmnet0/statistics/rx_bytes 和sys/class/net/ppp0/statistics/rx_bytes 这两文件。而且在getUidRxBytes返回的值中包含了本地通信的流量,比如本地进程间的socket通信。所以这两个值加起来有所出入,这也是我们在测试流量统计时偶尔也会遇到的问题,那就是在飞行模式下应用程序也会提示有几十B的2G/3G流量消耗。经过测试,这本地通信的流量值很小,只有几KB甚至几十B.