Skip to content

Commit 4330b77

Browse files
committed
feat: add option to subscribe to overlay status: overlay showing or overlay closed
1 parent 489c313 commit 4330b77

File tree

5 files changed

+70
-30
lines changed

5 files changed

+70
-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
@@ -28,8 +28,7 @@
2828
import io.flutter.embedding.engine.plugins.FlutterPlugin;
2929
import io.flutter.embedding.engine.plugins.activity.ActivityAware;
3030
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding;
31-
import io.flutter.plugin.common.BasicMessageChannel;
32-
import io.flutter.plugin.common.JSONMessageCodec;
31+
import io.flutter.plugin.common.JSONMethodCodec;
3332
import io.flutter.plugin.common.MethodCall;
3433
import io.flutter.plugin.common.MethodChannel;
3534
import io.flutter.plugin.common.MethodChannel.MethodCallHandler;
@@ -187,37 +186,37 @@ private void registerMessageChannel(boolean isMainAppEngine) {
187186
private void unregisterMessageChannel(boolean isMainAppEngine) {
188187
if(isMainAppEngine) {
189188
if (CachedMessageChannels.mainAppMessageChannel == null) return;
190-
CachedMessageChannels.mainAppMessageChannel.setMessageHandler(null);
189+
CachedMessageChannels.mainAppMessageChannel.setMethodCallHandler(null);
191190
CachedMessageChannels.mainAppMessageChannel = null;
192191
} else {
193192
if(CachedMessageChannels.overlayMessageChannel == null) return;
194-
CachedMessageChannels.overlayMessageChannel.setMessageHandler(null);
193+
CachedMessageChannels.overlayMessageChannel.setMethodCallHandler(null);
195194
CachedMessageChannels.overlayMessageChannel = null;
196195
}
197196
}
198197

199198
private void registerOverlayMessageChannel(io.flutter.plugin.common.BinaryMessenger overlyEngineBinaryMessenger) {
200-
BasicMessageChannel<Object> overlayMessageChannel = new BasicMessageChannel<>(overlyEngineBinaryMessenger, OverlayConstants.MESSENGER_TAG, JSONMessageCodec.INSTANCE);
201-
overlayMessageChannel.setMessageHandler((message, reply) -> {
199+
MethodChannel overlayMessageChannel = new MethodChannel(overlyEngineBinaryMessenger, OverlayConstants.MESSENGER_TAG, JSONMethodCodec.INSTANCE);
200+
overlayMessageChannel.setMethodCallHandler((call, result) -> {
202201
if (CachedMessageChannels.mainAppMessageChannel == null) {
203-
reply.reply(false);
202+
result.success(false);
204203
return;
205204
}
206-
CachedMessageChannels.mainAppMessageChannel.send(message);
207-
reply.reply(true);
205+
CachedMessageChannels.mainAppMessageChannel.invokeMethod("message", call.arguments);
206+
result.success(true);
208207
});
209208
CachedMessageChannels.overlayMessageChannel = overlayMessageChannel;
210209
}
211210

212211
private void registerMainAppMessageChannel(io.flutter.plugin.common.BinaryMessenger mainAppEngineBinaryMessenger) {
213-
BasicMessageChannel<Object> mainAppMessageChannel = new BasicMessageChannel<>(mainAppEngineBinaryMessenger, OverlayConstants.MESSENGER_TAG, JSONMessageCodec.INSTANCE);
214-
mainAppMessageChannel.setMessageHandler((message, reply) -> {
212+
MethodChannel mainAppMessageChannel = new MethodChannel(mainAppEngineBinaryMessenger, OverlayConstants.MESSENGER_TAG, JSONMethodCodec.INSTANCE);
213+
mainAppMessageChannel.setMethodCallHandler((call, result) -> {
215214
if (CachedMessageChannels.overlayMessageChannel == null) {
216-
reply.reply(false);
215+
result.success(false);
217216
return;
218217
}
219-
CachedMessageChannels.overlayMessageChannel.send(message);
220-
reply.reply(true);
218+
CachedMessageChannels.overlayMessageChannel.invokeMethod("message", call.arguments);
219+
result.success(true);
221220
});
222221
CachedMessageChannels.mainAppMessageChannel = mainAppMessageChannel;
223222
}

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
@@ -85,6 +85,7 @@ public void onDestroy() {
8585
flutterView.detachFromFlutterEngine();
8686
flutterView = null;
8787
}
88+
OverlayStatusEmitter.emitIsShowing(false);
8889
NotificationManager notificationManager = (NotificationManager) getApplicationContext().getSystemService(Context.NOTIFICATION_SERVICE);
8990
notificationManager.cancel(OverlayConstants.NOTIFICATION_ID);
9091

@@ -168,6 +169,7 @@ public int onStartCommand(Intent intent, int flags, int startId) {
168169
flutterView.setOnTouchListener(this);
169170
windowManager.addView(flutterView, params);
170171
moveOverlay(dx, dy, null);
172+
OverlayStatusEmitter.emitIsShowing(true);
171173
return START_STICKY;
172174
}
173175

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
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+
7+
static void emitIsShowing(boolean isShowing) {
8+
if(isShowing == lastEmittedStatus) return;
9+
lastEmittedStatus = isShowing;
10+
if(CachedMessageChannels.mainAppMessageChannel != null) {
11+
CachedMessageChannels.mainAppMessageChannel.invokeMethod(methodName, isShowing);
12+
}
13+
if(CachedMessageChannels.overlayMessageChannel != null) {
14+
CachedMessageChannels.overlayMessageChannel.invokeMethod(methodName, isShowing);
15+
}
16+
}
17+
}

lib/src/overlay_window.dart

Lines changed: 35 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,20 @@
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/models/overlay_position.dart';
76
import 'package:flutter_overlay_window/src/overlay_config.dart';
87

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

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

2019
/// Open overLay content
2120
///
@@ -107,19 +106,29 @@ class FlutterOverlayWindow {
107106
///
108107
/// Returns `true` if the [data] was sent successfully, otherwise `false`.
109108
static Future<bool> shareData(dynamic data) async {
110-
final isSent = await _overlayMessageChannel.send(data);
109+
final isSent = await _overlayMessageChannel.invokeMethod('', data);
111110
return isSent as bool;
112111
}
113112

114113
/// Streams message shared between overlay and main app
115114
static Stream<dynamic> get overlayListener {
116-
_overlayMessageChannel.setMessageHandler((message) async {
117-
_controller.add(message);
118-
return message;
119-
});
115+
_registerOverlayMessageHandler();
120116
return _controller.stream;
121117
}
122118

119+
/// Overlay status stream.
120+
///
121+
/// Emit `true` when overlay is showing, and `false` when overlay is closed.
122+
///
123+
/// Emit value only once for every state change.
124+
///
125+
/// Doesn't emit a change when the overlay is already showing and [showOverlay] is called,
126+
/// as in this case the overlay will almost immediately reopen.
127+
static Stream<bool> get overlayStatusListener {
128+
_registerOverlayMessageHandler();
129+
return _controllerOverlayStatus.stream;
130+
}
131+
123132
/// Update the overlay flag while the overlay in action
124133
static Future<bool?> updateFlag(OverlayFlag flag) async {
125134
final bool? _res = await _overlayChannel
@@ -173,6 +182,19 @@ class FlutterOverlayWindow {
173182
return _res ?? false;
174183
}
175184

185+
static void _registerOverlayMessageHandler() {
186+
_overlayMessageChannel.setMethodCallHandler((call) async {
187+
switch (call.method) {
188+
case 'isShowingOverlay':
189+
_controllerOverlayStatus.add(call.arguments as bool);
190+
break;
191+
case 'message':
192+
_controller.add(call.arguments);
193+
break;
194+
}
195+
});
196+
}
197+
176198
/// Dispose overlay stream.
177199
///
178200
/// Once disposed, only a complete restart of the application will re-initialize the listener.

0 commit comments

Comments
 (0)