Skip to content

Commit 1a595d2

Browse files
committed
Merge branch 'main' into chore/sync_1.2.0
# Conflicts: # CHANGELOG.md # common/darwin/Classes/FlutterWebRTCPlugin.m # ios/stream_webrtc_flutter.podspec # lib/src/native/factory_impl.dart # macos/stream_webrtc_flutter.podspec # pubspec.yaml
2 parents cfb7e55 + 8002e09 commit 1a595d2

File tree

7 files changed

+48
-14
lines changed

7 files changed

+48
-14
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@
2020
* [Apple/Android] Local recording API for Darwin and Android (#1880)
2121
* [Apple/Android] Data Packet Cryptor Support.
2222

23+
[1.0.13] - 2025-10-28
24+
* Exposed `eventStream` in `MediaDevices`.
25+
* [Android] Sends event when screen capture ends.
26+
2327
[1.0.12] - 2025-09-30
2428
* [Android] Changed the configuration used when creating EGL rendering context to one that supports alpha channel to fix an issue with Impeller blending background with video texture on some devices.
2529
* [Android] Migrate from onSurfaceDestroyed to onSurfaceCleanup for SurfaceProducer.Callback.

android/src/main/java/io/getstream/webrtc/flutter/GetUserMediaImpl.java

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ public class GetUserMediaImpl {
9696
private static final int DEFAULT_HEIGHT = 720;
9797
private static final int DEFAULT_FPS = 30;
9898

99+
private static final String EVENT_DISPLAY_MEDIA_STOPPED = "screenSharingStopped";
99100
private static final String PERMISSION_AUDIO = Manifest.permission.RECORD_AUDIO;
100101
private static final String PERMISSION_VIDEO = Manifest.permission.CAMERA;
101102
private static final String PERMISSION_SCREEN = "android.permission.MediaProjection";
@@ -518,19 +519,24 @@ private void getDisplayMedia(final Result result, final MediaStream mediaStream,
518519
/* Create ScreenCapture */
519520
VideoTrack displayTrack = null;
520521
VideoCapturer videoCapturer = null;
521-
videoCapturer =
522-
new OrientationAwareScreenCapturer(
523-
applicationContext,
524-
mediaProjectionData,
525-
new MediaProjection.Callback() {
526-
@Override
527-
public void onStop() {
528-
super.onStop();
529-
// After Huawei P30 and Android 10 version test, the onstop method is called, which will not affect the next process,
530-
// and there is no need to call the resulterror method
531-
//resultError("MediaProjection.Callback()", "User revoked permission to capture the screen.", result);
532-
}
533-
});
522+
String trackId = stateProvider.getNextTrackUUID();
523+
524+
videoCapturer = new OrientationAwareScreenCapturer(
525+
applicationContext,
526+
mediaProjectionData,
527+
new MediaProjection.Callback() {
528+
@Override
529+
public void onStop() {
530+
super.onStop();
531+
532+
ConstraintsMap params = new ConstraintsMap();
533+
params.putString("event", EVENT_DISPLAY_MEDIA_STOPPED);
534+
params.putString("trackId", trackId);
535+
FlutterWebRTCPlugin.sharedSingleton.sendEvent(params.toMap());
536+
}
537+
}
538+
);
539+
534540
if (videoCapturer == null) {
535541
resultError("screenRequestPermissions", "GetDisplayMediaFailed, User revoked permission to capture the screen.", result);
536542
return;
@@ -562,7 +568,6 @@ public void onStop() {
562568
videoCapturer.startCapture(info.width, info.height, info.fps);
563569
Log.d(TAG, "OrientationAwareScreenCapturer.startCapture: " + info.width + "x" + info.height + "@" + info.fps);
564570

565-
String trackId = stateProvider.getNextTrackUUID();
566571
mVideoCapturers.put(trackId, info);
567572
mVideoSources.put(trackId, videoSource);
568573

common/darwin/Classes/FlutterWebRTCPlugin.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,8 @@ typedef void (^CapturerStopHandler)(CompletionHandler _Nonnull handler);
105105
- (RTCRtpSender* _Nullable)getRtpSenderById:(RTCPeerConnection* _Nonnull)peerConnection
106106
Id:(NSString* _Nonnull)Id;
107107

108+
- (void)postEventWithName:(NSString* _Nonnull)eventName data:(NSDictionary* _Nullable)data;
109+
108110
+ (FlutterWebRTCPlugin* _Nullable)sharedSingleton;
109111

110112
@end

common/darwin/Classes/FlutterWebRTCPlugin.m

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2618,6 +2618,21 @@ - (FlutterRTCVideoRenderer*)findRendererByTrackId:(NSString*)trackId {
26182618
return nil;
26192619
}
26202620

2621+
#pragma mark - Event Posting Helper
2622+
2623+
- (void)postEventWithName:(NSString*)eventName data:(NSDictionary*)data {
2624+
if (!self.eventSink) {
2625+
return;
2626+
}
2627+
2628+
NSMutableDictionary* eventData = [NSMutableDictionary dictionaryWithObject:eventName forKey:@"event"];
2629+
if (data) {
2630+
[eventData addEntriesFromDictionary:data];
2631+
}
2632+
2633+
postEvent(self.eventSink, eventData);
2634+
}
2635+
26212636
#pragma mark - RTCAudioDeviceModuleDelegate methods
26222637

26232638
- (void)audioDeviceModuleDidUpdateDevices:(RTCAudioDeviceModule*)audioDeviceModule {

lib/src/native/factory_impl.dart

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,5 +189,8 @@ MediaDevices get mediaDevices => MediaDeviceNative.instance;
189189

190190
FrameCryptorFactory get frameCryptorFactory => FrameCryptorFactoryImpl.instance;
191191

192+
Stream<Map<String, dynamic>> get eventStream =>
193+
MediaDeviceNative.instance.eventStream;
194+
192195
DataPacketCryptorFactory get dataPacketCryptorFactory =>
193196
DataPacketCryptorFactoryImpl.instance;

lib/src/native/mediadevices_impl.dart

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@ class MediaDeviceNative extends MediaDevices {
1919

2020
static final MediaDeviceNative instance = MediaDeviceNative._internal();
2121

22+
Stream<Map<String, dynamic>> get eventStream =>
23+
FlutterWebRTCEventChannel.instance.handleEvents.stream;
24+
2225
void handleEvent(String event, final Map<dynamic, dynamic> map) async {
2326
switch (map['event']) {
2427
case 'onDeviceChange':

lib/src/web/factory_impl.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,5 @@ Future<void> handleCallInterruptionCallbacks(
2222
throw UnimplementedError(
2323
'handleCallInterruptionCallbacks() is not supported on web');
2424
}
25+
26+
Stream<Map<String, dynamic>> get eventStream => Stream.empty();

0 commit comments

Comments
 (0)