Commit 08ba8dc4 authored by Adam Barth's avatar Adam Barth Committed by GitHub

Add a mechanism for receiving platform messages (#6361)

parent 88e065de
...@@ -3,12 +3,14 @@ ...@@ -3,12 +3,14 @@
// found in the LICENSE file. // found in the LICENSE file.
import 'dart:async'; import 'dart:async';
import 'dart:ui' as ui;
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'asset_bundle.dart'; import 'asset_bundle.dart';
import 'image_cache.dart'; import 'image_cache.dart';
import 'shell.dart'; import 'shell.dart';
import 'platform_messages.dart';
/// Ensures that the [MojoShell] singleton is created synchronously /// Ensures that the [MojoShell] singleton is created synchronously
/// during binding initialization. This allows other binding classes /// during binding initialization. This allows other binding classes
...@@ -27,6 +29,8 @@ abstract class ServicesBinding extends BindingBase { ...@@ -27,6 +29,8 @@ abstract class ServicesBinding extends BindingBase {
@override @override
void initInstances() { void initInstances() {
super.initInstances(); super.initInstances();
ui.window
..onPlatformMessage = PlatformMessages.handlePlatformMessage;
new MojoShell(); new MojoShell();
LicenseRegistry.addLicense(_addLicenses); LicenseRegistry.addLicense(_addLicenses);
} }
......
...@@ -7,8 +7,21 @@ import 'dart:convert'; ...@@ -7,8 +7,21 @@ import 'dart:convert';
import 'dart:typed_data'; import 'dart:typed_data';
import 'dart:ui' as ui; import 'dart:ui' as ui;
String _decodeUTF8(ByteData data) { import 'package:flutter/foundation.dart';
return data != null ? UTF8.decoder.convert(data.buffer.asUint8List()) : null;
ByteData _encodeUTF8(String message) {
if (message == null)
return null;
Uint8List encoded = UTF8.encoder.convert(message);
return encoded.buffer.asByteData();
}
String _decodeUTF8(ByteData message) {
return message != null ? UTF8.decoder.convert(message.buffer.asUint8List()) : null;
}
String _encodeJSON(dynamic message) {
return message != null ? JSON.encode(message) : null;
} }
dynamic _decodeJSON(String message) { dynamic _decodeJSON(String message) {
...@@ -18,12 +31,52 @@ dynamic _decodeJSON(String message) { ...@@ -18,12 +31,52 @@ dynamic _decodeJSON(String message) {
void _sendString(String name, String message, void callback(String reply)) { void _sendString(String name, String message, void callback(String reply)) {
Uint8List encoded = UTF8.encoder.convert(message); Uint8List encoded = UTF8.encoder.convert(message);
ui.window.sendPlatformMessage(name, encoded.buffer.asByteData(), (ByteData reply) { ui.window.sendPlatformMessage(name, encoded.buffer.asByteData(), (ByteData reply) {
callback(_decodeUTF8(reply)); try {
callback(_decodeUTF8(reply));
} catch (exception, stack) {
FlutterError.reportError(new FlutterErrorDetails(
exception: exception,
stack: stack,
library: 'services library',
context: 'during a platform message response callback',
));
}
}); });
} }
/// Sends messages to the hosting application. typedef Future<ByteData> _PlatformMessageHandler(ByteData message);
/// Sends message to and receives messages from the underlying platform.
class PlatformMessages { class PlatformMessages {
static final Map<String, _PlatformMessageHandler> _handlers =
<String, _PlatformMessageHandler>{};
/// Calls the handler registered for the given name.
///
/// Typically called by [ServicesBinding] to handle platform messages received
/// from [ui.window.onPlatformMessage].
///
/// To register a handler for a given message name, see
/// [setStringMessageHandler] and [setJSONMessageHandler].
static Future<Null> handlePlatformMessage(
String name, ByteData data, ui.PlatformMessageResponseCallback callback) async {
ByteData response;
try {
_PlatformMessageHandler handler = _handlers[name];
if (handler != null)
response = await handler(data);
} catch (exception, stack) {
FlutterError.reportError(new FlutterErrorDetails(
exception: exception,
stack: stack,
library: 'services library',
context: 'during a platform message callback',
));
} finally {
callback(response);
}
}
/// Send a string message to the host application. /// Send a string message to the host application.
static Future<String> sendString(String name, String message) { static Future<String> sendString(String name, String message) {
Completer<String> completer = new Completer<String>(); Completer<String> completer = new Completer<String>();
...@@ -41,4 +94,33 @@ class PlatformMessages { ...@@ -41,4 +94,33 @@ class PlatformMessages {
}); });
return completer.future; return completer.future;
} }
/// Set a callback for receiving binary messages from the platform.
///
/// The given callback will replace the currently registered callback (if any).
static void setBinaryMessageHandler(String name, Future<ByteData> handler(ByteData message)) {
_handlers[name] = handler;
}
/// Set a callback for receiving string messages from the platform.
///
/// The given callback will replace the currently registered callback (if any).
static void setStringMessageHandler(String name, Future<String> handler(String message)) {
setBinaryMessageHandler(name, (ByteData message) async {
return _encodeUTF8(await handler(_decodeUTF8(message)));
});
}
/// Set a callback for receiving JSON messages from the platform.
///
/// Messages received are decoded as JSON before being passed to the given
/// callback. The result of the callback is encoded as JSON before being
/// returned as the response to the message.
///
/// The given callback will replace the currently registered callback (if any).
static void setJSONMessageHandler(String name, Future<dynamic> handler(dynamic message)) {
setStringMessageHandler(name, (String message) async {
return _encodeJSON(await handler(_decodeJSON(message)));
});
}
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment