Skip to content

Commit b1f6086

Browse files
committed
[macos] Implement register metnod
1 parent 5b526fa commit b1f6086

File tree

12 files changed

+197
-55
lines changed

12 files changed

+197
-55
lines changed

example/lib/main.dart

Lines changed: 7 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -16,33 +16,18 @@ class MyApp extends StatefulWidget {
1616
}
1717

1818
class _MyAppState extends State<MyApp> {
19-
String _platformVersion = 'Unknown';
19+
late Stream<String?> _protocolStream;
2020

2121
@override
2222
void initState() {
2323
super.initState();
24-
initPlatformState();
24+
init();
2525
}
2626

27-
// Platform messages are asynchronous, so we initialize in an async method.
28-
Future<void> initPlatformState() async {
29-
String platformVersion;
30-
// Platform messages may fail, so we use a try/catch PlatformException.
31-
// We also handle the message potentially returning null.
32-
try {
33-
platformVersion =
34-
await ProtocolHandler.platformVersion ?? 'Unknown platform version';
35-
} on PlatformException {
36-
platformVersion = 'Failed to get platform version.';
37-
}
38-
39-
// If the widget was removed from the tree while the asynchronous platform
40-
// message was in flight, we want to discard the reply rather than calling
41-
// setState to update our non-existent appearance.
42-
if (!mounted) return;
43-
44-
setState(() {
45-
_platformVersion = platformVersion;
27+
void init() {
28+
_protocolStream = protocolHandler.register(protocol: 'myprotocol');
29+
_protocolStream.listen((event) {
30+
print(event);
4631
});
4732
}
4833

@@ -54,7 +39,7 @@ class _MyAppState extends State<MyApp> {
5439
title: const Text('Plugin example app'),
5540
),
5641
body: Center(
57-
child: Text('Running on: $_platformVersion\n'),
42+
child: Container(),
5843
),
5944
),
6045
);

example/macos/Podfile.lock

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
PODS:
2+
- FlutterMacOS (1.0.0)
3+
- protocol_handler (0.0.1):
4+
- FlutterMacOS
5+
6+
DEPENDENCIES:
7+
- FlutterMacOS (from `Flutter/ephemeral`)
8+
- protocol_handler (from `Flutter/ephemeral/.symlinks/plugins/protocol_handler/macos`)
9+
10+
EXTERNAL SOURCES:
11+
FlutterMacOS:
12+
:path: Flutter/ephemeral
13+
protocol_handler:
14+
:path: Flutter/ephemeral/.symlinks/plugins/protocol_handler/macos
15+
16+
SPEC CHECKSUMS:
17+
FlutterMacOS: 57701585bf7de1b3fc2bb61f6378d73bbdea8424
18+
protocol_handler: 587e1caf6c0b92ce351ab14081968dae49cb8cc6
19+
20+
PODFILE CHECKSUM: 6eac6b3292e5142cfc23bdeb71848a40ec51c14c
21+
22+
COCOAPODS: 1.11.2

example/macos/Runner.xcodeproj/project.pbxproj

Lines changed: 66 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; };
2727
33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; };
2828
33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; };
29+
B56664EB5892C2D616E2FD83 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8AE8DAA65A039BA8B277A732 /* Pods_Runner.framework */; };
2930
/* End PBXBuildFile section */
3031

3132
/* Begin PBXContainerItemProxy section */
@@ -54,7 +55,7 @@
5455
/* Begin PBXFileReference section */
5556
333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = "<group>"; };
5657
335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = "<group>"; };
57-
33CC10ED2044A3C60003C045 /* protocol_handler_example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "protocol_handler_example.app"; sourceTree = BUILT_PRODUCTS_DIR; };
58+
33CC10ED2044A3C60003C045 /* protocol_handler_example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = protocol_handler_example.app; sourceTree = BUILT_PRODUCTS_DIR; };
5859
33CC10F02044A3C60003C045 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
5960
33CC10F22044A3C60003C045 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = Runner/Assets.xcassets; sourceTree = "<group>"; };
6061
33CC10F52044A3C60003C045 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = "<group>"; };
@@ -66,15 +67,20 @@
6667
33E51913231747F40026EE4D /* DebugProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DebugProfile.entitlements; sourceTree = "<group>"; };
6768
33E51914231749380026EE4D /* Release.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Release.entitlements; sourceTree = "<group>"; };
6869
33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = "<group>"; };
70+
4BF58CCD3C9D63F2C6A05DDE /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
6971
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = "<group>"; };
72+
8AE8DAA65A039BA8B277A732 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
7073
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = "<group>"; };
74+
B0A11D7E9C90094312FB8AF1 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; };
75+
D6422017C2350B0C016B0C9F /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
7176
/* End PBXFileReference section */
7277

7378
/* Begin PBXFrameworksBuildPhase section */
7479
33CC10EA2044A3C60003C045 /* Frameworks */ = {
7580
isa = PBXFrameworksBuildPhase;
7681
buildActionMask = 2147483647;
7782
files = (
83+
B56664EB5892C2D616E2FD83 /* Pods_Runner.framework in Frameworks */,
7884
);
7985
runOnlyForDeploymentPostprocessing = 0;
8086
};
@@ -99,6 +105,7 @@
99105
33CEB47122A05771004F2AC0 /* Flutter */,
100106
33CC10EE2044A3C60003C045 /* Products */,
101107
D73912EC22F37F3D000D13A0 /* Frameworks */,
108+
AD8DB0CC717F7A2F2A8D98E0 /* Pods */,
102109
);
103110
sourceTree = "<group>";
104111
};
@@ -145,9 +152,20 @@
145152
path = Runner;
146153
sourceTree = "<group>";
147154
};
155+
AD8DB0CC717F7A2F2A8D98E0 /* Pods */ = {
156+
isa = PBXGroup;
157+
children = (
158+
B0A11D7E9C90094312FB8AF1 /* Pods-Runner.debug.xcconfig */,
159+
D6422017C2350B0C016B0C9F /* Pods-Runner.release.xcconfig */,
160+
4BF58CCD3C9D63F2C6A05DDE /* Pods-Runner.profile.xcconfig */,
161+
);
162+
path = Pods;
163+
sourceTree = "<group>";
164+
};
148165
D73912EC22F37F3D000D13A0 /* Frameworks */ = {
149166
isa = PBXGroup;
150167
children = (
168+
8AE8DAA65A039BA8B277A732 /* Pods_Runner.framework */,
151169
);
152170
name = Frameworks;
153171
sourceTree = "<group>";
@@ -159,11 +177,13 @@
159177
isa = PBXNativeTarget;
160178
buildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */;
161179
buildPhases = (
180+
93E2185084FE73C300034036 /* [CP] Check Pods Manifest.lock */,
162181
33CC10E92044A3C60003C045 /* Sources */,
163182
33CC10EA2044A3C60003C045 /* Frameworks */,
164183
33CC10EB2044A3C60003C045 /* Resources */,
165184
33CC110E2044A8840003C045 /* Bundle Framework */,
166185
3399D490228B24CF009A79C7 /* ShellScript */,
186+
EA119A9E57DD6D65159F765B /* [CP] Embed Pods Frameworks */,
167187
);
168188
buildRules = (
169189
);
@@ -188,7 +208,6 @@
188208
33CC10EC2044A3C60003C045 = {
189209
CreatedOnToolsVersion = 9.2;
190210
LastSwiftMigration = 1100;
191-
ProvisioningStyle = Automatic;
192211
SystemCapabilities = {
193212
com.apple.Sandbox = {
194213
enabled = 1;
@@ -270,6 +289,45 @@
270289
shellPath = /bin/sh;
271290
shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh && touch Flutter/ephemeral/tripwire";
272291
};
292+
93E2185084FE73C300034036 /* [CP] Check Pods Manifest.lock */ = {
293+
isa = PBXShellScriptBuildPhase;
294+
buildActionMask = 2147483647;
295+
files = (
296+
);
297+
inputFileListPaths = (
298+
);
299+
inputPaths = (
300+
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
301+
"${PODS_ROOT}/Manifest.lock",
302+
);
303+
name = "[CP] Check Pods Manifest.lock";
304+
outputFileListPaths = (
305+
);
306+
outputPaths = (
307+
"$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt",
308+
);
309+
runOnlyForDeploymentPostprocessing = 0;
310+
shellPath = /bin/sh;
311+
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
312+
showEnvVarsInLog = 0;
313+
};
314+
EA119A9E57DD6D65159F765B /* [CP] Embed Pods Frameworks */ = {
315+
isa = PBXShellScriptBuildPhase;
316+
buildActionMask = 2147483647;
317+
files = (
318+
);
319+
inputFileListPaths = (
320+
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
321+
);
322+
name = "[CP] Embed Pods Frameworks";
323+
outputFileListPaths = (
324+
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist",
325+
);
326+
runOnlyForDeploymentPostprocessing = 0;
327+
shellPath = /bin/sh;
328+
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
329+
showEnvVarsInLog = 0;
330+
};
273331
/* End PBXShellScriptBuildPhase section */
274332

275333
/* Begin PBXSourcesBuildPhase section */
@@ -359,8 +417,10 @@
359417
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
360418
CLANG_ENABLE_MODULES = YES;
361419
CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements;
420+
CODE_SIGN_IDENTITY = "Apple Development";
362421
CODE_SIGN_STYLE = Automatic;
363422
COMBINE_HIDPI_IMAGES = YES;
423+
DEVELOPMENT_TEAM = G83H824X6L;
364424
INFOPLIST_FILE = Runner/Info.plist;
365425
LD_RUNPATH_SEARCH_PATHS = (
366426
"$(inherited)",
@@ -485,8 +545,10 @@
485545
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
486546
CLANG_ENABLE_MODULES = YES;
487547
CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements;
548+
CODE_SIGN_IDENTITY = "Apple Development";
488549
CODE_SIGN_STYLE = Automatic;
489550
COMBINE_HIDPI_IMAGES = YES;
551+
DEVELOPMENT_TEAM = G83H824X6L;
490552
INFOPLIST_FILE = Runner/Info.plist;
491553
LD_RUNPATH_SEARCH_PATHS = (
492554
"$(inherited)",
@@ -505,8 +567,10 @@
505567
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
506568
CLANG_ENABLE_MODULES = YES;
507569
CODE_SIGN_ENTITLEMENTS = Runner/Release.entitlements;
570+
CODE_SIGN_IDENTITY = "Apple Development";
508571
CODE_SIGN_STYLE = Automatic;
509572
COMBINE_HIDPI_IMAGES = YES;
573+
DEVELOPMENT_TEAM = G83H824X6L;
510574
INFOPLIST_FILE = Runner/Info.plist;
511575
LD_RUNPATH_SEARCH_PATHS = (
512576
"$(inherited)",

example/macos/Runner.xcworkspace/contents.xcworkspacedata

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

example/macos/Runner/Info.plist

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,19 @@
2626
<string>$(PRODUCT_COPYRIGHT)</string>
2727
<key>NSMainNibFile</key>
2828
<string>MainMenu</string>
29+
<key>CFBundleURLTypes</key>
30+
<array>
31+
<dict>
32+
<key>CFBundleTypeRole</key>
33+
<string>Editor</string>
34+
<key>CFBundleURLName</key>
35+
<string></string>
36+
<key>CFBundleURLSchemes</key>
37+
<array>
38+
<string>myprotocol</string>
39+
</array>
40+
</dict>
41+
</array>
2942
<key>NSPrincipalClass</key>
3043
<string>NSApplication</string>
3144
</dict>

example/macos/Runner/Release.entitlements

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
33
<plist version="1.0">
44
<dict>
5+
<key>com.apple.developer.associated-domains</key>
6+
<array/>
57
<key>com.apple.security.app-sandbox</key>
68
<true/>
79
</dict>

lib/protocol_handler.dart

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1 @@
1-
2-
import 'dart:async';
3-
4-
import 'package:flutter/services.dart';
5-
6-
class ProtocolHandler {
7-
static const MethodChannel _channel = MethodChannel('protocol_handler');
8-
9-
static Future<String?> get platformVersion async {
10-
final String? version = await _channel.invokeMethod('getPlatformVersion');
11-
return version;
12-
}
13-
}
1+
export 'src/protocol_handler.dart';
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import 'package:flutter/services.dart';
2+
3+
class MethodChannelProtocolHandler {
4+
final MethodChannel _channel = const MethodChannel('protocol_handler');
5+
final EventChannel _eventChannel =
6+
const EventChannel('protocol_handler/events');
7+
8+
@override
9+
late final Stream<String?> protocolStream = _eventChannel
10+
.receiveBroadcastStream()
11+
.map<String?>((dynamic v) => v as String?);
12+
}

lib/src/protocol_handler.dart

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import 'dart:async';
2+
3+
import 'method_channel/method_channel_protocol_handler.dart';
4+
5+
class ProtocolHandler {
6+
ProtocolHandler._();
7+
8+
/// The shared instance of [ProtocolHandler].
9+
static final ProtocolHandler instance = ProtocolHandler._();
10+
11+
final MethodChannelProtocolHandler _methodChannel =
12+
MethodChannelProtocolHandler();
13+
14+
Stream<String?> register({
15+
required String protocol,
16+
}) {
17+
return _methodChannel.protocolStream;
18+
}
19+
}
20+
21+
final protocolHandler = ProtocolHandler.instance;
Lines changed: 46 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,51 @@
11
import Cocoa
22
import FlutterMacOS
33

4-
public class ProtocolHandlerPlugin: NSObject, FlutterPlugin {
5-
public static func register(with registrar: FlutterPluginRegistrar) {
6-
let channel = FlutterMethodChannel(name: "protocol_handler", binaryMessenger: registrar.messenger)
7-
let instance = ProtocolHandlerPlugin()
8-
registrar.addMethodCallDelegate(instance, channel: channel)
9-
}
10-
11-
public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
12-
switch call.method {
13-
case "getPlatformVersion":
14-
result("macOS " + ProcessInfo.processInfo.operatingSystemVersionString)
15-
default:
16-
result(FlutterMethodNotImplemented)
4+
public class ProtocolHandlerPlugin: NSObject, FlutterPlugin, FlutterStreamHandler {
5+
private var _eventSink: FlutterEventSink?
6+
7+
override init(){
8+
super.init();
9+
NSAppleEventManager.shared().setEventHandler(self, andSelector: #selector(handleURLEvent(_:with:)), forEventClass: AEEventClass(kInternetEventClass), andEventID: AEEventID(kAEGetURL))
10+
}
11+
12+
public static func register(with registrar: FlutterPluginRegistrar) {
13+
let instance = ProtocolHandlerPlugin()
14+
15+
let channel = FlutterMethodChannel(name: "protocol_handler", binaryMessenger: registrar.messenger)
16+
registrar.addMethodCallDelegate(instance, channel: channel)
17+
18+
let eventChannel = FlutterEventChannel(name: "protocol_handler/events", binaryMessenger: registrar.messenger)
19+
eventChannel.setStreamHandler(instance)
20+
}
21+
22+
@objc
23+
private func handleURLEvent(_ event: NSAppleEventDescriptor, with replyEvent: NSAppleEventDescriptor) {
24+
guard let urlString = event.paramDescriptor(forKeyword: AEKeyword(keyDirectObject))?.stringValue else { return }
25+
_eventSink!(urlString);
26+
}
27+
28+
public func application(_ application: NSApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([NSUserActivityRestoring]) -> Void) -> Bool {
29+
if (userActivity.activityType == NSUserActivityTypeBrowsingWeb) {
30+
// TODO
31+
}
32+
return false
33+
}
34+
35+
public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
36+
switch call.method {
37+
default:
38+
result(FlutterMethodNotImplemented)
39+
}
40+
}
41+
42+
public func onListen(withArguments arguments: Any?, eventSink events: @escaping FlutterEventSink) -> FlutterError? {
43+
self._eventSink = events;
44+
return nil
45+
}
46+
47+
public func onCancel(withArguments arguments: Any?) -> FlutterError? {
48+
self._eventSink = nil
49+
return nil
1750
}
18-
}
1951
}

0 commit comments

Comments
 (0)