Android?獲取實時網(wǎng)速實現(xiàn)詳解
正文
最近接到個需求,需要計算WebView加載網(wǎng)頁時的網(wǎng)速。查詢了一下,Android沒有提供直接獲取網(wǎng)速的Api,但是提供了獲取流量的類TrafficStats。本文介紹如何使用Trafficstats來實現(xiàn)獲取網(wǎng)速功能。
TrafficStats簡介
TrafficStats提供了一些獲取設(shè)備從本次開機到目前為止傳輸/接收的流量的接口,如下:
| 方法 | 參數(shù) | 說明 |
|---|---|---|
| getTotalTxBytes | - | 獲取設(shè)備本次開機到目前為止,WI-FI、流量下傳輸?shù)淖止?jié)總數(shù)。 |
| getTotalRxBytes | - | 獲取設(shè)備本次開機到目前為止,WI-FI、流量下接收的字節(jié)總數(shù)。 |
| getMobileTxBytes | - | 獲取設(shè)備本次開機到目前為止,流量下傳輸?shù)淖止?jié)總數(shù)。 |
| getMobileRxBytes | - | 獲取設(shè)備本次開機到目前為止,流量下接收的字節(jié)總數(shù)。 |
| getUidTxBytes | uid | 獲取應(yīng)用從本次開機到目前為止,WI-FI、流量下傳輸?shù)淖止?jié)總數(shù)。 |
| getUidRxBytes | uid | 獲取應(yīng)用從本次開機到目前為止,WI-FI、流量下接收的字節(jié)總數(shù)。 |
上述接口可以滿足實現(xiàn)計算網(wǎng)速的需求,TrafficStats類其他接口可以查看官方文檔。
實現(xiàn)獲取網(wǎng)速
可以通過一段時間內(nèi)傳輸?shù)牧髁砍r間計算出上行網(wǎng)速,通過一段時間內(nèi)接收的流量除去時間計算出下行網(wǎng)速。
TrafficStats類的接口獲取的網(wǎng)速是從開機時就開始計算的,因此,要計算一段時間內(nèi)的流量需要在開始時獲取一次流量數(shù)據(jù),結(jié)束時獲取一次流量數(shù)據(jù),相減得出一段時間的實際流量。
實時網(wǎng)速
本文用getUidTxBytes和getUidRxBytes來演示,其他方法也是類似的,如下:
object NetSpeedUtils {
var netSpeedCallback: NetSpeedCallback? = null
private var timer: Timer? = null
private var timerTask: TimerTask? = null
private var lastTotalReceiveBytes: Long = 0
private var lastTotalTransferBytes: Long = 0
/**
* 根據(jù)應(yīng)用uid獲取設(shè)備啟動以來,該應(yīng)用接收到的總字節(jié)數(shù)
*
* @param uid 應(yīng)用的uid
*/
fun getTotalReceiveBytes(): Long {
var receiveBytes: Long = TrafficStats.UNSUPPORTED.toLong()
ExampleApplication.exampleContext?.run {
receiveBytes = TrafficStats.getUidRxBytes(applicationInfo.uid)
}
// 當(dāng)獲取不到時,會返回TrafficStats.UNSUPPORTED
return if (receiveBytes == TrafficStats.UNSUPPORTED.toLong()) 0 else receiveBytes / 1024
}
/**
* 根據(jù)應(yīng)用uid獲取設(shè)備啟動以來,該應(yīng)用傳輸?shù)目傋止?jié)數(shù)
*
* @param uid 應(yīng)用的uid
*/
fun getTotalTransferBytes(): Long {
var transferBytes: Long = TrafficStats.UNSUPPORTED.toLong()
ExampleApplication.exampleContext?.run {
transferBytes = TrafficStats.getUidTxBytes(applicationInfo.uid)
}
// 當(dāng)獲取不到時,會返回TrafficStats.UNSUPPORTED
return if (transferBytes == TrafficStats.UNSUPPORTED.toLong()) 0 else transferBytes / 1024
}
// 通過Timer每隔1秒計算網(wǎng)速
private fun calculateNetSpeed() {
ExampleApplication.exampleContext?.run {
val nowTotalReceiveBytes = getTotalReceiveBytes()
val nowTotalTransferBytes = getTotalTransferBytes()
val downloadSpeed = nowTotalReceiveBytes - lastTotalReceiveBytes
val uploadSpeed = nowTotalTransferBytes - lastTotalTransferBytes
lastTotalReceiveBytes = nowTotalReceiveBytes
lastTotalTransferBytes = nowTotalTransferBytes
netSpeedCallback?.onNetSpeedChange("$downloadSpeed kb/s", "$uploadSpeed kb/s")
}
}
fun startMeasuringNetSpeed() {
if (timer == null && timerTask == null) {
timer = Timer()
timerTask = object : TimerTask() {
override fun run() {
calculateNetSpeed()
}
}
timer?.run { timerTask?.let { schedule(it, 0L, 1000L) } }
}
}
fun stopMeasuringNetSpeed() {
timerTask?.cancel()
timerTask = null
timer?.cancel()
timer = null
}
interface NetSpeedCallback {
fun onNetSpeedChange(downloadSpeed: String, uploadSpeed: String)
}
}
// 示例類
class TrafficStatsActivity : BaseGestureDetectorActivity() {
private lateinit var binding: LayoutTrafficStatsActivityBinding
@SuppressLint("SetTextI18n")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = DataBindingUtil.setContentView(this, R.layout.layout_traffic_stats_activity)
binding.includeTitle.tvTitle.text = "TrafficStatsExample"
NetSpeedUtils.netSpeedCallback = object : NetSpeedUtils.NetSpeedCallback {
override fun onNetSpeedChange(downloadSpeed: String, uploadSpeed: String) {
binding.tvNetSpeed.run { post { text = "downloadSpeed:$downloadSpeed , uploadSpeed:$uploadSpeed" } }
}
}
binding.btnStartMeasureNetSpeed.setOnClickListener {
NetSpeedUtils.startMeasuringNetSpeed()
}
binding.btnStopMeasureNetSpeed.setOnClickListener {
NetSpeedUtils.stopMeasuringNetSpeed()
}
initWebViewSetting(binding.webView)
binding.webView.loadUrl("https://go.minigame.vip/")
}
@SuppressLint("JavascriptInterface", "SetJavaScriptEnabled")
private fun initWebViewSetting(webView: WebView?) {
webView?.run {
settings.cacheMode = WebSettings.LOAD_DEFAULT
settings.domStorageEnabled = true
settings.allowContentAccess = true
settings.allowFileAccess = true
settings.useWideViewPort = true
settings.loadWithOverviewMode = true
settings.mixedContentMode = WebSettings.MIXED_CONTENT_ALWAYS_ALLOW
settings.javaScriptEnabled = true
settings.javaScriptCanOpenWindowsAutomatically = true
settings.setSupportMultipleWindows(true)
}
}
override fun onDestroy() {
super.onDestroy()
binding.webView.clearHistory()
binding.webView.loadDataWithBaseURL(null, "", "text/html", "utf-8", null)
binding.root.run {
if (this is ViewGroup) {
this.removeView(binding.webView)
}
}
binding.webView.destroy()
}
}
效果如圖:

以上就是Android 獲取實時網(wǎng)速實現(xiàn)詳解的詳細內(nèi)容,更多關(guān)于Android 獲取實時網(wǎng)速的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
解決Android Studio 3.0 butterknife:7.0.1配置的問題
下面小編就為大家分享一篇解決Android Studio 3.0 butterknife:7.0.1配置的問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2017-12-12
Android實現(xiàn)可收縮和擴展的TextView
這篇文章主要為大家詳細介紹了Android實現(xiàn)可收縮和擴展的TextView,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-03-03
Android 中自定義Dialog樣式的Activity點擊空白處隱藏軟鍵盤功能(dialog不消失)
項目中需要開發(fā)帶有EditText的Dialog顯示,要求在編輯完EditText時,點擊Dilog的空白處隱藏軟鍵盤。但是Dialog不會消失。下面通過實例代碼給大家分享實現(xiàn)方法,需要的的朋友參考下吧2017-04-04
Android自定義View實現(xiàn)QQ運動積分轉(zhuǎn)盤抽獎功能
這篇文章主要為大家詳細介紹了Android自定義View實現(xiàn)QQ運動積分轉(zhuǎn)盤抽獎功能,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-10-10
Flutter開發(fā)之Widget自定義總結(jié)
這篇文章主要給大家介紹了關(guān)于Flutter開發(fā)中Widget自定義的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家學(xué)習(xí)或者使用Flutter具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧2019-04-04

