{"id":13548006,"url":"https://github.com/leanflutter/protocol_handler","last_synced_at":"2026-03-09T13:05:47.770Z","repository":{"id":40247738,"uuid":"470179062","full_name":"leanflutter/protocol_handler","owner":"leanflutter","description":"This plugin allows Flutter apps to register and handle custom protocols (i.e. deep linking).","archived":false,"fork":false,"pushed_at":"2025-03-23T04:06:15.000Z","size":450,"stargazers_count":83,"open_issues_count":5,"forks_count":18,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-03-06T19:49:57.078Z","etag":null,"topics":["deep-linking","deeplinking"],"latest_commit_sha":null,"homepage":"https://pub.dev/packages/protocol_handler","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/leanflutter.png","metadata":{"files":{"readme":"README-ZH.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null},"funding":{"liberapay":"lijy91"}},"created_at":"2022-03-15T13:46:11.000Z","updated_at":"2026-02-20T23:56:36.000Z","dependencies_parsed_at":"2023-12-17T13:27:23.684Z","dependency_job_id":"136c32dd-99e9-47c3-9d5a-8aa3f71b4b68","html_url":"https://github.com/leanflutter/protocol_handler","commit_stats":{"total_commits":22,"total_committers":3,"mean_commits":7.333333333333333,"dds":0.09090909090909094,"last_synced_commit":"b5b157659b492d30493283f7789860bc85e7012a"},"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"purl":"pkg:github/leanflutter/protocol_handler","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leanflutter%2Fprotocol_handler","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leanflutter%2Fprotocol_handler/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leanflutter%2Fprotocol_handler/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leanflutter%2Fprotocol_handler/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/leanflutter","download_url":"https://codeload.github.com/leanflutter/protocol_handler/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leanflutter%2Fprotocol_handler/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30297111,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-09T11:12:22.024Z","status":"ssl_error","status_checked_at":"2026-03-09T11:10:54.577Z","response_time":61,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["deep-linking","deeplinking"],"created_at":"2024-08-01T12:01:04.474Z","updated_at":"2026-03-09T13:05:47.728Z","avatar_url":"https://github.com/leanflutter.png","language":"C++","readme":"\u003e **🚀 快速发布您的应用**: 试试 [Fastforge](https://fastforge.dev) - 构建、打包和分发您的 Flutter 应用最简单的方式。\n\n# protocol_handler\n\n[![pub version][pub-image]][pub-url] [![][discord-image]][discord-url] ![][visits-count-image]\n\n[pub-image]: https://img.shields.io/pub/v/protocol_handler.svg\n[pub-url]: https://pub.dev/packages/protocol_handler\n[discord-image]: https://img.shields.io/discord/884679008049037342.svg\n[discord-url]: https://discord.gg/zPa6EZ2jqb\n[visits-count-image]: https://img.shields.io/badge/dynamic/json?label=Visits%20Count\u0026query=value\u0026url=https://api.countapi.xyz/hit/leanflutter.protocol_handler/visits\n\n这个插件允许 Flutter 应用注册及处理自定义协议（即深度链接）。\n\n---\n\n[English](./README.md) | 简体中文\n\n---\n\n\u003c!-- START doctoc generated TOC please keep comment here to allow auto update --\u003e\n\u003c!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE --\u003e\n\n- [平台支持](#%E5%B9%B3%E5%8F%B0%E6%94%AF%E6%8C%81)\n- [截图](#%E6%88%AA%E5%9B%BE)\n- [快速开始](#%E5%BF%AB%E9%80%9F%E5%BC%80%E5%A7%8B)\n  - [安装](#%E5%AE%89%E8%A3%85)\n  - [用法](#%E7%94%A8%E6%B3%95)\n      - [Android](#android)\n      - [iOS](#ios)\n      - [macOS](#macos)\n      - [Windows](#windows)\n  - [监听事件](#%E7%9B%91%E5%90%AC%E4%BA%8B%E4%BB%B6)\n- [谁在用使用它？](#%E8%B0%81%E5%9C%A8%E7%94%A8%E4%BD%BF%E7%94%A8%E5%AE%83)\n- [许可证](#%E8%AE%B8%E5%8F%AF%E8%AF%81)\n\n\u003c!-- END doctoc generated TOC please keep comment here to allow auto update --\u003e\n\n## 平台支持\n\n| Android | iOS | Linux | macOS | Windows |\n| :-----: | :-: | :---: | :---: | :-----: |\n|   ✔️    | ✔️  |  ➖   |  ✔️   |   ✔️    |\n\n## 截图\n\nhttps://user-images.githubusercontent.com/3889523/167283452-aff2535b-c322-45c7-949f-d1c80c2e4a60.mp4\n\n## 快速开始\n\n### 安装\n\n将此添加到你的软件包的 pubspec.yaml 文件：\n\n```yaml\ndependencies:\n  protocol_handler: ^0.2.0\n```\n\n或\n\n```yaml\ndependencies:\n  protocol_handler:\n    git:\n      url: https://github.com/leanflutter/protocol_handler.git\n      ref: main\n```\n\n### 用法\n\n##### Android\n\n更改文件 `android/app/src/main/AndroidManifest.xml` 如下：\n\n```diff\n\u003cmanifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    package=\"dev.leanflutter.plugins.protocol_handler_example\"\u003e\n\n    \u003capplication\n        android:name=\"${applicationName}\"\n        android:icon=\"@mipmap/ic_launcher\"\n        android:label=\"protocol_handler_example\"\u003e\n        \u003cactivity\n            android:name=\".MainActivity\"\n            android:configChanges=\"orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode\"\n            android:exported=\"true\"\n            android:hardwareAccelerated=\"true\"\n            android:launchMode=\"singleTop\"\n            android:theme=\"@style/LaunchTheme\"\n            android:windowSoftInputMode=\"adjustResize\"\u003e\n            \u003c!-- Specifies an Android theme to apply to this Activity as soon as\n                 the Android process has started. This theme is visible to the user\n                 while the Flutter UI initializes. After that, this theme continues\n                 to determine the Window background behind the Flutter UI. --\u003e\n            \u003cmeta-data\n                android:name=\"io.flutter.embedding.android.NormalTheme\"\n                android:resource=\"@style/NormalTheme\" /\u003e\n\n            \u003cintent-filter\u003e\n                \u003caction android:name=\"android.intent.action.MAIN\" /\u003e\n                \u003ccategory android:name=\"android.intent.category.LAUNCHER\" /\u003e\n            \u003c/intent-filter\u003e\n+            \u003cintent-filter\u003e\n+                \u003caction android:name=\"android.intent.action.VIEW\" /\u003e\n+\n+                \u003ccategory android:name=\"android.intent.category.DEFAULT\" /\u003e\n+                \u003ccategory android:name=\"android.intent.category.BROWSABLE\" /\u003e\n+                \u003c!-- Accepts URIs that begin with YOUR_SCHEME://YOUR_HOST --\u003e\n+                \u003cdata android:scheme=\"myprotocol\" /\u003e\n+            \u003c/intent-filter\u003e\n        \u003c/activity\u003e\n        \u003c!-- Don't delete the meta-data below.\n             This is used by the Flutter tool to generate GeneratedPluginRegistrant.java --\u003e\n        \u003cmeta-data\n            android:name=\"flutterEmbedding\"\n            android:value=\"2\" /\u003e\n    \u003c/application\u003e\n\u003c/manifest\u003e\n```\n\n##### iOS\n\n更改文件 `ios/Runner/Info.plist` 如下：\n\n```diff\n\u003c?xml version=\"1.0\" encoding=\"UTF-8\"?\u003e\n\u003c!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\"\u003e\n\u003cplist version=\"1.0\"\u003e\n\u003cdict\u003e\n\t\u003ckey\u003eCFBundleDevelopmentRegion\u003c/key\u003e\n\t\u003cstring\u003e$(DEVELOPMENT_LANGUAGE)\u003c/string\u003e\n\t\u003ckey\u003eCFBundleDisplayName\u003c/key\u003e\n\t\u003cstring\u003eProtocol Handler\u003c/string\u003e\n\t\u003ckey\u003eCFBundleExecutable\u003c/key\u003e\n\t\u003cstring\u003e$(EXECUTABLE_NAME)\u003c/string\u003e\n\t\u003ckey\u003eCFBundleIdentifier\u003c/key\u003e\n\t\u003cstring\u003e$(PRODUCT_BUNDLE_IDENTIFIER)\u003c/string\u003e\n\t\u003ckey\u003eCFBundleInfoDictionaryVersion\u003c/key\u003e\n\t\u003cstring\u003e6.0\u003c/string\u003e\n\t\u003ckey\u003eCFBundleName\u003c/key\u003e\n\t\u003cstring\u003eprotocol_handler_example\u003c/string\u003e\n\t\u003ckey\u003eCFBundlePackageType\u003c/key\u003e\n\t\u003cstring\u003eAPPL\u003c/string\u003e\n\t\u003ckey\u003eCFBundleShortVersionString\u003c/key\u003e\n\t\u003cstring\u003e$(FLUTTER_BUILD_NAME)\u003c/string\u003e\n\t\u003ckey\u003eCFBundleSignature\u003c/key\u003e\n\t\u003cstring\u003e????\u003c/string\u003e\n\t\u003ckey\u003eCFBundleVersion\u003c/key\u003e\n\t\u003cstring\u003e$(FLUTTER_BUILD_NUMBER)\u003c/string\u003e\n\t\u003ckey\u003eLSRequiresIPhoneOS\u003c/key\u003e\n\t\u003ctrue/\u003e\n\t\u003ckey\u003eUILaunchStoryboardName\u003c/key\u003e\n\t\u003cstring\u003eLaunchScreen\u003c/string\u003e\n\t\u003ckey\u003eUIMainStoryboardFile\u003c/key\u003e\n\t\u003cstring\u003eMain\u003c/string\u003e\n+\t\u003ckey\u003eCFBundleURLTypes\u003c/key\u003e\n+\t\u003carray\u003e\n+\t\t\u003cdict\u003e\n+\t\t\t\u003ckey\u003eCFBundleTypeRole\u003c/key\u003e\n+\t\t\t\u003cstring\u003eEditor\u003c/string\u003e\n+\t\t\t\u003ckey\u003eCFBundleURLName\u003c/key\u003e\n+\t\t\t\u003cstring\u003e\u003c/string\u003e\n+\t\t\t\u003ckey\u003eCFBundleURLSchemes\u003c/key\u003e\n+\t\t\t\u003carray\u003e\n+\t\t\t\t\u003cstring\u003emyprotocol\u003c/string\u003e\n+\t\t\t\u003c/array\u003e\n+\t\t\u003c/dict\u003e\n+\t\u003c/array\u003e\n\t\u003ckey\u003eUISupportedInterfaceOrientations\u003c/key\u003e\n\t\u003carray\u003e\n\t\t\u003cstring\u003eUIInterfaceOrientationPortrait\u003c/string\u003e\n\t\t\u003cstring\u003eUIInterfaceOrientationLandscapeLeft\u003c/string\u003e\n\t\t\u003cstring\u003eUIInterfaceOrientationLandscapeRight\u003c/string\u003e\n\t\u003c/array\u003e\n\t\u003ckey\u003eUISupportedInterfaceOrientations~ipad\u003c/key\u003e\n\t\u003carray\u003e\n\t\t\u003cstring\u003eUIInterfaceOrientationPortrait\u003c/string\u003e\n\t\t\u003cstring\u003eUIInterfaceOrientationPortraitUpsideDown\u003c/string\u003e\n\t\t\u003cstring\u003eUIInterfaceOrientationLandscapeLeft\u003c/string\u003e\n\t\t\u003cstring\u003eUIInterfaceOrientationLandscapeRight\u003c/string\u003e\n\t\u003c/array\u003e\n\t\u003ckey\u003eUIViewControllerBasedStatusBarAppearance\u003c/key\u003e\n\t\u003cfalse/\u003e\n\u003c/dict\u003e\n\u003c/plist\u003e\n\n```\n\n##### macOS\n\n更改文件 `macos/Runner/Info.plist` 如下：\n\n```diff\n\u003c?xml version=\"1.0\" encoding=\"UTF-8\"?\u003e\n\u003c!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\"\u003e\n\u003cplist version=\"1.0\"\u003e\n\u003cdict\u003e\n\t\u003ckey\u003eCFBundleDevelopmentRegion\u003c/key\u003e\n\t\u003cstring\u003e$(DEVELOPMENT_LANGUAGE)\u003c/string\u003e\n\t\u003ckey\u003eCFBundleExecutable\u003c/key\u003e\n\t\u003cstring\u003e$(EXECUTABLE_NAME)\u003c/string\u003e\n\t\u003ckey\u003eCFBundleIconFile\u003c/key\u003e\n\t\u003cstring\u003e\u003c/string\u003e\n\t\u003ckey\u003eCFBundleIdentifier\u003c/key\u003e\n\t\u003cstring\u003e$(PRODUCT_BUNDLE_IDENTIFIER)\u003c/string\u003e\n\t\u003ckey\u003eCFBundleInfoDictionaryVersion\u003c/key\u003e\n\t\u003cstring\u003e6.0\u003c/string\u003e\n\t\u003ckey\u003eCFBundleName\u003c/key\u003e\n\t\u003cstring\u003e$(PRODUCT_NAME)\u003c/string\u003e\n\t\u003ckey\u003eCFBundlePackageType\u003c/key\u003e\n\t\u003cstring\u003eAPPL\u003c/string\u003e\n\t\u003ckey\u003eCFBundleShortVersionString\u003c/key\u003e\n\t\u003cstring\u003e$(FLUTTER_BUILD_NAME)\u003c/string\u003e\n\t\u003ckey\u003eCFBundleVersion\u003c/key\u003e\n\t\u003cstring\u003e$(FLUTTER_BUILD_NUMBER)\u003c/string\u003e\n\t\u003ckey\u003eLSMinimumSystemVersion\u003c/key\u003e\n\t\u003cstring\u003e$(MACOSX_DEPLOYMENT_TARGET)\u003c/string\u003e\n\t\u003ckey\u003eNSHumanReadableCopyright\u003c/key\u003e\n\t\u003cstring\u003e$(PRODUCT_COPYRIGHT)\u003c/string\u003e\n\t\u003ckey\u003eNSMainNibFile\u003c/key\u003e\n\t\u003cstring\u003eMainMenu\u003c/string\u003e\n+\t\u003ckey\u003eCFBundleURLTypes\u003c/key\u003e\n+\t\u003carray\u003e\n+\t\t\u003cdict\u003e\n+\t\t\t\u003ckey\u003eCFBundleTypeRole\u003c/key\u003e\n+\t\t\t\u003cstring\u003eEditor\u003c/string\u003e\n+\t\t\t\u003ckey\u003eCFBundleURLName\u003c/key\u003e\n+\t\t\t\u003cstring\u003e\u003c/string\u003e\n+\t\t\t\u003ckey\u003eCFBundleURLSchemes\u003c/key\u003e\n+\t\t\t\u003carray\u003e\n+\t\t\t\t\u003cstring\u003emyprotocol\u003c/string\u003e\n+\t\t\t\u003c/array\u003e\n+\t\t\u003c/dict\u003e\n+\t\u003c/array\u003e\n\t\u003ckey\u003eNSPrincipalClass\u003c/key\u003e\n\t\u003cstring\u003eNSApplication\u003c/string\u003e\n\u003c/dict\u003e\n\u003c/plist\u003e\n```\n\n##### Windows\n\n更改文件 `windows/runner/main.cpp` 如下：\n\n```diff\n#include \u003cflutter/dart_project.h\u003e\n#include \u003cflutter/flutter_view_controller.h\u003e\n#include \u003cwindows.h\u003e\n\n#include \"flutter_window.h\"\n#include \"utils.h\"\n\n+#include \u003cprotocol_handler_windows/protocol_handler_windows_plugin_c_api.h\u003e\n\nint APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev,\n                      _In_ wchar_t *command_line, _In_ int show_command) {\n+  // Replace protocol_handler_example with your_window_title.\n+  HWND hwnd = ::FindWindow(L\"FLUTTER_RUNNER_WIN32_WINDOW\", L\"protocol_handler_example\");\n+  if (hwnd != NULL) {\n+    DispatchToProtocolHandler(hwnd);\n+\n+    ::ShowWindow(hwnd, SW_NORMAL);\n+    ::SetForegroundWindow(hwnd);\n+    return EXIT_FAILURE;\n+  }\n\n  // Attach to console when present (e.g., 'flutter run') or create a\n  // new console when running with a debugger.\n  if (!::AttachConsole(ATTACH_PARENT_PROCESS) \u0026\u0026 ::IsDebuggerPresent()) {\n    CreateAndAttachConsole();\n  }\n\n  // Initialize COM, so that it is available for use in the library and/or\n  // plugins.\n  ::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED);\n\n  flutter::DartProject project(L\"data\");\n\n  std::vector\u003cstd::string\u003e command_line_arguments =\n      GetCommandLineArguments();\n\n  project.set_dart_entrypoint_arguments(std::move(command_line_arguments));\n\n  FlutterWindow window(project);\n  Win32Window::Point origin(10, 10);\n  Win32Window::Size size(1280, 720);\n  if (!window.CreateAndShow(L\"protocol_handler_example\", origin, size)) {\n    return EXIT_FAILURE;\n  }\n  window.SetQuitOnClose(true);\n\n  ::MSG msg;\n  while (::GetMessage(\u0026msg, nullptr, 0, 0)) {\n    ::TranslateMessage(\u0026msg);\n    ::DispatchMessage(\u0026msg);\n  }\n\n  ::CoUninitialize();\n  return EXIT_SUCCESS;\n}\n```\n\n如果你使用 `MSIX` 打包应用，需要在 `msix_config` 中添加 `protocol_activation` 配置：\n\n```yaml\nmsix_config:\n  protocol_activation: myprotocol\n```\n\n```dart\nimport 'package:protocol_handler/protocol_handler.dart';\n\nvoid main() async {\n  // 必须加上这一行。\n  WidgetsFlutterBinding.ensureInitialized();\n\n  // 注册一个自定义协议。\n  // 对于 macOS 平台需要在 ios/Runner/Info.plist 中声明 scheme。\n  await protocolHandler.register('myprotocol');\n\n  runApp(MyApp());\n}\n```\n\n### 监听事件\n\n```dart\nclass HomePage extends StatefulWidget {\n  const HomePage({Key? key}) : super(key: key);\n\n  @override\n  State\u003cHomePage\u003e createState() =\u003e _HomePageState();\n}\n\nclass _HomePageState extends State\u003cHomePage\u003e with ProtocolListener {\n  @override\n  void initState() {\n    protocolHandler.addListener(this);\n    super.initState();\n  }\n\n  @override\n  void dispose() {\n    protocolHandler.removeListener(this);\n    super.dispose();\n  }\n\n  @override\n  Widget build(BuildContext context) {\n    // ...\n  }\n\n  @override\n  void onProtocolUrlReceived(String url) {\n    String log = 'Url received: $url)';\n    print(log);\n  }\n}\n```\n\n\u003e 请看这个插件的示例应用，以了解完整的例子。\n\n## 谁在用使用它？\n\n- [比译](https://biyidev.com/) - 一个便捷的翻译和词典应用程序。\n\n## 许可证\n\n[MIT](./LICENSE)\n","funding_links":["https://liberapay.com/lijy91"],"categories":["C++","Packages"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fleanflutter%2Fprotocol_handler","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fleanflutter%2Fprotocol_handler","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fleanflutter%2Fprotocol_handler/lists"}