2018-11-07 12:24:35 -08:00
|
|
|
// Copyright 2013 The Flutter Authors. All rights reserved.
|
2017-11-02 02:57:29 -07:00
|
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
|
|
|
// found in the LICENSE file.
|
|
|
|
|
|
2017-03-01 13:54:32 +01:00
|
|
|
package io.flutter.plugin.common;
|
|
|
|
|
|
|
|
|
|
import java.nio.ByteBuffer;
|
|
|
|
|
import org.json.JSONArray;
|
|
|
|
|
import org.json.JSONException;
|
|
|
|
|
import org.json.JSONObject;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* A {@link MethodCodec} using UTF-8 encoded JSON method calls and result envelopes.
|
2017-04-28 23:31:11 +02:00
|
|
|
*
|
|
|
|
|
* <p>This codec is guaranteed to be compatible with the corresponding
|
|
|
|
|
* <a href="https://docs.flutter.io/flutter/services/JSONMethodCodec-class.html">JSONMethodCodec</a>
|
|
|
|
|
* on the Dart side. These parts of the Flutter SDK are evolved synchronously.</p>
|
|
|
|
|
*
|
|
|
|
|
* <p>Values supported as methods arguments and result payloads are those supported by
|
|
|
|
|
* {@link JSONMessageCodec}.</p>
|
2017-03-01 13:54:32 +01:00
|
|
|
*/
|
|
|
|
|
public final class JSONMethodCodec implements MethodCodec {
|
2017-04-19 21:53:46 +02:00
|
|
|
// This codec must match the Dart codec of the same name in package flutter/services.
|
2017-03-17 09:04:59 +01:00
|
|
|
public static final JSONMethodCodec INSTANCE = new JSONMethodCodec();
|
2017-03-01 13:54:32 +01:00
|
|
|
|
2017-03-17 09:04:59 +01:00
|
|
|
private JSONMethodCodec() {
|
2017-03-01 13:54:32 +01:00
|
|
|
}
|
|
|
|
|
|
2017-03-17 09:04:59 +01:00
|
|
|
@Override
|
|
|
|
|
public ByteBuffer encodeMethodCall(MethodCall methodCall) {
|
|
|
|
|
try {
|
|
|
|
|
final JSONObject map = new JSONObject();
|
|
|
|
|
map.put("method", methodCall.method);
|
2017-04-06 10:15:06 -07:00
|
|
|
map.put("args", JSONUtil.wrap(methodCall.arguments));
|
2017-03-17 09:04:59 +01:00
|
|
|
return JSONMessageCodec.INSTANCE.encodeMessage(map);
|
|
|
|
|
} catch (JSONException e) {
|
|
|
|
|
throw new IllegalArgumentException("Invalid JSON", e);
|
|
|
|
|
}
|
|
|
|
|
}
|
2017-03-01 13:54:32 +01:00
|
|
|
|
2017-03-17 09:04:59 +01:00
|
|
|
@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");
|
2017-04-27 07:52:56 +02:00
|
|
|
final Object arguments = unwrapNull(map.opt("args"));
|
2017-03-17 09:04:59 +01:00
|
|
|
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
|
2017-04-06 10:15:06 -07:00
|
|
|
.encodeMessage(new JSONArray().put(JSONUtil.wrap(result)));
|
2017-03-17 09:04:59 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public ByteBuffer encodeErrorEnvelope(String errorCode, String errorMessage,
|
|
|
|
|
Object errorDetails) {
|
|
|
|
|
return JSONMessageCodec.INSTANCE.encodeMessage(new JSONArray()
|
|
|
|
|
.put(errorCode)
|
2017-04-27 07:52:56 +02:00
|
|
|
.put(JSONUtil.wrap(errorMessage))
|
2017-04-06 10:15:06 -07:00
|
|
|
.put(JSONUtil.wrap(errorDetails)));
|
2017-03-17 09:04:59 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@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) {
|
2017-04-27 07:52:56 +02:00
|
|
|
return unwrapNull(array.opt(0));
|
2017-03-17 09:04:59 +01:00
|
|
|
}
|
|
|
|
|
if (array.length() == 3) {
|
|
|
|
|
final Object code = array.get(0);
|
2017-04-27 07:52:56 +02:00
|
|
|
final Object message = unwrapNull(array.opt(1));
|
|
|
|
|
final Object details = unwrapNull(array.opt(2));
|
2017-03-17 09:04:59 +01:00
|
|
|
if (code instanceof String && (message == null || message instanceof String)) {
|
|
|
|
|
throw new FlutterException((String) code, (String) message, details);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2017-04-27 07:52:56 +02:00
|
|
|
throw new IllegalArgumentException("Invalid envelope: " + json);
|
2017-03-17 09:04:59 +01:00
|
|
|
} catch (JSONException e) {
|
|
|
|
|
throw new IllegalArgumentException("Invalid JSON", e);
|
|
|
|
|
}
|
|
|
|
|
}
|
2017-04-27 07:52:56 +02:00
|
|
|
|
|
|
|
|
Object unwrapNull(Object value) {
|
|
|
|
|
return (value == JSONObject.NULL) ? null : value;
|
|
|
|
|
}
|
2017-03-01 13:54:32 +01:00
|
|
|
}
|