Android TrafficStats流量监控

别来无恙 提交于 2019-12-10 04:11:47

一、流量监控TrafficStats

对于Android流量统计来说在2.2版中新加入了TrafficStats类可以轻松获取,其实本身TrafficStats类也是读取Linux提供的文件对象系统类型的文本进行解析。android.net.TrafficStats类中,提供了多种静态方法,可以直接调用获取,返回类型均为 long型,如果返回等于-1代表 UNSUPPORTED 当前设备不支持统计。 

static long  getMobileRxBytes()  //获取通过Mobile连接收到的字节总数,不包含WiFi  
static long  getMobileRxPackets()  //获取Mobile连接收到的数据包总数  
static long  getMobileTxBytes()  //Mobile发送的总字节数  
static long  getMobileTxPackets()  //Mobile发送的总数据包数  
static long  getTotalRxBytes()  //获取总的接受字节数,包含Mobile和WiFi等  
static long  getTotalRxPackets()  //总的接受数据包数,包含Mobile和WiFi等  
static long  getTotalTxBytes()  //总的发送字节数,包含Mobile和WiFi等  
static long  getTotalTxPackets()  //发送的总数据包数,包含Mobile和WiFi等   
static long  getUidRxBytes(int uid)  //获取某个网络UID的接受字节数  
static long  getUidTxBytes(int uid) //获取某个网络UID的发送字节数   

总接受流量TrafficStats.getTotalRxBytes(), 
总发送流量TrafficStats.getTotalTxBytes()); 
不包含WIFI的手机GPRS接收量TrafficStats.getMobileRxBytes()); 
不包含Wifi的手机GPRS发送量TrafficStats.getMobileTxBytes()); 

某一个进程的总接收量TrafficStats.getUidRxBytes(Uid)); 
某一个进程的总发送量TrafficStats.getUidTxBytes(Uid)); 

这些都是从第一次启动程序到最后一次启动的统计量。并不是这篇文章里所说的“从本次开机到本次关机的统计量”! 

用法举例,注意这里得到的单位都是"KB" 

 

public long getTotalRxBytes(){  //获取总的接受字节数,包含Mobile和WiFi等  
        return TrafficStats.getTotalRxBytes()==TrafficStats.UNSUPPORTED?0:(TrafficStats.getTotalRxBytes()/1024);  
    }  
    public long getTotalTxBytes(){  //总的发送字节数,包含Mobile和WiFi等  
        return TrafficStats.getTotalTxBytes()==TrafficStats.UNSUPPORTED?0:(TrafficStats.getTotalTxBytes()/1024);  
    }  
    public long getMobileRxBytes(){  //获取通过Mobile连接收到的字节总数,不包含WiFi  
        return TrafficStats.getMobileRxBytes()==TrafficStats.UNSUPPORTED?0:(TrafficStats.getMobileRxBytes()/1024);  
    }  

 

二、TrafficStatsCompat

此方法是v4包中兼容TrafficStats的方法,基本用法和TrafficStats类似。再次不在赘述。

 

三、Android 6.0 NetworkStatsManager

在Android 6.0(API23)中新增加的类,提供网络使用历史统计信息,同时特别强调了可查询指定时间间隔内的统计信息。

查询指定网络类型在某时间间隔内的总的流量统计信息      

NetworkStats.BucketquerySummaryForDevice(intnetworkType,StringsubscriberId,longstartTime,longendTime)

查询某uid在指定网络类型和时间间隔内的流量统计信息

NetworkStatsqueryDetailsForUid(intnetworkType,StringsubscriberId,longstartTime,longendTime,intuid)

查询指定网络类型在某时间间隔内的详细的流量统计信息(包括每个uid)

NetworkStatsqueryDetails(intnetworkType,StringsubscriberId,longstartTime,longendTime)

        从上述函数和文档看,NetworkStatsManager类克服了TrafficStats的查询限制,而且统计信息也不再是设备重启以来的数据。

NetworkStatsManager的使用需要额外的权限,”android.permission.PACKAGE_USAGE_STATS”是系统权限,需要主动引导用户开启应用的“有权查看使用情况的应用”(使用记录访问权限)权限,后面会有代码示例。

 

AndroidManifest中添加权限声明

<user-permission android:name="android.permission.READ_PHONE_STATE"/>

<user-permission android:name="android.permission.PACKAGE_USAGE_STATS" />

<user-permission android:name="android.permission.READ_NETWORK_USAGE_HISTORY" />

获取权限代码如下

private boolean hasPermissionToReadNetworkStats() {

  int permissionCheck = 
  ContextCompat.checkSelfPermission(this,Manifest.permission.READ_PHONE_STATE);

 if (permissionCheck != PackageManager.PERMISSION_GRANTED) {

      ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_PHONE_STATE}, REQUEST_READ_PHONE_STATE);

} else {

 

}

   if(Build.VERSION.SDK_INT<23)

     return true;

 }

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

 }

  requestReadNetworkStats();

  return false;

}

//如果未获得权限,主动去设置界面开启
private void  requestReadNetworkStats(){

Intentintent=newIntent(Settings.ACTION_USAGE_ACCESS_SETTINGS);

startActivity(intent);

}

 

查看设备和某应用的流量统计

(1)获取NetworkStatsManager示例对象

NetworkStatsManagernetworkStatsManager=(NetworkStatsManager)getSystemService(NETWORK_STATS_SERVICE);

(2)查询设备总的流量统计信息

NetworkStats.Bucketbucket=null;//获取到目前为止设备的Wi-Fi流量统计

bucket=networkStatsManager.querySummaryForDevice(ConnectivityManager.TYPE_WIFI,"",0,System.currentTimeMillis());

Log.i("Info","Total: "+(bucket.getRxBytes()+bucket.getTxBytes()));

(3)查询某应用(uid)的数据流量统计信息


//获取subscriberId

TelephonyManager tm=TelephonyManager)getSystemService(TELEPHONY_SERVICE);
StringsubId=tm.getSubscriberId();

NetworkStatssummaryStats;

longsummaryRx=0;
longsummaryTx=0;
longsummaryRx =0;
longStartTx=0;

NetworkStats.BucketsummaryBucket=newNetworkStats.Bucket();

longsummaryTotal=0;

summaryStats=networkStatsManager.querySummary(ConnectivityManager.TYPE_MOBILE,subId,getTimesMonthmorning(),System.currentTimeMillis());

do{

              summaryStats.getNextBucket(summaryBucket);

              intsummaryUid=summaryBucket.getUid();

             if(uid==summaryUid){

                summaryRx+=summaryBucket.getRxBytes();
                Rx+=summaryRx;
                summaryTx+=summaryBucket.getTxBytes();

               Tx+=summaryTx;

              }        

}while(summaryStats.hasNextBucket());

四、补充知识

Jar包冲突的原因

  1. jar包重复依赖,使用了Build Path,必须移除才行

  2. jar包版本不同,比如v4,同一个项目中,必须使用同一版本的v4,v7等

LogCat

Dex Loader] Unable to execute dex: Multiple dex files define Landroid/annotation/SuppressLint;
CustomViewTest] Conversion to Dalvik format failed: Unable to execute dex: Multiple dex files define Landroid/annotation/SuppressLint;

android.annotation.SuppressLint类被多次定义了,也就是说jar包内的某些类冲突了,删除冲突的jar包 annotation.jar即可

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!