Android应用流量统计——NetworkStatsManager使用

2023-05-16

在没有Root的情况下,Android应用流量统计在6.0之前一直没有太好的办法,官方虽然提供了TrafficStats,但其主要功能是设备启动以来流量的统计信息,和时间信息无法很好的配合。最近再看TrafficStats类时,发现说明中提到,为获取更具鲁棒性的网络历史数据,建议使用NetworkStatsManager。

本文首先简单对比下TrafficStats和NetworkStatsManager各自的限制和优缺点,然后详细说明NetworkStatsManager的用法,并给出主要代码。

TrafficStats

Android API8提供了android.net.TrafficStats类。
通过此类能获取设备重启以来网络信息,部分函数如下所示:

static long  getMobileRxBytes()  //获取通过移动数据网络收到的字节总数
static long  getMobileTxBytes()  //通过移动数据网发送的总字节数  
static long  getTotalRxBytes()  //获取设备总的接收字节数 
static long  getTotalTxBytes()  //获取设备总的发送字节数
static long  getUidRxBytes(int uid)  //获取指定uid的接收字节数  
static long  getUidTxBytes(int uid) //获取指定uid的发送字节数 

通过文档及上述函数可以知道,TrafficStats能够获取设备的数据流量和总的网络流量消耗(一般情况下也就得到Wi-Fi下的流量信息);可以查询uid对应的流量信息,而uid可以通过应用的包名查询到,因此能够查询某个应用的流量统计信息(不考虑shareuid)。非常方便的是,它的使用不需要特别的权限。另一方面它也一些限制:
(1)无法获取应用的数据流量消耗
从文档中仅能获取到指定uid的流量,但无法区分不同网络类型下的消耗
间接方法是通过监听网络切换,做好流量记录(但是要保证你的应用一直存活,且一定准确接收到网络切换信息),基本不可用。
(2)无法获取某个时间段内的流量消耗
从API文档中看,函数参数没有与时间相关的信息。而且重要的一点是,TrafficStats类中记录的是设备重启以来的流量统计信息。因为TrafficStats 类,底层还是读取/proc/net/xt_qtaguid/stats 对内容进行解析,将得到对应的结果返回上层。

NetworkStatsManager

在Android 6.0(API23)中新增加的类,提供网络使用历史统计信息,同时特别强调了可查询指定时间间隔内的统计信息。看看部分函数(非静态):

//查询指定网络类型在某时间间隔内的总的流量统计信息
NetworkStats.Bucket querySummaryForDevice(int networkType, String subscriberId, long startTime, long endTime)

 //查询某uid在指定网络类型和时间间隔内的流量统计信息
NetworkStats queryDetailsForUid(int networkType, String subscriberId, long startTime, long endTime, int uid)  

//查询指定网络类型在某时间间隔内的详细的流量统计信息(包括每个uid)
NetworkStats queryDetails(int networkType, String subscriberId, long startTime, long endTime) 

从上述函数和文档看,NetworkStatsManager类克服了TrafficStats的查询限制,而且统计信息也不再是设备重启以来的数据。但它也有自己的限制和缺点。
(1)权限限制
NetworkStatsManager的使用需要额外的权限,”android.permission.PACKAGE_USAGE_STATS”是系统权限,需要主动引导用户开启应用的“有权查看使用情况的应用”(使用记录访问权限)权限,后面会有代码示例。
(2)文档不完善
不好说是文档不全,还是我没找对。首先文档中没有给出类的实例对象的构造方法,一开始还是反射获取的,后来才发现可以通过获取系统服务方式得到。另外queryDetailsForUid函数中设置的时间间隔不太有用,没能及时的获取流量统计信息,而是有两个小时的时间间隔。还好可以在querySummary函数中获得。

代码示例

下面说说具体的使用和代码,使用前必须明确的是这里的统计信息都是在网络层以上的数据。
1.权限设置
(1)AndroidManifest中添加权限声明

<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.PACKAGE_USAGE_STATS" tools:ignore="ProtectedPermissions"/>

(2)代码中主动引导用户开启权限
这里没有说明READ_PHONE_STATE的主动获取,大家根据自己的targetSdkVersion设置

    private boolean hasPermissionToReadNetworkStats() {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
            return true;
        }
        final AppOpsManager appOps = (AppOpsManager) getSystemService(Context.APP_OPS_SERVICE);
        int mode = appOps.checkOpNoThrow(AppOpsManager.OPSTR_GET_USAGE_STATS,
                android.os.Process.myUid(), getPackageName());
        if (mode == AppOpsManager.MODE_ALLOWED) {
            return true;
        }

        requestReadNetworkStats();
        return false;
    }
    // 打开“有权查看使用情况的应用”页面
    private void requestReadNetworkStats() {
        Intent intent = new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS);
        startActivity(intent);
    }

2.查看设备和某应用的流量统计
(1)获取NetworkStatsManager示例对象

NetworkStatsManager networkStatsManager = (NetworkStatsManager) getSystemService(NETWORK_STATS_SERVICE);

(2)查询设备总的流量统计信息

NetworkStats.Bucket bucket = null;
// 获取到目前为止设备的Wi-Fi流量统计
bucket = networkStatsManager.querySummaryForDevice(ConnectivityManager.TYPE_WIFI, "", 0, System.currentTimeMillis());
Log.i("Info", "Total: " + (bucket.getRxBytes() + bucket.getTxBytes()));

(3)查询某应用(uid)的数据流量统计信息

// 获取subscriberId
TelephonyManager tm = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
String subId = tm.getSubscriberId();

NetworkStats summaryStats;
long summaryRx = 0;
long summaryTx = 0;
NetworkStats.Bucket summaryBucket = new NetworkStats.Bucket();
long summaryTotal = 0;

summaryStats = networkStatsManager.querySummary(ConnectivityManager.TYPE_MOBILE, subId, getTimesMonthmorning(), System.currentTimeMillis());
do {
    summaryStats.getNextBucket(summaryBucket);
    int summaryUid = summaryBucket.getUid();
    if (uid == summaryUid) {
        summaryRx += summaryBucket.getRxBytes();
        summaryTx += summaryBucket.getTxBytes();
    }
    Log.i(MainActivity.class.getSimpleName(), "uid:" + summaryBucket.getUid() + " rx:" + summaryBucket.getRxBytes() +
" tx:" + summaryBucket.getTxBytes());
    summaryTotal += summaryBucket.getRxBytes() + summaryBucket.getTxBytes();
} while (summaryStats.hasNextBucket());

3.附赠实用函数
(1)应用包名查uid

public static int getUidByPackageName(Context context, String packageName) {
    int uid = -1;
    PackageManager packageManager = context.getPackageManager();
    try {
        PackageInfo packageInfo = packageManager.getPackageInfo(packageName, PackageManager.GET_META_DATA);

        uid = packageInfo.applicationInfo.uid;
        Log.i(MainActivity.class.getSimpleName(), packageInfo.packageName + " uid:" + uid);


    } catch (PackageManager.NameNotFoundException e) {
    }

    return uid;
}

(2)获得本月第一天0点时间

public static long getTimesMonthMorning() {
        Calendar cal = Calendar.getInstance();
        cal.set(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH), cal.get(Calendar.DAY_OF_MONTH), 0, 0, 0);
        cal.set(Calendar.DAY_OF_MONTH, cal.getActualMinimum(Calendar.DAY_OF_MONTH));
        return cal.getTimeInMillis();
    }

4.提示无权限信息

15:39:06.531 5276-5276/cn.arainfo.test.android.testapp1 E/AndroidRuntime: FATAL EXCEPTION: main
Process: cn.arainfo.test.android.testapp1, PID: 5276
java.lang.SecurityException: Network stats history of uid 10145 is forbidden for caller 10144
    at android.os.Parcel.readException(Parcel.java:1665)
    at android.os.Parcel.readException(Parcel.java:1618)
    at android.net.INetworkStatsSession$Stub$Proxy.getHistoryIntervalForUid(INetworkStatsSession.java:425)
    at android.app.usage.NetworkStats.startHistoryEnumeration(NetworkStats.java:433)
    at android.app.usage.NetworkStatsManager.queryDetailsForUidTag(NetworkStatsManager.java:254)
    at android.app.usage.NetworkStatsManager.queryDetailsForUid(NetworkStatsManager.java:219)

统计测试

(1)测试设备
小米5S Plus Android 6.0 和 华为Mate9 Android 7.0设备上实际测试
(2)流量差距
实际测试流量有30M左右,和运营商流量统计相差2M左右

转载请注明出处:http://blog.csdn.net/w7849516230,欢迎关注微信公众号“编程阳光”
“编程阳光”微信公众号

参考链接:
1.android.net.TrafficStats
2.android.app.usage.NetworkStatsManager
3.stack overflow里的两个问题
http://stackoverflow.com/questions/38783836/how-to-fetch-data-usage-report-for-all-uids-using-the-new-networkstatsmanager-c

http://stackoverflow.com/questions/36702621/getting-mobile-data-usage-history-using-networkstatsmanager

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Android应用流量统计——NetworkStatsManager使用 的相关文章

随机推荐

  • 部署Vista – 第15部分:实施Windows部署服务

    原创作品 xff0c 允许转载 xff0c 转载时请务必以超链接形式标明文章 原始出处 作者信息和本声明 否则将追究法律责任 http iwantfly blog 51cto com 1048259 239540 上篇文章介绍了Window
  • 部署Vista – 第16部分:配置Windows部署服务

    原创作品 xff0c 允许转载 xff0c 转载时请务必以超链接形式标明文章 原始出处 作者信息和本声明 否则将追究法律责任 http iwantfly blog 51cto com 1048259 239994 介绍Windows部署服务
  • 部署Vista – 第17部分:Windows DS映像存储

    原创作品 xff0c 允许转载 xff0c 转载时请务必以超链接形式标明文章 原始出处 作者信息和本声明 否则将追究法律责任 http iwantfly blog 51cto com 1048259 240347 介绍Windows部署服务
  • 部署Vista – 第19部分:管理Windows部署服务(续)

    原创作品 xff0c 允许转载 xff0c 转载时请务必以超链接形式标明文章 原始出处 作者信息和本声明 否则将追究法律责任 http iwantfly blog 51cto com 1048259 241462 继续介绍如何管理和配置运行
  • Windows Server 2003 Service Pack 2 安装和部署指南

    本指南适用于安装带有 Service Pack 2 SP2 的 Microsoft Windows Server 2003 操作系统的系统管理员 其中包含在小型企业或公司环境中的多台计算机上安装 SP2 的技术信息 操作步骤和建议 尽管本指
  • 如何远程安装Linux

    https www ibm com developerworks cn linux l tip prompt l pex http www ibm com developerworks cn linux es linux pservers
  • 利用windows 2003实现从网络安装系统

    利用windows 2003 实现从网络安装系统 xff0c 下面以远程安装windows 2003为例 Windows Server 2003支持多种操作系统的部署方法 xff0c 远程安装 xff08 RIS xff09 就是其中之一
  • 基于linux+pxe+dhcp+tftp+samba+ris网络安装windows server 2003

    一 xff0e 原理简介 RIS 远程安装服务 Remote Installation Services 是windows server的可选服务 xff0c 利用RIS可以让管理员很方便地为客户端部署操作系统 二 xff0e 环境说明 s
  • PXE+Centos5+Unattended4.7自动化安装Windows 2003

    这几天在折腾如何自动化安装windows 2003操作系统 xff0c 想象的结果应该是这样的 xff1a 机器一开机就通过PXE引导 xff0c 到dhcp服务器获得IP xff0c 然后到tftp服务器获得启动镜象 xff0c 镜象启动
  • Microsoft Windows Server 2003自动化安装指南

    最小化安装 最小化安装即Mini Setup xff0c 在Microsoft Windows Server 2003 家族和 Windows XP 64 Bit Edition 中首次出现 使用Sysprep 命令行选项 xff0c 我们
  • 简单介绍libevent快速上手

    http blog chukong inc com index php 2012 02 26 E7 AE 80 E5 8D 95 E4 BB 8B E7 BB 8Dlibevent E5 BF AB E9 80 9F E4 B8 8A E6
  • 惠普微软推VirtualSystem私有云套件

    惠普微软推VirtualSystem私有云套件 发布时间 xff1a 2012 4 24 来源 xff1a 中关村在线 惠普和微软通过整合高效服务器 存储和软件平台合力共推VirtualSystem私有云高端产品系列 据报道 xff0c V
  • python跟expect资料

    探索 Pexpect xff0c 第 1 部分 xff1a 剖析 Pexpect xff1a http www ibm com developerworks cn linux l cn pexpect1 index html 探索 Pexp
  • 精辟,从1到10谈圆通人际关系

  • 【飞控学习】APM和PX4飞控源码下载及安装

    对于无人机开发的专业人员来说 xff0c APM和PX4是现今市面上最强大的2个开源无人机飞控 学习和查看他们2者的源码 xff0c 将会提高我们对整个无人机的姿态解算和控制的深入理解 现在我们就来下载2者的源码和安装查看2者源码的软件 1
  • 值得你关注的Android6.0上的重要变化(一)

    伴随着众多新特性和新功能 xff0c Android6 0 xff08 API level 23 xff09 在系统和API上都有着诸多的改变 本文着重介绍几个关键变化 xff0c 以帮助你理解这些改变对你的APP产生的影响 一 运行时权限
  • 编译开源LibreOffice的Android版本——开源Office文档查看器

    项目近期需要用到文档查看器 xff0c 现有的WPS之类确实比较好用 xff0c 无奈还需要对应用做些处理 xff0c 只好寻找开源的实现 开源的文档查看器主要两种方式 xff0c 一种是完整的Android版本实现 xff0c 直接拿来即
  • Linux下利用信号的异步串口中断响应

    先悔过一下 因为一个月前就在学习这个 xff0c 当时解决的差不多了 xff0c 想着抽个空再记录这些 xff0c 没想到这么短的时间就已经忘得 差不多了 xff0c 真是不好 xff0c 应该趁热打铁 废话不多说了 xff0c 这里主要介
  • 值得你关注的Android8.0(Android O)上的重要变化

    刚适配完Android7 0还没多久 xff0c 就看到Google官方推出的Android8 0 xff08 Android O xff09 的开发者预览版新闻 xff0c 我的心情你可以好好想想 对于上层应用开发者的我来说 xff0c
  • Android应用流量统计——NetworkStatsManager使用

    在没有Root的情况下 xff0c Android应用流量统计在6 0之前一直没有太好的办法 xff0c 官方虽然提供了TrafficStats xff0c 但其主要功能是设备启动以来流量的统计信息 xff0c 和时间信息无法很好的配合 最