Skip to main content

๐Ÿ’™ Flutter

The bbb_meeting_sdk plugin opens the meeting full-screen on top of the Flutter view and hands control back, with the leave reason, when the user leaves. No React Native or Expo in your project: the meeting client ships as the prebuilt native SDKs (Android AAR, iOS XCFrameworks), which your build downloads.

Packagebbb_meeting_sdk 0.1.0 on pub.dev
RequirementsFlutter 3.44 or later (built and tested with Flutter 3.47 on Android and iOS); iOS builds need Xcode 26.x, as for the native iOS SDK

๐Ÿ“ฆ 1. Installโ€‹

flutter pub add bbb_meeting_sdk

Then apply the Android and iOS host settings below.


๐Ÿ’ป 2. Usageโ€‹

import 'package:bbb_meeting_sdk/bbb_meeting_sdk.dart';

await BbbMeetingSdk.initialize(); // optional warm-up
final sub = BbbMeetingSdk.events.listen((event) { /* BbbJoinedEvent, BbbLeftEvent, BbbErrorEvent */ });
final left = await BbbMeetingSdk.join(BbbJoinOptions(joinUrl: url, meetingName: 'Weekly'));
// completes when the user is back: left.reason is left | ended | error | unsupported | cancelled
// while the meeting is open (for example from a timer): await BbbMeetingSdk.leave();

BbbJoinOptions also carries theme, pictureInPicture, screensharePresenter, embedMode, largeScreenLayout and devLogging. BbbSdkConfig, passed as initialize(config: โ€ฆ), carries clientType and appVersion. All options are in the ๐Ÿ“˜ API reference.

Instead of opening a meeting, join throws a PlatformException:

CodeWhen
already_in_meetinga meeting is already open
invalid_argumentsno join URL was given
no_activity / no_view_controllerthere is nothing to present the meeting from
join_failed(Android) the SDK cannot start the meeting

initialize throws no_application on Android when there is no application context yet.


๐Ÿค– 3. Android host appโ€‹

The plugin's own Gradle file adds the SDK's Maven repository, pins fbjni 0.7.0, ships R8 keep rules for the SDK and swaps the debug variants of react-android / hermes-android for their release AARs (a debug flutter run would otherwise crash at startup). What stays in your app, in android/app/build.gradle.kts:

android {
defaultConfig {
minSdk = 24
// The SDK ships 64-bit libraries only. The Flutter Gradle plugin has already filled abiFilters
// with armeabi-v7a, arm64-v8a and x86_64, so `+=` alone would keep armeabi-v7a: clear it first.
ndk {
abiFilters.clear()
abiFilters += listOf("arm64-v8a", "x86_64")
}
}
packaging {
// react-android and fbjni both ship these
jniLibs { pickFirsts += listOf("**/libc++_shared.so", "**/libfbjni.so") }
}
buildTypes {
release {
// Flutter minifies release builds; the SDK is not R8-safe (its native code looks classes up by
// name). The plugin's keep rules are best effort: keep minification off for now.
isMinifyEnabled = false
isShrinkResources = false
}
}
}
  • The SDK's AAR (about 88 MB) carries the permissions, the meeting activity (BbbMeetingActivity, single task, picture-in-picture) and the foreground service: nothing to add to AndroidManifest.xml.
  • Use compileSdk 36 and Java 17.
  • Check the result: unzip -l build/app/outputs/flutter-apk/app-release.apk | grep armeabi should print nothing. A 32-bit armeabi-v7a folder would hold an incomplete set of libraries and crash on 32-bit devices. Don't combine the filter with --split-per-abi.
  • Gradle downloads the AAR from the SDK's Maven repository. To use a mirror or a local copy, set bbbSdkMavenUrl=<url> in android/gradle.properties.
  • Play Console: declare the foreground-service use cases microphone, media playback and media projection.
Build release

Build release (flutter build apk --release, flutter run --release): the SDK is built from release React Native libraries. Debug builds rely on the plugin's variant rule, which has not been exercised yet.


๐ŸŽ 4. iOS host appโ€‹

  • Set the Runner's minimum deployment target to iOS 16.4 (Xcode: Runner โ†’ General โ†’ Minimum Deployments, or IPHONEOS_DEPLOYMENT_TARGET = 16.4 in ios/Runner.xcodeproj). Flutter raises its generated package to match.
  • Info.plist: NSMicrophoneUsageDescription, NSCameraUsageDescription, NSBluetoothAlwaysUsageDescription, NSBluetoothPeripheralUsageDescription, NSLocalNetworkUsageDescription, NSPhotoLibraryUsageDescription, NSPhotoLibraryAddUsageDescription, UIBackgroundModes = audio, UIViewControllerBasedStatusBarAppearance = false (the meeting UI drives the status bar through React Native; without it the calls are no-ops that log an error on every join), and optionally io.livekit.reactnative.expo.ENABLE_MULTITASKING_CAMERA_ACCESS = true (the camera keeps running in picture-in-picture where iOS allows it).
  • Frameworks: the SDK's XCFrameworks are about 230 MB of zips, downloaded once and checked against pinned SHA-256 checksums. With Swift Package Manager (Flutter's default) the plugin depends on the SDK's Swift package, same version as the plugin. With CocoaPods (SwiftPM disabled), the first pod install runs the plugin's ios/fetch_frameworks.sh, which downloads the same zips; use platform :ios, '16.4'.
  • Screen sharing from the device needs a Broadcast Upload Extension in your app (๐Ÿ–ฅ๏ธ iOS screen sharing); pass screensharePresenter: true only then.

๐Ÿงช Exampleโ€‹

The plugin's example/lib/main.dart is one screen with a join URL field, a Join meeting button and a log of the SDK events. In a new app (flutter create), apply the host settings above, add the package and use that file as lib/main.dart:

flutter run --release --dart-define=BBB_JOIN_URL='https://<server>/html5client/join?sessionToken=<token>'