|
1 | 1 | # Pigeon
|
2 | 2 |
|
3 | 3 | Pigeon is a code generator tool to make communication between Flutter and the
|
4 |
| -host platform type-safe, easier and faster. |
| 4 | +host platform type-safe, easier, and faster. |
5 | 5 |
|
6 |
| -## Supported Platforms |
| 6 | +Pigeon removes the necessity to manage strings across multiple platforms and languages. |
| 7 | +It also improves efficiency over common method channel patterns. Most importantly though, |
| 8 | +it removes the need to write custom platform channel code, since pigeon generates it for you. |
7 | 9 |
|
8 |
| -Currently Pigeon supports generating: |
| 10 | +For usage examples, see the [Example README](./example/README.md). |
| 11 | + |
| 12 | +## Features |
| 13 | + |
| 14 | +### Supported Platforms |
| 15 | + |
| 16 | +Currently pigeon supports generating: |
9 | 17 | * Kotlin and Java code for Android
|
10 | 18 | * Swift and Objective-C code for iOS and macOS
|
11 | 19 | * C++ code for Windows
|
12 | 20 |
|
13 |
| -## Runtime Requirements |
| 21 | +### Supported Datatypes |
| 22 | + |
| 23 | +Pigeon uses the `StandardMessageCodec` so it supports |
| 24 | +[[any datatype platform channels support](https://flutter.dev/docs/development/platform-integration/platform-channels#codec)]. |
| 25 | + |
| 26 | +Custom classes and nested datatypes are also supported. |
| 27 | + |
| 28 | +#### Enums |
| 29 | + |
| 30 | +Pigeon currently supports enum generation in class fields only. |
| 31 | +See issue: [87307](https://github.com/flutter/flutter/issues/87307). |
| 32 | + |
| 33 | +### Synchronous and Asynchronous methods |
| 34 | + |
| 35 | +While all calls across platform channel APIs (such as pigeon methods) are asynchronous, |
| 36 | +pigeon methods can be written on the native side as synchronous methods, |
| 37 | +to make it simpler to always reply exactly once. |
14 | 38 |
|
15 |
| -Pigeon generates all the code that is needed to communicate between Flutter and |
16 |
| -the host platform, there is no extra runtime requirement. A plugin author |
17 |
| -doesn't need to worry about conflicting versions of Pigeon. |
| 39 | +If asynchronous methods are needed, the `@async` annotation can be used. This will require |
| 40 | +results or errors to be returned via a provided callback. [Example](./example/README.md#HostApi_Example). |
| 41 | + |
| 42 | +### Error Handling |
| 43 | + |
| 44 | +#### Kotlin, Java and Swift |
| 45 | + |
| 46 | +All Host API exceptions are translated into Flutter `PlatformException`. |
| 47 | +* For synchronous methods, thrown exceptions will be caught and translated. |
| 48 | +* For asynchronous methods, there is no default exception handling; errors |
| 49 | +should be returned via the provided callback. |
| 50 | + |
| 51 | +To pass custom details into `PlatformException` for error handling, |
| 52 | +use `FlutterError` in your Host API. [Example](./example/README.md#HostApi_Example). |
| 53 | + |
| 54 | +To use `FlutterError` in Swift you must first extend a standard error. |
| 55 | +[Example](./example/README.md#AppDelegate.swift). |
| 56 | + |
| 57 | +#### Objective-C and C++ |
| 58 | + |
| 59 | +Host API errors can be sent using the provided `FlutterError` class (translated into `PlatformException`). |
| 60 | + |
| 61 | +For synchronous methods: |
| 62 | +* Objective-C - Set the `error` argument to a `FlutterError` reference. |
| 63 | +* C++ - Return a `FlutterError`. |
| 64 | + |
| 65 | +For async methods: |
| 66 | +* Return a `FlutterError` through the provided callback. |
| 67 | + |
| 68 | + |
| 69 | +### Task Queue |
| 70 | + |
| 71 | +When targeting a Flutter version that supports the |
| 72 | +[TaskQueue API](https://docs.flutter.dev/development/platform-integration/platform-channels?tab=type-mappings-kotlin-tab#channels-and-platform-threading) |
| 73 | +the threading model for handling HostApi methods can be selected with the |
| 74 | +`TaskQueue` annotation. |
18 | 75 |
|
19 | 76 | ## Usage
|
20 | 77 |
|
21 |
| -1) Add Pigeon as a `dev_dependency`. |
| 78 | +1) Add pigeon as a `dev_dependency`. |
22 | 79 | 1) Make a ".dart" file outside of your "lib" directory for defining the
|
23 | 80 | communication interface.
|
24 | 81 | 1) Run pigeon on your ".dart" file to generate the required Dart and
|
25 | 82 | host-language code: `flutter pub get` then `flutter pub run pigeon`
|
26 |
| - with suitable arguments (see [example](./example)). |
| 83 | + with suitable arguments. [Example](./example/README.md#Invocation). |
27 | 84 | 1) Add the generated Dart code to `./lib` for compilation.
|
28 | 85 | 1) Implement the host-language code and add it to your build (see below).
|
29 | 86 | 1) Call the generated Dart methods.
|
30 | 87 |
|
| 88 | +### Rules for defining your communication interface |
| 89 | +[Example](./example/README.md#HostApi_Example) |
| 90 | + |
| 91 | +1) The file should contain no method or function definitions, only declarations. |
| 92 | +1) Custom classes used by APIs are defined as classes with fields of the |
| 93 | + supported datatypes (see the supported Datatypes section). |
| 94 | +1) APIs should be defined as an `abstract class` with either `@HostApi()` or |
| 95 | + `@FlutterApi()` as metadata. `@HostApi()` being for procedures that are defined |
| 96 | + on the host platform and the `@FlutterApi()` for procedures that are defined in Dart. |
| 97 | +1) Method declarations on the API classes should have arguments and a return |
| 98 | + value whose types are defined in the file, are supported datatypes, or are |
| 99 | + `void`. |
| 100 | +1) Generics are supported, but can currently only be used with nullable types |
| 101 | + (example: `List<int?>`). |
| 102 | +1) Objc and Swift have special naming conventions that can be utilized with the |
| 103 | + `@ObjCSelector` and `@SwiftFunction` respectively. |
| 104 | + |
31 | 105 | ### Flutter calling into iOS steps
|
32 | 106 |
|
33 | 107 | 1) Add the generated Objective-C or Swift code to your Xcode project for compilation
|
@@ -58,214 +132,12 @@ doesn't need to worry about conflicting versions of Pigeon.
|
58 | 132 |
|
59 | 133 | ### Calling into Flutter from the host platform
|
60 | 134 |
|
61 |
| -Flutter also supports calling in the opposite direction. The steps are similar |
| 135 | +Pigeon also supports calling in the opposite direction. The steps are similar |
62 | 136 | but reversed. For more information look at the annotation `@FlutterApi()` which
|
63 |
| -denotes APIs that live in Flutter but are invoked from the host platform. |
64 |
| - |
65 |
| -### Rules for defining your communication interface |
66 |
| - |
67 |
| -1) The file should contain no method or function definitions, only declarations. |
68 |
| -1) Custom classes used by APIs are defined as classes with fields of the |
69 |
| - supported datatypes (see the supported Datatypes section). |
70 |
| -1) APIs should be defined as an `abstract class` with either `HostApi()` or |
71 |
| - `FlutterApi()` as metadata. The former being for procedures that are defined |
72 |
| - on the host platform and the latter for procedures that are defined in Dart. |
73 |
| -1) Method declarations on the API classes should have arguments and a return |
74 |
| - value whose types are defined in the file, are supported datatypes, or are |
75 |
| - `void`. |
76 |
| -1) Generics are supported, but can currently only be used with nullable types |
77 |
| - (example: `List<int?>`). |
78 |
| - |
79 |
| -## Supported Datatypes |
80 |
| - |
81 |
| -Pigeon uses the `StandardMessageCodec` so it supports any datatype Platform |
82 |
| -Channels supports |
83 |
| -[[documentation](https://flutter.dev/docs/development/platform-integration/platform-channels#codec)]. |
84 |
| -Nested datatypes are supported, too. |
85 |
| - |
86 |
| -## Features |
87 |
| - |
88 |
| -### Asynchronous Handlers |
89 |
| - |
90 |
| -By default Pigeon will generate synchronous handlers for messages and |
91 |
| -asynchronous methods. If you want a handler to be able to respond to a message |
92 |
| -asynchronously you can use the @async annotation as of version 0.1.20. |
93 |
| - |
94 |
| -Example: |
95 |
| - |
96 |
| -```dart |
97 |
| -class Value { |
98 |
| - int? number; |
99 |
| -} |
100 |
| -
|
101 |
| -@HostApi() |
102 |
| -abstract class Api2Host { |
103 |
| - @async |
104 |
| - Value calculate(Value value); |
105 |
| -} |
106 |
| -``` |
107 |
| - |
108 |
| -Generates: |
109 |
| - |
110 |
| -```objc |
111 |
| -// Objective-C |
112 |
| -@protocol Api2Host |
113 |
| --(void)calculate:(nullable Value *)input |
114 |
| - completion:(void(^)(Value *_Nullable, FlutterError *_Nullable))completion; |
115 |
| -@end |
116 |
| -``` |
117 |
| -
|
118 |
| -```swift |
119 |
| -// Swift |
120 |
| -
|
121 |
| -/** Generated interface from Pigeon that represents a handler of messages from Flutter.*/ |
122 |
| -protocol Api2Host { |
123 |
| - func calculate(value: Value, completion: @escaping (Value) -> Void) |
124 |
| -} |
125 |
| -``` |
126 |
| - |
127 |
| -```java |
128 |
| -// Java |
129 |
| -public interface Result<T> { |
130 |
| - void success(T result); |
131 |
| -} |
132 |
| - |
133 |
| -/** Generated interface from Pigeon that represents a handler of messages from Flutter.*/ |
134 |
| -public interface Api2Host { |
135 |
| - void calculate(Value arg, Result<Value> result); |
136 |
| -} |
137 |
| -``` |
138 |
| - |
139 |
| -```kotlin |
140 |
| -// Kotlin |
141 |
| - |
142 |
| -/** Generated interface from Pigeon that represents a handler of messages from Flutter.*/ |
143 |
| -interface Api2Host { |
144 |
| - fun calculate(value: Value, callback: (Result<Value>) -> Unit) |
145 |
| -} |
146 |
| -``` |
147 |
| - |
148 |
| -```c++ |
149 |
| -// C++ |
150 |
| - |
151 |
| -/** Generated class from Pigeon that represents a handler of messages from Flutter.*/ |
152 |
| -class Api2Host { |
153 |
| -public: |
154 |
| - virtual void calculate(Value value, flutter::MessageReply<Value> result) = 0; |
155 |
| -} |
156 |
| -``` |
157 |
| -
|
158 |
| -### Null Safety (NNBD) |
159 |
| -
|
160 |
| -Pigeon supports generating null-safe code, but it doesn't yet support: |
161 |
| -
|
162 |
| -1) Nullable generics type arguments |
163 |
| -1) Nullable enum arguments to methods |
164 |
| -
|
165 |
| -### Enums |
166 |
| -
|
167 |
| -Pigeon supports enum generation in class fields. For example: |
168 |
| -```dart |
169 |
| -enum State { |
170 |
| - pending, |
171 |
| - success, |
172 |
| - error, |
173 |
| -} |
174 |
| -
|
175 |
| -class StateResult { |
176 |
| - String? errorMessage; |
177 |
| - State? state; |
178 |
| -} |
179 |
| -
|
180 |
| -@HostApi() |
181 |
| -abstract class Api { |
182 |
| - StateResult queryState(); |
183 |
| -} |
184 |
| -``` |
185 |
| - |
186 |
| -### Primitive Data-types |
187 |
| - |
188 |
| -Prior to version 1.0 all arguments to API methods had to be wrapped in a class, now they can be used directly. For example: |
189 |
| - |
190 |
| -```dart |
191 |
| -@HostApi() |
192 |
| -abstract class Api { |
193 |
| - Map<String?, int?> makeMap(List<String?> keys, List<String?> values); |
194 |
| -} |
195 |
| -``` |
196 |
| - |
197 |
| -### TaskQueues |
198 |
| - |
199 |
| -When targeting a Flutter version that supports the |
200 |
| -[TaskQueue API](https://docs.flutter.dev/development/platform-integration/platform-channels?tab=type-mappings-kotlin-tab#channels-and-platform-threading) |
201 |
| -the threading model for handling HostApi methods can be selected with the |
202 |
| -`TaskQueue` annotation: |
203 |
| - |
204 |
| -```dart |
205 |
| -@HostApi() |
206 |
| -abstract class Api2Host { |
207 |
| - @TaskQueue(type: TaskQueueType.serialBackgroundThread) |
208 |
| - int add(int x, int y); |
209 |
| -} |
210 |
| -``` |
211 |
| -
|
212 |
| -### Error Handling |
213 |
| -
|
214 |
| -#### Kotlin, Java and Swift |
215 |
| -
|
216 |
| -All Host API exceptions are translated into Flutter `PlatformException`. |
217 |
| -* For synchronous methods, thrown exceptions will be caught and translated. |
218 |
| -* For asynchronous methods, there is no default exception handling; errors should be returned via the provided callback. |
219 |
| -
|
220 |
| -To pass custom details into `PlatformException` for error handling, use `FlutterError` in your Host API. |
221 |
| -For example: |
222 |
| -
|
223 |
| -```kotlin |
224 |
| -// Kotlin |
225 |
| -class MyApi : GeneratedApi { |
226 |
| - // For synchronous methods |
227 |
| - override fun doSomething() { |
228 |
| - throw FlutterError('error_code', 'message', 'details') |
229 |
| - } |
230 |
| -
|
231 |
| - // For async methods |
232 |
| - override fun doSomethingAsync(callback: (Result<Unit>) -> Unit) { |
233 |
| - callback(Result.failure(FlutterError('error_code', 'message', 'details')) |
234 |
| - } |
235 |
| -} |
236 |
| -``` |
237 |
| - |
238 |
| -#### Objective-C and C++ |
239 |
| - |
240 |
| -Likewise, Host API errors can be sent using the provided `FlutterError` class (translated into `PlatformException`). |
241 |
| - |
242 |
| -For synchronous methods: |
243 |
| -* Objective-C - Assign the `error` argument to a `FlutterError` reference. |
244 |
| -* C++ - Return a `FlutterError` directly (for void methods) or within an `ErrorOr` instance. |
245 |
| - |
246 |
| -For async methods: |
247 |
| -* Both - Return a `FlutterError` through the provided callback. |
248 |
| - |
249 |
| -#### Handling the errors |
250 |
| - |
251 |
| -Then you can implement error handling on the Flutter side: |
252 |
| - |
253 |
| -```dart |
254 |
| -// Dart |
255 |
| -void doSomething() { |
256 |
| - try { |
257 |
| - myApi.doSomething() |
258 |
| - } catch (PlatformException e) { |
259 |
| - if (e.code == 'error_code') { |
260 |
| - // Perform custom error handling |
261 |
| - assert(e.message == 'message') |
262 |
| - assert(e.details == 'details') |
263 |
| - } |
264 |
| - } |
265 |
| -} |
266 |
| -``` |
| 137 | +denotes APIs that live in Flutter but are invoked from the host platform. |
| 138 | +[Example](./example/README.md#FlutterApi_Example). |
267 | 139 |
|
268 | 140 | ## Feedback
|
269 | 141 |
|
270 |
| -File an issue in [flutter/flutter](https://github.com/flutter/flutter) with the |
271 |
| -word "pigeon" in the title. |
| 142 | +File an issue in [flutter/flutter](https://github.com/flutter/flutter) with |
| 143 | +"[pigeon]" at the start of the title. |
0 commit comments