- Notifications
You must be signed in to change notification settings - Fork8
A comprehensive sample app built by OpenTok Accelerator Packs
License
opentok/accelerator-sample-apps-ios
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
This app is built usingaccelerator-core-ios and the following accelerator packs:
Use CocoaPods to install the project files and dependencies.
- Install CocoaPods as described inCocoaPods Getting Started.
- In Terminal,
cd
to your project directory and typepod install
. (Sometimes,pod update
is magical) - Reopen your project in Xcode using the new
*.xcworkspace
file.
Configure the sample app code. Then, build and run the app.
The applicationrequires values forAPI Key,Session ID, andToken. In the sample, you can get these values at theOpenTok Developer Dashboard. For production deployment, you must generate theSession ID andToken values using one of theOpenTok Server SDKs.
Replace the following empty strings with the correspondingAPI Key,Session ID, andToken values:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { self.acceleratorSession = [[OTAcceleratorSessionalloc]initWithOpenTokApiKey:<#apikey#>sessionId:<#sessionid#>token:<#token#>];returnYES;}
func application(_ application:UIApplication, didFinishLaunchingWithOptions launchOptions:[UIApplicationLaunchOptionsKey:Any]?=nil)->Bool{ session=OTAcceleratorSession.init(openTokApiKey:<#apikey#>, sessionId:<#sessionid#>, token:<#token#>)returntrue}
Use Xcode to build and run the app on an iOS simulator or device.
This section shows you how to prepare, build, and run the sample application. Example code is added inObjective-C andSwift. With the sample application you can:
For details about developing with the SDK and the APIs this sample uses, see theOpenTok iOS SDK Requirements and theOpenTok iOS SDK Reference.
NOTE: This sample app collects anonymous usage data for internal TokBox purposes only. Please do not modify or remove any logging code from this sample application.
###Call
When the call button is pressedOTMultiPartyCommunicator
initiates the connection to the OpenTok session and sets up the listeners for the publisher and subscriber streams:
// start call[SVProgressHUDshow];__weak MainViewController *weakSelf = self;[self.multipartyCommunicatorconnectWithHandler:^(OTCommunicationSignal signal, OTMultiPartyRemote *subscriber,NSError *error) {if (!error) { [weakSelfhandleCommunicationSignal:signalremote:subscriber]; }else { [SVProgressHUDshowErrorWithStatus:error.localizedDescription]; }}];
// start callSVProgressHUD.show()multipartyCommunicator.connect{[unowned self](signal, remote, error)inguard error==nilelse{SVProgressHUD.showError(withStatus: error!.localizedDescription)return}self.handleCommunicationSignal(signal, remote: remote)}
The remote connection to the subscriber is handled according to the signal obtained:
- (void)handleCommunicationSignal:(OTCommunicationSignal)signal remote:(OTMultiPartyRemote *)remote {switch (signal) {case OTPublisherCreated: {// join a call [SVProgressHUDpopActivity]; self.multipartyCommunicator.publisherView.showAudioVideoControl =NO; [self.mainViewenableControlButtonsForCall:YES]; [self.mainViewconnectCallHolder:self.multipartyCommunicator.isCallEnabled]; [self.mainViewaddPublisherView:self.multipartyCommunicator.publisherView];break; }case OTSubscriberCreated: {// one participant is ready to join [SVProgressHUDshow]; }case OTSubscriberReady: {// one participant joins [SVProgressHUDpopActivity];if (![self.subscriberscontainsObject:remote]) { [self.subscribersaddObject:remote]; [self.mainViewupdateSubscriberViews:self.subscriberspublisherView:self.multipartyCommunicator.publisherView]; }break; }case OTSubscriberDestroyed:{// one participant leavesif ([self.subscriberscontainsObject:remote]) { [self.subscribersremoveObject:remote]; [self.mainViewupdateSubscriberViews:self.subscriberspublisherView:self.multipartyCommunicator.publisherView]; }break; } ... }}
fileprivatefunc handleCommunicationSignal(_ signal:OTCommunicationSignal, remote:OTMultiPartyRemote?){switch signal{case.publisherCreated: // join a callguardlet multipartyCommunicator= multipartyCommunicatorelse{break}SVProgressHUD.popActivity() multipartyCommunicator.publisherView.showAudioVideoControl=false mainView.enableControlButtonsForCall(enabled:true) mainView.connectCallHolder(connected: multipartyCommunicator.isCallEnabled) mainView.addPublisherView(multipartyCommunicator.publisherView)case.subscriberReady: // one participant joinsSVProgressHUD.popActivity()iflet remote= remote, subscribers.firstIndex(of: remote)==nil{ subscribers.append(remote) mainView.updateSubscriberViews(subscribers, publisherView: multipartyCommunicator?.publisherView)}case.subscriberDestroyed: // one participant leavesiflet remote= remote,let index= subscribers.firstIndex(of: remote){ subscribers.remove(at: index) mainView.updateSubscriberViews(subscribers, publisherView: multipartyCommunicator?.publisherView)}...}}
TheTextCHat feature is built usingaccelerator-textchat-ios. When the text message button is pressed the view changes to present the chat UI:
- (IBAction)textMessageButtonPressed:(id)sender { [selfpresentViewController:[[TextChatTableViewControlleralloc]init]animated:YEScompletion:nil];//When the text message button is pressed the view changes to present the chat UI}
The textchat logic and UI is pre-configured, you can also change properties liketextChatNavigationBar.topItem.title
andalias
inTextChatTableViewController
:
- (void)viewDidLoad { [superviewDidLoad]; self.textChat = [[OTTextChatalloc]init]; self.textChat.dataSource = self; self.textChat.alias =@"Tokboxer"; self.textMessages = [[NSMutableArrayalloc]init]; self.textChatNavigationBar.topItem.title = self.textChat.alias; self.tableView.textChatTableViewDelegate = self; self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone; self.textChatInputView.textField.delegate = self; __weak TextChatTableViewController *weakSelf = self; [self.textChatconnectWithHandler:^(OTTextChatConnectionEventSignal signal, OTConnection *connection,NSError *error) {if (signal == OTTextChatConnectionEventSignalDidConnect) {NSLog(@"Text Chat starts"); }elseif (signal == OTTextChatConnectionEventSignalDidDisconnect) {NSLog(@"Text Chat stops"); } }messageHandler:^(OTTextChatMessageEventSignal signal, OTTextMessage *message,NSError *error) {if (signal == OTTextChatMessageEventSignalDidSendMessage || signal == OTTextChatMessageEventSignalDidReceiveMessage) {if (!error) { [weakSelf.textMessagesaddObject:message]; [weakSelf.tableViewreloadData]; weakSelf.textChatInputView.textField.text =nil; [weakSelfscrollTextChatTableViewToBottom]; } } }]; [self.textChatInputView.sendButtonaddTarget:selfaction:@selector(sendTextMessage)forControlEvents:UIControlEventTouchUpInside];}
overridefunc viewDidLoad(){ super.viewDidLoad() textChat=OTTextChat() textChat?.dataSource=self textChat?.alias="Toxboxer" textChatNavigationBar.topItem?.title= textChat?.alias tableView.textChatTableViewDelegate=self tableView.separatorStyle=.none textChatInputView.textField.delegate=self textChat?.connect(handler:{(signal, connection, error)inguard error==nilelse{SVProgressHUD.showError(withStatus: error!.localizedDescription)return}if signal==.didConnect{print("Text Chat starts")}elseif signal==.didDisconnect{print("Text Chat stops")}}){[unowned self](signal, message, error)inguard error==nil,let message= messageelse{SVProgressHUD.showError(withStatus: error!.localizedDescription)return}self.textMessages.append(message)self.tableView.reloadData()self.textChatInputView.textField.text=nilself.scrollTextChatTableViewToBottom()} textChatInputView.sendButton.addTarget(self, action: #selector(sendTextMessage), for:.touchUpInside)}
Thescreen share features shares images from your camera roll using theScreenShareViewController
class which publishes the content.
- (void)startScreenSharing { self.multipartyScreenSharer = [[OTMultiPartyCommunicatoralloc]initWithView:self.annotationView]; self.multipartyScreenSharer.dataSource = self;// publishOnly here is to avoid subscripting to those who already subscribed self.multipartyScreenSharer.publishOnly =YES; __weak ScreenShareViewController *weakSelf = self; [self.multipartyScreenSharerconnectWithHandler:^(OTCommunicationSignal signal, OTMultiPartyRemote *subscriber,NSError *error) {if (error) { [weakSelfdismissViewControllerAnimated:YEScompletion:^(){ [SVProgressHUDshowErrorWithStatus:error.localizedDescription]; }];return; }if (signal == OTPublisherCreated) { weakSelf.multipartyScreenSharer.publishAudio =NO; [weakSelfstartAnnotation]; } }];}
fileprivatefunc startScreenSharing(){ multipartyScreenSharer=OTMultiPartyCommunicator.init(view: annotationView) multipartyScreenSharer?.dataSource=self // publishOnly here is to avoid subscripting to those who already subscribed multipartyScreenSharer?.isPublishOnly=true multipartyScreenSharer?.connect{[unowned self](signal, remote, error)inguard error==nilelse{self.dismiss(animated:true){SVProgressHUD.showError(withStatus: error!.localizedDescription)}return}if signal==.publisherCreated{self.multipartyScreenSharer?.isPublishAudio=falseself.startAnnotation()}}}
TheScreenShareViewController
class also handles local annotation:
The beta version is unstable when it comes to work with cross-platform, it's much stable if two canvas has same aspect ratio.
- (void)startAnnotation { self.annotator = [[OTAnnotatoralloc]init]; self.annotator.dataSource = self; __weak ScreenShareViewController *weakSelf = self; [self.annotatorconnectWithCompletionHandler:^(OTAnnotationSignal signal,NSError *error) {if (error) { [weakSelfdismissViewControllerAnimated:YEScompletion:^(){ [SVProgressHUDshowErrorWithStatus:error.localizedDescription]; }];return; }if (signal == OTAnnotationSessionDidConnect) {// using frame and self.view to contain toolbarView is for having more space to interact with color picker [weakSelf.annotator.annotationScrollViewinitializeToolbarView]; weakSelf.annotator.annotationScrollView.toolbarView.toolbarViewDataSource = self; weakSelf.annotator.annotationScrollView.toolbarView.frame = weakSelf.annotationToolbarView.frame; [weakSelf.viewaddSubview:weakSelf.annotator.annotationScrollView.toolbarView]; weakSelf.annotator.annotationScrollView.frame = weakSelf.annotationView.bounds; weakSelf.annotator.annotationScrollView.scrollView.contentSize =CGSizeMake(CGRectGetWidth(weakSelf.annotator.annotationScrollView.bounds),CGRectGetHeight(weakSelf.annotator.annotationScrollView.bounds)); [weakSelf.annotationViewaddSubview:weakSelf.annotator.annotationScrollView]; weakSelf.annotator.annotationScrollView.annotatable =NO; } }];}
fileprivatefunc startAnnotation(){ annotator=OTAnnotator() annotator?.dataSource=self annotator?.connect{[unowned self](signal, error)inguard error==nilelse{self.dismiss(animated:true){SVProgressHUD.showError(withStatus: error!.localizedDescription)}return}if signal==.sessionDidConnect{guardlet annotator=self.annotator,let toolbarView= annotator.annotationScrollView.toolbarViewelse{print("Error on launching annotation")return} // using frame and self.view to contain toolbarView is for having more space to interact with color pickerself.annotator?.annotationScrollView.initializeToolbarView() toolbarView.toolbarViewDataSource=self toolbarView.frame=self.annotationToolbarView.frameself.view.addSubview(toolbarView) annotator.annotationScrollView.frame=self.annotationView.bounds; annotator.annotationScrollView.scrollView.contentSize=CGSize(width:CGFloat(annotator.annotationScrollView.bounds.width), height:CGFloat(annotator.annotationScrollView.bounds.height))self.annotationView.addSubview(annotator.annotationScrollView) annotator.annotationScrollView.isAnnotatable=false}}}
Interested in contributing? We ❤️ pull requests! See theContribution guidelines.
We love to hear from you so if you have questions, comments or find a bug in the project, let us know! You can either:
- Open an issue on this repository
- Seehttps://support.tokbox.com/ for support options
- Tweet at us! We're@VonageDev on Twitter
- Orjoin the Vonage Developer Community Slack
- Check out the Developer Documentation athttps://tokbox.com/developer/
About
A comprehensive sample app built by OpenTok Accelerator Packs
Topics
Resources
License
Code of conduct
Uh oh!
There was an error while loading.Please reload this page.
Stars
Watchers
Forks
Releases
Packages0
Uh oh!
There was an error while loading.Please reload this page.
Contributors6
Uh oh!
There was an error while loading.Please reload this page.