Flutter网络代理选择插件proxy_selector的使用
Flutter网络代理选择插件proxy_selector的使用
该插件允许您为特定的URL检索代理设置。
目前支持iOS和Android平台。
在Android上,它使用了java.net
包中的ProxySelector
。
在iOS上,它使用了CFNetworkCopySystemProxySettings
/CFNetworkCopyProxiesForURL
来解析代理设置,并且对于PAC(脚本/Url)使用了CFNetworkExecuteProxyAutoConfigurationURL
/CFNetworkExecuteProxyAutoConfigurationScript
来解析PAC脚本。
注意:FTP(仅限iOS)和SOCKS尚未测试。iOS上的凭证不支持。
如何测试
您可以使用自己的代理服务器或任何其他代理工具进行测试。这里以Proxyman为例:
- 安装Proxyman
- 配置您的物理设备以使用Proxyman,目的是能够跟踪所有流量
- 打开浏览器并输入一些随机地址
- Proxyman会显示所有请求
- 在您的设备上运行示例项目
- 执行输入的URL
- Proxyman中没有显示代理
- 启用代理
- 再次执行输入的URL
- 显示代理设置
测试PAC
您需要在您的设备上安装nginx,并且有一个PAC文件。为了方便设置,可以使用指向Proxyman代理的PAC文件。
function FindProxyForURL (url, host) {
// return 'PROXY 1111.1111.1111.1111:9999; DIRECT';
return 'PROXY [Enter here ip address of Proxyman and port]; DIRECT';
}
并且配置nginx.conf文件,将根目录设置为包含pac文件的目录。
events {}
http {
include mime.types;
default_type application/x-ns-proxy-autoconfig;
server {
location / {
# path to root where testfile.pac located
root /../../../;
}
}
}
完成上述步骤后,重新加载或启动nginx。您的PAC现在应该可以通过本地IP地址(localhost)访问。请注意,返回的文件应具有application/x-ns-proxy-autoconfig
MIME类型。
在设备的代理设置中输入您的IP地址作为URL。之后,您可以使用示例测试PAC。
Example:
1111.1111.1111.1111/testfile.pac
源码
以下来源用于实现此插件。
iOS:
Android:
示例代码
以下是使用proxy_selector
插件的完整示例代码:
import 'package:dio/dio.dart';
import 'package:dio_proxy_adapter/dio_proxy_adapter.dart';
import 'package:flutter/material.dart';
import 'dart:async';
import 'package:flutter/services.dart';
import 'package:proxy_selector/models/proxy_dto.dart';
import 'package:proxy_selector/proxy_selector.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatefulWidget {
const MyApp({super.key});
[@override](/user/override)
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
TextEditingController textEditingController = TextEditingController();
String _proxy = '未知';
String _response = "-";
String? _error;
String? _timeForExecution;
bool _activateProxy = false;
ProxySelector _proxyPlugin = ProxySelector();
[@override](/user/override)
void initState() {
super.initState();
textEditingController.text = "https://example.com";
}
// 平台消息是异步的,所以我们初始化在一个异步方法中。
Future<void> _buttonCall() async {
_proxyPlugin = ProxySelector();
String? proxyAsList = "-";
Response? response;
String? error;
String? timeForExecution;
if (!mounted) return;
setState(() {
_proxy = proxyAsList ?? "-";
_response = response?.data.toString() ?? "-";
_error = error;
});
// 平台消息可能会失败,所以我们使用try/catch来捕获PlatformException。
// 我们还处理消息可能返回null的情况。
Dio dio = Dio();
try {
final address = Uri.tryParse(textEditingController.text);
if (!(address != null)) {
error = "无法解析您的输入";
} else {
final stopwatch = Stopwatch()..start();
final proxyForThisURL = _activateProxy
? (await _proxyPlugin.getSystemProxyForUri(address))
: null;
timeForExecution =
_activateProxy ? stopwatch.elapsed.inMilliseconds.toString() : null;
stopwatch.stop();
if (proxyForThisURL != null && proxyForThisURL.isNotEmpty) {
proxyAsList = proxyForThisURL.join();
List<ProxyDto> proxies = List.from(proxyForThisURL);
proxies.removeWhere((element) => element.type == "NONE");
if (proxies.isNotEmpty) {
dio.useProxy("${proxies.first.host}:${proxies.first.port}");
}
} else {
error = "未找到代理";
}
response = await dio.get(
address.toString(),
);
}
} on PlatformException {
_error = "获取代理失败。";
} on DioError {
_error = "请求失败";
}
// 如果小部件从树中被移除而异步平台消息还在飞行中,我们希望丢弃回复而不是调用setState来更新我们的不存在的外观。
if (!mounted) return;
setState(() {
_proxy = proxyAsList ?? "-";
_response = response?.data.toString() ?? "-";
_timeForExecution = timeForExecution ?? "-";
_error = error;
});
}
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('代理'),
backgroundColor: Colors.green,
actions: [
const Text("代理开启: "),
Switch(
value: _activateProxy,
onChanged: (value) {
setState(() {
_activateProxy = value;
});
},
)
],
),
body: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
TextField(
controller: textEditingController,
),
Text(_proxy),
Text("获取代理所需时间: $_timeForExecution ms"),
if (_error != null && _error!.isNotEmpty)
Text(
_error!,
style: const TextStyle(color: Colors.red),
),
OutlinedButton(
onPressed: _buttonCall,
child: const Text("获取代理并调用")),
Expanded(
child: SingleChildScrollView(
child: Text(_response),
),
),
],
),
),
);
}
}
更多关于Flutter网络代理选择插件proxy_selector的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter网络代理选择插件proxy_selector的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
在 Flutter 中,proxy_selector
是一个用于选择网络代理的插件。它可以帮助你在应用中动态地选择和配置网络代理,以便在不同的网络环境下进行调试或访问特定的网络资源。以下是如何使用 proxy_selector
插件的基本步骤:
1. 添加依赖
首先,你需要在 pubspec.yaml
文件中添加 proxy_selector
插件的依赖:
dependencies:
flutter:
sdk: flutter
proxy_selector: ^1.0.0 # 请使用最新版本
然后运行 flutter pub get
来安装依赖。
2. 导入插件
在你的 Dart 文件中导入 proxy_selector
插件:
import 'package:proxy_selector/proxy_selector.dart';
3. 设置代理
你可以使用 ProxySelector
类来设置代理。以下是一个简单的示例,展示如何设置 HTTP 和 HTTPS 代理:
void setProxy() {
ProxySelector().setProxy(
ProxySettings(
httpProxy: 'http://proxy.example.com:8080',
httpsProxy: 'https://proxy.example.com:8080',
bypass: ['localhost', '127.0.0.1'],
),
);
}
在上面的代码中,httpProxy
和 httpsProxy
分别设置了 HTTP 和 HTTPS 代理的地址和端口。bypass
参数用于指定不需要通过代理的地址。
4. 清除代理
如果你想清除之前设置的代理,可以调用 clearProxy
方法:
void clearProxy() {
ProxySelector().clearProxy();
}
5. 获取当前代理设置
你可以通过 getProxySettings
方法来获取当前的代理设置:
void getCurrentProxy() async {
ProxySettings? settings = await ProxySelector().getProxySettings();
if (settings != null) {
print('HTTP Proxy: ${settings.httpProxy}');
print('HTTPS Proxy: ${settings.httpsProxy}');
print('Bypass: ${settings.bypass}');
} else {
print('No proxy settings.');
}
}
6. 处理代理设置的变化
proxy_selector
插件还提供了监听代理设置变化的功能。你可以通过 onProxyChanged
来监听代理设置的变更:
void listenProxyChanges() {
ProxySelector().onProxyChanged.listen((ProxySettings settings) {
print('Proxy settings changed:');
print('HTTP Proxy: ${settings.httpProxy}');
print('HTTPS Proxy: ${settings.httpsProxy}');
print('Bypass: ${settings.bypass}');
});
}
7. 示例代码
以下是一个完整的示例代码,展示了如何使用 proxy_selector
插件来设置、获取和监听代理设置:
import 'package:flutter/material.dart';
import 'package:proxy_selector/proxy_selector.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Proxy Selector Example'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ElevatedButton(
onPressed: setProxy,
child: Text('Set Proxy'),
),
ElevatedButton(
onPressed: clearProxy,
child: Text('Clear Proxy'),
),
ElevatedButton(
onPressed: getCurrentProxy,
child: Text('Get Current Proxy'),
),
],
),
),
),
);
}
void setProxy() {
ProxySelector().setProxy(
ProxySettings(
httpProxy: 'http://proxy.example.com:8080',
httpsProxy: 'https://proxy.example.com:8080',
bypass: ['localhost', '127.0.0.1'],
),
);
}
void clearProxy() {
ProxySelector().clearProxy();
}
void getCurrentProxy() async {
ProxySettings? settings = await ProxySelector().getProxySettings();
if (settings != null) {
print('HTTP Proxy: ${settings.httpProxy}');
print('HTTPS Proxy: ${settings.httpsProxy}');
print('Bypass: ${settings.bypass}');
} else {
print('No proxy settings.');
}
}
}