blob: f0574df814a0ea1a8a3f3f53483c9f1b056054f7 [file] [log] [blame] [view]
<?code-excerpt path-base="app"?>
# Pigeon Examples
The examples here will cover basic usage. For a more thorough set of examples,
check the [core_tests pigeon file](../pigeons/core_tests.dart) and
[platform test folder](../platform_tests/) ([shared_test_plugin_code](../platform_tests/shared_test_plugin_code/) and [alternate_language_test_plugin](../platform_tests/alternate_language_test_plugin/) especially).
## Invocation
Begin by configuring pigeon at the top of the `.dart` input file.
In actual use, you would include only the languages
needed for your project.
<?code-excerpt "pigeons/messages.dart (config)"?>
```dart
@ConfigurePigeon(PigeonOptions(
dartOut: 'lib/src/messages.g.dart',
dartOptions: DartOptions(),
cppOptions: CppOptions(namespace: 'pigeon_example'),
cppHeaderOut: 'windows/runner/messages.g.h',
cppSourceOut: 'windows/runner/messages.g.cpp',
kotlinOut:
'android/app/src/main/kotlin/dev/flutter/pigeon_example_app/Messages.g.kt',
kotlinOptions: KotlinOptions(),
javaOut: 'android/app/src/main/java/io/flutter/plugins/Messages.java',
javaOptions: JavaOptions(),
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',
))
```
Then make a simple call to run pigeon on the Dart file containing your definitions.
```sh
flutter pub run pigeon --input path/to/input.dart
```
## HostApi Example
This example gives an overview of how to use Pigeon to call into the
host platform from Flutter.
### Dart input
This is the Pigeon file that describes the interface that will be used to call
from Flutter to the host-platform.
<?code-excerpt "pigeons/messages.dart (host-definitions)"?>
```dart
enum Code { one, two }
class MessageData {
MessageData({required this.code, required this.data});
String? name;
String? description;
Code code;
Map<String?, String?> data;
}
@HostApi()
abstract class ExampleHostApi {
String getHostLanguage();
// These annotations create more idiomatic naming of methods in Objc and Swift.
@ObjCSelector('addNumber:toNumber:')
@SwiftFunction('add(_:to:)')
int add(int a, int b);
@async
bool sendMessage(MessageData message);
}
```
### Dart
This is the code that will use the generated Dart code to make calls from Flutter to
the host platform.
<?code-excerpt "lib/main.dart (main-dart)"?>
```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.one,
data: <String?, String?>{'header': 'this is a header'},
description: 'uri text',
);
try {
return _api.sendMessage(message);
} catch (e) {
// handle error.
return Future<bool>(() => true);
}
}
```
### Swift
This is the code that will use the generated Swift code to receive calls from Flutter.
packages/pigeon/example/app/ios/Runner/AppDelegate.swift
<?code-excerpt "ios/Runner/AppDelegate.swift (swift-class)"?>
```swift
// This extension of Error is required to do use FlutterError in any Swift code.
extension FlutterError: Error {}
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))
}
}
```
### Kotlin
<?code-excerpt "android/app/src/main/kotlin/dev/flutter/pigeon_example_app/MainActivity.kt (kotlin-class)"?>
```kotlin
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))
}
}
```
### C++
<?code-excerpt "windows/runner/flutter_window.cpp (cpp-class)"?>
```c++
class PigeonApiImplementation : public ExampleHostApi {
public:
PigeonApiImplementation() {}
virtual ~PigeonApiImplementation() {}
ErrorOr<std::string> GetHostLanguage() override { return "C++"; }
ErrorOr<int64_t> Add(int64_t a, int64_t b) {
if (a < 0 || b < 0) {
return FlutterError("code", "message", "details");
}
return a + b;
}
void SendMessage(const MessageData& message,
std::function<void(ErrorOr<bool> reply)> result) {
if (message.code == Code.one) {
result(FlutterError("code", "message", "details"));
return;
}
result(true);
}
};
```
## FlutterApi Example
This example gives an overview of how to use Pigeon to call into the Flutter
app from the host platform.
### Dart input
<?code-excerpt "pigeons/messages.dart (flutter-definitions)"?>
```dart
@FlutterApi()
abstract class MessageFlutterApi {
String flutterMethod(String? aString);
}
```
### Dart
This is the code that will use the generated Dart code to handle calls made to
Flutter from the host platform.
<?code-excerpt "lib/main.dart (main-dart-flutter)"?>
```dart
class _ExampleFlutterApi implements MessageFlutterApi {
@override
String flutterMethod(String? aString) {
return aString ?? '';
}
}
// ยทยทยท
MessageFlutterApi.setup(_ExampleFlutterApi());
```
### Swift
<?code-excerpt "ios/Runner/AppDelegate.swift (swift-class-flutter)"?>
```swift
private class PigeonFlutterApi {
var flutterAPI: MessageFlutterApi
init(binaryMessenger: FlutterBinaryMessenger) {
flutterAPI = MessageFlutterApi(binaryMessenger: binaryMessenger)
}
func callFlutterMethod(aString aStringArg: String?, completion: @escaping (Result<String, Error>) -> Void) {
flutterAPI.flutterMethod(aString: aStringArg) {
completion(.success($0))
}
}
}
```
### Kotlin
<?code-excerpt "android/app/src/main/kotlin/dev/flutter/pigeon_example_app/MainActivity.kt (kotlin-class-flutter)"?>
```kotlin
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(Result.success(echo))
}
}
}
```
### C++
<?code-excerpt "windows/runner/flutter_window.cpp (cpp-method-flutter)"?>
```c++
void TestPlugin::CallFlutterMethod(
String aString, std::function<void(ErrorOr<int64_t> reply)> result) {
MessageFlutterApi->FlutterMethod(
aString, [result](String echo) { result(echo); },
[result](const FlutterError& error) { result(error); });
}
```
## Swift / Kotlin Plugin Example
A downloadable example of using Pigeon to create a Flutter Plugin with Swift and
Kotlin can be found at
[gaaclarke/flutter_plugin_example](https://github.com/gaaclarke/pigeon_plugin_example).
## Swift / Kotlin Add-to-app Example
A full example of using Pigeon for add-to-app with Swift on iOS can be found at
[samples/add_to_app/books](https://github.com/flutter/samples/tree/master/add_to_app/books).
## Video player plugin
A full real-world example can also be found in the
[video_player plugin](https://github.com/flutter/packages/tree/main/packages/video_player).