Search packages, repositories and app categories

Package detailsv0.2.0

protocol_handler

This plugin allows Flutter apps to register and handle custom protocols (i.e. deep linking).

AndroidiOSmacOSWindows
30-day downloads
3.7K
Likes
69
Pub points
150

Install package

flutter pub add protocol_handler

Package Overview

Package selection guidance compiled from public package information, community data, and project usage.

The protocol_handler package enables Flutter applications to register and respond to custom URL schemes, facilitating deep linking across platforms. It allows apps to handle external links (e.g., myapp://open) by launching the app and passing data through the URI. This is particularly useful for integrating with other apps, web services, or system-level triggers. The plugin supports Android, iOS, macOS, and Windows, making it ideal for cross-platform desktop and mobile apps that require seamless navigation from external sources.

Use cases

  • Handling custom URL schemes
  • Enabling deep linking from emails or websites
  • Integrating with third-party apps
  • Supporting desktop and mobile workflows
  • Launching app from external links

Key features

  • Cross-platform support
  • Custom protocol registration
  • URI data extraction
  • Simple API integration
  • Desktop and mobile compatibility

Suitable for

  • Apps needing deep linking
  • Desktop and mobile hybrid apps
  • External service integrations
  • App-to-app communication
  • Developers building universal links

Considerations

  • Requires platform-specific setup
  • May need additional configuration on iOS
  • Limited to supported platforms
  • Security considerations with URI handling
  • Not suitable for standard HTTP URLs

Original README

Original README snapshot from the linked source repository. Visit the repository for the latest content.

🚀 Ship Your App Faster: Try Fastforge - The simplest way to build, package and distribute your Flutter apps.

protocol_handler

pub version

This plugin allows Flutter apps to register and handle custom protocols (i.e. deep linking).


English | 简体中文


Platform Support

Android iOS Linux macOS Windows
✔️ ✔️ ➖ ✔️ ✔️

Screenshots

https://user-images.githubusercontent.com/3889523/167283452-aff2535b-c322-45c7-949f-d1c80c2e4a60.mp4

Quick Start

Installation

Add this to your package's pubspec.yaml file:

dependencies:
  protocol_handler: ^0.2.0

Or

dependencies:
  protocol_handler:
    git:
      url: https://github.com/leanflutter/protocol_handler.git
      ref: main
Usage
Android

Change the file android/app/src/main/AndroidManifest.xml as follows:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="dev.leanflutter.plugins.protocol_handler_example">

    <application
        android:name="${applicationName}"
        android:icon="@mipmap/ic_launcher"
        android:label="protocol_handler_example">
        <activity
            android:name=".MainActivity"
            android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
            android:exported="true"
            android:hardwareAccelerated="true"
            android:launchMode="singleTop"
            android:theme="@style/LaunchTheme"
            android:windowSoftInputMode="adjustResize">
            <!-- Specifies an Android theme to apply to this Activity as soon as
                 the Android process has started. This theme is visible to the user
                 while the Flutter UI initializes. After that, this theme continues
                 to determine the Window background behind the Flutter UI. -->
            <meta-data
                android:name="io.flutter.embedding.android.NormalTheme"
                android:resource="@style/NormalTheme" />

            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
+            <intent-filter>
+                <action android:name="android.intent.action.VIEW" />
+
+                <category android:name="android.intent.category.DEFAULT" />
+                <category android:name="android.intent.category.BROWSABLE" />
+                <!-- Accepts URIs that begin with YOUR_SCHEME://YOUR_HOST -->
+                <data android:scheme="myprotocol" />
+            </intent-filter>
        </activity>
        <!-- Don't delete the meta-data below.
             This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
        <meta-data
            android:name="flutterEmbedding"
            android:value="2" />
    </application>
</manifest>
iOS

Change the file ios/Runner/Info.plist as follows:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>CFBundleDevelopmentRegion</key>
	<string>$(DEVELOPMENT_LANGUAGE)</string>
	<key>CFBundleDisplayName</key>
	<string>Protocol Handler</string>
	<key>CFBundleExecutable</key>
	<string>$(EXECUTABLE_NAME)</string>
	<key>CFBundleIdentifier</key>
	<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
	<key>CFBundleInfoDictionaryVersion</key>
	<string>6.0</string>
	<key>CFBundleName</key>
	<string>protocol_handler_example</string>
	<key>CFBundlePackageType</key>
	<string>APPL</string>
	<key>CFBundleShortVersionString</key>
	<string>$(FLUTTER_BUILD_NAME)</string>
	<key>CFBundleSignature</key>
	<string>????</string>
	<key>CFBundleVersion</key>
	<string>$(FLUTTER_BUILD_NUMBER)</string>
	<key>LSRequiresIPhoneOS</key>
	<true/>
	<key>UILaunchStoryboardName</key>
	<string>LaunchScreen</string>
	<key>UIMainStoryboardFile</key>
	<string>Main</string>
+	<key>CFBundleURLTypes</key>
+	<array>
+		<dict>
+			<key>CFBundleTypeRole</key>
+			<string>Editor</string>
+			<key>CFBundleURLName</key>
+			<string></string>
+			<key>CFBundleURLSchemes</key>
+			<array>
+				<string>myprotocol</string>
+			</array>
+		</dict>
+	</array>
	<key>UISupportedInterfaceOrientations</key>
	<array>
		<string>UIInterfaceOrientationPortrait</string>
		<string>UIInterfaceOrientationLandscapeLeft</string>
		<string>UIInterfaceOrientationLandscapeRight</string>
	</array>
	<key>UISupportedInterfaceOrientations~ipad</key>
	<array>
		<string>UIInterfaceOrientationPortrait</string>
		<string>UIInterfaceOrientationPortraitUpsideDown</string>
		<string>UIInterfaceOrientationLandscapeLeft</string>
		<string>UIInterfaceOrientationLandscapeRight</string>
	</array>
	<key>UIViewControllerBasedStatusBarAppearance</key>
	<false/>
</dict>
</plist>

macOS

Change the file macos/Runner/Info.plist as follows:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>CFBundleDevelopmentRegion</key>
	<string>$(DEVELOPMENT_LANGUAGE)</string>
	<key>CFBundleExecutable</key>
	<string>$(EXECUTABLE_NAME)</string>
	<key>CFBundleIconFile</key>
	<string></string>
	<key>CFBundleIdentifier</key>
	<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
	<key>CFBundleInfoDictionaryVersion</key>
	<string>6.0</string>
	<key>CFBundleName</key>
	<string>$(PRODUCT_NAME)</string>
	<key>CFBundlePackageType</key>
	<string>APPL</string>
	<key>CFBundleShortVersionString</key>
	<string>$(FLUTTER_BUILD_NAME)</string>
	<key>CFBundleVersion</key>
	<string>$(FLUTTER_BUILD_NUMBER)</string>
	<key>LSMinimumSystemVersion</key>
	<string>$(MACOSX_DEPLOYMENT_TARGET)</string>
	<key>NSHumanReadableCopyright</key>
	<string>$(PRODUCT_COPYRIGHT)</string>
	<key>NSMainNibFile</key>
	<string>MainMenu</string>
+	<key>CFBundleURLTypes</key>
+	<array>
+		<dict>
+			<key>CFBundleTypeRole</key>
+			<string>Editor</string>
+			<key>CFBundleURLName</key>
+			<string></string>
+			<key>CFBundleURLSchemes</key>
+			<array>
+				<string>myprotocol</string>
+			</array>
+		</dict>
+	</array>
	<key>NSPrincipalClass</key>
	<string>NSApplication</string>
</dict>
</plist>
Windows

Change the file windows/runner/main.cpp as follows:

#include <flutter/dart_project.h>
#include <flutter/flutter_view_controller.h>
#include <windows.h>

#include "flutter_window.h"
#include "utils.h"

+#include <protocol_handler_windows/protocol_handler_windows_plugin_c_api.h>

int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev,
                      _In_ wchar_t *command_line, _In_ int show_command) {
+  // Replace protocol_handler_example with your_window_title.
+  HWND hwnd = ::FindWindow(L"FLUTTER_RUNNER_WIN32_WINDOW", L"protocol_handler_example");
+  if (hwnd != NULL) {
+    DispatchToProtocolHandler(hwnd);
+
+    ::ShowWindow(hwnd, SW_NORMAL);
+    ::SetForegroundWindow(hwnd);
+    return EXIT_FAILURE;
+  }

  // Attach to console when present (e.g., 'flutter run') or create a
  // new console when running with a debugger.
  if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::IsDebuggerPresent()) {
    CreateAndAttachConsole();
  }

  // Initialize COM, so that it is available for use in the library and/or
  // plugins.
  ::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED);

  flutter::DartProject project(L"data");

  std::vector<std::string> command_line_arguments =
      GetCommandLineArguments();

  project.set_dart_entrypoint_arguments(std::move(command_line_arguments));

  FlutterWindow window(project);
  Win32Window::Point origin(10, 10);
  Win32Window::Size size(1280, 720);
  if (!window.CreateAndShow(L"protocol_handler_example", origin, size)) {
    return EXIT_FAILURE;
  }
  window.SetQuitOnClose(true);

  ::MSG msg;
  while (::GetMessage(&msg, nullptr, 0, 0)) {
    ::TranslateMessage(&msg);
    ::DispatchMessage(&msg);
  }

  ::CoUninitialize();
  return EXIT_SUCCESS;
}

If you use MSIX to package your application, you need to add protocol_activation configuration in msix_config:

msix_config:
  protocol_activation: myprotocol

See this issue for details: YehudaKremer/msix#187

import 'package:protocol_handler/protocol_handler.dart';

void main() async {
  // Must add this line.
  WidgetsFlutterBinding.ensureInitialized();

  // Register a custom protocol
  // For macOS platform needs to declare the scheme in ios/Runner/Info.plist
  await protocolHandler.register('myprotocol');

  runApp(MyApp());
}
Listening events
class HomePage extends StatefulWidget {
  const HomePage({Key? key}) : super(key: key);

  @override
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> with ProtocolListener {
  @override
  void initState() {
    protocolHandler.addListener(this);
    super.initState();
  }

  @override
  void dispose() {
    protocolHandler.removeListener(this);
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    // ...
  }

  @override
  void onProtocolUrlReceived(String url) {
    String log = 'Url received: $url)';
    print(log);
  }
}

Please see the example app of this plugin for a full example.

Who's using it?

  • Biyi - A convenient translation and dictionary app.

License

MIT

Categories

Dependencies

Dependency list 5 items

  • protocol_handler_android^0.2.0
  • protocol_handler_ios^0.2.0
  • protocol_handler_macos^0.2.0
  • protocol_handler_platform_interface^0.2.0
  • protocol_handler_windows^0.2.0

Source repository

Projects using this package