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