Tool plugin: Pigeon
The official must-see example: Pigeon_plugin_example
4. Pigeons: ① pigeon/example ② pigeons
Pigeon is a code generator tool to make communication between Flutter and the host platform type-safe, easier and faster. A code generation tool that makes Flutter and its host platform safer, simpler, and faster to communicate.
The Dart entry generates template code that is common to both ends, while the native interface needs to be overridden within the template without managing the implementation of the Method Channel. Parameters can be generated synchronously from templates.
Pigeon currently supports only OC and Java code generation.
1. Create a commandPlugin
$ flutter create --template=plugin --platforms=android,ios -i swift -a kotlin flutter_pigeon_plugin
2,flutter
In the projectpubspec.yaml
thedev_dependencies
, addpigeon
Plug-in dependencies
Dev_dependencies: flutter_test: SDK: flutter_lints: ^1.0.0:Copy the code
3, inFlutter
The projectlib
Create one outside the directorypigeons
Folder, inpigeons
Create in folderall_types_pigeon.dart
import 'package:pigeon/pigeon.dart'; class Everything { bool? aBool; int? anInt; double? aDouble; String? aString; Uint8List? aByteArray; Int32List? a4ByteArray; Int64List? a8ByteArray; Float64List? aFloatArray; // ignore: always_specify_types List? aList; // ignore: always_specify_types Map? aMap; List<List<bool? >? >? nestedList; Map<String? , String? >? mapWithAnnotations; } /// the native method of Flutter calls @hostapi () abstract class HostEverything {Everything giveMeEverything(); Everything echo(Everything everything); } @flutterAPI () abstract class FlutterEverything {Everything giveMeEverythingFlutter(); Everything echoFlutter(Everything everything); }Copy the code
4. Run the command
First create a folder for the generated files: Under Android/SRC /mian create the Java /com/example/ Flutter_pigeon_plugin/folder where you will get the generated Java files.
Under the project directory ~/flutter_pigeon_plugin, execute the following command: $ flutter pub run pigeon –input pigeons/all_types_pigeon.dart –dart_out lib/all_types_pigeon.dart –objc_header_out ios/Classes/AllTypesPigeon.h –objc_source_out ios/Classes/AllTypesPigeon.m –java_out android/src/main/java/com/example/flutter_pigeon_plugin/AllTypesPigeon.java –java_package “com.example.flutter_pigeon_plugin”
Command disassembly: ①` flutter pub run pigeon`Command to generate code ②` --input pigeons/all_types_pigeon.dart `Specifies the input to generate code`dart`The file 3.`--dart_out lib/all_types_pigeon.dart `Specify output generation`dart`File directory file ④`--objc_header_out ios/Classes/AllTypesPigeon.h `Specifies what to build`iOS`the`.h`File path ⑤`--objc_source_out ios/Classes/AllTypesPigeon.m `Specifies what to build`iOS`the`.m`File path ⑥`--java_out android/src/main/java/com/example/flutter_pigeon_plugin/AllTypesPigeon.java `Specifies what to build`Android`the`.java`File path ⑦`--java_package "com.example.flutter_pigeon_plugin`The specified`Android`Package name, in`android/src/main/`Under the`AndroidManifest.xml`In the`package`
⑧ `--objc_prefix FLT`(Optional) Specify the prefix of the GENERATED OC file as FLT. The prefix is self-defined.Copy the code
/run_pigeon. Sh: run_pigeon. Sh: run_pigeon.
flutter pub run pigeon \
--input pigeons/all_types_pigeon.dart \
--dart_out lib/all_types_pigeon.dart \
--objc_header_out ios/Classes/AllTypesPigeon.h \
--objc_source_out ios/Classes/AllTypesPigeon.m \
--objc_prefix FLT \
--java_out android/src/main/java/com/example/flutter_pigeon_plugin/AllTypesPigeon.java \
--java_package "com.example.flutter_pigeon_plugin"
Copy the code
When the command is executed, response files are automatically generated in the specified locations.
5,iOS
implementationFlutter
Call the native method
A method called HostEverythingSetup is automatically generated in AllTypesPigeon
void HostEverythingSetup(id<FlutterBinaryMessenger> binaryMessenger, NSObject<HostEverything> *api) { { FlutterBasicMessageChannel *channel = [FlutterBasicMessageChannel messageChannelWithName:@"dev.flutter.pigeon.HostEverything.giveMeEverything" binaryMessenger:binaryMessenger codec:HostEverythingGetCodec()]; if (api) { NSCAssert([api respondsToSelector:@selector(giveMeEverythingWithError:)], @"HostEverything api doesn't respond to @selector(giveMeEverythingWithError:)"); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { FlutterError *error; Everything *output = [api giveMeEverythingWithError:&error]; callback(wrapResult(output, error)); }]; } else { [channel setMessageHandler:nil]; } } { FlutterBasicMessageChannel *channel = [FlutterBasicMessageChannel messageChannelWithName:@"dev.flutter.pigeon.HostEverything.echo" binaryMessenger:binaryMessenger codec:HostEverythingGetCodec()]; if (api) { NSCAssert([api respondsToSelector:@selector(echoEverything:error:)], @"HostEverything api doesn't respond to @selector(echoEverything:error:)"); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { NSArray *args = message; Everything *arg_everything = args[0]; FlutterError *error; Everything *output = [api echoEverything:arg_everything error:&error]; callback(wrapResult(output, error)); }]; } else { [channel setMessageHandler:nil]; }}}Copy the code
(3) in SwiftFlutterPigeonPlugin. Swift registration method, call the setup method to initialize and Settings
public static func register(with registrar: FlutterPluginRegistrar) {
let messenger: FlutterBinaryMessenger = registrar.messenger()
let api: HostEverything & NSObjectProtocol = SwiftFlutterPigeonPlugin.init()
HostEverythingSetup(messenger, api)
}
Copy the code
4. Swiftflutterutterthing Plugin complies with the HostEverything protocol, which implements the native method of Flutter
import Flutter
import UIKit
Follow the HostEverything protocol to implement the native method of Flutter
public class SwiftFlutterPigeonPlugin: NSObject.FlutterPlugin.HostEverything {
public static func register(with registrar: FlutterPluginRegistrar) {
let messenger: FlutterBinaryMessenger = registrar.messenger()
let api: HostEverything & NSObjectProtocol = SwiftFlutterPigeonPlugin.init(a)HostEverythingSetup(messenger, api)
}
// MARK: HostEverything
public func giveMeEverythingWithError(_ error: AutoreleasingUnsafeMutablePointer<FlutterError? >) -> Everything? {
let everyThing = Everything()
everyThing.aString = "Native string returned to Flutter"
everyThing.aBool = false
everyThing.anInt = 11
return everyThing
}
Follow the HostEverything protocol to implement the native method of Flutter
public func echo(_ everything: Everything.error: AutoreleasingUnsafeMutablePointer<FlutterError? >) -> Everything? {
everything.aString = "Native exchanged strings for Flutter"
everything.aBool = false
everything.anInt = 12
return everything
}
}
Copy the code
⑤ To iOS/Classes, create the flutter_pigeon_plugin.h file and import the header file. This file is automatically referenced in the iOS auto-generated
file.
//
// flutter_pigeon_plugin.h
// Pods
//
// Created by yuanzhiying on 2021/9/13.
//
#ifndef flutter_pigeon_plugin_h
#define flutter_pigeon_plugin_h
#import "AllTypesPigeon.h"
#endif /* flutter_pigeon_plugin_h */
Copy the code
6,flutter_pigeon_plugin.dart
In the implementation of plug-in tuning native method
import 'dart:async';
import 'package:flutter_pigeon_plugin/all_types_pigeon.dart';
class FlutterPigeonPlugin {
static final HostEverything _hostEverything = HostEverything();
/// Flutter calls native methods
static Future<Everything> getEverything() async {
return await _hostEverything.giveMeEverything();
}
/// Flutter calls native methods
static Future<Everything> echoEveryThing(Everything everything) async {
return await_hostEverything.echo(everything); }}Copy the code
7. Using plug-ins
Future<void> getHostData() async {
/// Invoke native methods through plug-ins
Everything everything = await FlutterPigeonPlugin.getEverything();
debugPrint('everything.aString: ${everything.aString}');
debugPrint('everything.aBool: ${everything.aBool}');
debugPrint('everything. AnInt:${everything.anInt}');
}
void echoHostData() async {
Everything echoEveryThing = Everything();
echoEveryThing.aString = 'String I want to swap with native';
echoEveryThing.aBool = true;
echoEveryThing.anInt = 10;
/// Invoke native methods through plug-ins
Everything everything = await FlutterPigeonPlugin.echoEveryThing(echoEveryThing);
debugPrint('everything.aString: ${everything.aString}');
debugPrint('everything.aBool: ${everything.aBool}');
debugPrint('everything. AnInt:${everything.anInt}');
}
Copy the code
At this point, Flutter calls the native iOS method to complete.
Eight,flutter
Call the android native implementation
(1) delete the old version number for the channel code. (2) FlutterPigeonPlugin kt inherit AllTypesPigeon. HostEverything, and implement the corresponding method
override fun giveMeEverything(a): AllTypesPigeon.Everything {
var everything: AllTypesPigeon.Everything = AllTypesPigeon.Everything()
everything.aString = "Native string returned to Flutter"
everything.aBool = false
everything.anInt = 11
return everything
}
override fun echo(everything: AllTypesPigeon.Everything?).: AllTypesPigeon.Everything? { everything? .aString ="Native exchanged strings for Flutter"everything? .aBool =falseeverything? .anInt =12
return everything
}
Copy the code
3 Use the automatically generated setup method to initialize and set the parameters
override fun onAttachedToEngine(@NonNull flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
AllTypesPigeon.HostEverything.setup(flutterPluginBinding.binaryMessenger, this)}override fun onDetachedFromEngine(@NonNull binding: FlutterPlugin.FlutterPluginBinding) {
AllTypesPigeon.HostEverything.setup(binding.binaryMessenger, null)}Copy the code
The final result is as follows:
package com.example.flutter_pigeon_plugin
import androidx.annotation.NonNull
import io.flutter.embedding.engine.plugins.FlutterPlugin
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugin.common.MethodChannel.MethodCallHandler
import io.flutter.plugin.common.MethodChannel.Result
/** FlutterPigeonPlugin */
class FlutterPigeonPlugin: FlutterPlugin.MethodCallHandler.AllTypesPigeon.HostEverything {
override fun onAttachedToEngine(@NonNull flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
AllTypesPigeon.HostEverything.setup(flutterPluginBinding.binaryMessenger, this)}override fun onMethodCall(@NonNull call: MethodCall.@NonNull result: Result) {
result.notImplemented()
}
override fun onDetachedFromEngine(@NonNull binding: FlutterPlugin.FlutterPluginBinding) {
AllTypesPigeon.HostEverything.setup(binding.binaryMessenger, null)}override fun giveMeEverything(a): AllTypesPigeon.Everything {
var everything: AllTypesPigeon.Everything = AllTypesPigeon.Everything()
everything.aString = "Native string returned to Flutter"
everything.aBool = false
everything.anInt = 11
return everything
}
override fun echo(everything: AllTypesPigeon.Everything?).: AllTypesPigeon.Everything? { everything? .aString ="Native exchanged strings for Flutter"everything? .aBool =falseeverything? .anInt =12
return everything
}
}
Copy the code
The project code is: Flutter_pigeon_plugin