You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter深度链接Windows端总是打开新应用,如何实现Mac端复用实例?

让Flutter Windows应用复用现有会话处理深度链接

Windows平台默认会为每个深度链接请求启动新的应用进程,要实现和Mac端一致的会话复用效果,核心是让新进程检测现有实例,传递链接参数后退出,由现有实例处理请求。以下是具体实现方案:

方案一:使用single_instance包快速实现

社区维护的single_instance包封装了跨平台单实例检测和参数传递逻辑,能减少手动开发量。

  1. 添加依赖
    在pubspec.yaml中引入包:
dependencies:
  single_instance: ^2.0.0
  1. 修改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');
}
  1. Windows端参数传递适配
    在Windows runner项目的main.cpp中,需要将命令行参数通过MethodChannel传递给Flutter端,确保深度链接参数能被正确捕获。

方案二:手动实现Windows单实例检测

如果不想依赖第三方包,可以通过Windows原生API实现互斥体检测和参数传递:

  1. 修改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;
}
  1. Flutter端监听Windows消息
    通过MethodChannel或平台通道,在Flutter端监听WM_COPYDATA消息,提取深度链接参数并处理,实现和Mac端一致的会话内跳转逻辑。

验证

编译Windows应用后,先打开一个实例,再点击深度链接,新进程会自动退出,现有实例会接收到链接参数并处理,即可实现和Mac端一致的行为。

内容的提问来源于stack exchange,提问作者Fraser Steel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 17:40:27