Android实现流量统计和网速监控悬浮窗
很多安全卫士类软件都实现了网速监测功能,也算是一个比较实用的功能。Android下,TrafficStats类实现了对流量的统计。
[java] view plain copy
- 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(intuid) //获取某个网络UID的发送字节数
这些就是TrafficStats提供的一些接口。那么,我们首先要创建一个桌面悬浮窗,用于显示网速。然后再Service里面,显示悬浮窗。
[java] view plain copy
- import android.app.Service;
- import android.content.Intent;
- import android.graphics.PixelFormat;
- import android.os.Binder;
- import android.os.IBinder;
- import android.util.Log;
- import android.view.Gravity;
- import android.view.LayoutInflater;
- import android.view.MotionEvent;
- import android.view.View;
- import android.view.View.OnClickListener;
- import android.view.View.OnTouchListener;
- import android.view.WindowManager;
- import android.view.WindowManager.LayoutParams;
- import android.widget.LinearLayout;
- import android.widget.TextView;
- import com.yyh.utils.WidgetUtils;
- public class ManagerService extends Service {
- private static final String TAG = "ManagerService";
- public LinearLayout mFloatLayout;
- public WindowManager.LayoutParams wmParams;
- public WindowManager mWindowManager;
- public TextView mFloatView;
- private ServiceBinder binder = new ServiceBinder();
- @Override
- public void onCreate() {
- super.onCreate();
- createFloatView();
- }
- @Override
- public int onStartCommand(Intent intent, int flags, int startId) {
- return START_STICKY_COMPATIBILITY;
- }
- @Override
- public IBinder onBind(Intent intent) {
- return binder;
- }
- @Override
- public void onTrimMemory(int level) {
- Log.i("test", " onTrimMemory...");
- }
- /** 创建悬浮窗 */
- private void createFloatView() {
- wmParams = new WindowManager.LayoutParams();
- mWindowManager = (WindowManager) getApplication().getSystemService(getApplication().WINDOW_SERVICE);
- wmParams.type = LayoutParams.TYPE_SYSTEM_ALERT;// 设置window
- // type为TYPE_SYSTEM_ALERT
- wmParams.format = PixelFormat.RGBA_8888;// 设置图片格式,效果为背景透明
- wmParams.flags = LayoutParams.FLAG_NOT_FOCUSABLE;// 设置浮动窗口不可聚焦(实现操作除浮动窗口外的其他可见窗口的操作)
- wmParams.gravity = Gravity.LEFT | Gravity.TOP;// 默认位置:左上角
- wmParams.width = WidgetUtils.dpToPx(getApplicationContext(), 65);
- wmParams.height = WindowManager.LayoutParams.WRAP_CONTENT;
- wmParams.x = (WidgetUtils.getScreenWidth(getApplicationContext()) - wmParams.width) / 2;// 设置x、y初始值,相对于gravity
- wmParams.y = 10;
- // 获取浮动窗口视图所在布局
- LayoutInflater inflater = LayoutInflater.from(getApplication());
- mFloatLayout = (LinearLayout) inflater.inflate(R.layout.float_layout, null);
- mWindowManager.addView(mFloatLayout, wmParams);// 添加mFloatLayout
- mFloatView = (TextView) mFloatLayout.findViewById(R.id.speed);
- mFloatLayout.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED), View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
- // 设置监听浮动窗口的触摸移动
- mFloatView.setOnTouchListener(new OnTouchListener() {
- @Override
- public boolean onTouch(View v, MotionEvent event) {
- // getRawX是触摸位置相对于屏幕的坐标,getX是相对于按钮的坐标
- wmParams.x = (int) event.getRawX() - mFloatView.getMeasuredWidth() / 2;
- Log.i(TAG, "RawX" + event.getRawX());
- Log.i(TAG, "X" + event.getX());
- wmParams.y = (int) event.getRawY() - mFloatView.getMeasuredHeight() / 2 - 25;// 减25为状态栏的高度
- Log.i(TAG, "RawY" + event.getRawY());
- Log.i(TAG, "Y" + event.getY());
- mWindowManager.updateViewLayout(mFloatLayout, wmParams);// 刷新
- return false; // 此处必须返回false,否则OnClickListener获取不到监听
- }
- });
- mFloatView.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View arg0) {
- // do something... 跳转到应用
- }
- });
- }
- public void setSpeed(String str) {
- mFloatView.setText(str.toString());
- }
- @Override
- public void onDestroy() {
- super.onDestroy();
- if (mFloatLayout != null && mWindowManager != null) {
- mWindowManager.removeView(mFloatLayout);// 移除悬浮窗口
- }
- startService(new Intent(this, ManagerService.class));
- }
- class ServiceBinder extends Binder {
- public ManagerService getService() {
- return ManagerService.this;
- }
- }
- }
然后构造一个网速监测的工具类,用于获取流量变化信息。
[java] view plain copy
- import java.io.FileNotFoundException;
- import java.io.IOException;
- import java.io.RandomAccessFile;
- import java.math.BigDecimal;
- import java.util.Timer;
- import java.util.TimerTask;
- import android.content.Context;
- import android.content.pm.ApplicationInfo;
- import android.content.pm.PackageManager;
- import android.content.pm.PackageManager.NameNotFoundException;
- import android.net.TrafficStats;
- import android.os.Handler;
- import android.os.Message;
- import android.util.Log;
- /**
- * 应用的流量信息
- * @author yuyuhang
- */
- public class TrafficInfo {
- private static final int UNSUPPORTED = -1;
- private static final String LOG_TAG = "test";
- private static TrafficInfo instance;
- static int uid;
- private long preRxBytes = 0;
- private Timer mTimer = null;
- private Context mContext;
- private Handler mHandler;
- /** 更新频率(每几秒更新一次,至少1秒) */
- private final int UPDATE_FREQUENCY = 1;
- private int times = 1;
- public TrafficInfo(Context mContext, Handler mHandler, int uid) {
- this.mContext = mContext;
- this.mHandler = mHandler;
- this.uid = uid;
- }
- public TrafficInfo(Context mContext, Handler mHandler) {
- this.mContext = mContext;
- this.mHandler = mHandler;
- }
- public static TrafficInfo getInstant(Context mContext, Handler mHandler) {
- if (instance == null) {
- instance = new TrafficInfo(mContext, mHandler);
- }
- return instance;
- }
- /**
- * 获取总流量
- */
- public long getTrafficInfo() {
- long rcvTraffic = UNSUPPORTED; // 下载流量
- long sndTraffic = UNSUPPORTED; // 上传流量
- rcvTraffic = getRcvTraffic();
- sndTraffic = getSndTraffic();
- if (rcvTraffic == UNSUPPORTED || sndTraffic == UNSUPPORTED)
- return UNSUPPORTED;
- else
- return rcvTraffic + sndTraffic;
- }
- /**
- * 获取下载流量 某个应用的网络流量数据保存在系统的/proc/uid_stat/$UID/tcp_rcv | tcp_snd文件中
- */
- public long getRcvTraffic() {
- long rcvTraffic = UNSUPPORTED; // 下载流量
- rcvTraffic = TrafficStats.getUidRxBytes(uid);
- if (rcvTraffic == UNSUPPORTED) { // 不支持的查询
- return UNSUPPORTED;
- }
- Log.i("test", rcvTraffic + "--1");
- RandomAccessFile rafRcv = null, rafSnd = null; // 用于访问数据记录文件
- String rcvPath = "/proc/uid_stat/" + uid + "/tcp_rcv";
- try {
- rafRcv = new RandomAccessFile(rcvPath, "r");
- rcvTraffic = Long.parseLong(rafRcv.readLine()); // 读取流量统计
- } catch (FileNotFoundException e) {
- Log.e(LOG_TAG, "FileNotFoundException: " + e.getMessage());
- rcvTraffic = UNSUPPORTED;
- } catch (IOException e) {
- Log.e(LOG_TAG, "IOException: " + e.getMessage());
- e.printStackTrace();
- } finally {
- try {
- if (rafRcv != null)
- rafRcv.close();
- if (rafSnd != null)
- rafSnd.close();
- } catch (IOException e) {
- Log.w(LOG_TAG, "Close RandomAccessFile exception: " + e.getMessage());
- }
- }
- Log.i("test", rcvTraffic + "--2");
- return rcvTraffic;
- }
- /**
- * 获取上传流量
- */
- public long getSndTraffic() {
- long sndTraffic = UNSUPPORTED; // 上传流量
- sndTraffic = TrafficStats.getUidTxBytes(uid);
- if (sndTraffic == UNSUPPORTED) { // 不支持的查询
- return UNSUPPORTED;
- }
- RandomAccessFile rafRcv = null, rafSnd = null; // 用于访问数据记录文件
- String sndPath = "/proc/uid_stat/" + uid + "/tcp_snd";
- try {
- rafSnd = new RandomAccessFile(sndPath, "r");
- sndTraffic = Long.parseLong(rafSnd.readLine());
- } catch (FileNotFoundException e) {
- Log.e(LOG_TAG, "FileNotFoundException: " + e.getMessage());
- sndTraffic = UNSUPPORTED;
- } catch (IOException e) {
- Log.e(LOG_TAG, "IOException: " + e.getMessage());
- e.printStackTrace();
- } finally {
- try {
- if (rafRcv != null)
- rafRcv.close();
- if (rafSnd != null)
- rafSnd.close();
- } catch (IOException e) {
- Log.w(LOG_TAG, "Close RandomAccessFile exception: " + e.getMessage());
- }
- }
- return sndTraffic;
- }
- /**
- * 获取当前下载流量总和
- */
- public static long getNetworkRxBytes() {
- return TrafficStats.getTotalRxBytes();
- }
- /**
- * 获取当前上传流量总和
- */
- public static long getNetworkTxBytes() {
- return TrafficStats.getTotalTxBytes();
- }
- /**
- * 获取当前网速,小数点保留一位
- */
- public double getNetSpeed() {
- long curRxBytes = getNetworkRxBytes();
- if (preRxBytes == 0)
- preRxBytes = curRxBytes;
- long bytes = curRxBytes - preRxBytes;
- preRxBytes = curRxBytes;
- //int kb = (int) Math.floor(bytes / 1024 + 0.5);
- double kb = (double)bytes / (double)1024;
- BigDecimal bd = new BigDecimal(kb);
- return bd.setScale(1, BigDecimal.ROUND_HALF_UP).doubleValue();
- }
- /**
- * 开启流量监控
- */
- public void startCalculateNetSpeed() {
- preRxBytes = getNetworkRxBytes();
- if (mTimer != null) {
- mTimer.cancel();
- mTimer = null;
- }
- if (mTimer == null) {
- mTimer = new Timer();
- mTimer.schedule(new TimerTask() {
- @Override
- public void run() {
- if(times == UPDATE_FREQUENCY){
- Message msg = new Message();
- msg.what = 1;
- //msg.arg1 = getNetSpeed();
- msg.obj = getNetSpeed();
- mHandler.sendMessage(msg);
- times = 1;
- } else {
- times++;
- }
- }
- }, 1000, 1000); // 每秒更新一次
- }
- }
- public void stopCalculateNetSpeed() {
- if (mTimer != null) {
- mTimer.cancel();
- mTimer = null;
- }
- }
- /**
- * 获取当前应用uid
- */
- public int getUid() {
- try {
- PackageManager pm = mContext.getPackageManager();
- ApplicationInfo ai = pm.getApplicationInfo(mContext.getPackageName(), PackageManager.GET_ACTIVITIES);
- return ai.uid;
- } catch (NameNotFoundException e) {
- e.printStackTrace();
- }
- return -1;
- }
- }
然后再Activity里面,就需要去启动Service,以显示悬浮窗,然后TrafficInfo通过Handler,把当前网速发给Activity,Activity调用Service的方法了来更新悬浮窗的View。
[java] view plain copy
- import java.util.List;
- import android.app.ActivityManager;
- import android.app.ActivityManager.RunningAppProcessInfo;
- import android.content.ComponentName;
- import android.content.Context;
- import android.content.Intent;
- import android.content.ServiceConnection;
- import android.os.Bundle;
- import android.os.Handler;
- import android.os.IBinder;
- import android.os.Message;
- import android.support.v7.app.ActionBarActivity;
- import android.util.Log;
- import android.widget.TextView;
- import com.yyh.utils.TrafficInfo;
- public class MainActivity extends ActionBarActivity {
- private ActivityManager mActivityManager;
- private TextView mTextView;
- Handler mHandler;
- TrafficInfo speed;
- ManagerService service;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- mActivityManager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
- mTextView = (TextView) findViewById(R.id.tv);
- try {
- mHandler = new Handler() {
- @Override
- public void handleMessage(Message msg) {
- if (msg.what == 1) {
- mTextView.setText(msg.obj + "kb/s");
- if(service != null)
- service.setSpeed(msg.obj+"kb/s"); // 设置网速
- }
- super.handleMessage(msg);
- }
- };
- speed = new TrafficInfo(this,mHandler,TrafficInfo.getUid());
- speed.startCalculateNetSpeed(); // 开启网速监测
- } catch (Exception e) {
- e.printStackTrace();
- }
- Log.i("test","总流量="+speed.getTrafficInfo());
- Intent intent = new Intent(MainActivity.this, ManagerService.class);
- bindService(intent, conn, Context.BIND_AUTO_CREATE);
- }
- private ServiceConnection conn = new ServiceConnection() {
- public void onServiceConnected(ComponentName name, IBinder binder) {
- service = ((ManagerService.ServiceBinder) binder).getService();
- }
- public void onServiceDisconnected(ComponentName name) {
- service = null;
- }
- };
- @Override
- protected void onDestroy() {
- super.onDestroy();
- speed.stopCalculateNetSpeed();
- unbindService(conn);
- }
- }
这样,就能够显示悬浮窗。如果还需要后台运行,那Service就需要常驻不被杀死,这部分请参考我另一篇博文:Android 通过JNI实现守护进程,保证Service服务不被杀死
附上Demo源码:Android 流量与网速监测(悬浮窗) 源码
原文地址:http://blog.csdn.net/yyh352091626/article/details/50599621
Android实现流量统计和网速监控悬浮窗相关推荐
- Windows网络通信流量和网速监控设计(一)
第二篇文章连接 文章目录 三种数据通信传输模式 一.单工通信 二.半双工通信 三.全双工通信 相关基础知识 1.__stdcall 2.GetIfTable()函数 3.MIB_IFTABLE结构体 ...
- android中检测网速,Android 流量与网速监测(悬浮窗) 源码
[实例简介] 对应博文链接:http://blog.csdn.net/yyh352091626/article/details/50599621 Android 实现流量与网速监测(悬浮窗) 源码. ...
- 网络知识:内网、外网、宽带、带宽、流量、网速之间的联系?
相信很多人都不知道内网.外网.宽带.带宽.流量.网速之间的区别与联系,今天小编给大家介绍一下,希望对大家能有所帮助! 一.带宽与宽带的区别是什么? 带宽是量词,指的是网速的大小,比如1Mbps的意思是 ...
- 物联网卡和流量卡网速对比,看看谁更强?
物联网卡和流量卡网速对比,看看谁更强? 物联网卡是运营商面向物联网企业提供的一种智能设备数据接入业务,物联网卡作为智能设备信息传递的桥梁,来实现物与物.物与人的交互结合,可以说物联网卡也是一种流量卡, ...
- 了解内网、外网、宽带、带宽、流量、网速
了解内网.外网.宽带.带宽.流量.网速. 一.带宽与宽带的区别是什么? 带宽是指在单位时间内(1秒)内能传输的数据量.网络和高速公路类似,带宽越大,就类似高速公路的车道越多,其通行能力越强.把城市的道 ...
- Android聊天室源码开发,悬浮窗的实现及封装思路
为了实现语音聊天室源码的多场景应用,悬浮小窗口在语音聊天室源码开发中还是比较常见的需求,主要是指用户在语音连麦过程中打开其它界面或者退到桌面时语音连麦不会中断且会有一个悬浮小窗口位于最上层,接下来我们 ...
- EveryDay-Shell之ifconfig输出详解“——netspeed.sh网速监控脚本
对应文件中,比如p1p1设备对应目录: $cd /sys/class/net/p1p1/statistics $ls -l -r--r--r-- 1 root root 4096 2月 4 14: ...
- 99%的人都不知道内网、外网、宽带、带宽、流量、网速之间的区别与联系
大纲结构 一.带宽与宽带的区别是什么? 带宽是量词,指的是网速的大小,比如1Mbps的意思是一兆比特每秒,这个数值就是指带宽. 宽带是名词,说明网络的传输速率很高 .宽带的标准各不相同,最初认为128 ...
- 【计算机网络】了解内网、外网、宽带、带宽、流量、网速
文章目录 一.带宽与宽带的区别是什么? 1.宽带 2.带宽 3.流量 二.带宽.网速和流量之间的关系 三.上行带宽和下行带宽是什么意思?各有什么作用? 四.服务器的上行和下行带宽理解 五.内网ip和外 ...
- 内网、外网、宽带、带宽、流量、网速之间的区别与联系
目录 一.带宽与宽带的区别是什么? 二.带宽.网速和流量之间的关系 三.上行带宽和下行带宽是什么意思?各有什么作用? 四.服务器的上行和下行带宽理解 五.内网ip和外网ip区别 一.带宽与宽带的区别是 ...
最新文章
- 手把手教你如何做建模竞赛(baseline代码讲解)
- 【RecyclerView】 十二、RecyclerView 数据更新 ( 修改单条数据 | 批量修改数据 )
- Win10 UWP开发系列:解决Win10不同版本的Style差异导致的兼容性问题
- Java 集合系列17之 TreeSet详细介绍(源码解析)和使用示例
- linux ping策略打开_linux ping策略打开_如何在Linux服务器禁止和开启ping包 互联网技术圈 互联网技术圈......
- 后台服务系统之搭建ZooKeeper注册中心
- 如何理解VMware内存资源管理
- 杭电1262--寻找素数对(打表)
- 141. 环形链表 golang
- Struts2基础知识(二)
- 苹果推出App Store搜索建议功能
- Python使用K-means聚类算法进行分类案例一则
- RISC-V架构能否有效挑战ARM和英特尔?
- Django简介与基本命令
- 39. 确保判别式是纯函数
- 阶段3 1.Mybatis_07.Mybatis的连接池及事务_3 mybatis连接池的分类
- 如何在网页中播放FLV文件的代码
- 最全中华古诗词数据库,收录30多万诗词
- 全国计算机二级证书NO00000,计算机二级成绩查询
- Android Studio打开之后class显示灰色 代码没有颜色区分 输入没了提示的解决方法
热门文章
- uniapp 日期时间 计算
- Linux中修改HTTP默认主页
- Kruskal算法 数据结构 浙江大学 陈越、何钦铭
- QGIS编译---QGIS3.10.6 + Qt5.11.2 + VS2015 ---32位版本
- moss2007 是什么_MOSS 2007站点权限
- 如何关掉visual studio 2012 实时调试器
- C语言实现程序的暂停
- 牛客 NC24858 [USACO 2009 Nov S]Job Hunt
- 2019辽宁公务员考试行测常识大全:公务员常识40000问(五十九)(2)
- css mix-blend,CSS混合模式mix-blend-mode/background-blend-mode简介