• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 package io.flutter.plugin.common;
6 
7 import android.support.annotation.NonNull;
8 import android.support.annotation.Nullable;
9 import android.support.annotation.UiThread;
10 import android.util.Log;
11 import java.nio.ByteBuffer;
12 
13 import io.flutter.BuildConfig;
14 import io.flutter.plugin.common.BinaryMessenger.BinaryReply;
15 import io.flutter.plugin.common.BinaryMessenger.BinaryMessageHandler;
16 
17 /**
18  * A named channel for communicating with the Flutter application using basic, asynchronous message passing.
19  *
20  * <p>Messages are encoded into binary before being sent, and binary messages received are decoded
21  * into Java objects. The {@link MessageCodec} used must be compatible with the
22  * one used by the Flutter application. This can be achieved by creating a
23  * <a href="https://docs.flutter.io/flutter/services/BasicMessageChannel-class.html">BasicMessageChannel</a>
24  * counterpart of this channel on the Dart side. The static Java type of messages sent and received
25  * is {@code Object}, but only values supported by the specified {@link MessageCodec} can be used.</p>
26  *
27  * <p>The logical identity of the channel is given by its name. Identically named channels will interfere
28  * with each other's communication.</p>
29  */
30 public final class BasicMessageChannel<T> {
31     private static final String TAG = "BasicMessageChannel#";
32 
33     @NonNull
34     private final BinaryMessenger messenger;
35     @NonNull
36     private final String name;
37     @NonNull
38     private final MessageCodec<T> codec;
39 
40     /**
41      * Creates a new channel associated with the specified {@link BinaryMessenger}
42      * and with the specified name and {@link MessageCodec}.
43      *
44      * @param messenger a {@link BinaryMessenger}.
45      * @param name a channel name String.
46      * @param codec a {@link MessageCodec}.
47      */
BasicMessageChannel(@onNull BinaryMessenger messenger, @NonNull String name, @NonNull MessageCodec<T> codec)48     public BasicMessageChannel(@NonNull BinaryMessenger messenger, @NonNull String name, @NonNull MessageCodec<T> codec) {
49         if (BuildConfig.DEBUG) {
50             if (messenger == null) {
51                 Log.e(TAG, "Parameter messenger must not be null.");
52             }
53             if (name == null) {
54                 Log.e(TAG, "Parameter name must not be null.");
55             }
56             if (codec == null) {
57                 Log.e(TAG, "Parameter codec must not be null.");
58             }
59         }
60         this.messenger = messenger;
61         this.name = name;
62         this.codec = codec;
63     }
64 
65     /**
66      * Sends the specified message to the Flutter application on this channel.
67      *
68      * @param message the message, possibly null.
69      */
send(@ullable T message)70     public void send(@Nullable T message) {
71         send(message, null);
72     }
73 
74     /**
75      * Sends the specified message to the Flutter application, optionally expecting a reply.
76      *
77      * <p>Any uncaught exception thrown by the reply callback will be caught and logged.</p>
78      *
79      * @param message the message, possibly null.
80      * @param callback a {@link Reply} callback, possibly null.
81      */
82     @UiThread
send(@ullable T message, @Nullable final Reply<T> callback)83     public void send(@Nullable T message, @Nullable final Reply<T> callback) {
84         messenger.send(name, codec.encodeMessage(message),
85             callback == null ? null : new IncomingReplyHandler(callback));
86     }
87 
88     /**
89      * Registers a message handler on this channel for receiving messages sent from the Flutter
90      * application.
91      *
92      * <p>Overrides any existing handler registration for (the name of) this channel.</p>
93      *
94      * <p>If no handler has been registered, any incoming message on this channel will be handled silently
95      * by sending a null reply.</p>
96      *
97      * @param handler a {@link MessageHandler}, or null to deregister.
98      */
99     @UiThread
setMessageHandler(@ullable final MessageHandler<T> handler)100     public void setMessageHandler(@Nullable final MessageHandler<T> handler) {
101         messenger.setMessageHandler(name,
102             handler == null ? null : new IncomingMessageHandler(handler));
103     }
104 
105     /**
106      * A handler of incoming messages.
107      */
108     public interface MessageHandler<T> {
109 
110         /**
111          * Handles the specified message received from Flutter.
112          *
113          * <p>Handler implementations must reply to all incoming messages, by submitting a single reply
114          * message to the given {@link Reply}. Failure to do so will result in lingering Flutter reply
115          * handlers. The reply may be submitted asynchronously.</p>
116          *
117          * <p>Any uncaught exception thrown by this method, or the preceding message decoding, will be
118          * caught by the channel implementation and logged, and a null reply message will be sent back
119          * to Flutter.</p>
120          *
121          * <p>Any uncaught exception thrown during encoding a reply message submitted to the {@link Reply}
122          * is treated similarly: the exception is logged, and a null reply is sent to Flutter.</p>
123          *
124          * @param message the message, possibly null.
125          * @param reply a {@link Reply} for sending a single message reply back to Flutter.
126          */
onMessage(@ullable T message, @NonNull Reply<T> reply)127         void onMessage(@Nullable T message, @NonNull Reply<T> reply);
128     }
129 
130     /**
131      * Message reply callback. Used to submit a reply to an incoming
132      * message from Flutter. Also used in the dual capacity to handle a reply
133      * received from Flutter after sending a message.
134      */
135     public interface Reply<T> {
136         /**
137          * Handles the specified message reply.
138          *
139          * @param reply the reply, possibly null.
140          */
reply(@ullable T reply)141         void reply(@Nullable T reply);
142     }
143 
144     private final class IncomingReplyHandler implements BinaryReply {
145         private final Reply<T> callback;
146 
IncomingReplyHandler(@onNull Reply<T> callback)147         private IncomingReplyHandler(@NonNull Reply<T> callback) {
148             this.callback = callback;
149         }
150 
151         @Override
reply(@ullable ByteBuffer reply)152         public void reply(@Nullable ByteBuffer reply) {
153             try {
154                 callback.reply(codec.decodeMessage(reply));
155             } catch (RuntimeException e) {
156                 Log.e(TAG + name, "Failed to handle message reply", e);
157             }
158         }
159     }
160 
161     private final class IncomingMessageHandler implements BinaryMessageHandler {
162         private final MessageHandler<T> handler;
163 
IncomingMessageHandler(@onNull MessageHandler<T> handler)164         private IncomingMessageHandler(@NonNull MessageHandler<T> handler) {
165             this.handler = handler;
166         }
167 
168         @Override
onMessage(@ullable ByteBuffer message, @NonNull final BinaryReply callback)169         public void onMessage(@Nullable ByteBuffer message, @NonNull final BinaryReply callback) {
170             try {
171                 handler.onMessage(codec.decodeMessage(message), new Reply<T>() {
172                     @Override
173                     public void reply(T reply) {
174                         callback.reply(codec.encodeMessage(reply));
175                     }
176                 });
177             } catch (RuntimeException e) {
178                 Log.e(TAG + name, "Failed to handle message", e);
179                 callback.reply(null);
180             }
181         }
182     }
183 }
184