Skip to content

Commit

Permalink
issue(123867): added modern asynchronous api for Swift and Kotlin
Browse files Browse the repository at this point in the history
  • Loading branch information
feduke-nukem committed Dec 23, 2024
1 parent 3515aba commit 9d35195
Show file tree
Hide file tree
Showing 27 changed files with 1,047 additions and 416 deletions.
1 change: 1 addition & 0 deletions packages/pigeon/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
## NEXT

* Updates minimum supported SDK version to Flutter 3.22/Dart 3.4.
* Added support of modern asynchronous api for Swift (async) and Kotlin (suspend).

## 22.7.0

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// 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.
// Autogenerated from Pigeon, do not edit directly.
// Autogenerated from Pigeon (v22.7.0), do not edit directly.
// See also: https://pub.dev/packages/pigeon

import static java.lang.annotation.ElementType.METHOD;
Expand All @@ -19,7 +19,9 @@
import java.lang.annotation.Target;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
Expand All @@ -37,7 +39,8 @@ public static class FlutterError extends RuntimeException {
/** The error details. Must be a datatype supported by the api codec. */
public final Object details;

public FlutterError(@NonNull String code, @Nullable String message, @Nullable Object details) {
public FlutterError(@NonNull String code, @Nullable String message, @Nullable Object details)
{
super(message);
this.code = code;
this.details = details;
Expand All @@ -56,15 +59,14 @@ protected static ArrayList<Object> wrapError(@NonNull Throwable exception) {
errorList.add(exception.toString());
errorList.add(exception.getClass().getSimpleName());
errorList.add(
"Cause: " + exception.getCause() + ", Stacktrace: " + Log.getStackTraceString(exception));
"Cause: " + exception.getCause() + ", Stacktrace: " + Log.getStackTraceString(exception));
}
return errorList;
}

@NonNull
protected static FlutterError createConnectionError(@NonNull String channelName) {
return new FlutterError(
"channel-error", "Unable to establish connection on channel: " + channelName + ".", "");
return new FlutterError("channel-error", "Unable to establish connection on channel: " + channelName + ".", "");
}

@Target(METHOD)
Expand Down Expand Up @@ -135,17 +137,10 @@ public void setData(@NonNull Map<String, String> setterArg) {

@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
if (this == o) { return true; }
if (o == null || getClass() != o.getClass()) { return false; }
MessageData that = (MessageData) o;
return Objects.equals(name, that.name)
&& Objects.equals(description, that.description)
&& code.equals(that.code)
&& data.equals(that.data);
return Objects.equals(name, that.name) && Objects.equals(description, that.description) && code.equals(that.code) && data.equals(that.data);
}

@Override
Expand Down Expand Up @@ -229,11 +224,10 @@ private PigeonCodec() {}
@Override
protected Object readValueOfType(byte type, @NonNull ByteBuffer buffer) {
switch (type) {
case (byte) 129:
{
Object value = readValue(buffer);
return value == null ? null : Code.values()[((Long) value).intValue()];
}
case (byte) 129: {
Object value = readValue(buffer);
return value == null ? null : Code.values()[((Long) value).intValue()];
}
case (byte) 130:
return MessageData.fromList((ArrayList<Object>) readValue(buffer));
default:
Expand All @@ -255,6 +249,7 @@ protected void writeValue(@NonNull ByteArrayOutputStream stream, Object value) {
}
}


/** Asynchronous error handling return type for non-nullable API method returns. */
public interface Result<T> {
/** Success case callback method for handling returns. */
Expand Down Expand Up @@ -282,43 +277,39 @@ public interface VoidResult {
/** Generated interface from Pigeon that represents a handler of messages from Flutter. */
public interface ExampleHostApi {

@NonNull
@NonNull
String getHostLanguage();

@NonNull
@NonNull
Long add(@NonNull Long a, @NonNull Long b);

void sendMessage(@NonNull MessageData message, @NonNull Result<Boolean> result);

void sendMessageModernAsync(@NonNull MessageData message, @NonNull Result<Boolean> result);

/** The codec used by ExampleHostApi. */
static @NonNull MessageCodec<Object> getCodec() {
return PigeonCodec.INSTANCE;
}
/** Sets up an instance of `ExampleHostApi` to handle messages through the `binaryMessenger`. */
/**Sets up an instance of `ExampleHostApi` to handle messages through the `binaryMessenger`. */
static void setUp(@NonNull BinaryMessenger binaryMessenger, @Nullable ExampleHostApi api) {
setUp(binaryMessenger, "", api);
}

static void setUp(
@NonNull BinaryMessenger binaryMessenger,
@NonNull String messageChannelSuffix,
@Nullable ExampleHostApi api) {
static void setUp(@NonNull BinaryMessenger binaryMessenger, @NonNull String messageChannelSuffix, @Nullable ExampleHostApi api) {
messageChannelSuffix = messageChannelSuffix.isEmpty() ? "" : "." + messageChannelSuffix;
{
BasicMessageChannel<Object> channel =
new BasicMessageChannel<>(
binaryMessenger,
"dev.flutter.pigeon.pigeon_example_package.ExampleHostApi.getHostLanguage"
+ messageChannelSuffix,
getCodec());
binaryMessenger, "dev.flutter.pigeon.pigeon_example_package.ExampleHostApi.getHostLanguage" + messageChannelSuffix, getCodec());
if (api != null) {
channel.setMessageHandler(
(message, reply) -> {
ArrayList<Object> wrapped = new ArrayList<>();
try {
String output = api.getHostLanguage();
wrapped.add(0, output);
} catch (Throwable exception) {
}
catch (Throwable exception) {
wrapped = wrapError(exception);
}
reply.reply(wrapped);
Expand All @@ -330,10 +321,7 @@ static void setUp(
{
BasicMessageChannel<Object> channel =
new BasicMessageChannel<>(
binaryMessenger,
"dev.flutter.pigeon.pigeon_example_package.ExampleHostApi.add"
+ messageChannelSuffix,
getCodec());
binaryMessenger, "dev.flutter.pigeon.pigeon_example_package.ExampleHostApi.add" + messageChannelSuffix, getCodec());
if (api != null) {
channel.setMessageHandler(
(message, reply) -> {
Expand All @@ -344,7 +332,8 @@ static void setUp(
try {
Long output = api.add(aArg, bArg);
wrapped.add(0, output);
} catch (Throwable exception) {
}
catch (Throwable exception) {
wrapped = wrapError(exception);
}
reply.reply(wrapped);
Expand All @@ -356,10 +345,7 @@ static void setUp(
{
BasicMessageChannel<Object> channel =
new BasicMessageChannel<>(
binaryMessenger,
"dev.flutter.pigeon.pigeon_example_package.ExampleHostApi.sendMessage"
+ messageChannelSuffix,
getCodec());
binaryMessenger, "dev.flutter.pigeon.pigeon_example_package.ExampleHostApi.sendMessage" + messageChannelSuffix, getCodec());
if (api != null) {
channel.setMessageHandler(
(message, reply) -> {
Expand All @@ -385,6 +371,35 @@ public void error(Throwable error) {
channel.setMessageHandler(null);
}
}
{
BasicMessageChannel<Object> channel =
new BasicMessageChannel<>(
binaryMessenger, "dev.flutter.pigeon.pigeon_example_package.ExampleHostApi.sendMessageModernAsync" + messageChannelSuffix, getCodec());
if (api != null) {
channel.setMessageHandler(
(message, reply) -> {
ArrayList<Object> wrapped = new ArrayList<>();
ArrayList<Object> args = (ArrayList<Object>) message;
MessageData messageArg = (MessageData) args.get(0);
Result<Boolean> resultCallback =
new Result<Boolean>() {
public void success(Boolean result) {
wrapped.add(0, result);
reply.reply(wrapped);
}

public void error(Throwable error) {
ArrayList<Object> wrappedError = wrapError(error);
reply.reply(wrappedError);
}
};

api.sendMessageModernAsync(messageArg, resultCallback);
});
} else {
channel.setMessageHandler(null);
}
}
}
}
/** Generated class from Pigeon that represents Flutter messages that can be called from Java. */
Expand All @@ -395,47 +410,40 @@ public static class MessageFlutterApi {
public MessageFlutterApi(@NonNull BinaryMessenger argBinaryMessenger) {
this(argBinaryMessenger, "");
}

public MessageFlutterApi(
@NonNull BinaryMessenger argBinaryMessenger, @NonNull String messageChannelSuffix) {
public MessageFlutterApi(@NonNull BinaryMessenger argBinaryMessenger, @NonNull String messageChannelSuffix) {
this.binaryMessenger = argBinaryMessenger;
this.messageChannelSuffix = messageChannelSuffix.isEmpty() ? "" : "." + messageChannelSuffix;
}

/** Public interface for sending reply. The codec used by MessageFlutterApi. */
/**
* Public interface for sending reply.
* The codec used by MessageFlutterApi.
*/
static @NonNull MessageCodec<Object> getCodec() {
return PigeonCodec.INSTANCE;
}

public void flutterMethod(@Nullable String aStringArg, @NonNull Result<String> result) {
final String channelName =
"dev.flutter.pigeon.pigeon_example_package.MessageFlutterApi.flutterMethod"
+ messageChannelSuffix;
final String channelName = "dev.flutter.pigeon.pigeon_example_package.MessageFlutterApi.flutterMethod" + messageChannelSuffix;
BasicMessageChannel<Object> channel =
new BasicMessageChannel<>(binaryMessenger, channelName, getCodec());
new BasicMessageChannel<>(
binaryMessenger, channelName, getCodec());
channel.send(
new ArrayList<>(Collections.singletonList(aStringArg)),
channelReply -> {
if (channelReply instanceof List) {
List<Object> listReply = (List<Object>) channelReply;
if (listReply.size() > 1) {
result.error(
new FlutterError(
(String) listReply.get(0), (String) listReply.get(1), listReply.get(2)));
result.error(new FlutterError((String) listReply.get(0), (String) listReply.get(1), listReply.get(2)));
} else if (listReply.get(0) == null) {
result.error(
new FlutterError(
"null-error",
"Flutter api returned null value for non-null return value.",
""));
result.error(new FlutterError("null-error", "Flutter api returned null value for non-null return value.", ""));
} else {
@SuppressWarnings("ConstantConditions")
String output = (String) listReply.get(0);
result.success(output);
}
} else {
} else {
result.error(createConnectionError(channelName));
}
}
});
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ import android.os.Looper
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.embedding.engine.plugins.FlutterPlugin
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.delay

// #docregion kotlin-class
private class PigeonApiImplementation : ExampleHostApi {
Expand All @@ -39,6 +43,16 @@ private class PigeonApiImplementation : ExampleHostApi {
}
callback(Result.success(true))
}

override suspend fun sendMessageModernAsync(message: MessageData): Boolean {
if (message.code == Code.ONE) {
throw FlutterError("code", "message", "details")
}

delay(2000)

return true
}
}
// #enddocregion kotlin-class

Expand Down Expand Up @@ -111,7 +125,7 @@ class MainActivity : FlutterActivity() {
super.configureFlutterEngine(flutterEngine)

val api = PigeonApiImplementation()
ExampleHostApi.setUp(flutterEngine.dartExecutor.binaryMessenger, api)
ExampleHostApi.setUp(flutterEngine.dartExecutor.binaryMessenger, api, coroutineScope = CoroutineScope(Dispatchers.Main + SupervisorJob()))
// #docregion kotlin-init-event
val eventListener = EventListener()
StreamEventsStreamHandler.register(flutterEngine.dartExecutor.binaryMessenger, eventListener)
Expand Down
Loading

0 comments on commit 9d35195

Please sign in to comment.