Skip to content
This repository was archived by the owner on Jan 18, 2020. It is now read-only.

Commit b65a90d

Browse files
Provide sample to play custom ringtone when answer-on-bridge is enabled (#195)
* Provide sample to play custom ringtone when answer-on-bridge is enabled
1 parent ff81c39 commit b65a90d

File tree

3 files changed

+83
-1
lines changed

3 files changed

+83
-1
lines changed

ObjcVoiceQuickstart.xcodeproj/project.pbxproj

+11
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
2459FDD61D83664300917CA9 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 2459FDD51D83664300917CA9 /* Assets.xcassets */; };
1515
2459FDD91D83664300917CA9 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 2459FDD71D83664300917CA9 /* LaunchScreen.storyboard */; };
1616
24BA34291D87431000B0B4F7 /* TwilioLogo.png in Resources */ = {isa = PBXBuildFile; fileRef = 24BA34281D87431000B0B4F7 /* TwilioLogo.png */; };
17+
8F6BABF623973FE80030BE4F /* ringtone.wav in Resources */ = {isa = PBXBuildFile; fileRef = 8F6BABF523973FE80030BE4F /* ringtone.wav */; };
1718
/* End PBXBuildFile section */
1819

1920
/* Begin PBXFileReference section */
@@ -29,6 +30,7 @@
2930
2459FDDA1D83664300917CA9 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
3031
24BA34241D87269500B0B4F7 /* ObjCVoiceQuickstart.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = ObjCVoiceQuickstart.entitlements; sourceTree = "<group>"; };
3132
24BA34281D87431000B0B4F7 /* TwilioLogo.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = TwilioLogo.png; sourceTree = "<group>"; };
33+
8F6BABF523973FE80030BE4F /* ringtone.wav */ = {isa = PBXFileReference; lastKnownFileType = audio.wav; path = ringtone.wav; sourceTree = "<group>"; };
3234
/* End PBXFileReference section */
3335

3436
/* Begin PBXFrameworksBuildPhase section */
@@ -48,6 +50,7 @@
4850
2459FDC81D83664300917CA9 /* ObjCVoiceQuickstart */,
4951
2459FDC71D83664300917CA9 /* Products */,
5052
5FF12A4D246637936B670360 /* Frameworks */,
53+
8F6BABF423973FE80030BE4F /* ringtone */,
5154
);
5255
sourceTree = "<group>";
5356
};
@@ -92,6 +95,14 @@
9295
name = Frameworks;
9396
sourceTree = "<group>";
9497
};
98+
8F6BABF423973FE80030BE4F /* ringtone */ = {
99+
isa = PBXGroup;
100+
children = (
101+
8F6BABF523973FE80030BE4F /* ringtone.wav */,
102+
);
103+
path = ringtone;
104+
sourceTree = "<group>";
105+
};
95106
/* End PBXGroup section */
96107

97108
/* Begin PBXNativeTarget section */

ObjcVoiceQuickstart/ViewController.m

+72-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
static NSString *const kIdentity = @"alice";
1919
static NSString *const kTwimlParamTo = @"to";
2020

21-
@interface ViewController () <PKPushRegistryDelegate, TVONotificationDelegate, TVOCallDelegate, CXProviderDelegate, UITextFieldDelegate>
21+
@interface ViewController () <PKPushRegistryDelegate, TVONotificationDelegate, TVOCallDelegate, CXProviderDelegate, UITextFieldDelegate, AVAudioPlayerDelegate>
2222

2323
@property (nonatomic, strong) NSString *deviceTokenString;
2424

@@ -45,6 +45,9 @@ @interface ViewController () <PKPushRegistryDelegate, TVONotificationDelegate, T
4545
@property (weak, nonatomic) IBOutlet UISwitch *muteSwitch;
4646
@property (weak, nonatomic) IBOutlet UISwitch *speakerSwitch;
4747

48+
@property (nonatomic, assign) BOOL playCustomRingback;
49+
@property (nonatomic, strong) AVAudioPlayer *ringtonePlayer;
50+
4851
@end
4952

5053
@implementation ViewController
@@ -71,6 +74,14 @@ - (void)viewDidLoad {
7174

7275
self.activeCallInvites = [NSMutableDictionary dictionary];
7376
self.activeCalls = [NSMutableDictionary dictionary];
77+
78+
/*
79+
Custom ringback will be played when this flag is enabled.
80+
When [answerOnBridge](https://www.twilio.com/docs/voice/twiml/dial#answeronbridge) is enabled in
81+
the <Dial> TwiML verb, the caller will not hear the ringback while the call is ringing and awaiting
82+
to be accepted on the callee's side. Configure this flag based on the TwiML application.
83+
*/
84+
self.playCustomRingback = NO;
7485
}
7586

7687
- (void)configureCallKit {
@@ -361,11 +372,25 @@ - (void)cancelledCallInviteReceived:(TVOCancelledCallInvite *)cancelledCallInvit
361372
- (void)callDidStartRinging:(TVOCall *)call {
362373
NSLog(@"callDidStartRinging:");
363374

375+
/*
376+
When [answerOnBridge](https://www.twilio.com/docs/voice/twiml/dial#answeronbridge) is enabled in the
377+
<Dial> TwiML verb, the caller will not hear the ringback while the call is ringing and awaiting to be
378+
accepted on the callee's side. The application can use the `AVAudioPlayer` to play custom audio files
379+
between the `[TVOCallDelegate callDidStartRinging:]` and the `[TVOCallDelegate callDidConnect:]` callbacks.
380+
*/
381+
if (self.playCustomRingback) {
382+
[self playRingback];
383+
}
384+
364385
[self.placeCallButton setTitle:@"Ringing" forState:UIControlStateNormal];
365386
}
366387

367388
- (void)callDidConnect:(TVOCall *)call {
368389
NSLog(@"callDidConnect:");
390+
391+
if (self.playCustomRingback) {
392+
[self stopRingback];
393+
}
369394

370395
self.callKitCompletionCallback(YES);
371396

@@ -425,6 +450,10 @@ - (void)callDisconnected:(TVOCall *)call {
425450

426451
self.userInitiatedDisconnect = NO;
427452

453+
if (self.playCustomRingback) {
454+
[self stopRingback];
455+
}
456+
428457
[self stopSpin];
429458
[self toggleUIState:YES showCallControl:NO];
430459
[self.placeCallButton setTitle:@"Call" forState:UIControlStateNormal];
@@ -686,4 +715,46 @@ - (void)performAnswerVoiceCallWithUUID:(NSUUID *)uuid
686715
}
687716
}
688717

718+
#pragma mark - Ringtone
719+
720+
- (void)playRingback {
721+
NSString *ringtonePath = [[NSBundle mainBundle] pathForResource:@"ringtone" ofType:@"wav"];
722+
if ([ringtonePath length] <= 0) {
723+
NSLog(@"Can't find sound file");
724+
return;
725+
}
726+
727+
NSError *error;
728+
self.ringtonePlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL URLWithString:ringtonePath] error:&error];
729+
if (error != nil) {
730+
NSLog(@"Failed to initialize audio player: %@", error);
731+
} else {
732+
self.ringtonePlayer.delegate = self;
733+
self.ringtonePlayer.numberOfLoops = -1;
734+
735+
self.ringtonePlayer.volume = 1.0f;
736+
[self.ringtonePlayer play];
737+
}
738+
}
739+
740+
- (void)stopRingback {
741+
if (!self.ringtonePlayer.isPlaying) {
742+
return;
743+
}
744+
745+
[self.ringtonePlayer stop];
746+
}
747+
748+
- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag {
749+
if (flag) {
750+
NSLog(@"Audio player finished playing successfully");
751+
} else {
752+
NSLog(@"Audio player finished playing with some error");
753+
}
754+
}
755+
756+
- (void)audioPlayerDecodeErrorDidOccur:(AVAudioPlayer *)player error:(NSError *)error {
757+
NSLog(@"Decode error occurred: %@", error);
758+
}
759+
689760
@end

ringtone/ringtone.wav

363 KB
Binary file not shown.

0 commit comments

Comments
 (0)