文章目录
1. pigeon
Pigeon 是一个代码生成器工具,用于使 Flutter 和宿主平台之间的通信类型安全、更轻松、更快捷
pub地址
2. 定义接口
创建pigeons/message.dart(lib同级目录创建)
import 'package:pigeon/pigeon.dart';
// 输出配置
// 控制台执行:dart run pigeon --input pigeons/message.dart
(PigeonOptions(
dartOut: 'lib/messages.g.dart',
dartOptions: DartOptions(),
kotlinOut:
'android/app/src/main/kotlin/com/app/studyplugin2/Messages.g.kt',
kotlinOptions: KotlinOptions(),
swiftOut: 'ios/Runner/Messages.g.swift',
swiftOptions: SwiftOptions(),
objcHeaderOut: 'macos/Runner/messages.g.h',
objcSourceOut: 'macos/Runner/messages.g.m',
// Set this to a unique prefix for your plugin or application, per Objective-C naming conventions.
objcOptions: ObjcOptions(prefix: 'PGN'),
// copyrightHeader: 'pigeons/copyright.txt',
// dartPackageName: 'pigeon_example_package',
))
// #enddocregion config
// This file and ./messages_test.dart must be identical below this line.
// #docregion host-definitions
enum Code { one, two }
class MessageData {
MessageData({required this.code, required this.data});
String? name;
String? description;
Code code;
Map<String?, String?> data;
}
()
abstract class ExampleHostApi {
String getHostLanguage();
// These annotations create more idiomatic naming of methods in Objc and Swift.
('addNumber:toNumber:')
('add(_:to:)')
int add(int a, int b);
bool sendMessage(MessageData message);
}
// #enddocregion host-definitions
// #docregion flutter-definitions
()
abstract class MessageFlutterApi {
String flutterMethod(String? aString);
}
// #enddocregion flutter-definitions
3.定义sh文件 pigeon.sh(lib同级目录创建)
java_package 目录可以随便填写, 目录如果创建失败 就手动创建目录
flutter pub run pigeon \
--input pigeons/message.dart
4. 运行sh文件 pigeon.sh 会生成一下文件
android/app/src/main/kotlin/com/app/studyplugin2/Messages.g.kt
ios/Runner/Messages.g.swift
lib/messages.g.dart
5. andorid使用
package com.app.studyplugin2
import ExampleHostApi
import FlutterError
import MessageData
import MessageFlutterApi
import androidx.annotation.NonNull
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.embedding.engine.plugins.FlutterPlugin
// #docregion kotlin-class
private class PigeonApiImplementation : ExampleHostApi {
override fun getHostLanguage(): String {
return "Kotlin"
}
override fun add(a: Long, b: Long): Long {
if (a < 0L || b < 0L) {
throw FlutterError("code", "message", "details")
}
return a + b
}
override fun sendMessage(message: MessageData, callback: (Result<Boolean>) -> Unit) {
if (message.code == Code.ONE) {
callback(Result.failure(FlutterError("code", "message", "details")))
return
}
callback(Result.success(true))
}
}
// #enddocregion kotlin-class
// #docregion kotlin-class-flutter
private class PigeonFlutterApi {
var flutterApi: MessageFlutterApi? = null
constructor(binding: FlutterPlugin.FlutterPluginBinding) {
flutterApi = MessageFlutterApi(binding.getBinaryMessenger())
}
fun callFlutterMethod(aString: String, callback: (Result<String>) -> Unit) {
flutterApi!!.flutterMethod(aString) { echo -> callback(echo) }
}
}
// #enddocregion kotlin-class-flutter
class MainActivity : FlutterActivity() {
override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
val api = PigeonApiImplementation()
ExampleHostApi.setUp(flutterEngine.dartExecutor.binaryMessenger, api)
}
}
6. Ios 使用
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import Flutter
import UIKit
// #docregion swift-class
// This extension of Error is required to do use FlutterError in any Swift code.
extension FlutterError: Error {}
enum MyErrors: Error {
case missingValue
}
private class PigeonApiImplementation: ExampleHostApi {
func getHostLanguage() throws -> String {
return "Swift"
}
func add(_ a: Int64, to b: Int64) throws -> Int64 {
if a < 0 || b < 0 {
throw FlutterError(code: "code", message: "message", details: "details")
}
return a + b
}
func sendMessage(message: MessageData, completion: @escaping (Result<Bool, Error>) -> Void) {
if message.code == Code.one {
completion(.failure(FlutterError(code: "code", message: "message", details: "details")))
return
}
completion(.success(true))
}
}
// #enddocregion swift-class
// #docregion swift-class-flutter
private class PigeonFlutterApi {
var flutterAPI: MessageFlutterApi
init(binaryMessenger: FlutterBinaryMessenger) {
flutterAPI = MessageFlutterApi(binaryMessenger: binaryMessenger)
}
func callFlutterMethod(
aString aStringArg: String?, completion: @escaping (Result<String, Error>) -> Void
) {
func optionalStringToResult(optionalString: String?) -> Result<String, Error> {
guard let nonOptionalString = optionalString else {
return .failure(MyErrors.missingValue)
}
return .success(nonOptionalString)
}
flutterAPI.flutterMethod(aString: aStringArg) { result in
switch result {
case .success(let value):
completion(.success(value))
case .failure(let error):
completion(.failure(error))
}
}
}
}
// #enddocregion swift-class-flutter
@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
GeneratedPluginRegistrant.register(with: self)
let controller = window?.rootViewController as! FlutterViewController
let api = PigeonApiImplementation()
ExampleHostApiSetup.setUp(binaryMessenger: controller.binaryMessenger, api: api)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
}
7. flutter 使用
class _ExampleFlutterApi implements MessageFlutterApi {
String flutterMethod(String? aString) {
return aString ?? '';
}
}
class _MyHomePageState extends State<MyHomePage> {
final ExampleHostApi _hostApi = ExampleHostApi();
String? _hostCallResult;
// #docregion main-dart
final ExampleHostApi _api = ExampleHostApi();
/// Calls host method `add` with provided arguments.
Future<int> add(int a, int b) async {
try {
return await _api.add(a, b);
} catch (e) {
// handle error.
return 0;
}
}
/// Sends message through host api using `MessageData` class
/// and api `sendMessage` method.
Future<bool> sendMessage(String messageText) {
final MessageData message = MessageData(
code: Code.two,
data: <String?, String?>{'header': 'this is a header'},
description: 'uri text',
);
try {
return _api.sendMessage(message);
} catch (e) {
// handle error.
return Future<bool>(() => true);
}
}
// #enddocregion main-dart
void initState() {
super.initState();
MessageFlutterApi.setUp(_ExampleFlutterApi());
_hostApi.getHostLanguage().then((String response) {
setState(() {
_hostCallResult = 'Hello from $response!';
});
}).onError<PlatformException>((PlatformException error, StackTrace _) {
setState(() {
_hostCallResult = 'Failed to get host language: ${error.message}';
});
});
}
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
title: Text(widget.title),
actions: [
TextButton(onPressed: (){
add(3, 2).then((value) => print("t=$value"));
}, child: Text("add")),
TextButton(onPressed: (){
sendMessage("sendMessage").then((value) => print("sendMessage=$value"));
}, child: Text("sendMessage")),
],
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
_hostCallResult ?? 'Waiting for host language...',
),
if (_hostCallResult == null) const CircularProgressIndicator(),
],
),
),
);
}
}