Flutter和Native 通信 pigeon

本文介绍了Pigeon,一个用于Flutter和主机平台间类型安全通信的代码生成器。通过定义接口,创建并运行sh文件,Pigeon能自动生成Android、iOS和Flutter端的绑定代码,简化跨平台交互。文中详细展示了在Android、iOS和Flutter中如何使用生成的代码进行实际操作。
部署运行你感兴趣的模型镜像

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(),
          ],
        ),
      ),
    );
  }
}

您可能感兴趣的与本文相关的镜像

Seed-Coder-8B-Base

Seed-Coder-8B-Base

文本生成
Seed-Coder

Seed-Coder是一个功能强大、透明、参数高效的 8B 级开源代码模型系列,包括基础变体、指导变体和推理变体,由字节团队开源

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值