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(); }
}
Android之TrafficStats实现流量实时监测相关推荐
- android基于蓝牙实验,基于Android智能蓝牙的血糖实时监测系统的设计与实现
摘要: 糖尿病是目前严重危害人类健康的一种疾病,掌握血糖的变化是现阶段临床上预防和控制糖尿病最重要也是最有效的方法.目前市场上已有的血糖仪大部分是以电化学方法为基础,将检测结果保存到检测仪器中,不利于 ...
- Android中TrafficStats流量监控类
这个类提供了网络流量统计,这个统计包括上传和下载的字节数和网络数据包数.需要注意的是这个统计不能在所有的平台上使用,如果设备不支持的话,就会返回UNSUPPORTED. 常用函数: public st ...
- java实时获取android网速_Android实现网速实时监测工具类
### 前言 今天在做app功能的时候,突然涉及到要监测网络的实时速度,于是一番折腾,整合了下相关知识,方便以后使用.下面让我们来学习下我封装的一个网速实时监测类--NetSpeed吧 今天涉及内容: ...
- android统计流量,Android 获取手机整体流量使用情况以及某个应用的流量的统计
很多安全卫士类软件都实现了网速监测功能,也算是一个比较实用的功能.Android下,TrafficStats类实现了对流量的统计. /proc/uid_stat/uid/tcp_send ...
- Linux下网络流量实时监控工具 大全
Linux下网络流量实时监控工具 大全 在工作中发现,经常因为业务的原因,需要即时了解某台服务器网卡的流量,虽然公司也部署了cacti软件,但cacti是五分钟统计的,没有即时性,并且 有时候打开监控 ...
- Linux下网络流量实时监控工具大全
Linux下网络流量实时监控工具 大全 在工作中发现,经常因为业务的原因,需要即时了解某台服务器网卡的流量,虽然公司也部署了cacti软件,但cacti是五分钟统计的,没有即时性,并且有时候打开监控页 ...
- [激光原理与应用-51]:《激光焊接质量实时监测系统研究》-2-激光焊接及其物理现象
目录 2.1 激光焊接过程概述 2.1.1 激光焊接的特点 2.1.2 焊接质量的影响因素 2.1.3 激光焊接热源模型 2.1.4 激光焊接技术的发展前景与面临的挑战 2.2 激光焊接中的小孔效应及 ...
- 工业物联网案例:船舶航行安全实时监测系统
对于航运公司来说,如何对船舶以及进行安全及时和高效的管理是一个难题.传统的管理模式依赖有经验的员工进行巡查巡检,无法实时掌握船舶航行的有关信息,从而影响到决策的制定与实施. 船舶航行安全实时监测系统, ...
- 如何基于人体人脸跟踪实时监测心率?
华为AR Engine是什么? 华为AR Engine服务是一个用于在Android上构建增强现实应用的引擎.基于芯片平台整合AR核心算法,提供了运动跟踪.环境跟踪.人体和人脸跟踪等AR基础能力,通过 ...
最新文章
- 第52章,bitmap图像处理(从零开始学android),第52章、Bitmap图像处理(从零开始学Android)...
- Linux常用的基本命令02
- 任务管理器taskmgr查看几核
- zookeeper客户端练习(idea-Junit测试)
- codeforces 133A-C语言解题报告
- 神奇!未来物联网的能源——纸生电
- 自己动手写CPU之第五阶段(1)——流水线数据相关问题
- 如何在没有域的环境中搭建AlwaysOn(二)
- 报错解决:No module named tensorflow.contrib
- java简历自我评价_java程序员简历自我评价怎么写
- Vue3.0官方文档
- DirectX SDK 各版本开发包下载地址合集
- matlab绘制正弦波频谱图,matlab对正弦信号作FFT得到频谱图
- coderunner运行c语言提示错误,vscode安装及使用coderunner运行C程序教程
- java jtree 异步_[Java]JTree实现文件管理器的bug,请高手帮助 - 代码贴 - BCCN
- Cypress 简介
- 计算机网络ip地址在哪里设置,网络ip地址设置多少_电脑ip地址一般设置多少-win7之家...
- 为什么技术面过了却挂在了HR面试之”谈谈你的职业生涯规划“
- XP系统添加网络打印机步骤
- 51单片机-4G模块
热门文章
- 在 .NET 6 中使用 DATEONLY 和 TIMEONLY
- 【需要重视的BUG】:偷权限的情况
- C#基础:理解装箱与拆箱
- Build 2021 :正式发布.NET 6 Preview4
- .NET之Docker部署详细流程
- 4月 .NET 线上 Meetup,快来报名
- Dotnet中Span, Memory和ReadOnlySequence之浅见
- .NET 中依赖注入组件 Autofac 的性能漫聊
- 使用 C# 9 的records作为强类型ID - 路由和查询参数
- 这么多Apache顶级项目,SkyWalking为何一枝独秀?