How to Implement Screen Share in Flutter Video Call App for Android?
Tags: flutter, dart
Published: 2024-04-24 06:29:57

---
title: How to Implement Screen Share in Flutter Video Call App for Android?
published: true
date: 2024-04-23 09:08:45 UTC
tags: flutter, dart
canonical_url: https://www.videosdk.live/blog/implement-screen-share-flutter-video-call-app-for-android
---

## 📌 Introduction
 ![How to Implement Screen Share in Flutter Video Call App for Android?](https://assets.videosdk.live/static-assets/ghost/2024/04/Screen-Share--Flutter-Android.png)

Implement Screen Share functionality into your [Flutter video call app for Android](https://www.videosdk.live/blog/video-calling-in-flutter) to enhance user experience and collaboration. With Screen Share, users can seamlessly share their device screens during video calls, making it easier to present documents, slideshows, or demonstrate apps. By integrating this feature, your app becomes a versatile tool for remote work, online learning, and virtual meetings. With Flutter's flexibility and powerful capabilities, you can quickly develop and deploy this feature, keeping your app at the forefront of modern communication technology.

**Benefits of implementing Screen Share in your Flutter video call app for Android:**

1. **Enhanced Collaboration** : Users can collaborate effectively by sharing their screens, allowing for real-time discussions and feedback.
2. **Efficient Communication** : Screen Share enables clearer communication by visually demonstrating ideas, documents, or presentations.
3. **Remote Work Facilitation** : Facilitates remote work by enabling virtual meetings where team members can share progress, review documents, and provide guidance.
4. **Technical Support** : Users can share their screens to seek technical assistance, allowing support staff to diagnose issues or guide troubleshooting steps more efficiently.
5. **Ease of Use** : The intuitive user interface makes it easy for users to initiate screen sharing, enhancing user experience.

**Use Cases Screen Share in your Flutter video call app:**

1. **Online Meetings** : Participants can share their screens to discuss reports, and presentations, or collaborate on projects.
2. **Remote Training** : Trainers can demonstrate software usage or guide trainees through processes by sharing their screens.
3. **Virtual Classrooms** : Educators can share educational content, conduct lectures, or provide one-on-one assistance to students.
4. **Software Demos** : Developers or product managers can provide software demonstrations to stakeholders or users.
5. **Collaborative Editing** : Users can collectively edit documents or work on projects by sharing their screens.

Elevate your app's capabilities and provide users with a truly immersive and productive video calling experience with screen sharing with VideoSDK.

## 🚀 Getting Started with VideoSDK

To take advantage of Screen Share, we must use the capabilities that the VideoSDK offers. Before diving into the implementation steps, let's ensure you complete the necessary prerequisites.

### Create a VideoSDK Account

Go to your [VideoSDK dashboard](https://www.videosdk.live/signup?utm_source=organicseo&utm_medium=devto&utm_campaign=screenshare_flutter_android) and sign up if you don't have an account. This account gives you access to the required Video SDK token, which acts as an authentication key that allows your application to interact with VideoSDK functionality.

### Generate your Auth Token

Visit your VideoSDK dashboard and navigate to the "API Key" section to generate your auth token. This token is crucial in authorizing your application to use VideoSDK features.

For a more visual understanding of the account creation and token generation process, consider referring to the [provided tutorial](https://docs.videosdk.live/flutter/guide/video-and-audio-calling-api-sdk/authentication-and-tokens#1-generating-token-from-dashboard).

### Prerequisites[​](https://docs.videosdk.live/flutter/guide/video-and-audio-calling-api-sdk/quick-start#prerequisites)

Before proceeding, ensure that your development environment meets the following requirements:

- Video SDK Developer Account (if you do not have one, follow [**VideoSDK Dashboard**](https://www.videosdk.live/signup?utm_source=organicseo&utm_medium=devto&utm_campaign=screenshare_flutter_android)
- The basic understanding of Flutter.
- **[Flutter VideoSDK](https://pub.dev/packages/videosdk)**
- Have Flutter installed on your device.

## 🛠️ Install Video SDK[​](https://docs.videosdk.live/flutter/guide/video-and-audio-calling-api-sdk/quick-start#install-video-sdk)

Install the VideoSDK using the below-mentioned flutter command. Make sure you are in your Flutter app directory before you run this command.

```dart
$ flutter pub add videosdk

//run this command to add http library to perform network call to generate roomId
$ flutter pub add http
```

### VideoSDK Compatibility
<!--kg-card-begin: html-->

| Android and iOS app | Web | Desktop app | Safari browser |
| --- | --- | --- | --- |
| <center> ✅ </center> | <center> ✅ </center> | <center> ✅ </center> | <center> ❌ </center> |

<!--kg-card-end: html-->
### Structure of the project[​](https://docs.videosdk.live/flutter/guide/video-and-audio-calling-api-sdk/quick-start#structure-of-the-project)

Your project structure should look like this.

```dart
    root
    ├── android
    ├── ios
    ├── lib
         ├── api_call.dart
         ├── join_screen.dart
         ├── main.dart
         ├── meeting_controls.dart
         ├── meeting_screen.dart
         ├── participant_tile.dart
```

We are going to create flutter widgets (JoinScreen, MeetingScreen, MeetingControls, and ParticipantTile).

### App Structure[​](https://docs.videosdk.live/flutter/guide/video-and-audio-calling-api-sdk/quick-start#app-structure)

The app widget will contain `JoinScreen` and `MeetingScreen` widget. `MeetingScreen` will have `MeetingControls` and `ParticipantTile` widget.

![How to Implement Screen Share in Flutter Video Call App for Android?](https://cdn.videosdk.live/website-resources/docs-resources/flutter_quick_start_arch.png)

### Configure Project

####   
For Android[​](https://docs.videosdk.live/flutter/guide/video-and-audio-calling-api-sdk/quick-start#for-android)

- Update `/android/app/src/main/AndroidManifest.xml` for the permissions we will be using to implement the audio and video features.

```dart
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<uses-permission android:name="android.permission.WAKE_LOCK" />
```

_AndroidManifest.xml_

- Also, you will need to set your build settings to Java 8 because the official WebRTC jar now uses static methods in `EglBase` an interface. Just add this to your app-level `/android/app/build.gradle`.

```dart
android {
    //...
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
}
```

- If necessary, in the same `build.gradle` you will need to increase `minSdkVersion` of `defaultConfig` up to `23` (currently default Flutter generator set to `16`).
- If necessary, in the same `build.gradle` you will need to increase `compileSdkVersion` and `targetSdkVersion` up to `33` (currently, the default Flutter generator set to `30`).

## 🎥 Essential Steps to Implement Video Calling Functionality

Before diving into the specifics of screen sharing implementation, it's crucial to ensure you have videoSDK properly installed and configured within your Flutter project. Refer to [VideoSDK's documentation](https://docs.videosdk.live/flutter/guide/video-and-audio-calling-api-sdk/quick-start) for detailed installation instructions. Once you have a functional video calling setup, you can proceed with adding the screen-sharing feature.

### Step 1: Get started with `api_call.dart`[​](https://docs.videosdk.live/flutter/guide/video-and-audio-calling-api-sdk/quick-start#step-1-get-started-with-api_calldart)

Before jumping to anything else, you will write a function to generate a unique meetingId. You will require an authentication token, you can generate it either by using [videosdk-rtc-api-server-examples](https://github.com/videosdk-live/videosdk-rtc-api-server-examples) or by generating it from the [VideoSDK Dashboard](https://app.videosdk.live/api-keys) for development.

```dart
import 'dart:convert';
import 'package:http/http.dart' as http;

//Auth token we will use to generate a meeting and connect to it
String token = "<Generated-from-dashboard>";

// API call to create meeting
Future<String> createMeeting() async {
  final http.Response httpResponse = await http.post(
    Uri.parse("https://api.videosdk.live/v2/rooms"),
    headers: {'Authorization': token},
  );

//Destructuring the roomId from the response
  return json.decode(httpResponse.body)['roomId'];
}
```

_api_call.dart_

### Step 2: Creating the JoinScreen[​](https://docs.videosdk.live/flutter/guide/video-and-audio-calling-api-sdk/quick-start#step-2--creating-the-joinscreen)

Let's create `join_screen.dart` file in `lib` directory and create JoinScreen `StatelessWidget`.

The JoinScreen will consist of:

- **Create Meeting Button** : This button will create a new meeting for you.
- **Meeting ID TextField** : This text field will contain the meeting ID, you want to join.
- **Join Meeting Button** : This button will join the meeting, which you have provided.

```dart
import 'package:flutter/material.dart';
import 'api_call.dart';
import 'meeting_screen.dart';

class JoinScreen extends StatelessWidget {
  final _meetingIdController = TextEditingController();

  JoinScreen({super.key});

  void onCreateButtonPressed(BuildContext context) async {
    // call api to create meeting and then navigate to MeetingScreen with meetingId,token
    await createMeeting().then((meetingId) {
      if (!context.mounted) return;
      Navigator.of(context).push(
        MaterialPageRoute(
          builder: (context) => MeetingScreen(
            meetingId: meetingId,
            token: token,
          ),
        ),
      );
    });
  }

  void onJoinButtonPressed(BuildContext context) {
    String meetingId = _meetingIdController.text;
    var re = RegExp("\\w{4}\\-\\w{4}\\-\\w{4}");
    // check meeting id is not null or invaild
    // if meeting id is vaild then navigate to MeetingScreen with meetingId,token
    if (meetingId.isNotEmpty && re.hasMatch(meetingId)) {
      _meetingIdController.clear();
      Navigator.of(context).push(
        MaterialPageRoute(
          builder: (context) => MeetingScreen(
            meetingId: meetingId,
            token: token,
          ),
        ),
      );
    } else {
      ScaffoldMessenger.of(context).showSnackBar(const SnackBar(
        content: Text("Please enter valid meeting id"),
      ));
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('VideoSDK QuickStart'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(12.0),
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            ElevatedButton(
              onPressed: () => onCreateButtonPressed(context),
              child: const Text('Create Meeting'),
            ),
            Container(
              margin: const EdgeInsets.fromLTRB(0, 8.0, 0, 8.0),
              child: TextField(
                decoration: const InputDecoration(
                  hintText: 'Meeting Id',
                  border: OutlineInputBorder(),
                ),
                controller: _meetingIdController,
              ),
            ),
            ElevatedButton(
              onPressed: () => onJoinButtonPressed(context),
              child: const Text('Join Meeting'),
            ),
          ],
        ),
      ),
    );
  }
}
```

_join_screen.dart_

- Update the home screen of the app in the `main.dart`

```dart
import 'package:flutter/material.dart';
import 'join_screen.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'VideoSDK QuickStart',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: JoinScreen(),
    );
  }
}
```

_main.dart_

### Step 3: Creating the MeetingControls[​](https://docs.videosdk.live/flutter/guide/video-and-audio-calling-api-sdk/quick-start#step-3--creating-the-meetingcontrols)

Let's create `meeting_controls.dart` file and create MeetingControls `StatelessWidget`.

The MeetingControls will consist of:

- **Leave Button** : This button will leave the meeting.
- **Toggle Mic Button** : This button will unmute or mute the mic.
- **Toggle Camera Button** : This button will enable or disable the camera.

MeetingControls will accept 3 functions in the constructor

- **onLeaveButtonPressed** : invoked when the Leave button pressed
- **onToggleMicButtonPressed** : invoked when the toggle mic button pressed
- **onToggleCameraButtonPressed** : invoked when the toggle Camera button pressed

```dart
import 'package:flutter/material.dart';

class MeetingControls extends StatelessWidget {
  final void Function() onToggleMicButtonPressed;
  final void Function() onToggleCameraButtonPressed;
  final void Function() onLeaveButtonPressed;

  const MeetingControls(
      {super.key,
      required this.onToggleMicButtonPressed,
      required this.onToggleCameraButtonPressed,
      required this.onLeaveButtonPressed});

  @override
  Widget build(BuildContext context) {
    return Row(
      mainAxisAlignment: MainAxisAlignment.spaceEvenly,
      children: [
        ElevatedButton(
            onPressed: onLeaveButtonPressed, child: const Text('Leave')),
        ElevatedButton(
            onPressed: onToggleMicButtonPressed, child: const Text('Toggle Mic')),
        ElevatedButton(
            onPressed: onToggleCameraButtonPressed,
            child: const Text('Toggle WebCam')),
      ],
    );
  }
}
```

_meeting_controls.dart_

### Step 4: Creating ParticipantTile[​](https://docs.videosdk.live/flutter/guide/video-and-audio-calling-api-sdk/quick-start#step-4--creating-participanttile)

Let's create `participant_tile.dart` file and create ParticipantTile `StatefulWidget`.

The ParticipantTile will consist of:

- **RTCVideoView** : This will show the participant's video stream.

ParticipantTile will accept `Participant` in constructor

- **participant:** participant of the meeting.

```dart
import 'package:flutter/material.dart';
import 'package:videosdk/videosdk.dart';

class ParticipantTile extends StatefulWidget {
  final Participant participant;
  const ParticipantTile({super.key, required this.participant});

  @override
  State<ParticipantTile> createState() => _ParticipantTileState();
}

class _ParticipantTileState extends State<ParticipantTile> {
  Stream? videoStream;

  @override
  void initState() {
    // initial video stream for the participant
    widget.participant.streams.forEach((key, Stream stream) {
      setState(() {
        if (stream.kind == 'video') {
          videoStream = stream;
        }
      });
    });
    _initStreamListeners();
    super.initState();
  }

  _initStreamListeners() {
    widget.participant.on(Events.streamEnabled, (Stream stream) {
      if (stream.kind == 'video') {
        setState(() => videoStream = stream);
      }
    });

    widget.participant.on(Events.streamDisabled, (Stream stream) {
      if (stream.kind == 'video') {
        setState(() => videoStream = null);
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.all(8.0),
      child: videoStream != null
          ? RTCVideoView(
              videoStream?.renderer as RTCVideoRenderer,
              objectFit: RTCVideoViewObjectFit.RTCVideoViewObjectFitCover,
            )
          : Container(
              color: Colors.grey.shade800,
              child: const Center(
                child: Icon(
                  Icons.person,
                  size: 100,
                ),
              ),
            ),
    );
  }
}
```

_participant_tile.dart_

### Step 5: Creating the MeetingScreen[​](https://docs.videosdk.live/flutter/guide/video-and-audio-calling-api-sdk/quick-start#step-5--creating-the-meetingscreen)

Let's create `meeting_screen.dart` file and create MeetingScreen `StatefulWidget`.

MeetingScreen will accept meetingId and token in the constructor.

- **meetingID:** meetingId, you want to join
- **token** : VideoSDK Auth token.

```dart
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:videosdk/videosdk.dart';
import './participant_tile.dart';

class MeetingScreen extends StatefulWidget {
  final String meetingId;
  final String token;

  const MeetingScreen(
      {super.key, required this.meetingId, required this.token});

  @override
  State<MeetingScreen> createState() => _MeetingScreenState();
}

class _MeetingScreenState extends State<MeetingScreen> {
  late Room _room;
  var micEnabled = true;
  var camEnabled = true;

  Map<String, Participant> participants = {};

  @override
  void initState() {
    // create room
    _room = VideoSDK.createRoom(
      roomId: widget.meetingId,
      token: widget.token,
      displayName: "John Doe",
      micEnabled: micEnabled,
      camEnabled: camEnabled
    );

    setMeetingEventListener();

    // Join room
    _room.join();

    super.initState();
  }

  // listening to meeting events
  void setMeetingEventListener() {
    _room.on(Events.roomJoined, () {
      setState(() {
        participants.putIfAbsent(
            _room.localParticipant.id, () => _room.localParticipant);
      });
    });

    _room.on(
      Events.participantJoined,
      (Participant participant) {
        setState(
          () => participants.putIfAbsent(participant.id, () => participant),
        );
      },
    );

    _room.on(Events.participantLeft, (String participantId) {
      if (participants.containsKey(participantId)) {
        setState(
          () => participants.remove(participantId),
        );
      }
    });

    _room.on(Events.roomLeft, () {
      participants.clear();
      Navigator.popUntil(context, ModalRoute.withName('/'));
    });
  }

  // onbackButton pressed leave the room
  Future<bool> _onWillPop() async {
    _room.leave();
    return true;
  }

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return WillPopScope(
      onWillPop: () => _onWillPop(),
      child: Scaffold(
        appBar: AppBar(
          title: const Text('VideoSDK QuickStart'),
        ),
        body: Padding(
          padding: const EdgeInsets.all(8.0),
          child: Column(
            children: [
              Text(widget.meetingId),
              //render all participant
              Expanded(
                child: Padding(
                  padding: const EdgeInsets.all(8.0),
                  child: GridView.builder(
                    gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
                      crossAxisCount: 2,
                      crossAxisSpacing: 10,
                      mainAxisSpacing: 10,
                      mainAxisExtent: 300,
                    ),
                    itemBuilder: (context, index) {
                      return ParticipantTile(
                        key: Key(participants.values.elementAt(index).id),
                          participant: participants.values.elementAt(index));
                    },
                    itemCount: participants.length,
                  ),
                ),
              ),
              MeetingControls(
                onToggleMicButtonPressed: () {
                  micEnabled ? _room.muteMic() : _room.unmuteMic();
                  micEnabled = !micEnabled;
                },
                onToggleCameraButtonPressed: () {
                  camEnabled ? _room.disableCam() : _room.enableCam();
                  camEnabled = !camEnabled;
                },
                onLeaveButtonPressed: () {
                  _room.leave()
                },
              ),
            ],
          ),
        ),
      ),
      home: JoinScreen(),
    );
  }
}
```

_meeting_screen.dart_

> **CAUTION**  
> If you get `webrtc/webrtc.h file not found` error at a runtime in iOS, then check the solution [here](https://docs.videosdk.live/flutter/guide/video-and-audio-calling-api-sdk/known-issues#issue--1).

> **TIP** :  
> You can checkout the complete quick start example [here](https://github.com/videosdk-live/quickstart/tree/main/flutter-rtc).

## 🔄 Integrate Screen Share Feature

Screen sharing in a meeting is the process of sharing your device screen with other participants in the meeting. It allows everyone in the meeting to see exactly what you are seeing on your screen, which can be helpful for presentations, demonstrations, or collaborations.

### Why Integrate Screen Sharing with VideoSDK?

Integrating screen sharing into your Flutter video calling app using VideoSDK presents several compelling reasons:

1. **Simplified Development** : With VideoSDK, the intricate tasks of screen capture and transmission are effortlessly managed, saving you valuable development time and resources.
2. **Native Functionality** : Harnessing the power of the Android Media Projection API, VideoSDK ensures a seamless and efficient screen-sharing experience for your users, providing them with a native feel and optimal performance.
3. **Seamless Integration** : The integration process with VideoSDK is intuitive and hassle-free, enabling you to seamlessly incorporate screen-sharing functionality into your existing video call features without extensive modifications.
4. **Robust Features** : VideoSDK offers a robust screen-sharing solution equipped with essential features such as permission handling and in-app sharing capabilities, guaranteeing a reliable and user-friendly experience.

By embracing screen sharing through VideoSDK, you elevate the functionality and appeal of your Flutter video-calling app, providing users with an enriched communication experience.

### Enable Screen Share

- By using `enableScreenShare()` function of `Room` object, a local participant can share his/her screen or window with other participants.
- The screen share stream of the participant can be accessed from the `streams` property of `Participant` object.

### Disable Screen Share

- By using `disableScreenShare()` function of `Room` object, a local participant can stop sharing his/her screen or window with other participants.

### Events associated with Screen Share[​](https://docs.videosdk.live/flutter/guide/video-and-audio-calling-api-sdk/handling-media/screen-share#events-associated-with-enablescreenshare)
<!--kg-card-begin: markdown-->
#### Events associated with Enable ScreenShare​
<!--kg-card-end: markdown-->

Every Participant will receive a callback on [`Events.streamEnabled`](https://docs.videosdk.live/flutter/api/sdk-reference/participant-class/events#streamenabled) of the [`Participant`](https://docs.videosdk.live/flutter/api/sdk-reference/participant-class/introduction) object with `Stream` object.

- Every Remote Participant will receive [`Events.presenterChanged`](https://docs.videosdk.live/flutter/api/sdk-reference/room-class/events#presenterchanged) callback on the [`Room`](https://docs.videosdk.live/flutter/api/sdk-reference/room-class/introduction) object with the participantId as `presenterId` who started the screen share.
<!--kg-card-begin: markdown-->
#### Events associated with Disable ScreenShare​
<!--kg-card-end: markdown-->
- Every Participant will receive a callback on [`Events.streamDisabled`](https://docs.videosdk.live/flutter/api/sdk-reference/participant-class/events#streamdisabled) of the [`Participant`](https://docs.videosdk.live/flutter/api/sdk-reference/participant-class/introduction) object with `Stream` object.
- Every Remote Participant will receive [`Events.presenterChanged`](https://docs.videosdk.live/flutter/api/sdk-reference/room-class/events#presenterchanged) callback on the [`Room`](https://docs.videosdk.live/flutter/api/sdk-reference/room-class/introduction) object with the `presenterId` as `null`.

### Example[​](https://docs.videosdk.live/flutter/guide/video-and-audio-calling-api-sdk/handling-media/screen-share#rendering-screen-share-stream)

To render the screenshare, you will need to know `participantId` who is presenting the screen, which can be found in the `presenterId` property of `Room` object.

We will listen for the `Events.presenterChanged` on `Room` object to check if some other participant starts screen share, `Events.streamEnabled` and `Events.streamDisabled` on the `localParticipant`'s object to identify if the local participant is presenting or not.

```dart
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:videosdk/videosdk.dart';
import './participant_tile.dart';
import './screen_share_view.dart';

class MeetingScreen extends StatefulWidget {
  final String meetingId;
  final String token;

  const MeetingScreen(
      {super.key, required this.meetingId, required this.token});

  @override
  State<MeetingScreen> createState() => _MeetingScreenState();
}

class _MeetingScreenState extends State<MeetingScreen> {
  late Room _room;
  var micEnabled = true;
  var camEnabled = true;
  String? _presenterId;

  Map<String, Participant> participants = {};

  @override
  void initState() {
    // create room
    _room = VideoSDK.createRoom(
      roomId: widget.meetingId,
      token: widget.token,
      displayName: "John Doe",
      micEnabled: micEnabled,
      camEnabled: camEnabled
    );

    setMeetingEventListener();

    // Join room
    _room.join();

    super.initState();
  }

  // listening to meeting events
  void setMeetingEventListener() {
   // ...

   //Listening if remote participant starts presenting
    _room.on(Events.presenterChanged, (String? presenterId) {
      setState(() => {_presenterId = presenterId});
    });

    //Listening if local participant starts presenting
    _room.localParticipant.on(Events.streamEnabled, (Stream stream) {
      if (stream.kind == "share") {
        setState(() => {_presenterId = _room.localParticipant.id});
      }
    });

    _room.localParticipant.on(Events.streamDisabled, (Stream stream) {
      if (stream.kind == "share") {
        setState(() => {_presenterId = null});
      }
    });
  }

  // onbackButton pressed leave the room
  Future<bool> _onWillPop() async {
    _room.leave();
    return true;
  }

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return WillPopScope(
      onWillPop: () => _onWillPop(),
      child: Scaffold(
        appBar: AppBar(
          title: const Text('VideoSDK QuickStart'),
        ),
        body: Padding(
          padding: const EdgeInsets.all(8.0),
          child: Column(
            children: [
              Text(widget.meetingId),
              //render all participant
              // ...
              
              //we will render the screenshare view if the presenterId is not null
              if (_presenterId != null)
                ScreenShareView(
                  participant: _presenterId == _room.localParticipant.id
                      ? _room.localParticipant
                      : _room.participants[_presenterId],
                ),
                // MeetingControls
                // ....
              ElevatedButton(
                  onPressed: () {
                    if (_presenterId != null) {
                      _room.disableScreenShare();
                    } else {
                      _room.enableScreenShare();
                    }
                  },
                  child: const Text('Toggle Screnshare')),
            ],
          ),
        ),
      ),
      home: JoinScreen(),
    );
  }
}
```

Now that we know if there is an active presenter, let us get the screen share stream from the `Participant` object and render it.

```dart
import 'package:flutter/material.dart';
import 'package:videosdk/videosdk.dart';

class ScreenShareView extends StatelessWidget {
  final Participant? participant;

  ScreenShareView({super.key, required this.participant}) {
  //intialize the shareStream
    participant?.streams.forEach((key, value) {
      if (value.kind == "share") {
        shareStream = value;
      }
    });
  }
  Stream? shareStream;

  @override
  Widget build(BuildContext context) {
    return Container(
      color: Colors.grey.shade800,
      height: 300,
      width: 200,
      //show the screen share stream
      child: shareStream != null
          ? RTCVideoView(
              shareStream?.renderer as RTCVideoRenderer,
              objectFit: RTCVideoViewObjectFit.RTCVideoViewObjectFitCover,
            )
          : null,
    );
  }
}
```

## 🔚 Conclusion

Integrating screen sharing into your Flutter video calling app using VideoSDK offers users a powerful tool to enhance communication and collaboration. This feature is beneficial in a range of scenarios, from business presentations to technical demonstrations, making your app a versatile and valuable platform. Leveraging [VideoSDK's](www.videosdk.live) seamless integration capabilities, the process of incorporating screen sharing becomes not only feasible but also streamlined, enabling you to devote more attention to crafting a remarkable user interface and experience.

Unlock VideoSDK's full potential and craft seamless video experiences effortlessly. [**Sign up**](https://www.videosdk.live/signup?utm_source=organicseo&utm_medium=devto&utm_campaign=screenshare_flutter_android) today and receive 10,000 free minutes to elevate your video app to new heights.