首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用NetworkStatsManager获取移动数据使用历史记录

使用NetworkStatsManager获取移动数据使用历史记录
EN

Stack Overflow用户
提问于 2016-04-18 19:22:14
回答 2查看 13.2K关注 0票数 16

我想知道数据使用历史,并注意到“新”的android-6 NetworkStatsManager,这似乎是积极的(我已经使用了TrafficStats一段时间,但这不会涵盖任何以前的重新启动)。

在API文档中:

注意:这个API需要权限PACKAGE_USAGE_STATS,这是一个系统级的权限,不会授予第三方应用程序。但是,声明该权限意味着要使用API,设备的用户可以通过Settings应用程序授予权限。配置文件所有者应用程序自动被授予查询其管理的配置文件数据的权限(也就是说,除了querySummaryForDevice(int、String、long、long)以外的任何查询)。设备所有者应用程序同样可以访问主用户的使用数据。

我想知道数据在聚合级别上的使用情况,而不是应用程序使用数据的情况,所以我尝试这样使用:

代码语言:javascript
复制
NetworkStatsManager service = context.getSystemService(NetworkStatsManager.class);

NetworkStats.Bucket bucket = 
        service.querySummaryForDevice(ConnectivityManager.TYPE_MOBILE, null, from, to);
...

不幸的是,这会抛出一个SecurityException

代码语言:javascript
复制
java.lang.SecurityException: NetworkStats: Neither user 10174 nor current process has android.permission.READ_NETWORK_USAGE_HISTORY.
at android.os.Parcel.readException(Parcel.java:1620)
at android.os.Parcel.readException(Parcel.java:1573)
at android.net.INetworkStatsSession$Stub$Proxy.getDeviceSummaryForNetwork(INetworkStatsSession.java:259)
at android.app.usage.NetworkStats.getDeviceSummaryForNetwork(NetworkStats.java:316)
at android.app.usage.NetworkStatsManager.querySummaryForDevice(NetworkStatsManager.java:100)
...

第三方应用程序不允许使用android.permission.READ_NETWORK_USAGE_HISTORY权限。所以这看起来像是死胡同。

但是,我深入了解了内部结构,发现您可以使用内部/隐藏API进行相同的操作,而无需请求任何权限:

代码语言:javascript
复制
INetworkStatsService service =
        INetworkStatsService.Stub.asInterface(
                ServiceManager.getService(Context.NETWORK_STATS_SERVICE));

INetworkStatsSession session = service.openSession();

NetworkTemplate mobileTemplate = NetworkTemplate.buildTemplateMobileWildcard();
int fields = NetworkStatsHistory.FIELD_RX_BYTES | NetworkStatsHistory.FIELD_TX_BYTES;

NetworkStatsHistory mobileHistory = session.getHistoryForNetwork(mobileTemplate, fields);

for (int i = 0; i < mobileHistory.size(); i++) {
    NetworkStatsHistory.Entry entry = mobileHistory.getValues(i, null);
    ...
}

session.close();

我真的想对公共API做同样的事情,那么,我如何才能做到这一点呢?

EN

回答 2

Stack Overflow用户

发布于 2016-09-09 12:58:15

有一种方法可以获得对NetworkStateManager的访问,而不需要访问私有API。以下是几个步骤:

  1. AndroidManifest.xml中声明所需的权限
代码语言:javascript
复制
1. Ask for permission in `Activity`

android.permission.PACKAGE_USAGE_STATS不是正常的权限,不能简单地请求。为了检查是否已授予许可,请检查:

appOps.checkOpNoThrow(AppOpsManager.OPSTR_GET_USAGE_STATS,appOps = ( AppOpsManager ) getSystemService(Context.APP_OPS_SERVICE);int appOps= android.os.Process.myUid(),getPackageName();if (模式== AppOpsManager.MODE_ALLOWED) {返回true;}

要请求这个权限,只需调用Intent

意图=新的Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS);startActivity(意图);

另外还需要执行另一项任务:Manifest.permission.READ_PHONE_STATE。当您需要获得移动数据统计时,只需要它。但是,这是正常的权限,所以可以是请求作为任何其他许可

代码语言:javascript
复制
1. Use `NetworkStatsManager`:

制作了一个演示使用情况的示例Github回购

票数 22
EN

Stack Overflow用户

发布于 2017-01-17 11:21:39

代码语言:javascript
复制
/*
getting youtube usage for both mobile and wifi.
 */
public long getYoutubeTotalusage(Context context) {
    String subId = getSubscriberId(context, ConnectivityManager.TYPE_MOBILE);
    return getYoutubeUsage(ConnectivityManager.TYPE_MOBILE, subId) + getYoutubeUsage(ConnectivityManager.TYPE_WIFI, "");
}


private long getYoutubeUsage(int networkType, String subScriberId) {
    NetworkStats networkStatsByApp;
    long currentYoutubeUsage = 0L;
    try {
        networkStatsByApp = networkStatsManager.querySummary(networkType, subScriberId, 0, System.currentTimeMillis());
        do {
            NetworkStats.Bucket bucket = new NetworkStats.Bucket();
            networkStatsByApp.getNextBucket(bucket);
            if (bucket.getUid() == packageUid) {
                //rajeesh : in some devices this is immediately looping twice and the second iteration is returning correct value. So result returning is moved to the end.
                currentYoutubeUsage = (bucket.getRxBytes() + bucket.getTxBytes());
            }
        } while (networkStatsByApp.hasNextBucket());

    } catch (RemoteException e) {
        e.printStackTrace();
    }

    return currentYoutubeUsage;
}


private String getSubscriberId(Context context, int networkType) {
    if (ConnectivityManager.TYPE_MOBILE == networkType) {
        TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
        return tm.getSubscriberId();
    }
    return "";
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/36702621

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档