๐ Screen Sharing status always false
AndreLiu1225 opened this issue ยท 7 comments
Description
Hello! I am unable to display a screen share on my Iphone (not simulator) that I am using for debugging. isScreenShareActive() always returns false and a screen share tile does not show.
Following the steps in this documentation https://www.100ms.live/docs/flutter/v2/how-to-guides/set-up-video-conferencing/screen-share#how-to-startstop-screenshare-from-the-app. I have done the following:
- Implemented startScreenShare() and stopScreenShare() override methods
- Added in switch cases in onSucces(), onTrackUpdate, and onException() for screenSharing
100ms Flutter Version
1.9.13
Steps to reproduce
Run Debug Mode in main.dart
Press Join Button
Press ScreenShare button
Expected results
I expected a screen sharing tile to pop up and the screen sharing button color to change to green.
Code example, screenshot, or link to a repository
meetingPage.dart
import 'package:flutter/material.dart';
import 'package:hmssdk_flutter/hmssdk_flutter.dart';
import 'package:translator/pages/homePage.dart';
import 'package:translator/widgets/peerTileWidget.dart';
class MeetingPage extends StatefulWidget {
const MeetingPage({super.key});
@override
State<MeetingPage> createState() => _MeetingPageState();
}
class _MeetingPageState extends State<MeetingPage>
implements HMSUpdateListener, HMSActionResultListener {
//SDK
late HMSSDK hmsSDK;
// Variables required for joining a room
String authToken =
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ2ZXJzaW9uIjoyLCJ0eXBlIjoiYXBwIiwiYXBwX2RhdGEiOm51bGwsImFjY2Vzc19rZXkiOiI2NjA3YTcwOGJhYmMzM2YwMGU0YWI4OTIiLCJyb2xlIjoiaG9zdCIsInJvb21faWQiOiI2NjA3YTcxZmNiMWIxZjA2M2FjZmMwYmQiLCJ1c2VyX2lkIjoiZGQ3ZDA0MmEtNzRiOC00MThkLTg1NzktNmEyMDBiZDc2NGM1IiwiZXhwIjoxNzExODkzOTIwLCJqdGkiOiJmZDFiMTkyNC05NjQ3LTRlMTEtYTlhMi04ZmZiZjFlOTliMmMiLCJpYXQiOjE3MTE4MDc1MjAsImlzcyI6IjY2MDdhNzA4YmFiYzMzZjAwZTRhYjg5MCIsIm5iZiI6MTcxMTgwNzUyMCwic3ViIjoiYXBpIn0.hvEpCMJLXGBfPRRWtQlLrrX553ulDL1GwsOi-udD4XU";
String userName = "test_user";
// Variables required for rendering video and peer info
HMSPeer? localPeer, remotePeer;
HMSVideoTrack? localPeerVideoTrack,
remotePeerVideoTrack,
localScreenShareTrack,
remoteScreenShareTrack;
// Pass the correct App Group & Preferred Extension Parameters in HMSScreenShareConfig class for screen share on IOS devices
HMSIOSScreenshareConfig iOSScreenshareConfig = HMSIOSScreenshareConfig(
appGroup: "group.com.example.translator",
preferredExtension: "flutterBroadCast");
// Screen sharing bool
bool isScreenSharing = false;
@override
void initState() {
super.initState();
initHMSSDK();
}
void initHMSSDK() async {
hmsSDK = HMSSDK(iOSScreenshareConfig: iOSScreenshareConfig);
await hmsSDK.build();
hmsSDK.addUpdateListener(listener: this);
hmsSDK.join(config: HMSConfig(authToken: authToken, userName: userName));
checkScreenShareStatus();
}
@override
void dispose() {
remotePeer = null;
remotePeerVideoTrack = null;
localPeer = null;
localPeerVideoTrack = null;
localScreenShareTrack = null;
remoteScreenShareTrack = null;
super.dispose();
}
// Called when peer joined the room - get current state of room by using HMSRoom obj
@override
void onJoin({required HMSRoom room}) {
room.peers?.forEach((peer) {
if (peer.isLocal) {
localPeer = peer;
if (peer.videoTrack != null) {
localPeerVideoTrack = peer.videoTrack;
}
if (mounted) {
setState(() {});
}
}
});
}
// Called when there's a peer update - use to update local & remote peer variables
@override
void onPeerUpdate({required HMSPeer peer, required HMSPeerUpdate update}) {
switch (update) {
case HMSPeerUpdate.peerJoined:
if (!peer.isLocal) {
if (mounted) {
setState(() {
remotePeer = peer;
});
}
}
break;
case HMSPeerUpdate.peerLeft:
if (!peer.isLocal) {
if (mounted) {
setState(() {
remotePeer = null;
});
}
}
break;
case HMSPeerUpdate.networkQualityUpdated:
return;
default:
if (mounted) {
setState(() {
localPeer = null;
});
}
}
}
// Called when there's a track update - use to update local & remtoe track variable
@override
void onTrackUpdate(
{required HMSTrack track,
required HMSTrackUpdate trackUpdate,
required HMSPeer peer}) {
if (track.kind == HMSTrackKind.kHMSTrackKindVideo) {
switch (trackUpdate) {
case HMSTrackUpdate.trackRemoved:
if (mounted) {
setState(() {
peer.isLocal
? localPeerVideoTrack = null
: remotePeerVideoTrack = null;
});
}
return;
default:
if (mounted) {
setState(() {
peer.isLocal
? localPeerVideoTrack = track as HMSVideoTrack
: remotePeerVideoTrack = track as HMSVideoTrack;
});
}
}
}
if (track.source == "SCREEN") {
switch (trackUpdate) {
case HMSTrackUpdate.trackAdded:
if (mounted) {
setState(() {
peer.isLocal
? localScreenShareTrack = track as HMSVideoTrack
: remoteScreenShareTrack = track as HMSVideoTrack;
isScreenSharing = true;
});
}
break;
case HMSTrackUpdate.trackRemoved:
if (mounted) {
setState(() {
peer.isLocal
? localScreenShareTrack = null
: remoteScreenShareTrack = null;
isScreenSharing = false;
});
}
break;
default:
break;
}
}
}
// More callbacks - no need to implement for quickstart
@override
void onAudioDeviceChanged(
{HMSAudioDevice? currentAudioDevice,
List<HMSAudioDevice>? availableAudioDevice}) {}
@override
void onSessionStoreAvailable({HMSSessionStore? hmsSessionStore}) {}
@override
void onChangeTrackStateRequest(
{required HMSTrackChangeRequest hmsTrackChangeRequest}) {}
@override
void onHMSError({required HMSException error}) {}
@override
void onMessage({required HMSMessage message}) {}
@override
void onReconnected() {}
@override
void onReconnecting() {}
@override
void onRemovedFromRoom(
{required HMSPeerRemovedFromPeer hmsPeerRemovedFromPeer}) {}
@override
void onRoleChangeRequest({required HMSRoleChangeRequest roleChangeRequest}) {}
@override
void onRoomUpdate({required HMSRoom room, required HMSRoomUpdate update}) {}
@override
void onUpdateSpeakers({required List<HMSSpeaker> updateSpeakers}) {}
@override
void onPeerListUpdate(
{required List<HMSPeer> addedPeers,
required List<HMSPeer> removedPeers}) {
// TODO: implement onPeerListUpdate
}
/*----------------------------Screen Sharing Implementation-----------------------------*/
void checkScreenShareStatus() {
hmsSDK.isScreenShareActive().then((screenShareStatus) {
print("Screen sharing status: $screenShareStatus");
});
}
void startScreenShare() {
///[hmsActionResultListener]: an instance of a class that implements HMSActionResultListener
//Here this is an instance of a class that implements HMSActionResultListener, that is, Meeting
hmsSDK.startScreenShare(hmsActionResultListener: this);
checkScreenShareStatus();
}
void stopScreenShare() {
///[hmsActionResultListener]: an instance of a class that implements HMSActionResultListener
//Here this is an instance of a class that implements HMSActionResultListener, that is, Meeting
hmsSDK.stopScreenShare(hmsActionResultListener: this);
checkScreenShareStatus();
}
@override
void onSuccess(
{HMSActionResultListenerMethod methodType =
HMSActionResultListenerMethod.unknown,
Map<String, dynamic>? arguments}) {
switch (methodType) {
case HMSActionResultListenerMethod.startScreenShare:
//Screen share started successfully
isScreenSharing = true;
break;
case HMSActionResultListenerMethod.stopScreenShare:
//Screen share stopped successfully
isScreenSharing = false;
break;
case HMSActionResultListenerMethod.leave:
return;
default:
break;
}
}
@override
void onException(
{HMSActionResultListenerMethod methodType =
HMSActionResultListenerMethod.unknown,
Map<String, dynamic>? arguments,
required HMSException hmsException}) {
switch (methodType) {
case HMSActionResultListenerMethod.startScreenShare:
// Check the HMSException object for details about the error
break;
case HMSActionResultListenerMethod.stopScreenShare:
// Check the HMSException object for details about the error
break;
case HMSActionResultListenerMethod.leave:
return;
default:
break;
}
}
@override
Widget build(BuildContext context) {
return PopScope(
canPop: true,
onPopInvoked: (didPop) async {
hmsSDK.leave();
WidgetsBinding.instance.addPostFrameCallback((_) {
Navigator.pushReplacement(
context, MaterialPageRoute(builder: (_) => HomePage()));
});
},
child: SafeArea(
child: Scaffold(
backgroundColor: Colors.black,
body: Stack(
children: [
// Grid of peer tiles
Container(
height: MediaQuery.of(context).size.height,
child: GridView(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
mainAxisExtent: (remotePeerVideoTrack == null)
? MediaQuery.of(context).size.height
: MediaQuery.of(context).size.height / 2,
crossAxisCount: 1),
children: [
if (remotePeerVideoTrack != null && remotePeer != null)
peerTile(
Key(remotePeerVideoTrack?.trackId ?? "" "mainVideo"),
remotePeerVideoTrack,
remoteScreenShareTrack,
remotePeer),
peerTile(
Key(localPeerVideoTrack?.trackId ?? "" "mainVideo"),
localPeerVideoTrack,
localScreenShareTrack,
localPeer),
],
),
),
// End button to leave the room
Align(
alignment: Alignment.bottomCenter,
child: RawMaterialButton(
onPressed: () {
hmsSDK.leave();
Navigator.pop(context);
},
elevation: 2.0,
fillColor: Colors.red,
padding: const EdgeInsets.all(15.0),
shape: const CircleBorder(),
child: const Icon(
Icons.call_end,
size: 25.0,
color: Colors.white,
),
),
),
// End button to leave the room
Align(
alignment: Alignment.bottomRight,
child: RawMaterialButton(
onPressed: () {
if (!isScreenSharing) {
startScreenShare();
} else {
stopScreenShare();
}
},
elevation: 2.0,
fillColor: isScreenSharing ? Colors.green : Colors.grey[850],
padding: const EdgeInsets.all(15.0),
shape: const CircleBorder(),
child: const Icon(
Icons.screen_share_outlined,
size: 25.0,
color: Colors.white,
),
),
),
],
),
),
),
);
}
}
peerTileWidget.dart
import 'package:flutter/material.dart';
import 'package:hmssdk_flutter/hmssdk_flutter.dart';
Widget peerTile(Key key, HMSVideoTrack? regularVideoTrack,
HMSVideoTrack? screenShareTrack, HMSPeer? peer) {
return Container(
key: key,
child: (screenShareTrack != null)
? HMSVideoView(
track: screenShareTrack,
scaleType: ScaleType.SCALE_ASPECT_FIT,
key: key,
)
: (regularVideoTrack != null && !(regularVideoTrack.isMute))
? HMSVideoView(
track: regularVideoTrack,
scaleType: ScaleType.SCALE_ASPECT_FILL,
key: key,
)
: Center(
child: Container(
decoration: BoxDecoration(
color: Colors.blue.withAlpha(4),
shape: BoxShape.circle,
boxShadow: const [
BoxShadow(
color: Colors.blue,
blurRadius: 20.0,
spreadRadius: 5.0,
),
],
),
child: Text(
peer?.name.substring(0, 1) ?? "Translate",
style: const TextStyle(
fontFamily: "Sans-serif",
color: Colors.white,
fontSize: 24,
fontWeight: FontWeight.w600,
),
),
),
),
);
}
Logs
Logs
<!-- Paste your logs here -->
Flutter Doctor output
Doctor output
<!-- Paste your output here -->
Hello! Thank you for filing an issue.
Please include relevant logs or detailed description for faster resolutions.
We really appreciate your contribution!
hey @AndreLiu1225
Can you try reproducing this on the latest version of hmssdk_flutter
which is 1.9.14
?
The version you mentioned - 1.0.0
is very old.
hey @AndreLiu1225 Can you try reproducing this on the latest version of
hmssdk_flutter
which is1.9.14
? The version you mentioned -1.0.0
is very old.
Hi there! Im so sorry! It's a typo, the version I;m using is 1.9.13
@AndreLiu1225 are you able to see screenshare on the other end ?
Nope, the screen share is just not active. I'm guessing that the screenShareTrack is null
@AndreLiu1225 are you able to see screenshare on the other end ?
If I'm not wrong upon pressing the screen sharing button, a screen broadcast pop up would appear and u could choose the app's broadcast extension, but nothing pops up.
Upon closer inspection, I realised the auth token was updated and that I was using an outdated one. @ygit @Decoder07 Thank u so much for ur time!