diff --git a/analysis_options.yaml b/analysis_options.yaml
index 318d8206..2627357c 100644
--- a/analysis_options.yaml
+++ b/analysis_options.yaml
@@ -1,4 +1,4 @@
-include: package:lint/analysis_options_package.yaml
+#include: package:lint/analysis_options_package.yaml
analyzer:
strong-mode:
diff --git a/catcher.iml b/catcher.iml
index c7d89491..bf68c1a8 100644
--- a/catcher.iml
+++ b/catcher.iml
@@ -11,6 +11,5 @@
-
\ No newline at end of file
diff --git a/example/lib/generated_plugin_registrant.dart b/example/lib/generated_plugin_registrant.dart
index 121523bf..118ae5b9 100644
--- a/example/lib/generated_plugin_registrant.dart
+++ b/example/lib/generated_plugin_registrant.dart
@@ -4,6 +4,7 @@
// ignore_for_file: lines_longer_than_80_chars
+import 'package:catcher/catcher_web_plugin.dart';
import 'package:device_info_plus_web/device_info_plus_web.dart';
import 'package:fluttertoast/fluttertoast_web.dart';
@@ -11,6 +12,7 @@ import 'package:flutter_web_plugins/flutter_web_plugins.dart';
// ignore: public_member_api_docs
void registerPlugins(Registrar registrar) {
+ CatcherWeb.registerWith(registrar);
DeviceInfoPlusPlugin.registerWith(registrar);
FluttertoastWebPlugin.registerWith(registrar);
registrar.registerMessageHandler();
diff --git a/example/linux/.gitignore b/example/linux/.gitignore
new file mode 100644
index 00000000..d3896c98
--- /dev/null
+++ b/example/linux/.gitignore
@@ -0,0 +1 @@
+flutter/ephemeral
diff --git a/example/linux/flutter/generated_plugin_registrant.cc b/example/linux/flutter/generated_plugin_registrant.cc
new file mode 100644
index 00000000..ec0d8001
--- /dev/null
+++ b/example/linux/flutter/generated_plugin_registrant.cc
@@ -0,0 +1,13 @@
+//
+// Generated file. Do not edit.
+//
+
+#include "generated_plugin_registrant.h"
+
+#include
+
+void fl_register_plugins(FlPluginRegistry* registry) {
+ g_autoptr(FlPluginRegistrar) catcher_registrar =
+ fl_plugin_registry_get_registrar_for_plugin(registry, "CatcherPlugin");
+ catcher_plugin_register_with_registrar(catcher_registrar);
+}
diff --git a/example/linux/flutter/generated_plugin_registrant.h b/example/linux/flutter/generated_plugin_registrant.h
new file mode 100644
index 00000000..9bf74789
--- /dev/null
+++ b/example/linux/flutter/generated_plugin_registrant.h
@@ -0,0 +1,13 @@
+//
+// Generated file. Do not edit.
+//
+
+#ifndef GENERATED_PLUGIN_REGISTRANT_
+#define GENERATED_PLUGIN_REGISTRANT_
+
+#include
+
+// Registers Flutter plugins.
+void fl_register_plugins(FlPluginRegistry* registry);
+
+#endif // GENERATED_PLUGIN_REGISTRANT_
diff --git a/example/linux/flutter/generated_plugins.cmake b/example/linux/flutter/generated_plugins.cmake
new file mode 100644
index 00000000..dda73536
--- /dev/null
+++ b/example/linux/flutter/generated_plugins.cmake
@@ -0,0 +1,16 @@
+#
+# Generated file, do not edit.
+#
+
+list(APPEND FLUTTER_PLUGIN_LIST
+ catcher
+)
+
+set(PLUGIN_BUNDLED_LIBRARIES)
+
+foreach(plugin ${FLUTTER_PLUGIN_LIST})
+ add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/linux plugins/${plugin})
+ target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin)
+ list(APPEND PLUGIN_BUNDLED_LIBRARIES $)
+ list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries})
+endforeach(plugin)
diff --git a/example/linux/main.cc b/example/linux/main.cc
new file mode 100644
index 00000000..e7c5c543
--- /dev/null
+++ b/example/linux/main.cc
@@ -0,0 +1,6 @@
+#include "my_application.h"
+
+int main(int argc, char** argv) {
+ g_autoptr(MyApplication) app = my_application_new();
+ return g_application_run(G_APPLICATION(app), argc, argv);
+}
diff --git a/example/linux/my_application.cc b/example/linux/my_application.cc
new file mode 100644
index 00000000..35e8cdb8
--- /dev/null
+++ b/example/linux/my_application.cc
@@ -0,0 +1,104 @@
+#include "my_application.h"
+
+#include
+#ifdef GDK_WINDOWING_X11
+#include
+#endif
+
+#include "flutter/generated_plugin_registrant.h"
+
+struct _MyApplication {
+ GtkApplication parent_instance;
+ char** dart_entrypoint_arguments;
+};
+
+G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION)
+
+// Implements GApplication::activate.
+static void my_application_activate(GApplication* application) {
+ MyApplication* self = MY_APPLICATION(application);
+ GtkWindow* window =
+ GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application)));
+
+ // Use a header bar when running in GNOME as this is the common style used
+ // by applications and is the setup most users will be using (e.g. Ubuntu
+ // desktop).
+ // If running on X and not using GNOME then just use a traditional title bar
+ // in case the window manager does more exotic layout, e.g. tiling.
+ // If running on Wayland assume the header bar will work (may need changing
+ // if future cases occur).
+ gboolean use_header_bar = TRUE;
+#ifdef GDK_WINDOWING_X11
+ GdkScreen *screen = gtk_window_get_screen(window);
+ if (GDK_IS_X11_SCREEN(screen)) {
+ const gchar* wm_name = gdk_x11_screen_get_window_manager_name(screen);
+ if (g_strcmp0(wm_name, "GNOME Shell") != 0) {
+ use_header_bar = FALSE;
+ }
+ }
+#endif
+ if (use_header_bar) {
+ GtkHeaderBar *header_bar = GTK_HEADER_BAR(gtk_header_bar_new());
+ gtk_widget_show(GTK_WIDGET(header_bar));
+ gtk_header_bar_set_title(header_bar, "catcher_example");
+ gtk_header_bar_set_show_close_button(header_bar, TRUE);
+ gtk_window_set_titlebar(window, GTK_WIDGET(header_bar));
+ }
+ else {
+ gtk_window_set_title(window, "catcher_example");
+ }
+
+ gtk_window_set_default_size(window, 1280, 720);
+ gtk_widget_show(GTK_WIDGET(window));
+
+ g_autoptr(FlDartProject) project = fl_dart_project_new();
+ fl_dart_project_set_dart_entrypoint_arguments(project, self->dart_entrypoint_arguments);
+
+ FlView* view = fl_view_new(project);
+ gtk_widget_show(GTK_WIDGET(view));
+ gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view));
+
+ fl_register_plugins(FL_PLUGIN_REGISTRY(view));
+
+ gtk_widget_grab_focus(GTK_WIDGET(view));
+}
+
+// Implements GApplication::local_command_line.
+static gboolean my_application_local_command_line(GApplication* application, gchar ***arguments, int *exit_status) {
+ MyApplication* self = MY_APPLICATION(application);
+ // Strip out the first argument as it is the binary name.
+ self->dart_entrypoint_arguments = g_strdupv(*arguments + 1);
+
+ g_autoptr(GError) error = nullptr;
+ if (!g_application_register(application, nullptr, &error)) {
+ g_warning("Failed to register: %s", error->message);
+ *exit_status = 1;
+ return TRUE;
+ }
+
+ g_application_activate(application);
+ *exit_status = 0;
+
+ return TRUE;
+}
+
+// Implements GObject::dispose.
+static void my_application_dispose(GObject *object) {
+ MyApplication* self = MY_APPLICATION(object);
+ g_clear_pointer(&self->dart_entrypoint_arguments, g_strfreev);
+ G_OBJECT_CLASS(my_application_parent_class)->dispose(object);
+}
+
+static void my_application_class_init(MyApplicationClass* klass) {
+ G_APPLICATION_CLASS(klass)->activate = my_application_activate;
+ G_APPLICATION_CLASS(klass)->local_command_line = my_application_local_command_line;
+ G_OBJECT_CLASS(klass)->dispose = my_application_dispose;
+}
+
+static void my_application_init(MyApplication* self) {}
+
+MyApplication* my_application_new() {
+ return MY_APPLICATION(g_object_new(my_application_get_type(),
+ "application-id", APPLICATION_ID,
+ nullptr));
+}
diff --git a/example/linux/my_application.h b/example/linux/my_application.h
new file mode 100644
index 00000000..72271d5e
--- /dev/null
+++ b/example/linux/my_application.h
@@ -0,0 +1,18 @@
+#ifndef FLUTTER_MY_APPLICATION_H_
+#define FLUTTER_MY_APPLICATION_H_
+
+#include
+
+G_DECLARE_FINAL_TYPE(MyApplication, my_application, MY, APPLICATION,
+ GtkApplication)
+
+/**
+ * my_application_new:
+ *
+ * Creates a new Flutter-based application.
+ *
+ * Returns: a new #MyApplication.
+ */
+MyApplication* my_application_new();
+
+#endif // FLUTTER_MY_APPLICATION_H_
diff --git a/example/macos/Flutter/GeneratedPluginRegistrant.swift b/example/macos/Flutter/GeneratedPluginRegistrant.swift
index 8692656b..6d264d07 100644
--- a/example/macos/Flutter/GeneratedPluginRegistrant.swift
+++ b/example/macos/Flutter/GeneratedPluginRegistrant.swift
@@ -5,12 +5,14 @@
import FlutterMacOS
import Foundation
+import catcher
import device_info_plus_macos
import flutter_local_notifications
import package_info
import path_provider_macos
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
+ CatcherPlugin.register(with: registry.registrar(forPlugin: "CatcherPlugin"))
DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin"))
FlutterLocalNotificationsPlugin.register(with: registry.registrar(forPlugin: "FlutterLocalNotificationsPlugin"))
FLTPackageInfoPlugin.register(with: registry.registrar(forPlugin: "FLTPackageInfoPlugin"))
diff --git a/example/macos/Runner.xcodeproj/project.pbxproj b/example/macos/Runner.xcodeproj/project.pbxproj
index cccd68f9..83a04a40 100644
--- a/example/macos/Runner.xcodeproj/project.pbxproj
+++ b/example/macos/Runner.xcodeproj/project.pbxproj
@@ -26,7 +26,7 @@
33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; };
33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; };
33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; };
- F178447C0A8D9FE298E8A7A8 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D5C11E12928D07B55964A9DB /* Pods_Runner.framework */; };
+ 3E3E2B985E5960525E5BADB7 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0B24CED0B1E10A24C5DA8786 /* Pods_Runner.framework */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
@@ -53,6 +53,8 @@
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
+ 05BA3BB79E6D74A4D474C860 /* 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 = ""; };
+ 0B24CED0B1E10A24C5DA8786 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = ""; };
335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = ""; };
33CC10ED2044A3C60003C045 /* catcher_example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = catcher_example.app; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -67,12 +69,10 @@
33E51913231747F40026EE4D /* DebugProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DebugProfile.entitlements; sourceTree = ""; };
33E51914231749380026EE4D /* Release.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Release.entitlements; sourceTree = ""; };
33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = ""; };
+ 3D08C8AD9DE33D277AB87F1C /* 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 = ""; };
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = ""; };
- 85EFE0C1CC477BC2143FE195 /* 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 = ""; };
- 86AA2755FE9FE4680AD06A32 /* 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 = ""; };
- 8B843E1885932BD6D83C0143 /* 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 = ""; };
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = ""; };
- D5C11E12928D07B55964A9DB /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
+ DFB4E83A10F6FD9F48EC9D46 /* 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 = ""; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -80,7 +80,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
- F178447C0A8D9FE298E8A7A8 /* Pods_Runner.framework in Frameworks */,
+ 3E3E2B985E5960525E5BADB7 /* Pods_Runner.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -104,8 +104,8 @@
33FAB671232836740065AC1E /* Runner */,
33CEB47122A05771004F2AC0 /* Flutter */,
33CC10EE2044A3C60003C045 /* Products */,
- D73912EC22F37F3D000D13A0 /* Frameworks */,
- 6D62F9A19FE20D0334E0956D /* Pods */,
+ 602A7C9497590F6A601B83C9 /* Pods */,
+ F28F4AE0D0746D317A77DE6A /* Frameworks */,
);
sourceTree = "";
};
@@ -152,21 +152,21 @@
path = Runner;
sourceTree = "";
};
- 6D62F9A19FE20D0334E0956D /* Pods */ = {
+ 602A7C9497590F6A601B83C9 /* Pods */ = {
isa = PBXGroup;
children = (
- 85EFE0C1CC477BC2143FE195 /* Pods-Runner.debug.xcconfig */,
- 8B843E1885932BD6D83C0143 /* Pods-Runner.release.xcconfig */,
- 86AA2755FE9FE4680AD06A32 /* Pods-Runner.profile.xcconfig */,
+ 3D08C8AD9DE33D277AB87F1C /* Pods-Runner.debug.xcconfig */,
+ 05BA3BB79E6D74A4D474C860 /* Pods-Runner.release.xcconfig */,
+ DFB4E83A10F6FD9F48EC9D46 /* Pods-Runner.profile.xcconfig */,
);
name = Pods;
path = Pods;
sourceTree = "";
};
- D73912EC22F37F3D000D13A0 /* Frameworks */ = {
+ F28F4AE0D0746D317A77DE6A /* Frameworks */ = {
isa = PBXGroup;
children = (
- D5C11E12928D07B55964A9DB /* Pods_Runner.framework */,
+ 0B24CED0B1E10A24C5DA8786 /* Pods_Runner.framework */,
);
name = Frameworks;
sourceTree = "";
@@ -178,13 +178,13 @@
isa = PBXNativeTarget;
buildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */;
buildPhases = (
- 667864DBD9A98F0B7378BFDC /* [CP] Check Pods Manifest.lock */,
+ 37FE6C4BF1A8ECF82EA45674 /* [CP] Check Pods Manifest.lock */,
33CC10E92044A3C60003C045 /* Sources */,
33CC10EA2044A3C60003C045 /* Frameworks */,
33CC10EB2044A3C60003C045 /* Resources */,
33CC110E2044A8840003C045 /* Bundle Framework */,
3399D490228B24CF009A79C7 /* ShellScript */,
- CE70D36827B5CE11A1F3C12B /* [CP] Embed Pods Frameworks */,
+ CD06C157728813A2A3570462 /* [CP] Embed Pods Frameworks */,
);
buildRules = (
);
@@ -291,7 +291,7 @@
shellPath = /bin/sh;
shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh && touch Flutter/ephemeral/tripwire";
};
- 667864DBD9A98F0B7378BFDC /* [CP] Check Pods Manifest.lock */ = {
+ 37FE6C4BF1A8ECF82EA45674 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
@@ -313,7 +313,7 @@
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";
showEnvVarsInLog = 0;
};
- CE70D36827B5CE11A1F3C12B /* [CP] Embed Pods Frameworks */ = {
+ CD06C157728813A2A3570462 /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
diff --git a/linux/catcher_plugin.cc b/linux/catcher_plugin.cc
new file mode 100644
index 00000000..32c9d53f
--- /dev/null
+++ b/linux/catcher_plugin.cc
@@ -0,0 +1,70 @@
+#include "include/catcher/catcher_plugin.h"
+
+#include
+#include
+#include
+
+#include
+
+#define CATCHER_PLUGIN(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj), catcher_plugin_get_type(), \
+ CatcherPlugin))
+
+struct _CatcherPlugin {
+ GObject parent_instance;
+};
+
+G_DEFINE_TYPE(CatcherPlugin, catcher_plugin, g_object_get_type())
+
+// Called when a method call is received from Flutter.
+static void catcher_plugin_handle_method_call(
+ CatcherPlugin* self,
+ FlMethodCall* method_call) {
+ g_autoptr(FlMethodResponse) response = nullptr;
+
+ const gchar* method = fl_method_call_get_name(method_call);
+
+ if (strcmp(method, "getPlatformVersion") == 0) {
+ struct utsname uname_data = {};
+ uname(&uname_data);
+ g_autofree gchar *version = g_strdup_printf("Linux %s", uname_data.version);
+ g_autoptr(FlValue) result = fl_value_new_string(version);
+ response = FL_METHOD_RESPONSE(fl_method_success_response_new(result));
+ } else {
+ response = FL_METHOD_RESPONSE(fl_method_not_implemented_response_new());
+ }
+
+ fl_method_call_respond(method_call, response, nullptr);
+}
+
+static void catcher_plugin_dispose(GObject* object) {
+ G_OBJECT_CLASS(catcher_plugin_parent_class)->dispose(object);
+}
+
+static void catcher_plugin_class_init(CatcherPluginClass* klass) {
+ G_OBJECT_CLASS(klass)->dispose = catcher_plugin_dispose;
+}
+
+static void catcher_plugin_init(CatcherPlugin* self) {}
+
+static void method_call_cb(FlMethodChannel* channel, FlMethodCall* method_call,
+ gpointer user_data) {
+ CatcherPlugin* plugin = CATCHER_PLUGIN(user_data);
+ catcher_plugin_handle_method_call(plugin, method_call);
+}
+
+void catcher_plugin_register_with_registrar(FlPluginRegistrar* registrar) {
+ CatcherPlugin* plugin = CATCHER_PLUGIN(
+ g_object_new(catcher_plugin_get_type(), nullptr));
+
+ g_autoptr(FlStandardMethodCodec) codec = fl_standard_method_codec_new();
+ g_autoptr(FlMethodChannel) channel =
+ fl_method_channel_new(fl_plugin_registrar_get_messenger(registrar),
+ "catcher",
+ FL_METHOD_CODEC(codec));
+ fl_method_channel_set_method_call_handler(channel, method_call_cb,
+ g_object_ref(plugin),
+ g_object_unref);
+
+ g_object_unref(plugin);
+}
diff --git a/linux/include/catcher/catcher_plugin.h b/linux/include/catcher/catcher_plugin.h
new file mode 100644
index 00000000..d0fe7077
--- /dev/null
+++ b/linux/include/catcher/catcher_plugin.h
@@ -0,0 +1,26 @@
+#ifndef FLUTTER_PLUGIN_CATCHER_PLUGIN_H_
+#define FLUTTER_PLUGIN_CATCHER_PLUGIN_H_
+
+#include
+
+G_BEGIN_DECLS
+
+#ifdef FLUTTER_PLUGIN_IMPL
+#define FLUTTER_PLUGIN_EXPORT __attribute__((visibility("default")))
+#else
+#define FLUTTER_PLUGIN_EXPORT
+#endif
+
+typedef struct _CatcherPlugin CatcherPlugin;
+typedef struct {
+ GObjectClass parent_class;
+} CatcherPluginClass;
+
+FLUTTER_PLUGIN_EXPORT GType catcher_plugin_get_type();
+
+FLUTTER_PLUGIN_EXPORT void catcher_plugin_register_with_registrar(
+ FlPluginRegistrar* registrar);
+
+G_END_DECLS
+
+#endif // FLUTTER_PLUGIN_CATCHER_PLUGIN_H_
diff --git a/macos/Classes/CatcherPlugin.swift b/macos/Classes/CatcherPlugin.swift
new file mode 100644
index 00000000..81d88ca4
--- /dev/null
+++ b/macos/Classes/CatcherPlugin.swift
@@ -0,0 +1,19 @@
+import Cocoa
+import FlutterMacOS
+
+public class CatcherPlugin: NSObject, FlutterPlugin {
+ public static func register(with registrar: FlutterPluginRegistrar) {
+ let channel = FlutterMethodChannel(name: "catcher", binaryMessenger: registrar.messenger)
+ let instance = CatcherPlugin()
+ registrar.addMethodCallDelegate(instance, channel: channel)
+ }
+
+ public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
+ switch call.method {
+ case "getPlatformVersion":
+ result("macOS " + ProcessInfo.processInfo.operatingSystemVersionString)
+ default:
+ result(FlutterMethodNotImplemented)
+ }
+ }
+}
diff --git a/macos/catcher.podspec b/macos/catcher.podspec
new file mode 100644
index 00000000..7b8d26d0
--- /dev/null
+++ b/macos/catcher.podspec
@@ -0,0 +1,22 @@
+#
+# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html.
+# Run `pod lib lint catcher.podspec` to validate before publishing.
+#
+Pod::Spec.new do |s|
+ s.name = 'catcher'
+ s.version = '0.0.1'
+ s.summary = 'A new flutter plugin project.'
+ s.description = <<-DESC
+A new flutter plugin project.
+ DESC
+ s.homepage = 'http://example.com'
+ s.license = { :file => '../LICENSE' }
+ s.author = { 'Your Company' => 'email@example.com' }
+ s.source = { :path => '.' }
+ s.source_files = 'Classes/**/*'
+ s.dependency 'FlutterMacOS'
+
+ s.platform = :osx, '10.11'
+ s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES' }
+ s.swift_version = '5.0'
+end