Flutter深度链接Windows端总是打开新应用,如何实现Mac端复用实例?
让Flutter Windows应用复用现有会话处理深度链接
Windows平台默认会为每个深度链接请求启动新的应用进程,要实现和Mac端一致的会话复用效果,核心是让新进程检测现有实例,传递链接参数后退出,由现有实例处理请求。以下是具体实现方案:
方案一:使用single_instance包快速实现
社区维护的single_instance包封装了跨平台单实例检测和参数传递逻辑,能减少手动开发量。
- 添加依赖
在pubspec.yaml中引入包:
dependencies: single_instance: ^2.0.0
- 修改
main函数逻辑
在main.dart中初始化单实例检测,处理参数传递:
import 'package:single_instance/single_instance.dart'; import 'package:flutter/services.dart'; void main() async { // 指定应用唯一标识(建议用包名) final instance = SingleInstance('com.yourcompany.yourapp'); // 检查是否为首个运行实例 final isFirstInstance = await instance.start(); if (!isFirstInstance) { // 获取当前进程的深度链接参数 final args = await _getDeepLinkArgs(); // 传递参数给已有实例 await instance.sendArgs(args); // 退出当前进程 return; } // 监听新实例传递的深度链接参数 instance.argsStream.listen((args) { if (args.isNotEmpty) { _handleDeepLink(args.first); } }); runApp(const MyApp()); } // 通过MethodChannel获取Windows端传递的命令行参数 Future<List<String>> _getDeepLinkArgs() async { final args = await const MethodChannel('deep_link_channel') .invokeMethod<List<dynamic>>('get_args'); return args?.cast<String>() ?? []; } // 处理深度链接的业务逻辑 void _handleDeepLink(String link) { // 示例:打印链接或导航到对应页面 print('Received deep link: $link'); }
- Windows端参数传递适配
在Windows runner项目的main.cpp中,需要将命令行参数通过MethodChannel传递给Flutter端,确保深度链接参数能被正确捕获。
方案二:手动实现Windows单实例检测
如果不想依赖第三方包,可以通过Windows原生API实现互斥体检测和参数传递:
- 修改Windows端
main.cpp
#include <windows.h> #include <flutter/dart_project.h> #include <flutter/flutter_view_controller.h> #include <memory> // 应用唯一互斥体名称 const wchar_t* kMutexName = L"com.yourcompany.yourapp.mutex"; // 用于传递参数的消息类型 const UINT kDeepLinkMsg = RegisterWindowMessage(L"FLUTTER_DEEP_LINK_MSG"); // 发送深度链接参数给现有实例 void SendDeepLinkToExistingInstance(const wchar_t* link) { HWND existingWindow = FindWindow(L"FLUTTER_RUNNER_WIN32_WINDOW", NULL); if (existingWindow != NULL) { COPYDATASTRUCT cds; cds.dwData = kDeepLinkMsg; cds.cbData = (wcslen(link) + 1) * sizeof(wchar_t); cds.lpData = (void*)link; SendMessage(existingWindow, WM_COPYDATA, 0, (LPARAM)&cds); } } int APIENTRY wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPWSTR lpCmdLine, _In_ int nCmdShow) { // 创建互斥体检测是否已有实例运行 HANDLE mutex = CreateMutex(NULL, TRUE, kMutexName); if (GetLastError() == ERROR_ALREADY_EXISTS) { // 已有实例,传递深度链接参数后退出 if (wcslen(lpCmdLine) > 0) { SendDeepLinkToExistingInstance(lpCmdLine); } CloseHandle(mutex); return 0; } // 原有Flutter应用启动逻辑 dart_project project(L"data"); std::unique_ptr<flutter::FlutterViewController> view_controller = std::make_unique<flutter::FlutterViewController>(project); // ... 其余启动代码 ... CloseHandle(mutex); return 0; }
- Flutter端监听Windows消息
通过MethodChannel或平台通道,在Flutter端监听WM_COPYDATA消息,提取深度链接参数并处理,实现和Mac端一致的会话内跳转逻辑。
验证
编译Windows应用后,先打开一个实例,再点击深度链接,新进程会自动退出,现有实例会接收到链接参数并处理,即可实现和Mac端一致的行为。
内容的提问来源于stack exchange,提问作者Fraser Steel
相关产品推荐
相关产品推荐

