blob: eef8e047a0afe3112d6646a88d2c1f82424555ba [file] [log] [blame]
// 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.
package io.flutter.plugin.common;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.UiThread;
import java.nio.ByteBuffer;
/**
* Facility for communicating with Flutter using asynchronous message passing with binary messages.
* The Flutter Dart code should use <a
* href="https://api.flutter.dev/flutter/services/BinaryMessages-class.html">BinaryMessages</a> to
* participate.
*
* <p>{@code BinaryMessenger} is expected to be utilized from a single thread throughout the
* duration of its existence. If created on the main thread, then all invocations should take place
* on the main thread. If created on a background thread, then all invocations should take place on
* that background thread.
*
* @see BasicMessageChannel , which supports message passing with Strings and semi-structured
* messages.
* @see MethodChannel , which supports communication using asynchronous method invocation.
* @see EventChannel , which supports communication using event streams.
*/
public interface BinaryMessenger {
/**
* An abstraction over the threading policy used to invoke message handlers.
*
* <p>These are generated by calling methods like {@link
* BinaryMessenger#makeBackgroundTaskQueue(TaskQueueOptions)} and can be passed into platform
* channels' constructors to control the threading policy for handling platform channels'
* messages.
*/
public interface TaskQueue {}
/** Options that control how a TaskQueue should operate and be created. */
public static class TaskQueueOptions {
private boolean isSerial = true;
public boolean getIsSerial() {
return isSerial;
}
/**
* Setter for `isSerial` property.
*
* <p>When this is true all tasks performed by the TaskQueue will be forced to happen serially
* (one completes before the other begins).
*/
public TaskQueueOptions setIsSerial(boolean isSerial) {
this.isSerial = isSerial;
return this;
}
}
/**
* Creates a TaskQueue that executes the tasks serially on a background thread.
*
* <p>There is no guarantee that the tasks will execute on the same thread, just that execution is
* serial. This is could be problematic if your code relies on ThreadLocal storage or
* introspection about what thread is actually executing.
*/
@UiThread
default TaskQueue makeBackgroundTaskQueue() {
return makeBackgroundTaskQueue(new TaskQueueOptions());
}
/**
* Creates a TaskQueue that executes the tasks serially on a background thread.
*
* <p>{@link TaskQueueOptions} can be used to configure the task queue to execute tasks
* concurrently. Doing so can be more performant, though users need to ensure that the task
* handlers are thread-safe.
*/
@UiThread
default TaskQueue makeBackgroundTaskQueue(TaskQueueOptions options) {
// TODO(92582): Remove default implementation when it is safe for Google Flutter users.
throw new UnsupportedOperationException("makeBackgroundTaskQueue not implemented.");
}
/**
* Sends a binary message to the Flutter application.
*
* @param channel the name {@link String} of the logical channel used for the message.
* @param message the message payload, a direct-allocated {@link ByteBuffer} with the message
* bytes between position zero and current position, or null.
*/
@UiThread
void send(@NonNull String channel, @Nullable ByteBuffer message);
/**
* Sends a binary message to the Flutter application, optionally expecting a reply.
*
* <p>Any uncaught exception thrown by the reply callback will be caught and logged.
*
* @param channel the name {@link String} of the logical channel used for the message.
* @param message the message payload, a direct-allocated {@link ByteBuffer} with the message
* bytes between position zero and current position, or null.
* @param callback a {@link BinaryReply} callback invoked when the Flutter application responds to
* the message, possibly null.
*/
@UiThread
void send(@NonNull String channel, @Nullable ByteBuffer message, @Nullable BinaryReply callback);
/**
* Registers a handler to be invoked when the Flutter application sends a message to its host
* platform.
*
* <p>Registration overwrites any previous registration for the same channel name. Use a null
* handler to deregister.
*
* <p>If no handler has been registered for a particular channel, any incoming message on that
* channel will be handled silently by sending a null reply.
*
* @param channel the name {@link String} of the channel.
* @param handler a {@link BinaryMessageHandler} to be invoked on incoming messages, or null.
*/
@UiThread
void setMessageHandler(@NonNull String channel, @Nullable BinaryMessageHandler handler);
/**
* Registers a handler to be invoked when the Flutter application sends a message to its host
* platform.
*
* <p>Registration overwrites any previous registration for the same channel name. Use a null
* handler to deregister.
*
* <p>If no handler has been registered for a particular channel, any incoming message on that
* channel will be handled silently by sending a null reply.
*
* @param channel the name {@link String} of the channel.
* @param handler a {@link BinaryMessageHandler} to be invoked on incoming messages, or null.
* @param taskQueue a {@link BinaryMessenger.TaskQueue} that specifies what thread will execute
* the handler. Specifying null means execute on the platform thread.
*/
@UiThread
default void setMessageHandler(
@NonNull String channel,
@Nullable BinaryMessageHandler handler,
@Nullable TaskQueue taskQueue) {
// TODO(92582): Remove default implementation when it is safe for Google Flutter users.
if (taskQueue != null) {
throw new UnsupportedOperationException(
"setMessageHandler called with nonnull taskQueue is not supported.");
}
setMessageHandler(channel, handler);
}
/**
* Enables the ability to queue messages received from Dart.
*
* <p>This is useful when there are pending channel handler registrations. For example, Dart may
* be initialized concurrently, and prior to the registration of the channel handlers. This
* implies that Dart may start sending messages while plugins are being registered.
*/
default void enableBufferingIncomingMessages() {
throw new UnsupportedOperationException("enableBufferingIncomingMessages not implemented.");
}
/**
* Disables the ability to queue messages received from Dart.
*
* <p>This can be used after all pending channel handlers have been registered.
*/
default void disableBufferingIncomingMessages() {
throw new UnsupportedOperationException("disableBufferingIncomingMessages not implemented.");
}
/** Handler for incoming binary messages from Flutter. */
interface BinaryMessageHandler {
/**
* Handles the specified message.
*
* <p>Handler implementations must reply to all incoming messages, by submitting a single reply
* message to the given {@link BinaryReply}. Failure to do so will result in lingering Flutter
* reply handlers. The reply may be submitted asynchronously.
*
* <p>Any uncaught exception thrown by this method will be caught by the messenger
* implementation and logged, and a null reply message will be sent back to Flutter.
*
* @param message the message {@link ByteBuffer} payload, possibly null.
* @param reply A {@link BinaryReply} used for submitting a reply back to Flutter.
*/
@UiThread
void onMessage(@Nullable ByteBuffer message, @NonNull BinaryReply reply);
}
/**
* Binary message reply callback. Used to submit a reply to an incoming message from Flutter. Also
* used in the dual capacity to handle a reply received from Flutter after sending a message.
*/
interface BinaryReply {
/**
* Handles the specified reply.
*
* @param reply the reply payload, a direct-allocated {@link ByteBuffer} or null. Senders of
* outgoing replies must place the reply bytes between position zero and current position.
* Reply receivers can read from the buffer directly.
*/
void reply(@Nullable ByteBuffer reply);
}
}