Flutter Zoom SDK

License

A Flutter plugin for the Zoom SDK.

Note: This plugin is still under active development, and some Zoom features might not be available yet. We are working to add more features. Feedback and Pull Requests are always welcome.

Zoom SDK Versions

Android: https://github.com/zoom/zoom-sdk-android/releases/tag/v4.6.21666.0429

Installation

First, add flutter_zoom_sdk: ^0.0.2 as a dependency in your pubspec.yaml file.

Android

Change the minimum Android sdk version to at the minimum 21 in your android/app/build.gradle file.

minSdkVersion 21

Add the zoom proguard content to your android project: https://github.com/zoom/zoom-sdk-android/blob/master/proguard.cfg

Examples

Meeting status

There are 2 ways to obtains the Zoom meeting status

  • Listen to Zoom Status Event stream, or
  • Polling the Zoom status using a Timer

The plugin emits the following Zoom meeting events:

For Android:

  • MEETING_STATUS_IDLE
  • MEETING_STATUS_CONNECTING
  • MEETING_STATUS_INMEETING
  • MEETING_STATUS_WEBINAR_PROMOTE
  • MEETING_STATUS_WEBINAR_DEPROMOTE
  • MEETING_STATUS_UNKNOWN
  • MEETING_STATUS_DISCONNECTING
  • MEETING_STATUS_FAILED
  • MEETING_STATUS_IN_WAITING_ROOM
  • MEETING_STATUS_RECONNECTING
  • MEETING_STATUS_WAITINGFORHOST

Join Meeting

class MeetingWidget extends StatelessWidget {

  ZoomOptions zoomOptions;
  ZoomMeetingOptions meetingOptions;

  Timer timer;

  MeetingWidget({Key key, meetingId, meetingPassword}) : super(key: key) {
    // Setting up the Zoom credentials
    this.zoomOptions = new ZoomOptions(
      domain: "zoom.us",
      appKey: "appKey", // Replace with with key got from the Zoom Marketplace
      appSecret: "appSecret", // Replace with with secret got from the Zoom Marketplace
    );

    // Setting Zoom meeting options (default to false if not set)
    this.meetingOptions = new ZoomMeetingOptions(
        userId: 'example',
        meetingId: meetingId,
        meetingPassword: meetingPassword,
        disableDialIn: "true",
        disableDrive: "true",
        disableInvite: "true",
        disableShare: "true",
        noAudio: "false",
        noDisconnectAudio: "false"
    );
  }

  bool _isMeetingEnded(String status) {
    var result = false;

    if (Platform.isAndroid)
      result = status == "MEETING_STATUS_DISCONNECTING" || status == "MEETING_STATUS_FAILED";
    else
      result = status == "MEETING_STATUS_IDLE";

    return result;
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
          title: Text('Initializing meeting '),
      ),
      body: Padding(
        padding: EdgeInsets.all(16.0),
        child: ZoomView(onViewCreated: (controller) {

          print("Created the view");

          controller.initZoom(this.zoomOptions)
              .then((results) {

            if(results[0] == 0) {

              // Listening on the Zoom status stream (1)
              controller.zoomStatusEvents.listen((status) {

                print("Meeting Status Stream: " + status[0] + " - " + status[1]);

                if (_isMeetingEnded(status[0])) {
                  Navigator.pop(context);
                  timer?.cancel();
                }
              });

              print("listen on event channel");

              controller.joinMeeting(this.meetingOptions)
                  .then((joinMeetingResult) {

                    // Polling the Zoom status (2)
                timer = Timer.periodic(new Duration(seconds: 2), (timer) {
                  controller.meetingStatus(this.meetingOptions.meetingId)
                      .then((status) {
                    print("Meeting Status Polling: " + status[0] + " - " + status[1]);
                  });
                });
              });
            }

          }).catchError((error) {
            print(error);
          });
        })
      ),
    );
  }
}

Start a Meeting - Non-login user

You need to obtain the User Token and Zoom Access Token (ZAK) in order to start meetings for a user. They are unique authentication tokens required to host a meeting on behalf of another user.

Example of getting User Token and ZAK here

More info about the User Token and Zoom Access Token here.

In order to run the example app:

  1. Create an JWT app to get a JWT token using the instructions here.

  2. Create a meeting (with a host of course) then get the Meeting ID (can be a 10 or 11-digit number).

  3. Use the Zoom API to obtain the tokens from the host.

     # User token
     curl --location --request GET 'https://api.zoom.us/v2/users/<zoom_user_id>/token?type=token&access_token=<jwt_token>'
    
     # Access token
     curl --location --request GET 'https://api.zoom.us/v2/users/<zoom_user_id>/token?type=zak&access_token=<jwt_token>'
    

    Note for obtaining tokens:

    The user must log in using their email and password to get the user token. If a user signed into Zoom using Google or Facebook, a null value will be returned for the token.

  4. Pass the meeting ID and tokens to the plugin.

class StartMeetingWidget extends StatelessWidget {

  ZoomOptions zoomOptions;
  ZoomMeetingOptions meetingOptions;

  Timer timer;

  StartMeetingWidget({Key key, meetingId}) : super(key: key) {
    this.zoomOptions = new ZoomOptions(
      domain: "zoom.us",
      appKey: "appKey", // Replace with with key got from the Zoom Marketplace
      appSecret: "appSecret", // Replace with with key got from the Zoom Marketplace
    );
    this.meetingOptions = new ZoomMeetingOptions(
        userId: '<zoom_user_id>', // Replace with the user email or Zoom user ID
        displayName: 'Example display Name',
        meetingId: meetingId, 
        zoomAccessToken: "<zak_token>", // Replace with the token obtained from the Zoom API
        zoomToken: "<zoom_token>", // Replace with the token obtained from the Zoom API
        disableDialIn: "true",
        disableDrive: "true",
        disableInvite: "true",
        disableShare: "true",
        noAudio: "false",
        noDisconnectAudio: "false"
    );
  }

  bool _isMeetingEnded(String status) {
    var result = false;

    if (Platform.isAndroid)
      result = status == "MEETING_STATUS_DISCONNECTING" || status == "MEETING_STATUS_FAILED";
    else
      result = status == "MEETING_STATUS_IDLE";

    return result;
  }

  @override
  Widget build(BuildContext context) {
    // Use the Todo to create the UI.
    return Scaffold(
      appBar: AppBar(
          title: Text('Initializing meeting '),
      ),
      body: Padding(
        padding: EdgeInsets.all(16.0),
        child: ZoomView(onViewCreated: (controller) {

          print("Created the view");

          controller.initZoom(this.zoomOptions)
              .then((results) {

            if(results[0] == 0) {

              controller.zoomStatusEvents.listen((status) {
                print("Meeting Status Stream: " + status[0] + " - " + status[1]);
                if (_isMeetingEnded(status[0])) {
                  Navigator.pop(context);
                  timer?.cancel();
                }
              });

              print("listen on event channel");

              controller.startMeeting(this.meetingOptions)
                  .then((joinMeetingResult) {

                timer = Timer.periodic(new Duration(seconds: 2), (timer) {
                  controller.meetingStatus(this.meetingOptions.meetingId)
                      .then((status) {
                    print("Meeting Status Polling: " + status[0] + " - " + status[1]);
                  });
                });

              });
            }

          }).catchError((error) {
            print(error);
          });
        })
      ),
    );
  }
}

Libraries

zoom_options
zoom_view