100mslive / 100ms-flutter

Flutter Live Streaming, Video Conferencing SDK & Sample App
https://www.100ms.live/
MIT License
143 stars 73 forks source link

🐛 Screen Sharing status always false #1755

Closed AndreLiu1225 closed 7 months ago

AndreLiu1225 commented 7 months ago

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:

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 ```console ```

Flutter Doctor output

Doctor output ```console ```
github-actions[bot] commented 7 months ago

Hello! Thank you for filing an issue.

Please include relevant logs or detailed description for faster resolutions.

We really appreciate your contribution!

ygit commented 7 months ago

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.

AndreLiu1225 commented 7 months ago

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.

Hi there! Im so sorry! It's a typo, the version I;m using is 1.9.13

Decoder07 commented 7 months ago

@AndreLiu1225 are you able to see screenshare on the other end ?

AndreLiu1225 commented 7 months ago

Nope, the screen share is just not active. I'm guessing that the screenShareTrack is null

AndreLiu1225 commented 7 months ago

@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.

AndreLiu1225 commented 7 months ago

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!