我想知道数据使用历史,并注意到“新的”android-6NetworkStatsManager
似乎是积极的(我已经使用TrafficStats
了一段时间,但不会涵盖重启之前的任何内容)。
从 API 文档:
注意:此 API 需要 PACKAGE_USAGE_STATS 权限,该权限为系统级权限,不会授予第三方应用。但是,声明权限意味着使用 API 的意图,并且设备的用户可以通过设置应用程序授予权限。配置文件所有者应用程序被自动授予查询他们管理的配置文件上的数据的权限(即,对于除 querySummaryForDevice(int, String, long, long) 之外的任何查询)。设备所有者应用程序同样可以访问主要用户的使用数据。
我想知道聚合级别的数据使用情况,而不是了解使用数据的应用程序,所以我尝试像这样使用它:
NetworkStatsManager service = context.getSystemService(NetworkStatsManager.class);
NetworkStats.Bucket bucket =
service.querySummaryForDevice(ConnectivityManager.TYPE_MOBILE, null, from, to);
...
不幸的是,这会引发SecurityException
:
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 来执行相同的操作,而无需请求任何权限:
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 做同样的事情,那么,我该怎么做呢?