有个用户说一夜间跑了几百兆的移动流量,流量是哪里产生的?是不是哪里有代码缺陷?怎样定位到问题? 于是想着把流量划分模块的统计下来,以便优化App的整体健康;
如果仅统计应用总流量,
现在我们需要分析流量的成分,一直没有发现比较好的方法。TrafficStats类的方法setThreadStatsTag(int)可以标记线程,那么这个标记什么时候使用呢?Android monitor里面获取的流量数据是包含有tag的,系统肯定将tag信息存储在了某个地方。后来发现Android系统将放流量数据信息保存在文件/proc/net/xt_qtaguid/stats 中(见源码),于是我们可以通过下面的方式,分析流量来源!
模块划分
首先要对应用进行模块划分,模块值Tag区间[0,0xFFFFFF00)。使用位表示模块与子模块之间的关系,例如0xGGPPCC00,GG一级模块、PP一级模块下的子模块,类推;千牛是按照API接口划分的,当然也可以按照业务场景划分模块;
标记流量源
使用TrafficStats.setThreadTag(int tag)方法标记的产生流量的线程,参数tag是上面模块相关的tag;@See TrafficStats;
NOTE:1、一个线程同时只会有一个有效的tag,并且不会传递,依赖包启动了新线程访问网络则需要依赖方提供标记支持;2、
native层socket、webview产生的流量无法使用此方法标记;
标记流量后,可以在monitor网络界面查看流量变化,不同的tag会绘制为不同的颜色,可以先在本地分析下,使用的时候网络请求是否有冗余;
获取统计值
通过adb命令可以查看流量内容 adb shell cat /proc/net/xt_qtaguid/stats :
iface:网络性质[vlan-wifi流量 lo-本地流量rmnet0-3g/2g流量 ...]
acct_tag_hex: 线程标记,也就是上面我们做的标记
uid_tag_int: 应用UID,据此判断是否是某应用统计的流量数据
cnt_set: 应用前后台标志位:1-前台,0-后台
rx_bytes: read 总接受字节
tx_bytes: transfer总发送字节
其中acct_tag_hex 为0x0的一行为某应用开机以来产生的总流量;
搞明白字段意思了解析起来也就比较容易了,直接贴代码
NOTE:这里统计的流量是开机之后所有的流量统计
try {
FileReader stream = new FileReader(DEV_FILE);
BufferedReader in = new BufferedReader(stream, 500);
String line;
String[] dataStrings;
while ((line = in.readLine()) != null) {
dataStrings = line.split(" ");
if (StringUtils.equals(uid, dataStrings[3])) {
TrafficData dataTotal = new TrafficData();
TrafficData dataDiff = new TrafficData();
dataTotal.iface = dataDiff.iface = dataStrings[1];
dataTotal.moduleTag = dataDiff.moduleTag = dataStrings[2];
dataTotal.cnt_set = dataDiff.cnt_set = dataStrings[4];
dataTotal.rx_bytes = Integer.parseInt(dataStrings[5]);
dataTotal.tx_bytes = Integer.parseInt(dataStrings[6]);
//全量
if (dataTotal.rx_bytes + dataTotal.tx_bytes > 0) {
trafficDataList.add(dataTotal);
//需要根据存储值计算增量
}
}
}
FileStoreProxy.setListValue(trafficDataList);
in.close();
stream.close();
} catch (Exception e) {
}