init method
初始化:释放 sing-box.exe / libcronet.dll / clash_sing_helper.exe 到应用目录, 并清除上次异常退出遗留的系统代理(崩溃自愈)。
Implementation
@override
Future<void> init() async {
debugPrint('flutter_sing_box 插件初始化 Windows 平台 startTime = ${DateTime.now()}');
final io.Directory dir = await ProfileStorage().getStorageDirectory();
final singBoxResult = await AssetUtil.copyAssetToDirectory(
WindowsConstants.singBoxAsset,
dir.path,
);
if (!singBoxResult) {
throw Exception('复制 sing_box.exe 资源失败');
}
final libcronetResult = await AssetUtil.copyAssetToDirectory(
WindowsConstants.libcronetAsset,
dir.path,
);
if (!libcronetResult) {
throw Exception('复制 libcronet.dll 资源失败');
}
// 释放独立服务程序 clash_sing_helper.exe,供 HelperCli 调用。
final helperResult = await AssetUtil.copyAssetToDirectory(
WindowsConstants.helperAsset,
dir.path,
);
if (!helperResult) {
throw Exception('复制 clash_sing_helper.exe 资源失败');
}
// 清理上次更新遗留的 .old(三个二进制走同一重命名降级路径,都会产生)。
// 被运行中进程锁定时删除失败是预期,忽略;服务重启路径另有 Go 侧
// Program.Start 兜底清理(服务启动时 sing-box 必已退出,删除必成功)
for (final String baseName in <String>[
WindowsConstants.helperFileName,
WindowsConstants.singBoxFileName,
WindowsConstants.libcronetFileName,
]) {
try {
final io.File stale = _oldFileIn(dir, baseName);
if (await stale.exists()) await stale.delete();
} catch (_) {
// 进程仍锁定该 .old(如服务正挂旧 helper / sing-box 未退出),留给清理
}
}
// 启动期代理状态恢复:仅服务 running 时经 helper HTTP 恢复 UI 状态;
// stopped 等其余状态跳过(stopped 时端口必无人监听,探测只会得到
// 连接拒绝的 Unhandled Exception,而代理状态初始即 stopped 已正确)
await restoreStartupProxyState(
queryStatus: queryServiceStatus,
restoreViaHttp: () => HelperHttpClient().status(),
);
// 崩溃自愈: 若上次异常退出遗留了系统代理,且 sing-box 当前未运行,则清除
if (CsSettingsStorage().systemProxyActive) {
final status = await queryServiceStatus();
if (status != WindowsServiceStatus.running) {
await SystemProxyService().disable();
}
}
debugPrint('flutter_sing_box 插件初始化 Windows 平台 endTime = ${DateTime.now()}');
}