我正在构建一个应用程序,它在一定时间间隔内监视应用程序的网络数据使用情况。
在Android5上,我使用TrafficStats没有问题,尽管在使用NetworkStats的Android8上,我总是收到相同的数据。我读到存储桶大约每30分钟刷新一次,所以我尝试了大约一个小时收听youtube,但仍然使用相同的数据(在com.google.android.youtube包中)。
那么,我的问题是,为什么NetworkStats总是返回相同的数据?
下面是我的代码:
public class DataService extends Service {
private int interval = 1000 * 5; //Time interval
private List<ApplicationInfo> infos;
private PackageManager packageManager;
private static int counter = 0;
private ArrayList<ValuesHolder> values;
private Context context;
private Handler mHandler;
public static final String DATA_INTENT_FILTER = "Transmitted data updated";
private Runnable mHandlerTask = new Runnable() {
@Override
public void run() {
update();
Intent intent = new Intent();
intent.setAction(DATA_INTENT_FILTER);
sendBroadcast(intent);
mHandler.postDelayed(mHandlerTask, interval);
}
};
@Override
public void onCreate() {
super.onCreate();
mHandler = new Handler();
context = this;
values = new ArrayList<>();
packageManager = getPackageManager();
infos = packageManager.getInstalledApplications(0);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
getNonSystemPackages();
}
mHandlerTask.run();
}
@RequiresApi(api = Build.VERSION_CODES.N)
private void getNonSystemPackages() {
PackageManager pm = getPackageManager();
List<ApplicationInfo> packages = pm.getInstalledApplications(PackageManager.GET_META_DATA);
for (ApplicationInfo packageInfo : packages) {
if (pm.getLaunchIntentForPackage(packageInfo.packageName) != null) {
String currAppName = packageInfo.packageName;
try {
int uid = pm.getPackageUid(currAppName, 0);
values.add(counter, new ValuesHolder(currAppName,
getTotalDataForMobile(uid) + getTotalDataForWifi(uid),
uid));
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
} else {
//System App
}
}
}
private void update() {
String saveString;
long difference;
long data;
int uid;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
try {
for (int i = 0; i < values.size(); i++) {
uid = values.get(i).getUid();
if (TrafficStats.getUidTxBytes(uid) == TrafficStats.UNSUPPORTED) {
data = getTotalDataForMobile(uid) + getTotalDataForWifi(uid);
//Always same data
Log.i(values.get(i).getPackageName(), " data" + data);
} else {
data = TrafficStats.getUidRxBytes(uid) + TrafficStats.getUidTxBytes(uid);
}
}
} catch (NullPointerException e) {
e.printStackTrace();
}
}
}
@RequiresApi(api = Build.VERSION_CODES.M)
private long getTotalDataForWifi(int uid) {
NetworkStatsManager networkStatsManager = (NetworkStatsManager) getApplicationContext().getSystemService(Context.NETWORK_STATS_SERVICE);
NetworkStats.Bucket bucket;
long totalData = 0;
NetworkStats networkStats = null;
try {
networkStats = networkStatsManager.queryDetailsForUid(
ConnectivityManager.TYPE_WIFI,
"",
0,
System.currentTimeMillis(),
uid);
} catch (RemoteException e) {
return -1;
}
do {
bucket = new NetworkStats.Bucket();
networkStats.getNextBucket(bucket);
totalData += bucket.getRxBytes() + bucket.getTxBytes();
} while (networkStats.hasNextBucket());
return totalData;
}
@RequiresApi(api = Build.VERSION_CODES.M)
private long getTotalDataForMobile(int uid) {
NetworkStatsManager networkStatsManager = (NetworkStatsManager) getApplicationContext().getSystemService(Context.NETWORK_STATS_SERVICE);
NetworkStats.Bucket bucket;
NetworkStats networkStats = null;
long totalData = 0;
try {
networkStats = networkStatsManager.queryDetailsForUid(
ConnectivityManager.TYPE_MOBILE,
"",
0,
System.currentTimeMillis(),
uid);
} catch (RemoteException e) {
return -1;
}
do {
bucket = new NetworkStats.Bucket();
networkStats.getNextBucket(bucket);
totalData += bucket.getRxBytes() + bucket.getTxBytes();
} while (networkStats.hasNextBucket());
return totalData;
}
}我在MainActivity中请求运行时权限,如下所示:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (checkSelfPermission(Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, Permissions.ARR_PHONE_STATE, Permissions.REQUEST_PHONE_STATE);
}
if
((checkSelfPermission(Manifest.permission.ACCESS_NETWORK_STATE) != PackageManager.PERMISSION_GRANTED)
|| (checkSelfPermission(Manifest.permission.ACCESS_WIFI_STATE) != PackageManager.PERMISSION_GRANTED)
|| (checkSelfPermission(Manifest.permission.INTERNET) != PackageManager.PERMISSION_GRANTED)) {
ActivityCompat.requestPermissions(this, Permissions.ARR_NETWORK, Permissions.REQUEST_NETWORK);
}
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) {
} else {
}
if (!Permissions.checkForPermission(this)) {
startActivity(new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS));
} else {
Log.i("SYSTEM", "PERMISSION GRANTED");
}
}权限被授予,我也在android清单中请求它们。
谢谢你的帮助。
发布于 2018-07-31 01:01:33
我偶然发现了这个非常精确的问题,并且我发现您仍然可以使用queryDetailsForUid方法。
正如您自己所说的,存储桶非常大(在2-3小时范围内),您可以增加该方法的结束时间间隔参数。
不使用System.currentTimeMillis()作为结束时间,而是获取一个Calendar.getInstance()对象,在该对象(calendar.add(Calendar.DATE, 1))上加上1天,并将其作为参数与calendar.getTimeInMillis()一起传递。
这样,您就可以确保当前存储桶也将被包括在内。
发布于 2018-03-10 01:29:18
回答我自己的问题,对于可能有同样问题的人。我发现使用queryDetailsForUid方法可以在相当长的时间间隔(3小时左右)刷新数据。
下面是一个运行良好的解决方案:
private long getApplicationUsage(int networkType, int uid) {
long usage = 0L;
NetworkStats networkStatsByApp;
NetworkStatsManager networkStatsManager = (NetworkStatsManager) getApplicationContext().getSystemService(Context.NETWORK_STATS_SERVICE);
try {
networkStatsByApp = networkStatsManager.querySummary(networkType, "", 0, System.currentTimeMillis());
do {
NetworkStats.Bucket bucket = new NetworkStats.Bucket();
networkStatsByApp.getNextBucket(bucket);
if (bucket.getUid() == uid) {
// in some devices this is immediately looping twice
// and the second iteration is returning correct value.
// So result is returned in the end.
usage = (bucket.getRxBytes() + bucket.getTxBytes());
}
} while (networkStatsByApp.hasNextBucket());
} catch (RemoteException e) {
e.printStackTrace();
}
return usage;
}在应用程序启动时,只需保存总结果,然后在所需的间隔后用保存的值减去总使用量,即可得到结果。(不要忘记保存新的结果)。
https://stackoverflow.com/questions/49179382
复制相似问题