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

Xamarin Android应用网络流量监控开发问题求助

解决Xamarin Android中TrafficStats监控特定应用流量的问题

问题分析

当前遇到两个编译错误:

  1. using Android.Net.TrafficStats;报错CS0138:TrafficStats是类而非命名空间,不能用普通using导入
  2. TrafficType.Mobile报错CS0103:当前上下文不存在TrafficType类型,Xamarin Android的TrafficStats方法无此重载

错误修正方案

1. 修正命名空间导入错误

将using Android.Net.TrafficStats;替换为静态导入,可直接调用TrafficStats的静态方法:

using static Android.Net.TrafficStats;

或者保留using Android.Net;,调用时使用完整类名Android.Net.TrafficStats.GetUidRxBytes(...)

2. 修正TrafficType不存在的问题

Xamarin Android的TrafficStats.GetUidRxBytes仅接受UID参数,无法直接指定网络类型(移动/Wi-Fi)。若需区分网络类型,需额外通过ConnectivityManager判断当前网络类型,再结合流量数据计算。

另外,获取应用UID需处理异常(应用未安装的情况),且Android 11及以上需添加查询特定应用的权限:

  • 在AndroidManifest.xml中添加:
<queries>
  <package android:name="com.spotify.android" />
  <package android:name="com.google.android.apps.maps" />
</queries>
  • 获取UID的代码需包裹在try-catch块中:
int spotifyUid = -1;
try
{
    spotifyUid = PackageManager.GetPackageUid("com.spotify.android", PackageInfoFlags.MatchAll);
}
catch (PackageManager.NameNotFoundException)
{
    // 处理应用未安装的情况
}

补充必要权限

除现有权限外,还需添加:

<!-- Android 10及以下访问外部存储 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="29" />
<!-- Android 11+访问外部存储(若使用传统文件路径) -->
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
<!-- 查询应用信息权限 -->
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" android:maxSdkVersion="30" />

针对Android 10,可在Application标签添加:

android:requestLegacyExternalStorage="true"

修正后的完整代码

using Android.Content.PM;
using Android.Net;
using static Android.Net.TrafficStats;
using System;
using System.IO;
using System.Threading;

// 获取PackageManager实例(需在Activity或Service中调用,若在其他类需传入上下文)
PackageManager packageManager = Application.Context.PackageManager;

// 获取Spotify应用的UID
int spotifyUid = -1;
try
{
    spotifyUid = packageManager.GetPackageUid("com.spotify.android", PackageInfoFlags.MatchAll);
}
catch (PackageManager.NameNotFoundException)
{
    Console.WriteLine("Spotify未安装");
    return;
}

// 初始化上一次的流量数据
long previousRxBytes = GetUidRxBytes(spotifyUid);
long previousTxBytes = GetUidTxBytes(spotifyUid);

// 指定CSV文件路径(Android 10+建议使用MediaStore,此处为兼容示例)
string csvFilePath = Path.Combine(Android.OS.Environment.GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryDocuments).AbsolutePath, "SpotifyTraffic.csv");

// 创建CSV文件并写入表头(仅当文件不存在时)
if (!File.Exists(csvFilePath))
{
    File.WriteAllText(csvFilePath, "Timestamp,Download (MB),Upload (MB),Download Speed (MB/s),Upload Speed (MB/s)\n");
}

// 周期性监控并记录网络流量
while (true)
{
    if (spotifyUid == -1) break;

    long currentRxBytes = GetUidRxBytes(spotifyUid);
    long currentTxBytes = GetUidTxBytes(spotifyUid);
    DateTime timestamp = DateTime.Now;

    // 计算本次间隔的流量变化量
    long rxDelta = currentRxBytes - previousRxBytes;
    long txDelta = currentTxBytes - previousTxBytes;

    // 转换为MB
    double downloadMB = rxDelta / (1024.0 * 1024.0);
    double uploadMB = txDelta / (1024.0 * 1024.0);

    // 计算速度(间隔1秒)
    double downloadSpeedMBps = downloadMB / 1;
    double uploadSpeedMBps = uploadMB / 1;

    // 将数据追加至CSV文件
    File.AppendAllText(csvFilePath, $"{timestamp:yyyy-MM-dd HH:mm:ss},{downloadMB:F2},{uploadMB:F2},{downloadSpeedMBps:F2},{uploadSpeedMBps:F2}\n");

    // 等待1秒
    Thread.Sleep(1000);

    // 更新上一次的流量数据
    previousRxBytes = currentRxBytes;
    previousTxBytes = currentTxBytes;
}

注意事项

  1. 线程问题:避免在主线程中执行Thread.Sleep,建议使用Handler或Task.Delay替代,防止UI卡顿
  2. 权限申请:动态申请WRITE_EXTERNAL_STORAGE或MANAGE_EXTERNAL_STORAGE权限,Android 11+需引导用户手动开启MANAGE_EXTERNAL_STORAGE权限
  3. 网络类型区分:若需区分移动和Wi-Fi流量,可通过ConnectivityManager获取当前网络类型,分别记录不同网络下的流量数据
  4. 应用未安装处理:必须捕获NameNotFoundException,避免崩溃

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 14:13:18