Why Choose flutter_zoom_sdk_advanced?

When your app needs more than a simple Zoom URL launch – for example, custom UI controls, real‑time participant events, or email‑based authentication – the flutter_zoom_sdk_advanced package gives you direct access to Zoom’s native Meeting SDK from pure Dart code. This eliminates the need to write separate Android and iOS bridge code while keeping the entire meeting lifecycle under your control.

When to Use This Package

  • Tele‑health platforms that require secure, authenticated video calls.
  • Remote‑learning apps that need to react to user join/leave events.
  • Collaboration tools that want to toggle audio/video, start screen share, or manage participants programmatically.
  • Any Flutter project that wants a native‑quality Zoom experience without leaving the Dart ecosystem.

Installation

Add the dependency with the Flutter CLI:

Code
flutter pub add flutter_zoom_sdk_advanced

After the package is added, run flutter pub get to fetch it.

Native Prerequisites

The Zoom Meeting SDK is only available for Android and iOS, so you must:

  • Register a Zoom Marketplace app to obtain an API Key and API Secret.
  • Configure the Android gradle files to include Zoom’s AAR binaries (see the package’s pub.dev page for exact steps).
  • Add the required permissions (INTERNET, CAMERA, RECORD_AUDIO) to AndroidManifest.xml and the corresponding keys to Info.plist on iOS.
Make sure the Zoom SDK version you embed matches the version listed in the package’s documentation; mismatched binaries will cause runtime crashes.

Basic Usage – A Complete Runnable Example

The snippet below demonstrates a minimal end‑to‑end flow: initialize the SDK, listen to meeting events, join a meeting, and leave when the user taps a button.

Dart / Flutter
import 'package:flutter/material.dart';
import 'package:flutter_zoom_sdk_advanced/flutter_zoom_sdk_advanced.dart';

void main() => runApp(const MyApp());

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Zoom Demo',
      theme: ThemeData(primarySwatch: Colors.blue),
      home: const ZoomDemo(),
    );
  }
}

class ZoomDemo extends StatefulWidget {
  const ZoomDemo({Key? key}) : super(key: key);

  @override
  State createState() => _ZoomDemoState();
}

class _ZoomDemoState extends State {
  // The service object provided by the package.
  final ZoomMeetingService _zoomService = ZoomMeetingService();
  bool _inMeeting = false;

  @override
  void initState() {
    super.initState();
    // Replace with your own credentials from the Zoom Marketplace.
    const apiKey = 'YOUR_API_KEY';
    const apiSecret = 'YOUR_API_SECRET';
    _zoomService.initialize(apiKey, apiSecret);

    // Listen to all meeting events – useful for UI updates.
    _zoomService.meetingEventStream.listen(_onMeetingEvent);
  }

  void _onMeetingEvent(ZoomMeetingEvent event) {
    if (event is MeetingEndedEvent) {
      setState(() => _inMeeting = false);
    } else if (event is UserJoinedEvent) {
      // Example: show a snackbar when a new participant joins.
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(content: Text('User ${event.userName} joined')),
      );
    }
  }

  Future _joinMeeting() async {
    try {
      await _zoomService.joinMeeting(
        meetingId: '123456789',
        meetingPassword: 'pwd',
        userName: 'Flutter User',
      );
      setState(() => _inMeeting = true);
    } catch (e) {
      // Always handle errors – the SDK throws descriptive exceptions.
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(content: Text('Failed to join: $e')),
      );
    }
  }

  Future _leaveMeeting() async {
    await _zoomService.leaveMeeting();
    setState(() => _inMeeting = false);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Zoom Demo')),
      body: Center(
        child: _inMeeting
            ? Column(
                mainAxisSize: MainAxisSize.min,
                children: [
                  const Text('You are in a meeting'),
                  const SizedBox(height: 16),
                  ElevatedButton(
                    onPressed: _leaveMeeting,
                    child: const Text('Leave Meeting'),
                  ),
                ],
              )
            : ElevatedButton(
                onPressed: _joinMeeting,
                child: const Text('Join Meeting'),
              ),
      ),
    );
  }
}

This example covers the most common tasks:

  • Calling initialize with your API credentials.
  • Subscribing to meetingEventStream for real‑time updates.
  • Joining a meeting with joinMeeting and handling errors.
  • Leaving the meeting via leaveMeeting.

Controlling Audio, Video, and Screen Share

Once you are inside a meeting, the SDK exposes control methods such as:

  • toggleAudio({required bool mute})
  • toggleVideo({required bool mute})
  • startScreenShare() / stopScreenShare()

These can be wired to UI buttons in the same way the Leave Meeting button is wired above.

Mistakes to Avoid

  • Skipping initialization. The SDK must be initialized before any meeting call; otherwise you’ll get a ZoomError.uninitialized exception.
  • Ignoring runtime permissions. Android 6+ and iOS 10+ require explicit camera/microphone permission requests at runtime. Use the permission_handler package or platform‑specific APIs.
  • Hard‑coding credentials. Store your API key/secret securely (e.g., via a backend token service) and never commit them to source control.
  • Forgetting to dispose streams. When the widget that owns meetingEventStream is disposed, cancel the subscription to avoid memory leaks.

Testing the Integration

Because the Zoom SDK relies on native binaries, you must run the app on a physical device or an emulator with Google Play services (Android) / a real iOS device. The plugin does not work in the Flutter web or desktop environments.

Further Resources

If you encounter a native crash, verify that the Zoom AAR (Android) or framework (iOS) versions match the ones referenced in the plugin’s pubspec.yaml. Mismatched versions are a common source of “ClassNotFoundException” errors.

Frequently Asked Questions

Do I need a Zoom account to use flutter_zoom_sdk_advanced?

Yes. You must have a Zoom account and create a Marketplace app to obtain an API Key and Secret, which are required for SDK initialization.

Can I use this package on web or desktop?

No. The underlying Zoom Meeting SDK only supports Android and iOS. For web or desktop you need a different solution such as Jitsi Meet or Agora.

How do I handle runtime permissions for camera and microphone?

The package does not request permissions automatically. Use a permission‑handling package (e.g., permission_handler) to request <code>CAMERA</code> and <code>RECORD_AUDIO</code> before calling <code>joinMeeting</code>.

What should I do if the meeting UI appears blank on Android?

Verify that the Zoom AAR binaries are correctly added to <code>app/build.gradle</code> and that the <code>minSdkVersion</code> meets Zoom’s minimum requirement (usually 21). Also ensure that ProGuard rules are not stripping Zoom classes.

Is it possible to start a meeting as a host programmatically?

Yes. Use <code>startMeeting</code> instead of <code>joinMeeting</code> and provide the host’s Zoom credentials (API Key/Secret) along with the meeting number and password.