如何以编程方式显示所有应用程序的数据使用情况? [英] How do I programmatically show data usage of all applications?

查看:109
本文介绍了如何以编程方式显示所有应用程序的数据使用情况?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

从Android 4.0开始,我们在手机中提供了数据使用控制选项.请检查所附的屏幕截图以进一步了解.

On Android 4.0 onwards we have data usage control options in the phone. Please check the attached screen shot for further understanding.

http://developer.android.com/about/versions/android-4.0-highlights.html

现在,我有一些要求从我的应用程序中检查这些内容(特定时间段/特定日期中所有应用程序的数据使用情况).我怎样才能做到这一点?我还将以下类用于网络使用情况详细信息.

Now I have some requirement to check these things (All Application's Data usage in specific time period/specific days) from my application. How can I achieve this? I am also using the below class for Network Usage details.

http://developer.oesf.biz/em/developer/reference/eggplant/android/net/NetworkStatsHistory.html

请检查以下链接图像.我需要开发相同类型的应用程序.

Please check the below link images. I need to develop the same kind of application.

http://developer.android.com/sdk/images/4.0/usage-maps-lg.png

感谢您共享代码,但是我需要了解每个应用程序而不是所有应用程序使用的数据.到目前为止,我在链接中观察到的是,没有人在谈论单个应用程序的数据使用情况.我已经知道如何显示设备中已安装的应用程序.现在,我想知道每个应用程序使用的数据是什么.

Thanks for sharing your code, but I need to know data used by each application instead of all applications. So far I observed in the links no one is talking about data usage of individual applications. I already know how to show installed applications in the device. Now I would like to know what's the data used by each and every application.

我正在使用以下代码获取设备中已安装应用程序的列表.

I am using the below code for list of installed applications in the device.

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;
}

我怎么知道每个应用程序使用什么数据?

How do I know what's the data used by each application?

实际上,我需要一个解决方案,该解决方案可以在给定的时间段内(即两天之间)给出应用程序的数据使用情况.

Actually, I need a solution which gives data usage of applications in a given time period, i.e. in between two days.

推荐答案


旧答案(通常适用于Api级别23以下的设备)

首先,获取所有正在运行的应用程序的过程信息的列表:


Old Answer (Mostly work for devices below Api level 23)

First, get a list of all running apps' process info:

List<RunningAppProcessInfo>

然后获取每个应用程序的UID,然后获取发送和接收该应用程序的流量:

Then get the UID of every app and get then send and receive traffic of the app:

// 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);
}


编辑后的答案

还有更多选择可以获取网络使用情况:


Edited Answer

There are some more options to get network usage :

  1. NetworkStatsManager -因此,NetworkStatsManager是一个选项,它还提供必需的信息,但有一个缺点,即该API仅在棉花糖(API级别23)或更高版本上可用.对于api 23以下的设备,可以使用我的旧答案.根据官方文档:
  1. NetworkStatsManager - So NetworkStatsManager is an option which is also provides required info but it has a drawback i.e. This API is available only on Marshmallow(API level 23) or higher. For the devices below to api 23 the my old answer can be used.
According to the official documentation:


[NetworkStatsManager]提供网络流量统计信息.这些统计信息包括发送和接收的字节以及网络数据包通过所有接口在移动设备上发送和接收界面,并基于每个UID.

[NetworkStatsManager] provides network traffic statistics. These statistics include bytes transmitted and received and network packets transmitted and received, over all interfaces, over the mobile interface, and on a per-UID basis.

因此要使用NetworkStatsManager:

So to use NetworkStatsManager :

  • 在AndroidManifest文件中声明所需的权限:

  • Declare required permissions in AndroidManifest file :

<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" 是系统级别权限,我们将需要以其他方式处理请求.为了检查是否已授予许可,请检查:

Since "android.permission.PACKAGE_USAGE_STATS" is a system level permission we will need to handle the request in a different manner. In order to check, whether the permission has been granted, check:

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目的启动一项活动即可帮助用户到达目的地:

This permission can be granted from the Settings -> Security -> Apps with usage access screen. To ask for this permission, simply start an activity with Settings.ACTION_USAGE_ACCESS_SETTINGS Intent to help the user to get there:


startActivity(new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS));

所有设置完成后,您可以获取NetworkStatsManager的实例,我们将需要该实例来获取网络使用情况数据:

Once everything has been set up you can get an instance of NetworkStatsManager which we will need to fetch network usage data:

NetworkStatsManager networkStatsManager = (NetworkStatsManager) context.getSystemService(Context.NETWORK_STATS_SERVICE);

  • 无论执行什么查询,结果都将得到NetworkStats.Bucket或NetworkStats(基本上是多个存储桶的容器,使用方法hasNextBucket()和getNextBucket()可以访问真实数据(也请记住在对象超出范围之前使用close().

    • Whatever query you will perform, you will get as a result a NetworkStats.Bucket or a NetworkStats (which is basically a container for multiple buckets with methods hasNextBucket() and getNextBucket() to access the real data (also remember to use close() before the object is out of scope).

      在每个查询中,您都必须指定网络类型(ConnectivityManager.TYPE_WIFI或ConnectivityManager.TYPE_MOBILE).

      In every query you will have to specify the network type (ConnectivityManager.TYPE_WIFI or ConnectivityManager.TYPE_MOBILE). 


      进行查询所需的订户ID,除非用户切换SIM卡或运营商,否则它保持不变.为了得到那个

      Subscriber Id required to make query and it remains same unless the user switches SIM card or carrier. To get that

      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:

        UIDs used for the network usage caused by : 


        • 已安装的应用程序:UID_REMOVED
        • 网络共享:UID_TETHERING
        • Android操作系统:SYSTEM_UID
        • 要获取所有应用程序的统计信息:UID_ALL

        一些示例查询:

        要获取Mobile的所有Rx和Tx字节:

        To get all Rx and Tx bytes of Mobile :

        NetworkStats.Bucket bucket = networkStatsManager.querySummaryForDevice(ConnectivityManager.TYPE_MOBILE, getSubscriberId(context, ConnectivityManager.TYPE_MOBILE), 0, System.currentTimeMillis());
        
    
        bucket.getRxBytes();
        bucket.getTxBytes();
        
        

        要获取Wifi的所有Rx和Tx字节:

        To get all Rx and Tx bytes of Wifi :

        NetworkStats.Bucket bucket = networkStatsManager.querySummaryForDevice(ConnectivityManager.TYPE_WIFI, "", 0, System.currentTimeMillis());
       
        bucket.getRxBytes();
        bucket.getTxBytes();
        

        获取包的Mobile的所有Rx和Tx字节:

        To get all Rx and Tx bytes of Mobile for package :

        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字节:

        To get all Rx and Tx bytes of Wifi for package :

        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牛轧糖)中添加的,因此,如果您以棉花糖(API级别23)为目标,则将无法使用它们.
        • API级别24(Android 7.0牛轧糖)起,如果您只想获取应用程序数据,则可以使用具有PACKAGE_USAGE_STATS权限的 NetworkStatsManager .如果您的目标是访问其他应用程序的统计信息,则仍然需要它.
        • Those queries should never be performed on the main thread or they will cause your app to drop frame.
        • NetworkStatsManager.query* throws RemoteException
        • Roaming and tag were added in API level 24 (Android 7.0 Nougat) so if you’re targeting Marshmallow (API level 23) you won’t be able to use those.
        • Since API level 24 (Android 7.0 Nougat) you can use NetworkStatsManager without the PACKAGE_USAGE_STATS permission if you only want to get your app data. You’d still need it if your goal is to access other apps’ stats.

        2.TrafficStats:它还提供必需的信息,但存在一些缺点,至少使其不可靠:

        2. TrafficStats : It also provides required info but there are some drawbacks which makes it unreliable at least :


        • 每次重启后数据都会重置
        • 在某些设备上也可能不支持.

        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);
        

        这篇关于如何以编程方式显示所有应用程序的数据使用情况?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆