mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00

This is waiting on - https://github.com/flutter/flutter/pull/148777 - https://github.com/flutter/flutter/pull/148790 After this PR lands, there will likely be 1-2 more clean up PRs, after which the migration will be done! --- This moves the remaining wiki pages as planned in [flutter.dev/go/migrate-flutter-wiki-spreadsheet](https://docs.google.com/spreadsheets/d/1x65189ZBdNiLRygpUYoU08pwvXD4M-Z157c6pm8deGI/edit?usp=sharing) It also adds the team labels to the label bot for future PRs. Changes to the content were only updating cross links, or links to refer to the main branch rather than master. Remaining links to the wiki will be updated once all other pages have finished moving, they still work in the meantime. Part of https://github.com/flutter/flutter/issues/145009
158 lines
5.4 KiB
Markdown
158 lines
5.4 KiB
Markdown
(This wiki page applies to people migrating code written before March 2017. It is unlikely to still be relevant.)
|
|
|
|
# Introduction
|
|
Prior to pull requests [flutter/flutter#8837](https://github.com/flutter/flutter/pull/8837) and [flutter/engine#3482](https://github.com/flutter/engine/pull/3482), both merged on March 17 2017, communication between Flutter app components written in Dart and host platform app components written for Android or iOS was accomplished by sending and receiving string/JSON messages using methods defined in the following types:
|
|
|
|
* `PlatformMessages` (Dart)
|
|
* `FlutterView` (Android)
|
|
* `FlutterViewController` (iOS)
|
|
|
|
These methods have been removed, leaving only methods for sending unencoded binary messages. A new channel concept has been introduced in their place:
|
|
|
|
* [`PlatformMessageChannel`](https://docs.flutter.io/flutter/services/PlatformMessageChannel-class.html), [`PlatformMethodChannel`](https://docs.flutter.io/flutter/services/PlatformMethodChannel-class.html) (Dart)
|
|
* `FlutterMessageChannel`, `FlutterMethodChannel` (Android, iOS)
|
|
|
|
The main goals of the new API are to achieve
|
|
|
|
* higher-level communication: asynchronous method calls and event streams
|
|
* less boilerplate and redundancy
|
|
* a more symmetric API across Dart, Android, and iOS
|
|
|
|
The following sections detail how to port code written against the old API.
|
|
|
|
# Flutter side
|
|
|
|
With the new API you define in one place the name and type of the channel you need:
|
|
|
|
var fooChannel = new PlatformMessageChannel<String>('foo', const StringCodec());
|
|
var barChannel = new PlatformMethodChannel('bar', const JSONMethodCodec());
|
|
|
|
There are four codecs to choose from: binary, string, JSON, and standard. The standard codec employs efficient binary serialization of JSON-like values, supporting also buffers as leaf values (e.g. Dart `TypedData`, Java primitive arrays, Cocoa `NSData`).
|
|
|
|
Once you have a channel, you can use it in multiple places without repeating the information needed for its creation.
|
|
|
|
## Sending messages to platform
|
|
|
|
Replace code like this
|
|
|
|
String reply = await PlatformMessages.sendString('foo', myString);
|
|
|
|
with code like this
|
|
|
|
String reply = await fooChannel.send(myString);
|
|
|
|
## Receiving messages from platform
|
|
|
|
Replace code like this
|
|
|
|
PlatformMessages.setStringMessageHandler('foo', (String message) async {
|
|
// do something, then
|
|
return reply;
|
|
});
|
|
|
|
with code like this
|
|
|
|
fooChannel.setMessageHandler((String message) async {
|
|
// do something, then
|
|
return reply;
|
|
});
|
|
|
|
## Invoking platform methods
|
|
|
|
Replace code like this
|
|
|
|
var arguments = { 'argA': 'hello', 'argB': 42 };
|
|
var message = {
|
|
'method': 'someMethod',
|
|
'args': <Map<String, dynamic>>[arguments],
|
|
};
|
|
dynamic reply = await PlatformMessages.sendJSON('bar', message);
|
|
// what about errors?
|
|
|
|
or this
|
|
|
|
var arguments = { 'argA': 'hello', 'argB': 42 };
|
|
dynamic reply = await PlatformMessages.invokeMethod(
|
|
'bar',
|
|
'someMethod',
|
|
<Map<String, dynamic>>[arguments],
|
|
);
|
|
// what about errors?
|
|
|
|
with code like this
|
|
|
|
try {
|
|
dynamic result = await barChannel.invokeMethod(
|
|
'someMethod',
|
|
{ 'argA': 'hello', 'argB': 42 },
|
|
);
|
|
// use result
|
|
} on PlatformException catch(e) {
|
|
// handle error
|
|
}
|
|
|
|
## Receiving method calls from platform code
|
|
|
|
Replace code like this
|
|
|
|
PlatformMessages.setJSONMessageHandler('bar', (dynamic methodCall) async {
|
|
String method = methodCall['method'];
|
|
List arguments = methodCall['args'];
|
|
// handle call then
|
|
return result;
|
|
// but what about errors?
|
|
});
|
|
|
|
with code like this
|
|
|
|
barChannel.setMethodCallHandler((MethodCall call) async {
|
|
String method = call.method;
|
|
dynamic arguments = call.arguments;
|
|
// handle call then
|
|
return result;
|
|
// or
|
|
throw new PlatformException(errorCode, anErrorMessage, someDetails);
|
|
});
|
|
|
|
See [platform_channel](../../examples/platform_channel/lib/main.dart) for an example.
|
|
|
|
## Android side
|
|
|
|
Similar to Flutter side, using `FlutterMessageChannel` and `FlutterMethodChannel` from `io.flutter.plugin.common`.
|
|
|
|
FlutterView view = ...
|
|
FlutterMessageChannel<String> fooChannel =
|
|
new FlutterMessageChannel<>(view, "foo", StringCodec.INSTANCE);
|
|
|
|
fooChannel.send(myString);
|
|
|
|
// or if you need to handle a reply:
|
|
|
|
fooChannel.send(myString, new ReplyHandler<String>() {
|
|
public void onReply(String reply) {
|
|
// do something with reply
|
|
}
|
|
});
|
|
|
|
[API documentation](https://docs.flutter.io/javadoc/). See [platform_channel](../../examples/platform_channel/android/app/src/main/java/com/example/platformchannel/MainActivity.java) for another example.
|
|
|
|
## iOS side
|
|
|
|
Similar to Flutter side, using `FlutterMessageChannel` and `FlutterMethodChannel` from `FlutterChannels.h`.
|
|
|
|
FlutterViewController controller = ...
|
|
FlutterMessageChannel* fooChannel =
|
|
[FlutterMessageChannel messageChannelWithName:@"foo"
|
|
binaryMessenger:controller
|
|
codec:[FlutterStringCodec sharedInstance]];
|
|
|
|
[fooChannel sendMessage:myString];
|
|
|
|
// or if you need to handle a reply:
|
|
|
|
[fooChannel sendMessage:myString replyHandler:^(id reply) {
|
|
// do something with (NSString*)reply
|
|
}];
|
|
|
|
|
|
[API documentation](https://github.com/flutter/engine/blob/main/shell/platform/darwin/ios/framework/Headers). See [platform_channel](../../examples/platform_channel/ios/Runner/AppDelegate.m) for another example. |