Talk to us
Talk to us

How to Build Clubhouse Clone App in Flutter

How to Build Clubhouse Clone App in Flutter

Clubhouse is a popular audio-based social networking app allowing users to join and listen to live conversations. Launched in 2020, it provides a one-of-a-kind platform for users to participate in live discussions, panel talks, and interviews on a diverse range of topics. This tutorial will teach how to build a Clubhouse clone in the Flutter framework with ZEGOCLOUD SDK. Let’s ignite our creative engines and dive right in!

Why build a Clubhouse clone?

Building a Clubhouse clone can be rewarding, considering its popularity and potential. By creating your own audio-based social networking app, you can tap into the growing demand for interactive and immersive experiences, fostering connections and conversations in a whole new way. Take advantage of the monetization opportunities to revolutionize the social media landscape!

How Can You Monetize the Clubhouse Clone App?

Here are five effective ways to generate revenue and capitalize on its growing popularity:

1. In-App Purchases

Offer users the option to buy exclusive features, premium content, or virtual goods within the app. For example, you could give users access to VIP rooms, extra speaking time, or unique badges – all while generating revenue.

2. Subscription Model

Create a subscription-based system where users pay a monthly or yearly fee to access premium features like ad-free listening, early access to rooms, or priority invitations to special events.

3. Sponsored Rooms and Events

Collaborate with brands, influencers, or organizations to host sponsored rooms and events. This will help advertisers target their audiences while generating income.

4. In-App Advertising

Display ads within your app to generate income, including banner ads, interstitial ads, or rewarded video ads.

5. Virtual Gifting

Introduce an in-app currency that users can purchase to access premium features, virtual goods, or exclusive content. Indeed, it is a great way to generate revenue while offering users more options.

How to Build a Clubhouse Clone App on Flutter

ZEGOCLOUD Voice Call SDK is the ultimate solution for crafting an irresistible audio-based social networking platform that rivals Clubhouse. Its SDK has cutting-edge features including real-time audio streaming, room management, and user authentication capabilities. Follow our expert guide to leverage these technologies and give birth to your own flutter or react native Clubhouse clone app with ease.

zegocloud voice call sdk

Discover the step-by-step process of leveraging these technologies to bring your unique Clubhouse clone app to fruition.


  • A ZEGOCLOUD developer account – Sign up
  • Get app credentials by creating a project on the admin console
  • Have Flutter 1.12 or later installed
  • An iOS/Android device or emulator
  • VS Code or any IDE of choice

Create a new project

To start with Flutter, follow the instructions below if you’re using VS Code. For other options, please visit Flutter Documentation.

  1. Open the command palette by pressing Ctrl+Shift+P or Cmd+Shift+P.
  2. Type “flutter” and select the “Flutter: New Project” command.
  1. Select “Application” as the project type.
  1. Create or select a folder/directory for the new project folder.
  1. Enter a project name, such as “Clubhouse_app“, and press Enter.
  1. Wait for project creation to complete and the “main.dart” file to appear.

Integrate the SDK

  1. To execute the following code, navigate to your project’s root directory.
flutter pub add zego_express_engine
  1. Import the zego_express_engine package in your Dart code
import 'package:zego_express_engine/zego_express_engine.dart';

Add permissions


Navigate to the app/src/main directory of your project and modify the AndroidManifest.xml file to include the necessary permissions.

<!-- Permissions required by the SDK -->
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />

<!-- Permissions required by the Demo App -->
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />

<uses-feature android:glEsVersion="0x00020000" android:required="true" />
<uses-feature android:name="" />
<uses-feature android:name="" />

As Android 6.0 mandates dynamic permissions for certain crucial permissions, static permissions cannot be solely applied through the “AndroidManifest.xml” file. To address this, you have two options: either utilize a third-party Flutter plugin from pub and implement it yourself, or refer to the Android native layer and execute the “requestPermissions” method within the “Activity” code.

String[] permissionNeeded = {

    if (ContextCompat.checkSelfPermission(this, "android.permission.CAMERA") != PackageManager.PERMISSION_GRANTED ||
        ContextCompat.checkSelfPermission(this, "android.permission.RECORD_AUDIO") != PackageManager.PERMISSION_GRANTED) {
        requestPermissions(permissionNeeded, 101);


  1. Choose the desired project, navigate to Info, and access Custom iOS Target Properties.
  1. Click the “+” button to include camera and microphone permissions. Add the following descriptions:
Privacy - Camera Usage Description

Privacy - Microphone Usage Description

Create a ZegoExpressEngine instance

Optional: Create the UI

Before initializing a ZegoExpressEngine instance, include an audio window and an “End” button to enable basic real-time audio functionality.

To create a ZegoExpressEngine instance, call the createEngineWithProfile() method with your project’s AppID and AppSign. The web platform does not require the appSign parameter.

ZegoEngineProfile profile = ZegoEngineProfile(
    appID, // Get your AppID from the ZEGOCLOUD Admin Console. The AppID is a 12-digit number.
    ZegoScenario.Default, // General scenario
    appSign: appSign,// Get your AppSign from the ZEGOCLOUD Admin Console.    );
// Create a ZegoExpressEngine instance.

Log in to a room

To log into a room, call the loginRoom() method with the room ID. If the room ID does not exist, a new room will be created, and you will be logged in automatically.

// create a user
ZegoUser user ='user1');

// set the token
ZegoRoomConfig config = ZegoRoomConfig.defaultConfig();
config.isUserStatusNotify = true;

// log in to a room
ZegoExpressEngine.instance.loginRoom('room1', user, config: config);

After successfully logging into a room, it is crucial to handle various events that may occur. You can implement relevant event callback methods in the event handler based on your specific requirements to achieve this. Here are some commonly used event callbacks related to room users and streams:

  • onRoomStateUpdate: This callback provides updates on the current user’s room connection status. It triggers when there is a change in the current user’s connection (e.g., disconnection from the room or authentication failure), and the SDK notifies you through this callback.
  • onRoomUserUpdate: Use this callback to receive updates on the status of other users in the room. The SDK sends an event notification via this callback whenever a user joins or leaves the room.
  • onRoomStreamUpdate: This callback informs you about the status of the streams in the room. It triggers when new streams are published, or existing streams in the room stop. The SDK utilizes this callback to send out event notifications.
// This callback is called whenever the current user's room connection status changes.
ZegoExpressEngine.onRoomStateUpdate = (String roomID, ZegoRoomState state, int errorCode, Map<String, dynamic> extendedData) {
    // Implement the callback handling logic.


// This callback is called whenever the status of another user in the room changes.

ZegoExpressEngine.onRoomUserUpdate = (String roomID, ZegoUpdateType updateType, List<ZegoUser> userList) {
    // Implement the callback handling logic.


// This callback is called whenever the status of a stream in the room changes. 
ZegoExpressEngine.onRoomStreamUpdate = (String roomID, ZegoUpdateType updateType, List<ZegoStream> streamList) {
    // Implement the callback handling logic.

Publish streams

To start sharing your local audio or video stream with other users, call the startPublishingStream() method and pass the stream ID of the stream, you want to share.


To listen for and handle events that may occur after stream publishing starts, you can implement the corresponding event callback methods of the event handler as needed. One common event callback related to stream publishing is the onPublisherStateUpdate callback. Any change in the status of stream publishing invokes this callback. For example, if stream publishing is interrupted due to network issues and the SDK retries to start publishing the stream again, the SDK will send out an event notification through this callback.

// This Callback updates users on stream publishing status.    
ZegoExpressEngine.onPublisherStateUpdate = (String streamID, ZegoPublisherState state, int errorCode, Map<String, dynamic> extendedData) {
    // code the callback handling logic. 

Play streams

To initiate playback of a remote audio-only stream, simply invoke the startPlayingStream() method, providing the relevant stream ID as the streamID parameter. This action will commence the stream playback and return a promise that resolves upon successful stream start or rejects in case of any errors.


To listen for stream-playing events, implement the onPlayerStateUpdate callback. This callback is invoked when the status of the stream playing changes. For example, if stream playing is interrupted due to network issues, the SDK will send out an event notification through this callback.

// Stream playing status callback

ZegoExpressEngine.onPlayerStateUpdate = (String streamID, ZegoPlayerState state, int errorCode, Map<String, dynamic> extendedData) {
    // code callback handling logic.

Stop publishing and playing streams

Cease the transmission of local audio streams to remote users by invoking the stopPublishingStream method. This action effectively stops the publication of audio streams from the local device to other participants in the session.


The stopPlayingStream() the method will stop playing the stream and return a promise that resolves when the stream is stopped or rejects if there is an error.


Log out of a room

To conclude your session in a room, simply call the logoutRoom method and provide the respective room ID as the parameter.


Destroy the ZegoExpressEngine instance

To release the occupied resources and dismantle the ZegoExpressEngine instance, execute the destroyEngine method.


Run a Demo

To test your implementation, run your app project on a real device or use our web platform for debugging.


Building a Clubhouse clone written in Flutter is an exciting venture. With the power of the ZEGOCLOUD Voice Call SDK, you can create a remarkable audio-based social networking app. Embrace the versatility of Flutter and leverage the SDK’s features to craft your own captivating Clubhouse clone. If you are still looking for how to build an Android Clubhouse clone app, sign up for ZEGOCLOUD which can help you achieve what you want.

Let’s Build APP Together

Start building with real-time video, voice & chat SDK for apps today!

Talk to us

Take your apps to the next level with our voice, video and chat APIs

Free Trial
  • 10,000 minutes for free
  • 4,000+ corporate clients
  • 3 Billion daily call minutes

Stay updated with us by signing up for our newsletter!

Don't miss out on important news and updates from ZEGOCLOUD!

* You may unsubscribe at any time using the unsubscribe link in the digest email. See our privacy policy for more information.