uni-app 真机调试:手动代理环境下访问内网 API 的解决方案
背景
使用 uni-app 开发了一款移动应用,需要调用部署在公司内网的 API 服务,地址为 http://10.13.5.195:8005。
公司对所有测试手机统一管理,要求 WiFi 必须设置手动代理:
| 配置项 | 值 |
|---|---|
| 代理服务器 | 172.16.95.16 |
| 端口 | 80 |
| 不使用的网址 | *.mflex.com.cn |
设置手动代理后,App 所有网络请求都会经过代理服务器转发。由于代理服务器无法访问 10.13.5.195 这个内网地址,导致 API 请求全部失败。
尝试过但不可行的方案
| 方案 | 结果 |
|---|---|
手机代理排除列表加 10.* |
公司不允许修改,且需要逐一配置大量手机 |
| Android Studio 原生插件(Proxy.NO_PROXY) | 电脑无法访问外网,缺少 uni-app SDK 的 AAR 文件(uniapp-v8-release.aar),无法编译 |
UTS 插件继承 ProxySelector |
UTS 对 Java 抽象类的继承存在类型兼容问题,反复报错 |
最终方案
使用 UTS 插件调用 java.lang.System.setProperty("http.nonProxyHosts", ...) 设置 Java 代理排除规则,让内网 IP 段的请求自动绕过系统代理。
方案原理
Android 底层使用 Java 的网络栈,http.nonProxyHosts 是 Java 标准的代理排除属性。设置后,匹配该规则的地址将直接连接,不经过系统代理:
设置前:App 请求 → 系统代理(172.16.95.16) → 无法到达 10.13.5.195 → 报错
设置后:App 请求 → 检查 nonProxyHosts → 匹配 10.* → 直连 10.13.5.195 → 成功
对于 uni.request() 的调用方式完全透明,现有代码一行都不用改。
环境信息
| 项目 | 版本 |
|---|---|
| HBuilderX | 5.07 |
| uni-app 项目类型 | Vue 3(app-vue) |
| 测试手机 | Android |
操作步骤
一、创建 UTS 插件
在 uni-app 项目上右键 → 新建 uni_modules 目录 → 输入插件 ID(格式要求:作者ID-插件名称,例如 hjl-directhttp)→ 选择分类为 UTS插件-API插件 → 点击创建。
HBuilderX 会自动生成以下目录结构:
uni_modules/
└── hjl-directhttp/
├── utssdk/
│ ├── app-android/
│ │ └── index.uts ← Android 平台实现(核心)
│ ├── app-harmony/ ← 鸿蒙平台(本次不用)
│ ├── app-iOS/ ← iOS 平台(本次不用)
│ ├── interface.uts ← 接口声明
│ └── unierror.uts ← 错误处理(本次不用)
├── package.json ← 插件配置
├── changelog.md
└── readme.md
二、编辑 interface.uts
声明插件对外暴露的函数接口。
文件路径:uni_modules/hjl-directhttp/utssdk/interface.uts
typescript
export function setupProxyBypass() : UTSJSONObject
三、编辑 index.uts(核心)
这是插件的核心实现,调用 Java 系统属性设置代理排除规则。
文件路径:uni_modules/hjl-directhttp/utssdk/app-android/index.uts
typescript
/**
* DirectHttp - 绕过系统代理访问内网 API
*
* 原理:通过设置 Java 系统属性 http.nonProxyHosts,
* 让匹配内网 IP 段的请求自动绕过代理直连。
*
* 覆盖的内网 IP 段:
* 10.x.x.x
* 172.16.x.x ~ 172.31.x.x
* 192.168.x.x
* 127.0.0.1 / localhost
*/
export function setupProxyBypass() : UTSJSONObject {
try {
java.lang.System.setProperty(
"http.nonProxyHosts",
"10.*|192.168.*|172.16.*|172.17.*|172.18.*|172.19.*|172.20.*|172.21.*|172.22.*|172.23.*|172.24.*|172.25.*|172.26.*|172.27.*|172.28.*|172.29.*|172.30.*|172.31.*|127.0.0.1|localhost"
)
console.log("DirectHttp: 代理排除规则设置成功")
const r = {} as UTSJSONObject
r["success"] = true
r["message"] = "配置成功"
return r
} catch (e) {
console.error("DirectHttp: 配置失败 - " + e.message)
const r = {} as UTSJSONObject
r["success"] = false
r["error"] = e.message
return r
}
}
四、修改 App.vue
在 onLaunch 中调用插件初始化函数,App 启动时执行一次即可。
文件路径:根目录 App.vue
javascript
<script>
// #ifdef APP-PLUS
import { setupProxyBypass } from '@/uni_modules/hjl-directhttp'
// #endif
export default {
onLaunch() {
console.log('App Launch')
// #ifdef APP-PLUS
try {
const result = setupProxyBypass()
console.log('代理绕过配置结果:', JSON.stringify(result))
} catch (e) {
console.error('DirectHttp 加载失败:', e)
}
// #endif
// ... 原有的 onLaunch 代码保持不变
},
onShow() {
// 原有代码保持不变
},
onHide() {
// 原有代码保持不变
}
}
</script>
五、修改 manifest.json
在源码视图中注册插件。
打开 manifest.json → 点击底部 「源码视图」 → 找到 app-plus → distribute → 添加 nativePlugins:
json
{
"app-plus": {
"distribute": {
"nativePlugins": {
"hjl-directhttp": {}
}
}
}
}
六、打包测试
HBuilderX → 运行 → 运行到手机或模拟器 → 制作自定义基座
等待云打包完成并安装到手机。
七、验证结果
在 HBuilderX 控制台中查看日志,出现以下内容表示配置成功:
DirectHttp: 代理排除规则设置成功
代理绕过配置结果: {"success":true,"message":"配置成功"}
此时访问 http://10.13.5.195:8005 的 API 请求会自动绕过代理直连,登录等业务功能恢复正常。
项目文件清单
整个方案涉及的文件如下:
项目根目录/
├── uni_modules/
│ └── hjl-directhttp/
│ ├── utssdk/
│ │ ├── app-android/
│ │ │ └── index.uts ← 核心:设置代理排除规则
│ │ ├── interface.uts ← 接口声明
│ │ └── ...
│ └── package.json ← 自动生成,无需修改
├── App.vue ← 调用插件初始化
└── manifest.json ← 注册插件
踩坑记录
1. UTS 插件 ID 格式
创建 uni_modules 目录时,插件 ID 必须包含短横线,格式为 作者ID-插件名称,例如 hjl-directhttp。直接输入 directhttp 会提示格式不正确。
2. 继承 Java 抽象类的问题
最初尝试在 UTS 中继承 java.net.ProxySelector 来实现更灵活的代理控制,但遇到一系列编译问题:
- 抽象类不能直接
new,必须用class extends继承 - 覆盖父类方法必须加
override关键字 - 不能显式声明
override方法的返回类型,需要让编译器自动推断 Collections.singletonList()返回的是 Kotlin 集合类型,无法直接当java.util.List使用ArrayList.size是属性而非方法,不能加括号调用- 循环变量是
Number类型,传给ArrayList.get(Int)需要as Int转换
这些问题说明 UTS 对 Java 原生 API 的调用存在较多类型系统差异,涉及抽象类继承、泛型、集合类型转换等场景时容易踩坑。
3. 最终选择的简洁方案
System.setProperty("http.nonProxyHosts", ...) 是一行代码就能解决的问题,完全避免了上述所有类型兼容问题。
适用场景
本方案适用于以下情况:
- 公司要求手机使用手动代理,但部分内网服务需要直连
- 无法修改手机代理排除列表(设备多、不允许修改等)
- 使用 uni-app 开发,且 HBuilderX 版本支持 UTS 插件(5.0+)
如需调整排除的 IP 段,只需修改 index.uts 中 http.nonProxyHosts 的值即可。