You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android实时流量吞吐量精准采集:替代TrafficStats的方案咨询

解决Android流量统计精度问题的方案

你遇到的TrafficStats统计值比iPerf3高10%的核心原因是:TrafficStats.getMobileRxBytes()统计的是整个设备的移动网络总接收流量,包含系统后台服务、其他应用的流量,而iPerf3仅统计自身测试产生的流量,两者统计范围不同导致误差。以下是几种更精准的流量统计方法:

1. 统计当前应用的专属流量

使用TrafficStats.getUidRxBytes()获取当前应用UID对应的接收流量,只统计本应用产生的流量,直接排除其他应用的干扰,这是最简便的优化方案:

修改你的代码如下:

public void writeDownloadThroughput() {
    if (!isOpen) {
        Log.e("InfluxDBManager", "InfluxDB client is not initialized. Please set credentials first.");
        return;
    }

    executorService.execute(() -> {
        // 获取当前应用的UID
        int appUid = getApplicationInfo().uid;
        long initialBytesReceived = TrafficStats.getUidRxBytes(appUid);

        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        long finalBytesReceived = TrafficStats.getUidRxBytes(appUid);
        long bytesReceivedIn500ms = finalBytesReceived - initialBytesReceived;

        if (bytesReceivedIn500ms <= 0) {
            Log.d("InfluxDBManager", "No download throughput detected.");
            return;
        }

        long throughputInBytesPerSecond = bytesReceivedIn500ms * 2;  

        Log.d("InfluxDBManager", "Download Throughput: " + throughputInBytesPerSecond + " bytes/second");

        Point point = Point.measurement("network_throughput")
                .addTag("device", Build.MODEL)
                .addField("download_throughput", throughputInBytesPerSecond) 
                .time(Instant.now(), WritePrecision.MS);

        try {
            writeApi.writePoint(point);  
        } catch (Exception e) {
            Log.e("InfluxDBManager", "Error writing to InfluxDB", e);
        }
    });
}

注意:如果你的应用有多个进程,需要获取对应进程的UID来统计,避免遗漏。

2. 读取系统底层的/proc/net/dev文件

/proc/net/dev是Linux系统提供的网络设备统计文件,记录了每个网络接口的收发字节数,精度更高。你可以解析该文件获取指定接口(如移动数据常用rmnet0,WiFi常用wlan0)的流量数据:

示例代码:

private long getInterfaceRxBytes(String interfaceName) {
    try (BufferedReader reader = new BufferedReader(new FileReader("/proc/net/dev"))) {
        String line;
        // 跳过前两行表头
        reader.readLine();
        reader.readLine();
        while ((line = reader.readLine()) != null) {
            line = line.trim();
            if (line.startsWith(interfaceName + ":")) {
                String[] parts = line.split("\\s+");
                // 第二个字段是接收的总字节数
                return Long.parseLong(parts[1]);
            }
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
    return 0;
}

// 在你的统计逻辑中使用
long initialBytes = getInterfaceRxBytes("rmnet0");
Thread.sleep(500);
long finalBytes = getInterfaceRxBytes("rmnet0");
long delta = finalBytes - initialBytes;

注意:不同设备的移动数据接口名称可能不同(如rmnet1、rmnet_data0),可以通过遍历接口列表动态匹配。

3. 采样校准与平滑处理

如果仍存在小范围误差,可以通过多次采样取平均值,或者对异常值(如突增的流量)进行过滤,减少瞬时波动的影响:

  • 连续采集3-5次500ms窗口的流量,取平均值作为最终结果
  • 忽略单次采样中超过阈值的异常值(比如远高于正常吞吐量的数值)

内容的提问来源于stack exchange,提问作者iThomas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 00:17:07