Android之TrafficStats实现流量实时监测

---恢复内容开始---


TrafficStats类是由Android提供的一个从你的手机开机开始,累计到现在使用的流量总量,或者统计某个或多个进程或应用所使用的流量,当然这个流量包括的Wifi和移动数据网Gprs。这里只针对手机所使用的流量作介绍,至于统计某个进程应用使用的流量,道理都差不多,小伙伴们可以自己查下文档。首先先介绍一下TrafficStats常用的一些方法:


TrafficStats.getTotalRxBytes() ——获取从此次开机起总接受流量(流量是分为上传与下载两类的,当然其实这里还有本地文件之间数据交换的流量,这个暂且不说,等下说明一下我遇到的问题);


TrafficStats.getTotalTxBytes()——获取从此次开机起总发送流量;


TrafficStats.getMobileRxBytes()——获取从此次开机起不包括Wifi的接受流量,即只统计数据网Gprs接受的流量;


TrafficStats.getMobileTxBytes()——获取从此次开机起不包括Wifi的发送流量,即只统计数据网Gprs发送的流量;


于是,小伙伴们可以用getTotalRxBytes() - getMobileRxBytes()获取手机Wifi的接受流量,同理获得Wifi的发送流量。


那么,现在问题来了(不说挖掘机,毕竟蓝翔强):我上面所说的几个方法都是统计从手机开机到现在所使用的总流量,而我需要实现的是检测手机的实时流量使用,或者说我还要算出此刻的网速。那该咋办呢?


这当然也难不了小伙伴们的,我是这样实现的:先获取此刻的总流量,譬如说00:00:00时刻的总使用流量,然后再统计00:00:01时刻的总使用流量,那么两者相减便是这1秒钟所使用的流量,当然你也可以设定为零点几秒。我这里是用线程来实现的,当然你们也可以用Timer,定时器之类的途径实现。


1.先写一个方法,用于统计Wifi下使用的流量:


public double getWifiTraffic(double time){
double rtotalGprs = TrafficStats.getTotalRxBytes();
double ttotalGprs = TrafficStats.getTotalTxBytes();
double rgprs = TrafficStats.getMobileRxBytes();
double tgprs = TrafficStats.getMobileTxBytes();
double rwifi = rtotalGprs - rgprs;
double twifi = ttotalGprs - tgprs;
totalWifi = rwifi + twifi;
return totalWifi;


}


2.用一个TextView来显示一下我们统计的流量数据:


 


3.然后我们新建一个线程用handler更新UI:


new Thread(new Runnable() {


@Override
public void run() {
while(true){


//获取当前时刻
double currentTime = System.currentTimeMillis();
// getWifiTraffic(currentTime);


获取当前时刻的Wifi流量
double totalWifi01 = getWifiTraffic(currentTime);


//让线程休眠1秒钟
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}


//获取1秒钟之后的时刻
double frontTime = System.currentTimeMillis();
// 获取一秒钟之后时刻所对应的Wifi使用流量
double totalWifi02 = getWifiTraffic(frontTime);


//两者相减得到这1秒钟所产生的Wifi流量
double errorTraffic = totalWifi02 - totalWifi01;


//这里之所以有一个流量<512b,不将其计入流量统计的原因就是由于我前面提及的本地进程产生的本地流量,如果不减的话,你会发现Android会把不联网状态下


//本地进程之间交互的本地流量也计算进去,我测试了一下大概在每秒钟200b左右
if(errorTraffic < 512){
errorTraffic = 1;
}
//将byte转化为为Mb,1048576=1024*1024,只不过在实际统计中计算会有少许偏差,小伙伴们可根据实际情况微调
wf += errorTraffic/1048576;
wifiTraffic = df.format(wf);
// Log.i("使用的流量", wifiTraffic + "");
Message message = new Message();
message.what = 1;
handler.sendMessage(message);
}
}
}).start();


 


final Handler handler = new Handler{ 


public void handleMessage(Message msg){
super.handleMessage(msg);
if(msg.what == 1){


//当流量小于1时,由于0.5这样的数我们会看到手机上会显示为.5,因此在前面加一个0以显示完整
if(Double.parseDouble(wifiTraffic) < 1){


tv.setText("0" + wifiTraffic + "MB");
}
else{
tv.setText(wifiTraffic + "MB");
}
}
}
};


下面贴一下整段代码:


import android.app.Activity;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.net.TrafficStats;
import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.widget.TextView;
import android.widget.Toast;


public class MainActivity extends Activity {
double totalWifi;
public static String wifiTraffic ;
public static double wf =0;
private TextView textView;
private WifiManager wifiManager;
public static int wifiStr;
DecimalFormat df = new DecimalFormat(".##");
private TextView tv;
private Handler handler1= null;
int hours = 0,minutes = 0,seconds = 0;


@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);


textView = (TextView)findViewById(R.id.textView);
wifiManager = (WifiManager)getSystemService(Context.WIFI_SERVICE);
wifiStr = wifiManager.getWifiState();


if(wifiStr != 3){
Toast.makeText(this, "Wifi未连接", 1000).show();
}
if(wifiStr == 3){
final Handler handler = new Handler(){
public void handleMessage(Message msg){
super.handleMessage(msg);
if(msg.what == 1){
if(Double.parseDouble(wifiTraffic) < 1){
Log.i("wifiTraffic", wifiTraffic);
textView.setText("0" + wifiTraffic + "MB");
}
else{
textView.setText(wifiTraffic + "MB");
}
}
}
};
tv = (TextView)findViewById(R.id.tv3);


if(wifiStr == 3){
handler1 = new Handler(){


public void handleMessage(Message msg1){
super.handleMessage(msg1);
if(msg1.what == 1){
tv.setText(new DecimalFormat("00").format(hours) + ":" + 
new DecimalFormat("00").format(minutes) + ":" + new DecimalFormat("00").format(seconds));
}
}
};
}


new Thread(new Runnable() {
public void run(){
for(int i = 0;;i++){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
seconds++;
Message msg1 = new Message();
msg1.what = 1;
handler1.sendMessage(msg1);
if(seconds == 60){
seconds = 0;
minutes++;
if(minutes == 60){
minutes = 0;
hours++;
}
}
}


}
}).start();


new Thread(new Runnable() {


@Override
public void run() {
while(true){
double currentTime = System.currentTimeMillis();
// getWifiTraffic(currentTime);
double totalWifi01 = getWifiTraffic(currentTime);;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
double frontTime = System.currentTimeMillis();
// getWifiTraffic(frontTime);
double totalWifi02 = getWifiTraffic(frontTime);
double errorTraffic = totalWifi02 - totalWifi01;
if(errorTraffic < 512){
errorTraffic = 1;
}


wf += errorTraffic/1111500;
wifiTraffic = df.format(wf);
// Log.i("使用的流量", wifiTraffic + "");
Message message = new Message();
message.what = 1;
handler.sendMessage(message);




}
}
}).start();
}


}
public double getWifiTraffic(double time){
double rtotalGprs = TrafficStats.getTotalRxBytes();
double ttotalGprs = TrafficStats.getTotalTxBytes();
double rgprs = TrafficStats.getMobileRxBytes();
double tgprs = TrafficStats.getMobileTxBytes();
double rwifi = rtotalGprs - rgprs;
double twifi = ttotalGprs - tgprs;
totalWifi = rwifi + twifi;
return totalWifi;
//totalWifi = rtotalGprs + ttotalGprs;
}


}


1、TrafficStats类的使用

以下结论,是自己真机实测的结果,与自己在网上看到的不同,大家可自测验证。

(1)getMobile...方法,获取Gprs/3G流量

(2)getTotal...方法,获取Gprs/3G+Wifi的流量

以上两类方法统计的都是,从打开网络开始,到关闭网络,这一段时间内使用的流量。例如:10点打开,11点关闭,那么getMobileRxBytes方法,回返的是这段时间内Gprs/3G接受到的字节数。

(3)getUid...方法,获取某个网络UID的流量。这类方法,返回的是,从开机到关机,某个网络UID(我理解就是某个应用,如果不对,请在评论中指正)使用的Gprs/3G+Wifi的流量


2、getUid...方法的使用

以下这段代码是网上找的,出处找不到了,希望原作者不要介意啊

List<PackageInfo> packinfos = pm.getInstalledPackages(PackageManager.GET_UNINSTALLED_PACKAGES | PackageManager.GET_PERMISSIONS);  
for (PackageInfo info : packinfos) {  String[] premissions = info.requestedPermissions;  if (premissions != null && premissions.length > 0) {  for (String premission : premissions) {  if ("android.permission.INTERNET".equals(premission)) {  // System.out.println(info.packageName+"访问网络");  int uid = info.applicationInfo.uid;  long rx = TrafficStats.getUidRxBytes(uid);  long tx = TrafficStats.getUidTxBytes(uid);  if (rx < 0 || tx < 0) {  System.out.println(info.packageName + "没有产生流量");  } else {  System.out.println(info.packageName + "的流量信息:");  System.out.println("下载的流量" + Formatter.formatFileSize(this, rx));  System.out.println("上传的流量" + Formatter.formatFileSize(this, tx));  }  }  }  System.out.println("---------");  }  
} 
3、获取流量信息的Service类

(1)因为两个广播都需要动态注册,所以写成了Service

(2)getMobile...和getTotal...方法获取的都是从打开网络开始,到关闭网络,这一段时间内使用的流量。

因此要在网络正在关闭时获取的就是这段时间的流量,WifiManager.WIFI_STATE_DISABLING表示的就是这个状态

(3)Gprs/3G貌似没有类似的状态,可以被监控到,只有,State.CONNECTED和State.DISCONNECTED。但是处于State.DISCONNECTED这个状态时,getMobile...方法获取到的值就都是0了

所有,我不得不在State.CONNECTED这个状态开始时,开启线程用于获取Gprs/3G的流量,直到我获取的到数据为0时,保存上一次的数据。

如果大家有更好的方法,请务必告诉我啊!

package forrest.forassist.service;  import android.app.Service;  
import android.content.BroadcastReceiver;  
import android.content.Context;  
import android.content.Intent;  
import android.content.IntentFilter;  
import android.net.ConnectivityManager;  
import android.net.NetworkInfo;  
import android.net.NetworkInfo.State;  
import android.net.TrafficStats;  
import android.net.wifi.WifiManager;  
import android.os.IBinder;  
import android.text.format.Formatter;  
import android.util.Log;  
import forrest.forassist.db.MySQLiteDatabase;  
import forrest.forassist.utils.Util;  public class TrafficService extends Service {  private TrafficReceiver tReceiver;  private WifiManager wifiManager;  private ConnectivityManager cManager;  public IBinder onBind(Intent intent) {  return null;  }  public void onCreate() {  // WifiManager,ConnectivityManager  wifiManager = (WifiManager) this.getSystemService(Context.WIFI_SERVICE);  cManager = (ConnectivityManager) this.getSystemService(Context.CONNECTIVITY_SERVICE);  // 注册TrafficReceiver  tReceiver = new TrafficReceiver();  IntentFilter filter = new IntentFilter();  filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);  filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);  registerReceiver(tReceiver, filter);  super.onCreate();  }  public int onStartCommand(Intent intent, int flags, int startId) {  return super.onStartCommand(intent, flags, startId);  }  private class TrafficReceiver extends BroadcastReceiver {  private String action = "";  private static final String TAG = "TrafficReceiver";  long mobileRx;  long mobileTx;  public void onReceive(Context context, Intent intent) {  action = intent.getAction();  if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) {  if (wifiManager.getWifiState() == WifiManager.WIFI_STATE_DISABLING) {  Log.i(TAG, "WIFI_STATE_DISABLING");  long wifiDown = TrafficStats.getTotalRxBytes() - TrafficStats.getMobileRxBytes();  long wifiUp = TrafficStats.getTotalTxBytes() - TrafficStats.getMobileTxBytes();  MySQLiteDatabase sqLite = new MySQLiteDatabase(context); // 打开数据库  sqLite.insertWifi(Util.todayDate, wifiDown, wifiUp);  sqLite.closeDB();  Log.i(TAG, "wifi下载流量" + Formatter.formatFileSize(context, wifiDown));  Log.i(TAG, "wifi上传流量" + Formatter.formatFileSize(context, wifiUp));  }  } else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) {  Log.i(TAG, "CONNECTIVITY_ACTION");  NetworkInfo networkInfo = cManager.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);  State state = networkInfo.getState();  if (state == State.CONNECTED) {  Log.i(TAG, "State.CONNECTED");  // 开始不断获取最近的流量信息,值为0时,跳过  new Thread() {  public void run() {  long mobileRxType = TrafficStats.getMobileRxBytes();  long mobileTxType = TrafficStats.getMobileTxBytes();  if (mobileRxType + mobileTxType != 0) {  try {  mobileRx = mobileRxType;  mobileTx = mobileTxType;  Log.i(TAG, "mobileRx:" + mobileRx);  Log.i(TAG, "mobileTx:" + mobileTx);  Thread.sleep(1000);  run();  } catch (InterruptedException e) {  e.printStackTrace();  }  } else {  // 写入数据库  Log.i(TAG, "写入数据库");  MySQLiteDatabase sqLite = new MySQLiteDatabase(TrafficService.this);  sqLite.insertGprs(Util.todayDate, mobileRx, mobileTx);  sqLite.closeDB();  }  };  }.start();  }   }  }  }  public void onDestroy() {  unregisterReceiver(tReceiver);  super.onDestroy();  }  
}  






本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/293157.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

mybatis 查询的时间不对_程序员,Mybatis 你踩过坑吗?

点击上方“Java基基”&#xff0c;选择“设为星标”做积极的人&#xff0c;而不是积极废人&#xff01;源码精品专栏 中文详细注释的开源项目RPC 框架 Dubbo 源码解析网络应用框架 Netty 源码解析消息中间件 RocketMQ 源码解析数据库中间件 Sharding-JDBC 和 MyCAT 源码解析作业…

李洪强iOS开发之- 实现简单的弹窗

李洪强iOS开发之- 实现简单的弹窗 实现的效果: 112222222222223333333333333333

数据挖掘模型生命周期管理

为成功地利用预测模型&#xff0c;您需要从开发阶段直至生产环境对模型进行全面管理。模型生命周期管理是由以下阶段组成的高效交替过程&#xff1a; • 确定业务目标 • 访问和管理数据 • 开发模型 • 验证模型 • 部署模型 • 监控模型 确定业务目标 第一步确定所需模型以及…

.NET 编码的基础知识

点击上方蓝字关注我们.NET 编码的一些基本概念和分析简单的类型概念Hex &#xff08;16进制&#xff09;byte 字节 范围是&#xff1a;0~255&#xff0c;二进制下的范围就是00000000~11111111&#xff0c;相当于1字节。byte[] 字节数组bit 比特&#xff0c;只有2种状态&#xf…

Android之android.os.NetworkOnMainThreadException异常

今天用handler.post(Runnable);的时候出现了android.os.NetworkOnMainThreadException Runnable里面使用的访问网络请求&#xff0c;网络请求是不可以放在主线程里面的&#xff0c;所以出现了这个问题 因为我想执行 handler.post(runnable); Runnable runnable new Runnable(…

什么是MVC?MVC框架的优势和特点

目录 一、什么是MVC 二、MVC模式的组成部分和工作原理 1、模型&#xff08;Model&#xff09; 2、视图&#xff08;View&#xff09; 3、控制器&#xff08;Controller&#xff09; 三、MVC模式的工作过程如下&#xff1a; 用户发送请求&#xff0c;请求由控制器处理。 …

每日英语:The First Day On A Job Is Tough Work

Why is the first day on the job often the worst?New employees tend to be greeted with stacks of benefits paperwork, technology hassles and dull presentations about company culture. hassle&#xff1a;激战&#xff0c;争辩&#xff0c;麻烦事    But some c…

docker没有下载完全_会用Docker的人都别装了,这多简单呐

学术又官方的说法Docker 是一个开源的应用容器引擎&#xff0c;让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux机器或Windows 机器上,也可以实现虚拟化,容器是完全使用沙箱机制,相互之间不会有任何接口。没用过的人能看懂这段话&#xf…

数据挖掘领域十大经典算法初探

一、C4.5 C4.5&#xff0c;是机器学习算法中的一个分类决策树算法&#xff0c; 它是决策树(决策树也就是做决策的节点间的组织方式像一棵树&#xff0c;其实是一个倒树)核心算法 ID3的改进算法&#xff0c;所以基本上了解了一半决策树构造方法就能构造它。 决策树构造方法其实就…

WPF MVVM实例三

在没给大家讲解wpf mwm示例之前先给大家简单说下MVVM理论知识&#xff1a;WPF技术的主要特点是数据驱动UI,所以在使用WPF技术开发的过程中是以数据为核心的&#xff0c;WPF提供了数据绑定机制&#xff0c;当数据发生变化时&#xff0c;WPF会自动发出通知去更新UI。我们使用模式…

linux命令chown和chmod什么区别

chown一般用来 更改属主。也就是文件所属用户。chmod功能要比chown要强大。可更改文件所有属性和权限。只有管理员账户才有权限用此命令。chown 是修改文件的所有者(owner),和所属组(group)chmod 是修改文件的执行属性(所属组,所属者以及其他人所有的权限,比如 读,写,执行)

stringcstdlibctimecstdargctimectypecmathclimits

转载地址&#xff1a;http://blog.csdn.net/kz_ang/article/details/7767335 <string>头文件 string构造函数 string s  生成一个空字符串s string s(str)  拷贝构造函数,生成str对象的复制品 string s(str,stridx)  将字符串str对象内"始于位置stridx"…

背包模板

背包模板&#xff0c;自己总结&#xff0c;做题可直接套用。 0-1背包 有N件物品和一个容量为V的背包。第i件物品的费用是c[i]&#xff0c;价值是w[i]。求解将哪些物品装入背包可使价值总和最大。 公式&#xff1a; f[i][v]max{f[i-1][v],f[i-1][v-c[i]]w[i]} 伪代码&#xff1a…

C3P0 释放连接 的问题

2019独角兽企业重金招聘Python工程师标准>>> 记录一下使用C3P0 时犯的低级错误&#xff0c;没有关闭connection 达到连接池最大限制后造成程序假死的现象&#xff0c;以后得仔细再仔细了&#xff01; 转载于:https://my.oschina.net/fusxian/blog/146700

python随机抽取人名_python的random

python的random函数更多的random用法可参阅&#xff1a;random --- 生成伪随机数 - Python 3.7.4 文档​docs.python.org以下使用了&#xff1a;洗牌&#xff1a;random.shuffle随机抽取元素&#xff0c;且元素不重复&#xff1a;random.sample随机抽取元素&#xff0c;且元素可…

PL/SQL Developer使用技巧总结

1、PL/SQL Developer记住登陆密码 在使用PL/SQL Developer时&#xff0c;为了工作方便希望PL/SQL Developer记住登录Oracle的用户名和密码&#xff1b; 设置方法&#xff1a;PL/SQL Developer 7.1.2 ->tools->Preferences->Oracle->Logon History &#xff0c; “…

Windows 11/10 正式版全新 ISO 镜像下载

微软现已发布 Windows 11/10 正式版&#xff08;版本 21H2&#xff09;全新 ISO 镜像。Windows 11 版本 21H2 全新镜像集成了 2021 年 10 月更新、11 月更新和 12 月更新。Windows 10 版本 21H2 全新镜像集成了 2021 年 11 月更新和 12 月更新。版本区别Windows 11/10 消费者版…