Build a Zoom meeting app


Explore the Zoom Client iOS SDK by learning how to build a simple meetings app that has the following two features:

  • Join a Meeting : A user with a Zoom meeting ID and meeting passcode can join a meeting anonymously without having to log into the app.

  • Start a Meeting: A meeting host can start the meeting after logging into the app with their Zoom account credentials.

You can find an existing sample application with these features on Github.

Prerequisites

  • Xcode 10.0 or later
  • An iOS Device (iOS 8 or later)
  • Meeting Number and the passcode of a Zoom meeting.
  • SDK Key and Secret, obtained by creating an SDK App. If you have not already generated these credentials, refer to the Build an SDK App to learn how to generate the SDK Key and Secret for your app.

This section of the tutorial demonstrates how to create an iOS project and integrate the Zoom Client iOS SDK into the project.

Create a new iOS project

Open Xcode and click Create a new Xcode project. Choose Single View App as the template and click Next. Fill out the relevant project information such as the project name, team and organization name. Choose Storyboard in the User Interface field, select a programming language and click Next. Specify the storagee path for the project and click Create. Next, connect your iOS device to your computer.

Import the Zoom SDK libraries

If you have not already downloaded the Zoom Client iOS SDK, download the SDK from the Zoom Marketplace.

To build with this version of the SDK in Xcode 13, you must validate your workspace by navigating to Build Settings and setting Validate Workspace to “YES”.

The downloaded package includes SDK libraries and sample apps. The SDK libraries are in the lib folders located inside the zoom-sdk-ios-master folder. Navigate to the downloaded SDK package, and select MobileRTC.framework and MobileRTCResources.bundle.

Next, copy the selected files into your Xcode project file.

In the next screen, select Copy items if needed and Create folder references options and click Finish.

Next, embed and sign the framework by navigating to the Project file > Targets: > General > Frameworks, Libraries, and Embedded Content and setting the Embed attribute to Embed & Sign instead of Do Not Embed.

Change project configurations for SDK compatibility

If you built your project using Xcode version 11 or higher, you may notice SceneDelegates being added to your project by default.

SceneDelegates are not compatible with the current version of the Zoom SDK. Thus, you must remove them from the iOS project. To do so, navigate to info.plist > Application Scene Manifest and delete it.

Next, delete the SceneDelegate files from the project navigator.

If you are using Objective-C for your project, delete SceneDelegate.m and SceneDelegate.h files from the project navigator. If you are using Swift, delete the SceneDelegate.swift file.

Lastly, navigate to AppDelegate file in the project navigator and remove the following UISceneSession code if it is present in the file.

AppDelegate.m
// If you are using Objective-C, delete the following lines of code from your AppDelegate.m file.
#pragma mark - UISceneSession lifecycle
- (UISceneConfiguration *)application:(UIApplication *)application configurationForConnectingSceneSession:(UISceneSession *)connectingSceneSession options:(UISceneConnectionOptions *)options {
return [[UISceneConfiguration alloc] initWithName:@"Default Configuration" sessionRole:connectingSceneSession.role];
}
- (void)application:(UIApplication *)application didDiscardSceneSessions:(NSSet<UISceneSession *> *)sceneSessions {
}
AppDelegate.swift
// If you are using Swift, delete the following lines of code from your AppDelegate.swift file.
// MARK: UISceneSession Lifecycle
func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
// Called when a new scene session is being created.
// Use this method to select a configuration to create the new scene with.
return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
}
func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) {
// Called when the user discards a scene session.
// If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
// Use this method to release any resources that were specific to the discarded scenes, as they will not return.
}

The Zoom SDK also does not support Bitcode, and Xcode enables it by default. Navigate to your Xcode project file, select Project > Build Settings and then, search for Enable Bitcode option and set the value of the option to No.

Add project permissions

Add the following permissions in the info.plist file to grant access to camera and microphone, needed for Zoom meetings to run on an iOS device. Navigate to info.plist, click the “+” icon next to Information Property List. Search for and select Privacy - Camera Usage Descriptions.

In the value of this field, provide a description to explain why you are requesting camera access, such as “To access the camera for a video meeting”. Repeat this step for Privacy - Microphone Usage Description.

Now that the framework is installed and the project is set up, you can start setting up the SDK. The tabs below show instructions for both Objective-C and Swift. Follow the instructions that are relevant to you depending on the programming language that you are using for this project.

Initialize the SDK

Navigate to the AppDelegate.h file. Since you disabled SceneDelagates earlier, you must add a UIWindow to the AppDelegate. Add the following line of code in your AppDelegate.h file.

AppDelegate.m
#import <UIKit/UIKit.h>
@interface AppDelegate : UIResponder <UIApplicationDelegate>
// 1. Add UIWindow
@property (strong, nonatomic) UIWindow *window;
@end

The MobileRTC class exposes a generic interface to allow initialization, authentication, and configuration of the Zoom SDK. In order to use the Zoom SDK, you must import the MobileRTC class and provide your SDK key and secret for authentication while initializing the SDK.

To do so, first, open your AppDelegate.m file and import the SDK framework by adding the following line of code:

AppDelegate.m
#import <MobileRTC/MobileRTC.h>

Next, store the SDK Key and SDK secret as non-atomic properties.

Note: Your SDK Key and secret are sensitive credentials. We are hardcoding these values here for demonstration purposes only. For production level implementations, we recommend that you generate a JWT using your SDK Key and Secret, and you should never let your Key, Secret, or JWT be publicly accessible.

AppDelegate.m
@property (nonatomic, copy) NSString *sdkKey;
@property (nonatomic, copy) NSString *sdkSecret;

Next, create a method named setupSDK that handles the initialization and authentication of the SDK. To do so, add the following code in your AppDelegate.m file:

AppDelegate.m
// Provide SDK Key and Secret for Authorization of SDK Initialization.
- (void)setupSDK:(NSString *)sdkKey sdkSecret:(NSString *)sdkSecret {
MobileRTCSDKInitContext *context = [[MobileRTCSDKInitContext alloc] init];
context.domain = @"zoom.us";
context.enableLog = YES;
// Initialize the SDK
BOOL sdkInitSuc = [[MobileRTC sharedRTC] initialize:context];
if (sdkInitSuc) {
// Get Auth Service
MobileRTCAuthService *authService = [[MobileRTC sharedRTC] getAuthService];
if (authService) {
// Set up Auth Service
authService.clientKey = sdkKey;
authService.clientSecret = sdkSecret;
authService.delegate = self;
// Call Authentication function to authenticate the SDK
[authService sdkAuth];
}
}
}

Set up a delegate to listen to the SDK authorization updates. First, import the Zoom SDK library and have the AppDelegate conform to MobileRTCAuthDelegate by adding the following code to your AppDelegate.h file:

AppDelegate.h
#import <UIKit/UIKit.h>
// 1. Import Zoom SDK library
#import <MobileRTC/MobileRTC.h>
// 2. Declare that AppDelegate conforms to MobileRTCAuthDelegate
@interface AppDelegate : UIResponder <UIApplicationDelegate, MobileRTCAuthDelegate>
// 3. Call setUpSDK method.
-(void)setupSDK:(NSString *)sdkKey sdkSecret:(NSString *)sdkSecret;
@property (strong, nonatomic) UIWindow *window;
@end

Next, in AppDelegate.m, set the delegate by declaring “authorizationService.delegate = self” and include the delegate functions to listen for changes in the SDK authorization state.

AppDelegate.m
#import "ViewController.h"
#import <MobileRTC/MobileRTC.h>
@interface AppDelegate()
@property (nonatomic, copy) NSString *sdkKey;
@property (nonatomic, copy) NSString *sdkSecret;
@end
@implementation AppDelegate
- (void)setupSDK:(NSString *)sdkKey sdkSecret:(NSString *)sdkSecret {
MobileRTCSDKInitContext *context = [[MobileRTCSDKInitContext alloc] init];
context.domain = @"zoom.us";
context.enableLog = YES;
BOOL sdkInitSuc = [[MobileRTC sharedRTC] initialize:context];
if (sdkInitSuc) {
MobileRTCAuthService *authService = [[MobileRTC sharedRTC] getAuthService];
if (authService) {
authService.clientKey = sdkKey;
authService.clientSecret = sdkSecret;
// Set the authService delegate.
authService.delegate = self;
[authService sdkAuth];
}
}
}
// Include MobileRTCAuthDelegate methods
#pragma mark - MobileRTCAuthDelegate
/**
* To monitor the status and catch errors that might occur during the authorization process, implement the onMobileRTCAuthReturn method
*/
- (void)onMobileRTCAuthReturn:(MobileRTCAuthError)returnValue {
switch (returnValue) {
case MobileRTCAuthError_Success:
NSLog(@"SDK successfully initialized.");
break;
case MobileRTCAuthError_KeyOrSecretEmpty:
NSLog(@"SDK key/secret was not provided. Replace sdkKey and sdkSecret at the top of this file with your SDK key/secret.");
break;
case MobileRTCAuthError_KeyOrSecretWrong:
NSLog(@"SDK key/secret is not valid.");
break;
case MobileRTCAuthError_Unknown:
NSLog(@"SDK key/secret is not valid.");
break;
default:
NSLog(@"SDK Authorization failed with MobileRTCAuthError: %u", returnValue);
}
}

Now, inside the didFinishLaunchingWithOptions, provide the SDK Key and Secret values that will be passed to the setupSDK method for initialization.

In your AppDelegate.m file, add the following lines of code under the line “@ implementation App Delegate” and enter your SDK Key and SDK Secret values in “self.sdkKey” and “self.sdkSecret” properties:

AppDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
/*
Obtain your SDK Key and SDK Secret and paste it here.
Your SDK Secret should NEVER be publicly accessible, only use the sdk key and secret for testing this demo app. For your production level application, you must generate a JWT using the SDK Keys and Secret on the server side instead of storing the SDK Key and SDK Secret directly on the Client.
*/
self.sdkKey = @"";
self.sdkSecret = @"";
[self setupSDK:self.sdkKey sdkSecret:self.sdkSecret];
return YES;
}

Compare your files with the following samples to ensure that you have everything set up properly so far:

#import <UIKit/UIKit.h>
#import <MobileRTC/MobileRTC.h>
@interface AppDelegate : UIResponder <UIApplicationDelegate, MobileRTCAuthDelegate>
-(void)setupSDK:(NSString *)sdkKey sdkSecret:(NSString *)sdkSecret;
@property (strong, nonatomic) UIWindow *window;
#import "AppDelegate.h"
#import "ViewController.h"
#import <MobileRTC/MobileRTC.h>
@interface AppDelegate()
@property (nonatomic, copy) NSString *sdkKey;
@property (nonatomic, copy) NSString *sdkSecret;
@end
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Obtain your SDK Key and SDK Secret and paste it here.
// Your SDK Secret should NEVER be publically accessible, only use the sdk key and secret for testing this demo app.
// For your own application, you must obtain a JWT instead of using the SDK Key and SDK Secret.
self.sdkKey = @"";
self.sdkSecret = @"";
[self setupSDK:self.sdkKey sdkSecret:self.sdkSecret];
return YES;
}
/**
* Initialize the SDK with your credentials. This is required before joining
*/
- (void)setupSDK:(NSString *)sdkKey sdkSecret:(NSString *)sdkSecret {
MobileRTCSDKInitContext *context = [[MobileRTCSDKInitContext alloc] init];
context.domain = @"zoom.us";
context.enableLog = YES;
BOOL sdkInitSuc = [[MobileRTC sharedRTC] initialize:context];
if (sdkInitSuc) {
MobileRTCAuthService *authService = [[MobileRTC sharedRTC] getAuthService];
if (authService) {
authService.clientKey = sdkKey;
authService.clientSecret = sdkSecret;
authService.delegate = self;
[authService sdkAuth];
}
}
}
#pragma mark - MobileRTCAuthDelegate
- (void)onMobileRTCAuthReturn:(MobileRTCAuthError)returnValue {
switch (returnValue) {
case MobileRTCAuthError_Success:
NSLog(@"SDK successfully initialized.");
break;
case MobileRTCAuthError_KeyOrSecretEmpty:
NSLog(@"SDK key/secret was not provided. Replace sdkKey and sdkSecret at the top of this file with your SDK key/secret.");
break;
case MobileRTCAuthError_KeyOrSecretWrong:
NSLog(@"SDK key/secret is not valid.");
break;
case MobileRTCAuthError_Unknown:
NSLog(@"SDK key/secret is not valid.");
break;
default:
NSLog(@"SDK Authorization failed with MobileRTCAuthError: %u", returnValue);
}
}
@end

Navigate to the AppDelegate.swift file. Since you disabled SceneDelagates, you must add a UIWindow to the AppDelegate. Add the following line of code in your AppDelegate.swift file.

AppDelegate.swift
import UIKit
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
//1. Add UIWindow
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
return true
}

The MobileRTC class exposes a generic interface to allow initialization, authentication, and configuration of the Zoom SDK. In order to use the Zoom SDK, you must import the MobileRTC class and provide your SDK key and secret for authentication while initializing the SDK.

To do so, import the SDK framework by adding the following line of code in AppDelegate.swift:

AppDelegate.swift
import MobileRTC

Next, store the SDK Key and SDK secret as constants and create a method named setupSDK that handles the initialization and authentication of the SDK by adding the following lines of code in AppDelegate.swift:

Note: Your SDK Key and secret are sensitive credentials. We are hardcoding these values here for demonstration purposes only. For production level implementations, we recommend that you generate a JWT using your SDK Key and Secret, and you should never let your Key, Secret, or JWT be publicly accessible.

AppDelegate.swift
// Obtain your SDK Key and Secret and paste it here.
let sdkKey = ""
let sdkSecret = ""
// Create a method that handles the initialization and authentication of the SDK
func setupSDK(sdkKey: String, sdkSecret: String) {
let context = MobileRTCSDKInitContext()
context.domain = "zoom.us"
context.enableLog = true
let sdkInitializedSuccessfully = MobileRTC.shared().initialize(context)
if sdkInitializedSuccessfully == true, let authorizationService = MobileRTC.shared().getAuthService() {
authorizationService.clientKey = sdkKey
authorizationService.clientSecret = sdkSecret
authorizationService.sdkAuth()
}
}

Set up a delegate to listen to the SDK authorization updates by conforming AppDelegate to MobileRTCAuthDelegate.

AppDelegate.swift
if sdkInitializedSuccessfully == true, let authorizationService = MobileRTC.shared().getAuthService() {
authorizationService.clientKey = sdkKey
authorizationService.clientSecret = sdkSecret
// Set the delegate
authorizationService.delegate = self
authorizationService.sdkAuth()
}
// MARK: - MobileRTCAuthDelegate
// Conform AppDelegate to MobileRTCAuthDelegate.
// MobileRTCAuthDelegate listens to authorization events like SDK authorization, user login, etc.
extension AppDelegate: MobileRTCAuthDelegate {
// Result of calling sdkAuth(). MobileRTCAuthError_Success represents a successful authorization.
func onMobileRTCAuthReturn(_ returnValue: MobileRTCAuthError) {
switch returnValue {
case MobileRTCAuthError_Success:
print("SDK successfully initialized.")
case MobileRTCAuthError_KeyOrSecretEmpty:
assertionFailure("SDK Key/Secret was not provided. Replace sdkKey and sdkSecret at the top of this file with your SDK Key/Secret.")
case MobileRTCAuthError_KeyOrSecretWrong, MobileRTCAuthError_Unknown:
assertionFailure("SDK Key/Secret is not valid.")
default:
assertionFailure("SDK Authorization failed with MobileRTCAuthError: (returnValue).")
}
}

Now, within the didFinishLaunchingWithOptions, call the setupSDK function to initialize and authorize the SDK.

AppDelegate.swift
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
setupSDK(sdkKey: sdkKey, sdkSecret: sdkSecret)
return true
}

Compare your file with the following sample to ensure that you have everything set up properly so far:

AppDelegate.swift
import UIKit
import MobileRTC
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
// Obtain your SDK Key and SDK Secret and paste it here.
// Your SDK Secret should never be publicly accessible, only use the sdk key and secret for testing this demo app.
// For a production level application, you must generate a JWT using SDK Key and Secret securely instead of using the SDK Key and SDK Secret directly on the client.
let sdkKey = ""
let sdkSecret = ""
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
setupSDK(sdkKey: sdkKey, sdkSecret: sdkSecret)
return true
}
/// setupSDK Creates, Initializes, and Authorizes an instance of the Zoom SDK. This must be called before calling any other SDK functions.
/// - Parameters:
/// - sdkKey: A valid SDK Client Key provided by the Zoom Marketplace.
/// - sdkSecret: A valid SDK Client Secret provided by the Zoom Marketplace.
func setupSDK(sdkKey: String, sdkSecret: String) {
// Create a MobileRTCSDKInitContext. This class contains attributes for determining how the SDK will be used. You must supply the context with a domain.
let context = MobileRTCSDKInitContext()
// The domain we will use is zoom.us
context.domain = "zoom.us"
// Turns on SDK logging. This is optional.
context.enableLog = true
// Call initialize(_ context: MobileRTCSDKInitContext) to create an instance of the Zoom SDK. Without initialization, the SDK will not be operational. This call will return true if the SDK was initialized successfully.
let sdkInitializedSuccessfully = MobileRTC.shared().initialize(context)
// Check if initialization was successful. Obtain a MobileRTCAuthService, this is for supplying credentials to the SDK for authorization.
if sdkInitializedSuccessfully == true, let authorizationService = MobileRTC.shared().getAuthService() {
// Supply the SDK with SDK Key and SDK Secret.
// To use a JWT instead, replace these lines with authorizationService.jwtToken = yourJWTToken.
authorizationService.clientKey = sdkKey
authorizationService.clientSecret = sdkSecret
// Assign AppDelegate to be a MobileRTCAuthDelegate to listen for authorization callbacks.
authorizationService.delegate = self
// Call sdkAuth to perform authorization.
authorizationService.sdkAuth()
}
}
}
// MARK: - MobileRTCAuthDelegate
// Conform AppDelegate to MobileRTCAuthDelegate.
// MobileRTCAuthDelegate listens to authorization events like SDK authorization, user login, etc.
extension AppDelegate: MobileRTCAuthDelegate {
// Result of calling sdkAuth(). MobileRTCAuthError_Success represents a successful authorization.
func onMobileRTCAuthReturn(_ returnValue: MobileRTCAuthError) {
switch returnValue {
case MobileRTCAuthError_Success:
print("SDK successfully initialized.")
case MobileRTCAuthError_KeyOrSecretEmpty:
assertionFailure("SDK Key/Secret was not provided. Replace sdkKey and sdkSecret at the top of this file with your SDK Key/Secret.")
case MobileRTCAuthError_KeyOrSecretWrong, MobileRTCAuthError_Unknown:
assertionFailure("SDK Key/Secret is not valid.")
default:
assertionFailure("SDK Authorization failed with MobileRTCAuthError: (returnValue).")
}
}
}

Click the Build and Run button in the top left corner. If the SDK has been initialized successfully, the app will deploy to your iOS device and you should see “SDK successfully initialized” message in the debugger.

If you run into Untrusted developer error on your device, resolve it by following these steps:

  • Navigate to Settings > General > Device Management.

  • Select the affected profile and trust it.

So far you learned how to successfully integrate the Zoom Client iOS SDK into your app. Next, learn how to design the UI of this app.

Next Steps

Need help?

If you're looking for help, try Developer Support or our Developer Forum. Priority support is also available with Premier Developer Support plans.