当前位置: 首页 > 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.dtcms.com/a/346363.html

相关文章:

  • 反射【Reflect】
  • 深入浅出【最小生成树】:Prim与Kruskal算法详解
  • 111、【OS】【Nuttx】【周边】效果呈现方案解析:-print0 选项
  • AQS模板方法
  • 使用 Google 开源 AI 工具 LangExtract 进行结构化信息抽取
  • 单片机---------WIFI模块
  • Seaborn数据可视化实战:Seaborn数据可视化入门-绘制统计图表与数据分析
  • Dify 从入门到精通(第 49/100 篇):Dify 的自动化测试
  • STM32 硬件I2C读写MPU6050
  • 【链表 - LeetCode】24. 两两交换链表中的节点
  • 纯手撸一个RAG
  • 黄飞对话小熊电器流程与IT负责人:企业数字化进阶与AI实践如何落地?
  • QIcon::actualSize的作用和用法
  • 2025/8/22 xxl-job速通
  • 解决 微信开发者工具 :下载基础库版本 2.31.0 失败
  • RAG和微调是什么?两者的区别?什么场景使用RAG或微调?判断依据是什么?
  • LINUX网络编程--网络的发展与通信
  • AI赋能环保精准治理:AI水质监测溯源快、空气质量预测施策准,守护生态新效能
  • 关于 java+gradle的弹窗多选应用app
  • 【GPT入门】第54课 量化位数与存储大小的影响
  • Java 面试题训练助手 Web 版本
  • 网络通信——UDP协议。
  • Kubernetes 1.28 集群部署指南(基于 Containerd 容器运行时)
  • 笔记:二叉树构建方法
  • 从“配置化思维”到“前端效率革命”:xiangjsoncraft 如何用 JSON 简化页面开发?
  • 【源码】MES系统:从下达计划、执行反馈、异常预警到过程控制的一整套执行中枢。
  • FastTracker:实时准确的视觉跟踪
  • 一键部署openGauss6.0.2轻量版单节点
  • DPY-3010: connections to this database server version are not supported by p
  • LoRA内幕机制解析(53)