在Android 4.0以后的版本中,我们在手机中有数据使用控制选项。请查看所附的屏幕截图以进一步了解。
http://developer.android.com/about/versions/android-4.0-highlights.html
现在我有一些要求从我的应用程序中检查这些东西(特定时间段/特定日期内所有应用程序的数据使用情况)。我怎样才能做到这一点?我也在使用下面的类来了解网络使用情况的详细信息。
http://developer.oesf.biz/em/developer/reference/eggplant/android/net/NetworkStatsHistory.html
请查看以下链接图片。我需要开发同样的应用程序。
-
http://developer.android.com/sdk/images/4.0/usage-all-lg.png
-
http://developer.android.com/sdk/images/4.0/usage-maps-lg.png
感谢分享您的代码,但我需要知道每个应用程序而不是所有应用程序使用的数据。到目前为止,我在链接中观察到,没有人谈论单个应用程序的数据使用情况。我已经知道如何在设备中显示已安装的应用程序。现在我想知道每个应用程序使用的数据是什么。
我正在使用以下代码查看设备中已安装的应用程序列表。
private ArrayList<PInfo> getInstalledApps(boolean getSysPackages) {
ArrayList<PInfo> res = new ArrayList<PInfo>();
List<PackageInfo> packs = getPackageManager().getInstalledPackages(0);
for (int i=0; i<packs.size(); i++) {
PackageInfo p = packs.get(i);
if ((!getSysPackages) && (p.versionName == null)) {
continue ;
}
PInfo newInfo = new PInfo();
newInfo.setAppname(p.applicationInfo.loadLabel(getPackageManager()).toString());
newInfo.setPname(p.packageName);
newInfo.setVersionName(p.versionName);
newInfo.setVersionCode(p.versionCode);
newInfo.setIcon(p.applicationInfo.loadIcon(getPackageManager()));
res.add(newInfo);
}
return res;
}
我如何知道每个应用程序使用的数据是什么?
事实上,我需要一个解决方案,它可以在给定的时间段内(即两天之间)提供应用程序的数据使用情况。
旧答案(主要适用于Api级别23以下的设备)
首先,获取所有正在运行的应用程序的进程信息列表:
List<RunningAppProcessInfo>
然后获取每个应用程序的UID,然后获取应用程序的发送和接收流量:
// Get running processes
ActivityManager manager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
List<RunningAppProcessInfo> runningApps = manager.getRunningAppProcesses();
for (RunningAppProcessInfo runningApp : runningApps) {
// Get UID of the selected process
int uid = ((RunningAppProcessInfo)getListAdapter().getItem(position)).uid;
// Get traffic data
long received = TrafficStats.getUidRxBytes(uid);
long send = TrafficStats.getUidTxBytes(uid);
Log.v("" + uid , "Send :" + send + ", Received :" + received);
}
编辑的答案
还有一些更多的选项可以获得网络使用:
- NetworkStatsManager-因此NetworkStatsMnager是一个选项,它也提供所需的信息,但它有一个缺点,即此API仅在棉花糖(API 23级)或更高版本上可用。对于api 23下面的设备,可以使用我以前的答案。u2028根据官方文件:u2028
[NetworkStatsManager]提供网络流量统计信息。这些统计信息包括发送和接收的字节数以及网络数据包通过所有接口,通过移动设备发送和接收接口,并基于每个UID。
因此,要使用NetworkStatsManager:
在AndroidManifest文件中声明所需权限:
<uses-permission android:name="android.permission.READ_PHONE_STATE" / > <uses-permission android:name="android.permission.PACKAGE_USAGE_STATS" tools:ignore="ProtectedPermissions" / >
由于"android.permission.PACKAGE_USAGE__STATS"是系统级许可我们将需要以不同的方式处理请求。为了检查是否已授予权限,请检查:
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;
}
可以通过设置授予此权限->安全性->具有使用访问屏幕的应用程序。要申请此权限,只需使用Settings.ACTION_USAGE_ACCESS_Settings Intent启动一个活动,即可帮助用户到达目的地:u2028
startActivity(new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS));
一旦一切都设置好了,您就可以获得NetworkStatsManager的实例,我们需要它来获取网络使用数据:
NetworkStatsManager networkStatsManager = (NetworkStatsManager) context.getSystemService(Context.NETWORK_STATS_SERVICE);
无论你要执行什么查询,你都会得到一个NetworkStats.Bucket或NetworkStats(它基本上是多个Bucket的容器,方法有hasNextBucket()和getNextBucket()来访问真实数据(还记得在对象超出范围之前使用close())。
在每个查询中,您都必须指定网络类型(ConnectivityManager.type_WIFI或ConnectivityManager.type_MOBILE)。u2028
进行查询所需的用户Id,除非用户切换SIM卡或运营商,否则该Id保持不变。获取
TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); String subscriberId = manager.getSubscriberId();
- 要访问单个应用程序统计数据,您需要该应用程序的uid,这是系统在安装时为每个应用程序分配的int值
PackageManager packageManager = context.getPackageManager(); ApplicationInfo info = packageManager.getApplicationInfo("com.example.app", 0); int uid = info.uid;
用于网络使用的UID由以下原因引起:u2028
- 未安装的应用程序:UID_REMOVEDu2028
- 系链:UID_Tethering
- Android操作系统:SYSTEM_UIDu2028
- 获取所有应用程序的统计信息:UID_all
一些示例查询:
获取移动设备的所有Rx和Tx字节:
NetworkStats.Bucket bucket = networkStatsManager.querySummaryForDevice(ConnectivityManager.TYPE_MOBILE, getSubscriberId(context, ConnectivityManager.TYPE_MOBILE), 0, System.currentTimeMillis());
bucket.getRxBytes();
bucket.getTxBytes();
获取Wifi的所有Rx和Tx字节:
NetworkStats.Bucket bucket = networkStatsManager.querySummaryForDevice(ConnectivityManager.TYPE_WIFI, ””, 0, System.currentTimeMillis());
bucket.getRxBytes();
bucket.getTxBytes();
要获取包的移动设备的所有Rx和Tx字节:
NetworkStats.Bucket bucket = networkStatsManager.queryDetailsForUid(ConnectivityManager.TYPE_MOBILE, getSubscriberId(context, ConnectivityManager.TYPE_MOBILE), 0, System.currentTimeMillis(),packageUid);
long rxBytes = 0L;
long txBytes = 0L;
NetworkStats.Bucket bucket = new NetworkStats.Bucket();
while (networkStats.hasNextBucket()) {
networkStats.getNextBucket(bucket);
rxBytes += bucket.getRxBytes();
txBytes += bucket.getTxBytes();
}
networkStats.close();
要获得包的Wifi的所有Rx和Tx字节:
NetworkStats.Bucket bucket = networkStatsManager.queryDetailsForUid(ConnectivityManager.TYPE_WIFI, “”, 0, System.currentTimeMillis(),packageUid);
long rxBytes = 0L;
long txBytes = 0L;
NetworkStats.Bucket bucket = new NetworkStats.Bucket();
while (networkStats.hasNextBucket()) {
networkStats.getNextBucket(bucket);
rxBytes += bucket.getRxBytes();
txBytes += bucket.getTxBytes();
}
networkStats.close();
注:
- 这些查询永远不应该在主线程或它们会导致你的应用程序掉帧
- NetworkStatsManager.query*引发RemoteException
- 在API 24级(Android 7.0 Nougat)中添加了漫游和标签,因此如果你的目标是棉花糖(API 23级),你将无法使用它们
- 由于API 24级(Android 7.0 Nougat),如果您只想获取应用程序数据,则可以在没有PACKAGE_USAGE_STATS权限的情况下使用NetworkStatsManager。如果你的目标是访问其他应用程序的统计数据,你仍然需要它
2.TrafficStats:它也提供所需的信息,但存在一些缺点,这至少使它不可靠:u2028
- 每次重新启动后数据重置u2028
- 某些设备可能也不支持它
TrafficStats的一些示例方法:
- To get Total Rx bytes - TrafficStats.getTotalRxBytes();
- To get Total Tx bytes - TrafficStats.getTotalTxBytes();
- To get all Mobile Rx bytes - TrafficStats.getMobileRxBytes();
- To get all Mobile Tx bytes - TrafficStats.getMobileTxBytes();
- To get all Wifi Rx bytes - TrafficStats.getTotalRxBytes() - TrafficStats.getMobileRxBytes();
- To get all Wifi Tx bytes - TrafficStats.getTotalTxBytes() - TrafficStats.getMobileTxBytes();
- To get Package Rx Bytes : - TrafficStats.getUidRxBytes(packageUid);
- To get Package Tx Bytes : - TrafficStats.getUidTxBytes(packageUid);
您可以使用android.net.TrafficStats
来获取网络使用情况的详细信息。
请在下面找到相同的示例程序。
package com.anchit.trafficstatus;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
public class TrafficStatus extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.e("bytes recvd", "" + android.net.TrafficStats.getMobileRxBytes());
Log.e("Total", "Bytes received" + android.net.TrafficStats.getTotalRxBytes());
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
2015年Arunendra的解决方案在SDK 28(Pie)上没有立即对我起作用。
所以我修改如下:
void networkUsage() {
// Get running processes
ActivityManager manager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
List<ActivityManager.RunningAppProcessInfo> runningApps = manager.getRunningAppProcesses();
for (ActivityManager.RunningAppProcessInfo runningApp : runningApps) {
long received = TrafficStats.getUidRxBytes(runningApp.uid);
long sent = TrafficStats.getUidTxBytes(runningApp.uid);
Log.d(LOG_TAG, String.format(Locale.getDefault(),
"uid: %1d - name: %s: Sent = %1d, Rcvd = %1d", runningApp.uid, runningApp.processName, sent, received));
}
}
请注意,此类返回的统计信息在每次重新启动后都会重置并从零开始。要访问更可靠的历史网络统计数据,请改用NetworkStatsManager。
Src:https://developer.android.com/reference/android/net/TrafficStats
有关如何使用NetworkStatsManager的详细信息,请查看此答案:https://stackoverflow.com/a/39412045/6341943