草庐IT

android - 如何以编程方式显示所有应用程序的数据使用情况?

coder 2023-11-18 原文

从 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

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

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

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

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

编辑后的答案

还有一些获取网络使用情况的选项:

  1. NetworkStatsManager - 因此 NetworkStatsManager 是一个选项,它也提供所需的信息,但它有一个缺点,即此 API 仅适用于 Marshmallow(API 级别 23)或更高 .对于 api 23 以下的设备,可以使用我的旧答案。根据官方文档:

[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 :

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

    <uses-permission android:name="android.permission.READ_PHONE_STATE" / >
    
    <uses-permission android:name="android.permission.PACKAGE_USAGE_STATS"
     tools:ignore="ProtectedPermissions" / >
    

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 启动一个 Activity 以帮助用户到达那里:

startActivity(new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS));

一切设置完成后,您可以获得 NetworkStatsManager 的实例,我们需要它来获取网络使用数据:

NetworkStatsManager networkStatsManager = (NetworkStatsManager) context.getSystemService(Context.NETWORK_STATS_SERVICE);
  • 无论您将执行什么查询,您都会得到一个 NetworkStats.Bucket 或 NetworkStats(它基本上是多个存储桶的容器,使用 hasNextBucket() 和 getNextBucket() 方法访问真实数据(也记得在对象超出范围之前使用 close()。

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

  • 进行查询时需要用户 ID,除非用户更换 SIM 卡或运营商,否则它会保持不变。为了得到那个

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;

UIDs used for the network usage caused by : 


  • Unistalled apps : UID_REMOVED

  • Tethering : UID_TETHERING
  • Android OS : SYSTEM_UID 

  • To get stats for all apps : UID_ALL

一些示例查询:

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

To get all Rx and Tx bytes of Wifi :

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

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

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

Note :

  • 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:它也提供所需的信息,但有一些缺点至少使它不可靠:

  • 每次重启后数据重置
  • 某些设备也可能不支持它。

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 - 如何以编程方式显示所有应用程序的数据使用情况?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17674790/

有关android - 如何以编程方式显示所有应用程序的数据使用情况?的更多相关文章

  1. ruby - 如何使用 Nokogiri 的 xpath 和 at_xpath 方法 - 2

    我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div

  2. ruby - 使用 RubyZip 生成 ZIP 文件时设置压缩级别 - 2

    我有一个Ruby程序,它使用rubyzip压缩XML文件的目录树。gem。我的问题是文件开始变得很重,我想提高压缩级别,因为压缩时间不是问题。我在rubyzipdocumentation中找不到一种为创建的ZIP文件指定压缩级别的方法。有人知道如何更改此设置吗?是否有另一个允许指定压缩级别的Ruby库? 最佳答案 这是我通过查看ruby​​zip内部创建的代码。level=Zlib::BEST_COMPRESSIONZip::ZipOutputStream.open(zip_file)do|zip|Dir.glob("**/*")d

  3. ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法? - 2

    类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc

  4. ruby-on-rails - 使用 Ruby on Rails 进行自动化测试 - 最佳实践 - 2

    很好奇,就使用ruby​​onrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提

  5. ruby - 在 Ruby 中使用匿名模块 - 2

    假设我做了一个模块如下:m=Module.newdoclassCendend三个问题:除了对m的引用之外,还有什么方法可以访问C和m中的其他内容?我可以在创建匿名模块后为其命名吗(就像我输入“module...”一样)?如何在使用完匿名模块后将其删除,使其定义的常量不再存在? 最佳答案 三个答案:是的,使用ObjectSpace.此代码使c引用你的类(class)C不引用m:c=nilObjectSpace.each_object{|obj|c=objif(Class===objandobj.name=~/::C$/)}当然这取决于

  6. ruby - 使用 ruby​​ 和 savon 的 SOAP 服务 - 2

    我正在尝试使用ruby​​和Savon来使用网络服务。测试服务为http://www.webservicex.net/WS/WSDetails.aspx?WSID=9&CATID=2require'rubygems'require'savon'client=Savon::Client.new"http://www.webservicex.net/stockquote.asmx?WSDL"client.get_quotedo|soap|soap.body={:symbol=>"AAPL"}end返回SOAP异常。检查soap信封,在我看来soap请求没有正确的命名空间。任何人都可以建议我

  7. python - 如何使用 Ruby 或 Python 创建一系列高音调和低音调的蜂鸣声? - 2

    关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。

  8. ruby-on-rails - 'compass watch' 是如何工作的/它是如何与 rails 一起使用的 - 2

    我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t

  9. ruby - 将差异补丁应用于字符串/文件 - 2

    对于具有离线功能的智能手机应用程序,我正在为Xml文件创建单向文本同步。我希望我的服务器将增量/差异(例如GNU差异补丁)发送到目标设备。这是计划:Time=0Server:hasversion_1ofXmlfile(~800kiB)Client:hasversion_1ofXmlfile(~800kiB)Time=1Server:hasversion_1andversion_2ofXmlfile(each~800kiB)computesdeltaoftheseversions(=patch)(~10kiB)sendspatchtoClient(~10kiBtransferred)Cl

  10. ruby - 使用 ruby​​ 将 HTML 转换为纯文本并维护结构/格式 - 2

    我想将html转换为纯文本。不过,我不想只删除标签,我想智能地保留尽可能多的格式。为插入换行符标签,检测段落并格式化它们等。输入非常简单,通常是格式良好的html(不是整个文档,只是一堆内容,通常没有anchor或图像)。我可以将几个正则表达式放在一起,让我达到80%,但我认为可能有一些现有的解决方案更智能。 最佳答案 首先,不要尝试为此使用正则表达式。很有可能你会想出一个脆弱/脆弱的解决方案,它会随着HTML的变化而崩溃,或者很难管理和维护。您可以使用Nokogiri快速解析HTML并提取文本:require'nokogiri'h

随机推荐