DEV Community

vmodal_ai
vmodal_ai

Posted on Originally published at example.com

Agora Video Calling SDK with Flutter: Build a Real-Time Video Call App

Agora Video Calling SDK with Flutter: Build a Real-Time Video Call App

Real-time video calling is common in healthcare, education, customer support, social networking, and collaboration applications. Instead of implementing WebRTC infrastructure yourself, Flutter developers can use the Agora RTC SDK.

In this tutorial, we'll build the foundation of a Flutter video calling application using agora_rtc_engine.

What We'll Build

  • Initialize the Agora engine.
  • Request camera and microphone permissions.
  • Join an Agora channel.
  • Publish local audio and video.
  • Display remote participants.
  • Leave the channel and release resources.

Step 1: Create a Flutter Project

flutter create agora_video_demo
cd agora_video_demo
Enter fullscreen mode Exit fullscreen mode

Step 2: Add the Agora Flutter SDK

flutter pub add agora_rtc_engine
flutter pub add permission_handler
Enter fullscreen mode Exit fullscreen mode

The current stable package is agora_rtc_engine 6.6.3 at the time of writing. Verify the current release before publishing or building your project.

Step 3: Configure Android Permissions

Add the required permissions to android/app/src/main/AndroidManifest.xml:

<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
<uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT"/>
Enter fullscreen mode Exit fullscreen mode

Step 4: Request Runtime Permissions

await [
  Permission.camera,
  Permission.microphone,
].request();
Enter fullscreen mode Exit fullscreen mode

Handle denied permissions properly in a production application.

Step 5: Create the RTC Engine

final RtcEngine engine = createAgoraRtcEngine();

await engine.initialize(
  const RtcEngineContext(
    appId: appId,
  ),
);
Enter fullscreen mode Exit fullscreen mode

RtcEngine is the main object for Agora real-time audio and video features.

Step 6: Register Event Handlers

engine.registerEventHandler(
  RtcEngineEventHandler(
    onJoinChannelSuccess: (connection, elapsed) {
      debugPrint('Joined: ${connection.channelId}');
    },
    onUserJoined: (connection, remoteUid, elapsed) {
      debugPrint('Remote user: $remoteUid');
    },
    onUserOffline: (connection, remoteUid, reason) {
      debugPrint('User left: $remoteUid');
    },
  ),
);
Enter fullscreen mode Exit fullscreen mode

Keep these events connected to your state-management layer for a larger application.

Step 7: Enable Video

await engine.enableVideo();
await engine.startPreview();
Enter fullscreen mode Exit fullscreen mode

Step 8: Join a Channel

await engine.joinChannel(
  token: token,
  channelId: 'demo-room',
  uid: 0,
  options: const ChannelMediaOptions(),
);
Enter fullscreen mode Exit fullscreen mode

For production, obtain short-lived tokens from your backend rather than embedding permanent credentials in the app.

Step 9: Render Local Video

AgoraVideoView(
  controller: VideoViewController(
    rtcEngine: engine,
    canvas: const VideoCanvas(uid: 0),
  ),
)
Enter fullscreen mode Exit fullscreen mode

Step 10: Render Remote Video

When onUserJoined fires, save the remote UID and render:

AgoraVideoView(
  controller: VideoViewController.remote(
    rtcEngine: engine,
    canvas: VideoCanvas(uid: remoteUid),
    connection: RtcConnection(
      channelId: 'demo-room',
    ),
  ),
)
Enter fullscreen mode Exit fullscreen mode

For multiple users, keep a list of remote UIDs in your application state.

Step 11: Mute Audio

await engine.muteLocalAudioStream(true);
Enter fullscreen mode Exit fullscreen mode

Toggle the value when the user presses the microphone button.

Step 12: Disable Video

await engine.muteLocalVideoStream(true);
Enter fullscreen mode Exit fullscreen mode

This lets the user turn video off without leaving the meeting.

Step 13: Leave the Channel

await engine.leaveChannel();
await engine.release();
Enter fullscreen mode Exit fullscreen mode

Release the engine when the call is finished.

Production Token Architecture

Use this pattern:

Flutter App
    |
    | Request token
    v
Your Backend
    |
    | Generate short-lived token
    v
Flutter App
    |
    | Join channel
    v
Agora
Enter fullscreen mode Exit fullscreen mode

Never place server-side secrets in Flutter.

Common Problems

Black Camera Preview

Check camera permission, enableVideo(), startPreview(), and whether another application is using the camera.

Remote Video Missing

Verify that both users joined the same channel and that the remote UID is being stored and rendered correctly.

Call Fails in Production

Implement a backend token service and handle token expiration instead of using development credentials.

Recommended Architecture

Flutter UI
    ↓
Call Controller / BLoC / Riverpod
    ↓
Agora Service
    ↓
Agora RTC Engine
Enter fullscreen mode Exit fullscreen mode

Keep Agora-specific code inside a service so your business logic remains independent of the SDK.

Conclusion

SDK integrations are easiest to maintain when credentials, platform-specific configuration, networking, and UI responsibilities are separated. Start with the smallest working flow, verify it on a physical device, and then add production concerns such as authentication, error handling, lifecycle management, and secure credential handling.

Stay tuned for more advanced Flutter SDK integration tutorials!

SEO Keywords

Flutter SDK tutorial, Flutter integration, Flutter mobile development, Dart SDK integration, Flutter Android, Flutter iOS, SDK integration

Tags

flutter dart mobiledevelopment sdk android

Useful Links

Website: www.v-modal.com

SDK Flutter: https://github.com/v-modal/vmodal_sdk_flutter

SDK Android: https://github.com/v-modal/vmodal_sdk_android

Discord: https://discord.gg/K72z28KUx

Top comments (0)