当前位置: 首页 > news >正文

【Android】 连接wifi时,强制应用使用流量

【Android】 连接wifi时,强制应用使用流量

两种方法,一种是绑定整个进程,一种是让部分请求可以走流量。

方法一:绑定整个应用进程

Android开发实战:Wi-Fi连接下强制App使用移动数据

在特定的业务场景下,例如执行高优先级的网络任务或测试不同网络环境,我们可能需要在Wi-Fi已连接的情况下,强制让应用通过移动数据(蜂窝网络)进行通信。本文将介绍如何在原生Android开发中实现这一高级功能。核心原理


自 Android 5.0 (API 21) 起,ConnectivityManager 提供了多网络连接管理API。其核心思想是:应用可以向系统请求一个特定类型的网络(如蜂窝网络),获取该网络的 Network 对象引用,然后将应用的全部或部分网络通信绑定到这个特定的 Network 对象上,从而绕过系统默认的Wi-Fi网络。


方法一:绑定整个应用进程(全局生效)

这是最直接的方法,它会使应用内的所有标准网络请求(OkHttp, Retrofit等)都切换到移动数据。

第1步:添加权限

AndroidManifest.xml 中确保具备网络权限:

`<uses-permission android:name="android.permission.INTERNET" /><uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />`

第2步:请求并绑定网络

创建一个管理类来封装网络切换逻辑。

import android.content.Context
import android.net.ConnectivityManager
import android.net.Network
import android.net.NetworkCapabilities
import android.net.NetworkRequest
import android.os.Buildclass CellularNetworkManager(context: Context) {private val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManagerprivate var networkCallback: ConnectivityManager.NetworkCallback? = null/*** 请求蜂窝网络并绑定当前应用进程。*/fun bind(onSuccess: () -> Unit, onError: (String) -> Unit) {if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {onError("Feature requires Android API 21+.")return}// 构建一个蜂窝网络请求val request = NetworkRequest.Builder().addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET).addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR).build()networkCallback = object : ConnectivityManager.NetworkCallback() {// 当蜂窝网络可用时override fun onAvailable(network: Network) {try {// 核心:将进程绑定到此网络connectivityManager.bindProcessToNetwork(network)onSuccess()} catch (e: Exception) {onError("Failed to bind: ${e.message}")}}// 当找不到合适的网络时override fun onUnavailable() {onError("Cellular network unavailable.")}}connectivityManager.requestNetwork(request, networkCallback!!)}/*** 解除绑定,恢复使用系统默认网络。*/fun unbind() {if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {connectivityManager.bindProcessToNetwork(null) // 传 null 解除绑定networkCallback?.let { connectivityManager.unregisterNetworkCallback(it) }networkCallback = null}}
}

第3步:在Activity/ViewModel中使用

// 在Activity中
private val cellularManager = CellularNetworkManager(this)// 绑定
cellularManager.bind(onSuccess = { // 绑定成功,现在发起的网络请求将通过流量Log.d("Network", "Process successfully bound to cellular network.")},onError = { errorMsg -> Log.e("Network", "Binding failed: $errorMsg") }
)// 在不再需要时,务必解除绑定,例如在 onDestroy() 中
override fun onDestroy() {cellularManager.unbind()super.onDestroy()
}

方法二:为特定请求(如OkHttp)指定网络(精准控制)

如果你只想让某一部分请求走流量,可以为 OkHttp 等网络库的客户端实例单独配置网络。

1. 获取Network对象

首先,通过 requestNetwork 获取到 Network 对象,但不要调用 bindProcessToNetwork

// 在 onAvailable(network: Network) 回调中
// 我们得到了 network 对象,用它来配置 OkHttp
val cellularOkHttpClient = createOkHttpClientFor(network)
// 使用这个 client 发起请求

2. 创建绑定的OkHttpClient

利用 Network 对象提供的 socketFactory 来构建 OkHttpClient

import okhttp3.OkHttpClientfun createOkHttpClientFor(network: Network): OkHttpClient {return OkHttpClient.Builder().socketFactory(network.socketFactory).build()
}

使用这个 cellularOkHttpClient 实例发起的请求将只通过蜂窝网络,而应用中其他常规的 OkHttpClient 实例则继续使用默认的Wi-Fi网络。

以上都是AI生成,写这篇文档的原因是:我使用的是方法二,按照最初方案并没有成功连接网路,而是需要添加DNS

补充:

        val cellularDns = object : Dns {override fun lookup(hostname: String): List<InetAddress> {return try {cellularNetwork?.getAllByName(hostname)?.toList() ?: emptyList()} catch (e: UnknownHostException) {throw e}}}fun createOkHttpClientFor(network: Network): OkHttpClient {return OkHttpClient.Builder().socketFactory(network.socketFactory).dns(cellularDns).build()
}
http://www.xdnf.cn/news/1349029.html

相关文章:

  • 【从零开始java学习|第九篇】方法的相关知识与练习
  • 【微服务的数据一致性分发问题】究极解决方案
  • 日志的配置
  • 一键部署openGauss6.0.2轻量版单节点
  • Spring原理
  • 最近 | 黄淮教务 | 小工具合集
  • 世界模型一种能够对现实世界环境进行仿真,并基于文本、图像、视频和运动等输入数据来生成视频、预测未来状态的生成式 AI 模型
  • Maxscript如何清理3dMax场景?
  • 打工人日报20250822
  • More Effective C++ 条款01:仔细区别 pointers 和 references
  • Java设计模式-外观模式
  • 滑动窗口+子串+普通数组算法
  • Elasticsearch搜索原理
  • HEVC(H.265)与HVC1的关系及区别
  • Unreal Engine UProjectileMovementComponent
  • 异步开发的三种实现方式
  • Unreal Engine USceneComponent
  • Unreal Engine Simulate Physics
  • 线段树01
  • 20250822 组题总结
  • 如何解决pip安装报错ModuleNotFoundError: No module named ‘uvicorn’问题
  • 北京-测试-入职甲方金融-上班第三天
  • 嵌入式第三十五天(网络编程(UDP))
  • GPS欺骗式干扰的产生
  • DSPy框架:从提示工程到声明式编程的革命性转变
  • 声网SDK更新,多场景抗弱网稳定性大幅增强
  • GaussDB GaussDB 数据库架构师修炼(十八)SQL引擎(1)-SQL执行流程
  • week3-[二维数组]小方块
  • ArrayList线程不安全问题及解决方案详解
  • 硬件驱动---linux内核驱动 启动