Skip to content

Commit

Permalink
Remove old flutter messaging API (#3482)
Browse files Browse the repository at this point in the history
Breaking change: removed facilities for JSON and string messaging from FlutterView/FlutterViewController, leaving only binary messaging there. All other use of flutter communication now goes through FlutterMessageChannel and FlutterMethodChannels. Retained use of String and JSON codecs for now.

Companion flutter PR: flutter/flutter#8837
  • Loading branch information
mravn-google committed Mar 17, 2017
1 parent 4a5a324 commit c4edec7
Show file tree
Hide file tree
Showing 37 changed files with 780 additions and 847 deletions.
6 changes: 3 additions & 3 deletions shell/platform/android/BUILD.gn
Expand Up @@ -82,18 +82,18 @@ android_library("java") {
"io/flutter/app/FlutterActivity.java",
"io/flutter/app/FlutterApplication.java",
"io/flutter/plugin/common/ActivityLifecycleListener.java",
"io/flutter/plugin/common/BinaryMessageCodec.java",
"io/flutter/plugin/common/BinaryCodec.java",
"io/flutter/plugin/common/FlutterException.java",
"io/flutter/plugin/common/FlutterMessageChannel.java",
"io/flutter/plugin/common/FlutterMethodChannel.java",
"io/flutter/plugin/common/JSONMessageCodec.java",
"io/flutter/plugin/common/JSONMessageListener.java",
"io/flutter/plugin/common/JSONMethodCodec.java",
"io/flutter/plugin/common/MessageCodec.java",
"io/flutter/plugin/common/MethodCodec.java",
"io/flutter/plugin/common/MethodCall.java",
"io/flutter/plugin/common/StandardMessageCodec.java",
"io/flutter/plugin/common/StandardMethodCodec.java",
"io/flutter/plugin/common/StringMessageCodec.java",
"io/flutter/plugin/common/StringCodec.java",
"io/flutter/plugin/editing/InputConnectionAdaptor.java",
"io/flutter/plugin/editing/TextInputPlugin.java",
"io/flutter/plugin/platform/PlatformPlugin.java",
Expand Down
Expand Up @@ -9,11 +9,11 @@
/**
* A {@link MessageCodec} using unencoded binary messages, represented as {@link ByteBuffer}s.
*/
public final class BinaryMessageCodec implements MessageCodec<ByteBuffer> {
public final class BinaryCodec implements MessageCodec<ByteBuffer> {
// This codec must match the Dart codec of the same name in package flutter/services.
public static final BinaryMessageCodec INSTANCE = new BinaryMessageCodec();
public static final BinaryCodec INSTANCE = new BinaryCodec();

private BinaryMessageCodec() {
private BinaryCodec() {
}

@Override
Expand Down
@@ -0,0 +1,20 @@
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package io.flutter.plugin.common;

/**
* Thrown to indicate that a Flutter method invocation failed on the Flutter side.
*/
public class FlutterException extends RuntimeException {
public final String code;
public final Object details;

FlutterException(String code, String message, Object details) {
super(message);
assert code != null;
this.code = code;
this.details = details;
}
}
Expand Up @@ -6,6 +6,7 @@

import android.util.Log;
import io.flutter.view.FlutterView;
import io.flutter.view.FlutterView.BinaryMessageReplyCallback;
import io.flutter.view.FlutterView.BinaryMessageResponse;
import io.flutter.view.FlutterView.OnBinaryMessageListenerAsync;
import java.nio.ByteBuffer;
Expand Down Expand Up @@ -60,6 +61,27 @@ public FlutterMethodChannel(FlutterView view, String name, MethodCodec codec) {
this.codec = codec;
}

/**
* Invokes a method on this channel, expecting no result.
*
* @param method the name String of the method.
* @param arguments the arguments for the invocation, possibly null.
*/
public void invokeMethod(String method, Object arguments) {
invokeMethod(method, arguments, null);
}

/**
* Invokes a method on this channel.
*
* @param call a {@link MethodCall}.
* @param handler a {@link Response} handler for the invocation result.
*/
public void invokeMethod(String method, Object arguments, Response handler) {
view.sendBinaryMessage(name, codec.encodeMethodCall(new MethodCall(method, arguments)),
handler == null ? null : new MethodCallResultCallback(handler));
}

/**
* Registers a method call handler on this channel.
*
Expand Down Expand Up @@ -106,7 +128,8 @@ public interface StreamHandler {
* Handles a stream setup request.
*
* @param arguments Stream configuration arguments, possibly null.
* @param eventSink A {@link EventSink} used to emit events once the stream has been set up.
* @param eventSink An {@link EventSink} used to emit events once the stream has been set
* up.
*/
void listen(Object arguments, EventSink eventSink);

Expand Down Expand Up @@ -150,6 +173,24 @@ public interface EventSink extends Response {
void done();
}

private final class MethodCallResultCallback implements BinaryMessageReplyCallback {
private final Response handler;

MethodCallResultCallback(Response handler) {
this.handler = handler;
}

@Override
public void onReply(ByteBuffer reply) {
try {
final Object result = codec.decodeEnvelope(reply);
handler.success(result);
} catch (FlutterException e) {
handler.error(e.code, e.getMessage(), e.details);
}
}
}

private final class MethodCallListener implements OnBinaryMessageListenerAsync {
private final MethodCallHandler handler;

Expand Down Expand Up @@ -188,7 +229,7 @@ private void checkDone() {
});
} catch (Exception e) {
Log.e(TAG + name, "Failed to handle method call", e);
response.send(codec.encodeErrorEnvelope("error", e.getMessage(),null));
response.send(codec.encodeErrorEnvelope("error", e.getMessage(), null));
}
}
}
Expand Down Expand Up @@ -236,13 +277,13 @@ public void done() {
if (cancelled.get()) {
return;
}
FlutterMethodChannel.this.view.sendToFlutter(name,null);
FlutterMethodChannel.this.view.sendBinaryMessage(name, null, null);
}
});
response.send(codec.encodeSuccessEnvelope(null));
} catch (Exception e) {
Log.e(TAG + name, "Failed to open event stream", e);
response.send(codec.encodeErrorEnvelope("error", e.getMessage(),null));
response.send(codec.encodeErrorEnvelope("error", e.getMessage(), null));
}
} else if (call.method.equals("cancel")) {
cancelled.set(true);
Expand All @@ -251,7 +292,7 @@ public void done() {
response.send(codec.encodeSuccessEnvelope(null));
} catch (Exception e) {
Log.e(TAG + name, "Failed to close event stream", e);
response.send(codec.encodeErrorEnvelope("error", e.getMessage(),null));
response.send(codec.encodeErrorEnvelope("error", e.getMessage(), null));
}
}
}
Expand Down
Expand Up @@ -26,7 +26,7 @@ public ByteBuffer encodeMessage(Object message) {
if (message == null) {
return null;
}
return StringMessageCodec.INSTANCE.encodeMessage(JSONObject.wrap(message).toString());
return StringCodec.INSTANCE.encodeMessage(JSONObject.wrap(message).toString());
}

@Override
Expand All @@ -35,7 +35,7 @@ public Object decodeMessage(ByteBuffer message) {
return null;
}
try {
final String json = StringMessageCodec.INSTANCE.decodeMessage(message);
final String json = StringCodec.INSTANCE.decodeMessage(message);
final JSONTokener tokener = new JSONTokener(json);
final Object value = tokener.nextValue();
if (tokener.more()) {
Expand Down

This file was deleted.

102 changes: 71 additions & 31 deletions shell/platform/android/io/flutter/plugin/common/JSONMethodCodec.java
Expand Up @@ -11,37 +11,77 @@
* {@link JSONMessageCodec}.
*/
public final class JSONMethodCodec implements MethodCodec {
public static final JSONMethodCodec INSTANCE = new JSONMethodCodec();

private JSONMethodCodec() {
}

@Override
public MethodCall decodeMethodCall(ByteBuffer message) {
try {
final Object json = JSONMessageCodec.INSTANCE.decodeMessage(message);
if (json instanceof JSONArray) {
final JSONArray pair = (JSONArray) json;
if (pair.length() == 2 && pair.get(0) instanceof String) {
return new MethodCall(pair.getString(0), pair.get(1));
public static final JSONMethodCodec INSTANCE = new JSONMethodCodec();

private JSONMethodCodec() {
}

@Override
public ByteBuffer encodeMethodCall(MethodCall methodCall) {
try {
final JSONObject map = new JSONObject();
map.put("method", methodCall.method);
map.put("args", JSONObject.wrap(methodCall.arguments));
return JSONMessageCodec.INSTANCE.encodeMessage(map);
} catch (JSONException e) {
throw new IllegalArgumentException("Invalid JSON", e);
}
}

@Override
public MethodCall decodeMethodCall(ByteBuffer message) {
try {
final Object json = JSONMessageCodec.INSTANCE.decodeMessage(message);
if (json instanceof JSONObject) {
final JSONObject map = (JSONObject) json;
final Object method = map.get("method");
final Object arguments = map.get("args");
if (method instanceof String) {
return new MethodCall((String) method, arguments);
}
}
throw new IllegalArgumentException("Invalid method call: " + json);
} catch (JSONException e) {
throw new IllegalArgumentException("Invalid JSON", e);
}
}

@Override
public ByteBuffer encodeSuccessEnvelope(Object result) {
return JSONMessageCodec.INSTANCE
.encodeMessage(new JSONArray().put(JSONObject.wrap(result)));
}

@Override
public ByteBuffer encodeErrorEnvelope(String errorCode, String errorMessage,
Object errorDetails) {
return JSONMessageCodec.INSTANCE.encodeMessage(new JSONArray()
.put(errorCode)
.put(errorMessage)
.put(JSONObject.wrap(errorDetails)));
}

@Override
public Object decodeEnvelope(ByteBuffer envelope) {
try {
final Object json = JSONMessageCodec.INSTANCE.decodeMessage(envelope);
if (json instanceof JSONArray) {
final JSONArray array = (JSONArray) json;
if (array.length() == 1) {
return array.get(0);
}
if (array.length() == 3) {
final Object code = array.get(0);
final Object message = array.get(1);
final Object details = array.get(2);
if (code instanceof String && (message == null || message instanceof String)) {
throw new FlutterException((String) code, (String) message, details);
}
}
}
throw new IllegalArgumentException("Invalid method call: " + json);
} catch (JSONException e) {
throw new IllegalArgumentException("Invalid JSON", e);
}
}
throw new IllegalArgumentException("Invalid method call: " + json);
} catch (JSONException e) {
throw new IllegalArgumentException("Invalid JSON", e);
}
}

@Override
public ByteBuffer encodeSuccessEnvelope(Object result) {
return JSONMessageCodec.INSTANCE.encodeMessage(new JSONArray().put(JSONObject.wrap(result)));
}

@Override
public ByteBuffer encodeErrorEnvelope(String errorCode, String errorMessage, Object errorDetails) {
return JSONMessageCodec.INSTANCE.encodeMessage(new JSONArray()
.put(errorCode)
.put(errorMessage)
.put(JSONObject.wrap(errorDetails)));
}
}
Expand Up @@ -4,8 +4,6 @@

package io.flutter.plugin.common;

import java.util.Objects;

/**
* Command object representing a method call on a {@link FlutterMessageChannel}.
*/
Expand Down
22 changes: 20 additions & 2 deletions shell/platform/android/io/flutter/plugin/common/MethodCodec.java
Expand Up @@ -16,6 +16,15 @@
* All operations throw {@link IllegalArgumentException}, if conversion fails.
*/
public interface MethodCodec {
/**
* Encodes a message call into binary.
*
* @param methodCall a {@link MethodCall}.
* @return a {@link ByteBuffer} containing the encoding between position 0 and
* the current position.
*/
ByteBuffer encodeMethodCall(MethodCall methodCall);

/**
* Decodes a message call from binary.
*
Expand All @@ -29,7 +38,7 @@ public interface MethodCodec {
* Encodes a successful result into a binary envelope message.
*
* @param result The result value, possibly null.
* @return a ByteBuffer containing the encoding between position 0 and
* @return a {@link ByteBuffer} containing the encoding between position 0 and
* the current position.
*/
ByteBuffer encodeSuccessEnvelope(Object result);
Expand All @@ -40,8 +49,17 @@ public interface MethodCodec {
* @param errorCode An error code String.
* @param errorMessage An error message String, possibly null.
* @param errorDetails Error details, possibly null.
* @return a ByteBuffer containing the encoding between position 0 and
* @return a {@link ByteBuffer} containing the encoding between position 0 and
* the current position.
*/
ByteBuffer encodeErrorEnvelope(String errorCode, String errorMessage, Object errorDetails);

/**
* Decodes a result envelope from binary.
*
* @param envelope the binary encoding of a result envelope as a {@link ByteBuffer}.
* @return the enveloped result Object.
* @throws FlutterException if the envelope was an error envelope.
*/
Object decodeEnvelope(ByteBuffer envelope);
}

0 comments on commit c4edec7

Please sign in to comment.