You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Android中实现每秒更新的WiFi与移动数据网速监测功能

嘿,这个需求我之前帮朋友做过类似的,其实核心就是实时采集系统的网络流量数据,然后计算每秒的差值得到速度。我给你拆解成几个关键步骤,跟着来就能搞定:

一、先搞定必要的权限

首先得在AndroidManifest.xml里声明需要的权限,因为要读取网络状态和流量数据:

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<!-- 如果需要后台运行,还要加这个 -->
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />

这些都是正常权限,不需要动态申请,直接在Manifest里声明就行。

二、核心逻辑:计算网络速度

Android系统提供了TrafficStats类,专门用来获取网络流量的统计数据。它能分别返回WiFi和移动数据的累计接收/发送字节数。

注意:这些字节数是从设备开机到现在的累计值,所以我们需要每秒记录一次当前值,和上一次的差值就是这1秒内的流量,除以1秒就是速度啦

步骤大概是这样:

  1. 每秒获取一次WiFi和移动数据的累计流量值
  2. 和上一秒记录的值做差,得到这1秒的流量消耗
  3. 把字节数转换成用户友好的单位(KB/s 或 MB/s)

另外,我们还需要判断当前的网络类型,比如用户现在连的是WiFi还是移动数据,这样可以针对性地展示对应的速度,或者提示“未连接”。

三、实时更新UI

要实现每秒更新,我们可以用Handler来做定时任务(或者用协程,看你习惯哪种)。因为更新UI必须在主线程,所以Handler默认绑定主线程的Looper,刚好合适。

每次计算出速度后,直接更新TextView的内容就行,记得把数值格式化成易读的样式,比如保留一位小数,自动切换KB/s和MB/s。

四、完整代码示例

我给你写一个简单的Activity实现,直接就能跑起来:

1. Activity代码(Kotlin)

import android.net.ConnectivityManager
import android.net.TrafficStats
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity

class SpeedMeterActivity : AppCompatActivity() {
    private lateinit var wifiSpeedTv: TextView
    private lateinit var mobileSpeedTv: TextView
    private val mainHandler = Handler(Looper.getMainLooper())
    // 保存上一次的流量累计值
    private var lastWifiRxBytes = 0L
    private var lastMobileRxBytes = 0L

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_speed_meter)
        
        wifiSpeedTv = findViewById(R.id.tv_wifi_speed)
        mobileSpeedTv = findViewById(R.id.tv_mobile_speed)
        
        // 启动每秒更新的任务
        mainHandler.post(speedUpdateRunnable)
    }

    private val speedUpdateRunnable = object : Runnable {
        override fun run() {
            calculateAndDisplaySpeed()
            // 1秒后再次执行
            mainHandler.postDelayed(this, 1000)
        }
    }

    private fun calculateAndDisplaySpeed() {
        val connectivityManager = getSystemService(CONNECTIVITY_SERVICE) as ConnectivityManager
        val activeNetwork = connectivityManager.activeNetworkInfo

        // 获取当前WiFi和移动数据的累计接收字节数
        val currentWifiRx = TrafficStats.getWifiRxBytes()
        val currentMobileRx = TrafficStats.getMobileRxBytes()

        // 计算并显示WiFi速度
        if (currentWifiRx != TrafficStats.UNSUPPORTED && lastWifiRxBytes != 0L) {
            val speedBytesPerSecond = currentWifiRx - lastWifiRxBytes
            val speedKbPerSecond = speedBytesPerSecond / 1024.0
            val (speed, unit) = if (speedKbPerSecond > 1024) {
                Pair(speedKbPerSecond / 1024, "MB/s")
            } else {
                Pair(speedKbPerSecond, "KB/s")
            }
            wifiSpeedTv.text = String.format("WiFi: %.1f %s", speed, unit)
        }
        lastWifiRxBytes = currentWifiRx

        // 计算并显示移动数据速度
        if (currentMobileRx != TrafficStats.UNSUPPORTED && lastMobileRxBytes != 0L) {
            val speedBytesPerSecond = currentMobileRx - lastMobileRxBytes
            val speedKbPerSecond = speedBytesPerSecond / 1024.0
            val (speed, unit) = if (speedKbPerSecond > 1024) {
                Pair(speedKbPerSecond / 1024, "MB/s")
            } else {
                Pair(speedKbPerSecond, "KB/s")
            }
            mobileSpeedTv.text = String.format("移动数据: %.1f %s", speed, unit)
        }
        lastMobileRxBytes = currentMobileRx

        // 处理未连接的情况
        if (activeNetwork?.type != ConnectivityManager.TYPE_WIFI) {
            wifiSpeedTv.text = "WiFi: 未连接"
        }
        if (activeNetwork?.type != ConnectivityManager.TYPE_MOBILE) {
            mobileSpeedTv.text = "移动数据: 未连接"
        }
    }

    override fun onDestroy() {
        super.onDestroy()
        // 销毁时移除任务,避免内存泄漏
        mainHandler.removeCallbacks(speedUpdateRunnable)
    }
}

2. 布局文件(activity_speed_meter.xml)

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:gravity="center"
    android:padding="24dp">

    <TextView
        android:id="@+id/tv_wifi_speed"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="28sp"
        android:text="WiFi: --"/>

    <TextView
        android:id="@+id/tv_mobile_speed"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="28sp"
        android:layout_marginTop="24dp"
        android:text="移动数据: --"/>

</LinearLayout>
五、一些需要注意的坑
  1. 兼容性问题:部分老设备可能不支持TrafficStats,会返回TrafficStats.UNSUPPORTED,所以一定要做判断,避免崩溃。
  2. 网络状态监听:上面的代码用了activeNetworkInfo,但这个方法在API 29(Android 10)之后被废弃了。如果要兼容新版本,推荐用ConnectivityManager.NetworkCallback来监听网络状态变化,这样更准确。
  3. 后台运行:如果需要应用在后台也显示网速,得用前台服务(Foreground Service),否则Android 8以上系统会限制后台进程,导致更新停止。
  4. 内存泄漏:Handler如果持有Activity的引用,可能会导致内存泄漏,所以在Activity销毁时一定要移除回调,或者使用WeakHandler。

这样基本就能实现一个每秒更新的网速仪了,如果需要更复杂的功能(比如悬浮窗、历史流量统计),随时说,我再给你补充细节~

内容的提问来源于stack exchange,提问作者Farshan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 03:40:50