Skip to content

Commit 4174ffe

Browse files
committed
feat: add option to subscribe to overlay status: overlay showing or overlay closed
1 parent 2857f75 commit 4174ffe

File tree

5 files changed

+69
-30
lines changed

5 files changed

+69
-30
lines changed
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
package flutter.overlay.window.flutter_overlay_window;
22

33
import androidx.annotation.Nullable;
4-
import io.flutter.plugin.common.BasicMessageChannel;
4+
import io.flutter.plugin.common.MethodChannel;
55

66
public abstract class CachedMessageChannels {
77
@Nullable
8-
public static BasicMessageChannel<Object> mainAppMessageChannel;
8+
public static MethodChannel mainAppMessageChannel;
99
@Nullable
10-
public static BasicMessageChannel<Object> overlayMessageChannel;
10+
public static MethodChannel overlayMessageChannel;
1111
}

android/src/main/java/flutter/overlay/window/flutter_overlay_window/FlutterOverlayWindowPlugin.java

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,7 @@
2121
import io.flutter.embedding.engine.plugins.FlutterPlugin;
2222
import io.flutter.embedding.engine.plugins.activity.ActivityAware;
2323
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding;
24-
import io.flutter.plugin.common.BasicMessageChannel;
25-
import io.flutter.plugin.common.JSONMessageCodec;
24+
import io.flutter.plugin.common.JSONMethodCodec;
2625
import io.flutter.plugin.common.MethodCall;
2726
import io.flutter.plugin.common.MethodChannel;
2827
import io.flutter.plugin.common.MethodChannel.MethodCallHandler;
@@ -165,37 +164,37 @@ private void registerMessageChannel(boolean isMainAppEngine) {
165164
private void unregisterMessageChannel(boolean isMainAppEngine) {
166165
if(isMainAppEngine) {
167166
if (CachedMessageChannels.mainAppMessageChannel == null) return;
168-
CachedMessageChannels.mainAppMessageChannel.setMessageHandler(null);
167+
CachedMessageChannels.mainAppMessageChannel.setMethodCallHandler(null);
169168
CachedMessageChannels.mainAppMessageChannel = null;
170169
} else {
171170
if(CachedMessageChannels.overlayMessageChannel == null) return;
172-
CachedMessageChannels.overlayMessageChannel.setMessageHandler(null);
171+
CachedMessageChannels.overlayMessageChannel.setMethodCallHandler(null);
173172
CachedMessageChannels.overlayMessageChannel = null;
174173
}
175174
}
176175

177176
private void registerOverlayMessageChannel(io.flutter.plugin.common.BinaryMessenger overlyEngineBinaryMessenger) {
178-
BasicMessageChannel<Object> overlayMessageChannel = new BasicMessageChannel<>(overlyEngineBinaryMessenger, OverlayConstants.MESSENGER_TAG, JSONMessageCodec.INSTANCE);
179-
overlayMessageChannel.setMessageHandler((message, reply) -> {
177+
MethodChannel overlayMessageChannel = new MethodChannel(overlyEngineBinaryMessenger, OverlayConstants.MESSENGER_TAG, JSONMethodCodec.INSTANCE);
178+
overlayMessageChannel.setMethodCallHandler((call, result) -> {
180179
if (CachedMessageChannels.mainAppMessageChannel == null) {
181-
reply.reply(false);
180+
result.success(false);
182181
return;
183182
}
184-
CachedMessageChannels.mainAppMessageChannel.send(message);
185-
reply.reply(true);
183+
CachedMessageChannels.mainAppMessageChannel.invokeMethod("message", call.arguments);
184+
result.success(true);
186185
});
187186
CachedMessageChannels.overlayMessageChannel = overlayMessageChannel;
188187
}
189188

190189
private void registerMainAppMessageChannel(io.flutter.plugin.common.BinaryMessenger mainAppEngineBinaryMessenger) {
191-
BasicMessageChannel<Object> mainAppMessageChannel = new BasicMessageChannel<>(mainAppEngineBinaryMessenger, OverlayConstants.MESSENGER_TAG, JSONMessageCodec.INSTANCE);
192-
mainAppMessageChannel.setMessageHandler((message, reply) -> {
190+
MethodChannel mainAppMessageChannel = new MethodChannel(mainAppEngineBinaryMessenger, OverlayConstants.MESSENGER_TAG, JSONMethodCodec.INSTANCE);
191+
mainAppMessageChannel.setMethodCallHandler((call, result) -> {
193192
if (CachedMessageChannels.overlayMessageChannel == null) {
194-
reply.reply(false);
193+
result.success(false);
195194
return;
196195
}
197-
CachedMessageChannels.overlayMessageChannel.send(message);
198-
reply.reply(true);
196+
CachedMessageChannels.overlayMessageChannel.invokeMethod("message", call.arguments);
197+
result.success(true);
199198
});
200199
CachedMessageChannels.mainAppMessageChannel = mainAppMessageChannel;
201200
}

android/src/main/java/flutter/overlay/window/flutter_overlay_window/OverlayService.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ public void onDestroy() {
8282
flutterView.detachFromFlutterEngine();
8383
flutterView = null;
8484
}
85+
OverlayStatusEmitter.emitIsShowing(false);
8586
NotificationManager notificationManager = (NotificationManager) getApplicationContext().getSystemService(Context.NOTIFICATION_SERVICE);
8687
notificationManager.cancel(OverlayConstants.NOTIFICATION_ID);
8788
}
@@ -153,6 +154,7 @@ public int onStartCommand(Intent intent, int flags, int startId) {
153154
params.gravity = WindowSetup.gravity;
154155
flutterView.setOnTouchListener(this);
155156
windowManager.addView(flutterView, params);
157+
OverlayStatusEmitter.emitIsShowing(true);
156158
return START_STICKY;
157159
}
158160

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package flutter.overlay.window.flutter_overlay_window;
2+
3+
public abstract class OverlayStatusEmitter {
4+
static private final String methodName = "isShowingOverlay";
5+
static private boolean lastEmittedStatus;
6+
static void emitIsShowing(boolean isShowing) {
7+
if(isShowing == lastEmittedStatus) return;
8+
lastEmittedStatus = isShowing;
9+
if(CachedMessageChannels.mainAppMessageChannel != null) {
10+
CachedMessageChannels.mainAppMessageChannel.invokeMethod(methodName, isShowing);
11+
}
12+
if(CachedMessageChannels.overlayMessageChannel != null) {
13+
CachedMessageChannels.overlayMessageChannel.invokeMethod(methodName, isShowing);
14+
}
15+
}
16+
}

lib/src/overlay_window.dart

Lines changed: 35 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,19 @@
11
import 'dart:async';
22
import 'dart:developer';
33

4-
import 'package:flutter/material.dart';
54
import 'package:flutter/services.dart';
65
import 'package:flutter_overlay_window/src/overlay_config.dart';
76

87
class FlutterOverlayWindow {
98
FlutterOverlayWindow._();
109

11-
static final StreamController _controller = StreamController.broadcast();
12-
static const MethodChannel _channel =
13-
MethodChannel("x-slayer/overlay_channel");
14-
static const MethodChannel _overlayChannel =
15-
MethodChannel("x-slayer/overlay");
16-
static const BasicMessageChannel _overlayMessageChannel =
17-
BasicMessageChannel("x-slayer/overlay_messenger", JSONMessageCodec());
10+
static final _controller = StreamController<dynamic>.broadcast();
11+
static final _controllerOverlayStatus = StreamController<bool>.broadcast();
12+
13+
static const _channel = MethodChannel("x-slayer/overlay_channel");
14+
static const _overlayChannel = MethodChannel("x-slayer/overlay");
15+
static const _overlayMessageChannel =
16+
MethodChannel("x-slayer/overlay_messenger", JSONMethodCodec());
1817

1918
/// Open overLay content
2019
///
@@ -93,19 +92,29 @@ class FlutterOverlayWindow {
9392
///
9493
/// Returns `true` if the [data] was sent successfully, otherwise `false`.
9594
static Future<bool> shareData(dynamic data) async {
96-
final isSent = await _overlayMessageChannel.send(data);
95+
final isSent = await _overlayMessageChannel.invokeMethod('', data);
9796
return isSent as bool;
9897
}
9998

10099
/// Streams message shared between overlay and main app
101100
static Stream<dynamic> get overlayListener {
102-
_overlayMessageChannel.setMessageHandler((message) async {
103-
_controller.add(message);
104-
return message;
105-
});
101+
_registerOverlayMessageHandler();
106102
return _controller.stream;
107103
}
108104

105+
/// Overlay status stream.
106+
///
107+
/// Emit `true` when overlay is showing, and `false` when overlay is closed.
108+
///
109+
/// Emit value only once for every state change.
110+
///
111+
/// Doesn't emit a change when the overlay is already showing and [showOverlay] is called,
112+
/// as in this case the overlay will almost immediately reopen.
113+
static Stream<bool> get overlayStatusListener {
114+
_registerOverlayMessageHandler();
115+
return _controllerOverlayStatus.stream;
116+
}
117+
109118
/// Update the overlay flag while the overlay in action
110119
static Future<bool?> updateFlag(OverlayFlag flag) async {
111120
final bool? _res = await _overlayChannel
@@ -131,6 +140,19 @@ class FlutterOverlayWindow {
131140
return _res ?? false;
132141
}
133142

143+
static void _registerOverlayMessageHandler() {
144+
_overlayMessageChannel.setMethodCallHandler((call) async {
145+
switch (call.method) {
146+
case 'isShowingOverlay':
147+
_controllerOverlayStatus.add(call.arguments as bool);
148+
break;
149+
case 'message':
150+
_controller.add(call.arguments);
151+
break;
152+
}
153+
});
154+
}
155+
134156
/// Dispose overlay stream.
135157
///
136158
/// Once disposed, only a complete restart of the application will re-initialize the listener.

0 commit comments

Comments
 (0)