Skip to content

Commit 5111fe2

Browse files
authored
Merge pull request #205 from react-native-webrtc/pr/169
Handle issue with JS not initialized on start to fix #107
2 parents 263dfa7 + b28e0ec commit 5111fe2

File tree

5 files changed

+78
-32
lines changed

5 files changed

+78
-32
lines changed

README.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -528,6 +528,26 @@ RNCallKeep.addEventListener('didPerformDTMFAction', ({ digits, callUUID }) => {
528528
- `callUUID` (string)
529529
- The UUID of the call.
530530

531+
### - didLoadWithEvents
532+
533+
iOS only.
534+
535+
Called as soon as JS context initializes if there were some actions performed by user before JS context has been created.
536+
537+
Since iOS 13, you must display incoming call on receiving PushKit push notification. But if app was killed, it takes some time to create JS context. If user answers the call (or ends it) before JS context has been initialized, user actions will be passed as events array of this event. Similar situation can happen if user would like to start a call from Recents or similar iOS app, assuming that your app was in killed state.
538+
539+
```js
540+
RNCallKeep.addEventListener('didLoadWithEvents', (events) => {
541+
// see example usage in https://github.com/react-native-webrtc/react-native-callkeep/pull/169
542+
});
543+
```
544+
545+
- `events` Array
546+
- `name`: string
547+
Native event name like: `RNCallKeepPerformAnswerCallAction`
548+
- `data`: object
549+
Object with data passed together with specific event so it can be handled in the same way like original event, for example `({ callUUID })` for `answerCall` event if `name` is `RNCallKeepPerformAnswerCallAction`
550+
531551
### - checkReachability
532552

533553
On Android when the application is in background, after a certain delay the OS will close every connection with informing about it.

actions.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ const RNCallKeepDidToggleHoldAction = 'RNCallKeepDidToggleHoldAction';
1414
const RNCallKeepDidPerformDTMFAction = 'RNCallKeepDidPerformDTMFAction';
1515
const RNCallKeepProviderReset = 'RNCallKeepProviderReset';
1616
const RNCallKeepCheckReachability = 'RNCallKeepCheckReachability';
17+
const RNCallKeepDidLoadWithEvents = 'RNCallKeepDidLoadWithEvents';
1718
const isIOS = Platform.OS === 'ios';
1819

1920
const didReceiveStartCallAction = handler => {
@@ -55,6 +56,11 @@ const didResetProvider = handler =>
5556
const checkReachability = handler =>
5657
eventEmitter.addListener(RNCallKeepCheckReachability, handler);
5758

59+
const didLoadWithEvents = handler =>
60+
eventEmitter.addListener(RNCallKeepDidLoadWithEvents, handler);
61+
62+
export const emit = (eventName, payload) => eventEmitter.emit(eventName, payload);
63+
5864
export const listeners = {
5965
didReceiveStartCallAction,
6066
answerCall,
@@ -67,4 +73,5 @@ export const listeners = {
6773
didPerformDTMFAction,
6874
didResetProvider,
6975
checkReachability,
76+
didLoadWithEvents,
7077
};

index.d.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ export type Events =
99
'didPerformDTMFAction' |
1010
'didResetProvider' |
1111
'checkReachability' |
12-
'didPerformSetMutedCallAction';
12+
'didPerformSetMutedCallAction' |
13+
'didLoadWithEvents';
1314

1415
type HandleType = 'generic' | 'number' | 'email';
1516

index.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { NativeModules, Platform, Alert } from 'react-native';
22

3-
import { listeners } from './actions'
3+
import { listeners, emit } from './actions'
44

55
const RNCallKeepModule = NativeModules.RNCallKeep;
66
const isIOS = Platform.OS === 'ios';
@@ -22,6 +22,12 @@ class RNCallKeep {
2222

2323
constructor() {
2424
this._callkeepEventHandlers = new Map();
25+
26+
this.addEventListener('didLoadWithEvents', (events) => {
27+
events.forEach(event => {
28+
emit(event.name, event.data);
29+
});
30+
});
2531
}
2632

2733
addEventListener = (type, handler) => {

ios/RNCallKeep/RNCallKeep.m

Lines changed: 42 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,14 @@
3333
static NSString *const RNCallKeepDidToggleHoldAction = @"RNCallKeepDidToggleHoldAction";
3434
static NSString *const RNCallKeepProviderReset = @"RNCallKeepProviderReset";
3535
static NSString *const RNCallKeepCheckReachability = @"RNCallKeepCheckReachability";
36+
static NSString *const RNCallKeepDidLoadWithEvents = @"RNCallKeepDidLoadWithEvents";
3637

3738
@implementation RNCallKeep
3839
{
3940
NSOperatingSystemVersion _version;
4041
BOOL _isStartCallActionEventListenerAdded;
42+
bool _hasListeners;
43+
NSMutableArray *_delayedEvents;
4144
}
4245

4346
static CXProvider* sharedProvider;
@@ -52,6 +55,7 @@ - (instancetype)init
5255
#endif
5356
if (self = [super init]) {
5457
_isStartCallActionEventListenerAdded = NO;
58+
_delayedEvents = [NSMutableArray array];
5559
}
5660
return self;
5761
}
@@ -92,10 +96,36 @@ - (void)dealloc
9296
RNCallKeepPerformPlayDTMFCallAction,
9397
RNCallKeepDidToggleHoldAction,
9498
RNCallKeepProviderReset,
95-
RNCallKeepCheckReachability
99+
RNCallKeepCheckReachability,
100+
RNCallKeepDidLoadWithEvents
96101
];
97102
}
98103

104+
- (void)startObserving
105+
{
106+
_hasListeners = YES;
107+
if ([_delayedEvents count] > 0) {
108+
[self sendEventWithName:RNCallKeepDidLoadWithEvents body:_delayedEvents];
109+
}
110+
}
111+
112+
- (void)stopObserving
113+
{
114+
_hasListeners = FALSE;
115+
}
116+
117+
- (void)sendEventWithNameWrapper:(NSString *)name body:(id)body {
118+
if (_hasListeners) {
119+
[self sendEventWithName:name body:body];
120+
} else {
121+
NSDictionary *dictionary = @{
122+
@"name": name,
123+
@"data": body
124+
};
125+
[_delayedEvents addObject:dictionary];
126+
}
127+
}
128+
99129
+ (void)initCallKitProvider {
100130
if (sharedProvider == nil) {
101131
NSDictionary *settings = [[NSUserDefaults standardUserDefaults] dictionaryForKey:@"RNCallKeepSettings"];
@@ -392,7 +422,7 @@ + (void)reportNewIncomingCall:(NSString *)uuidString
392422
[RNCallKeep initCallKitProvider];
393423
[sharedProvider reportNewIncomingCallWithUUID:uuid update:callUpdate completion:^(NSError * _Nullable error) {
394424
RNCallKeep *callKeep = [RNCallKeep allocWithZone: nil];
395-
[callKeep sendEventWithName:RNCallKeepDidDisplayIncomingCall body:@{
425+
[callKeep sendEventWithNameWrapper:RNCallKeepDidDisplayIncomingCall body:@{
396426
@"error": error && error.localizedDescription ? error.localizedDescription : @"",
397427
@"callUUID": uuidString,
398428
@"handle": handle,
@@ -588,7 +618,7 @@ + (BOOL)application:(UIApplication *)application
588618
};
589619

590620
RNCallKeep *callKeep = [RNCallKeep allocWithZone: nil];
591-
[callKeep handleStartCallNotification: userInfo];
621+
[callKeep sendEventWithNameWrapper:RNCallKeepDidReceiveStartCallAction body:userInfo];
592622
return YES;
593623
}
594624
return NO;
@@ -599,24 +629,6 @@ + (BOOL)requiresMainQueueSetup
599629
return YES;
600630
}
601631

602-
- (void)handleStartCallNotification:(NSDictionary *)userInfo
603-
{
604-
#ifdef DEBUG
605-
NSLog(@"[RNCallKeep][handleStartCallNotification] userInfo = %@", userInfo);
606-
#endif
607-
int delayInSeconds;
608-
if (!_isStartCallActionEventListenerAdded) {
609-
// Workaround for when app is just launched and JS side hasn't registered to the event properly
610-
delayInSeconds = OUTGOING_CALL_WAKEUP_DELAY;
611-
} else {
612-
delayInSeconds = 0;
613-
}
614-
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
615-
dispatch_after(popTime, dispatch_get_main_queue(), ^{
616-
[self sendEventWithName:RNCallKeepDidReceiveStartCallAction body:userInfo];
617-
});
618-
}
619-
620632
#pragma mark - CXProviderDelegate
621633

622634
- (void)providerDidReset:(CXProvider *)provider{
@@ -625,7 +637,7 @@ - (void)providerDidReset:(CXProvider *)provider{
625637
#endif
626638
//this means something big changed, so tell the JS. The JS should
627639
//probably respond by hanging up all calls.
628-
[self sendEventWithName:RNCallKeepProviderReset body:nil];
640+
[self sendEventWithNameWrapper:RNCallKeepProviderReset body:nil];
629641
}
630642

631643
// Starting outgoing call
@@ -637,7 +649,7 @@ - (void)provider:(CXProvider *)provider performStartCallAction:(CXStartCallActio
637649
//do this first, audio sessions are flakey
638650
[self configureAudioSession];
639651
//tell the JS to actually make the call
640-
[self sendEventWithName:RNCallKeepDidReceiveStartCallAction body:@{ @"callUUID": [action.callUUID.UUIDString lowercaseString], @"handle": action.handle.value }];
652+
[self sendEventWithNameWrapper:RNCallKeepDidReceiveStartCallAction body:@{ @"callUUID": [action.callUUID.UUIDString lowercaseString], @"handle": action.handle.value }];
641653
[action fulfill];
642654
}
643655

@@ -662,7 +674,7 @@ - (void)provider:(CXProvider *)provider performAnswerCallAction:(CXAnswerCallAct
662674
NSLog(@"[RNCallKeep][CXProviderDelegate][provider:performAnswerCallAction]");
663675
#endif
664676
[self configureAudioSession];
665-
[self sendEventWithName:RNCallKeepPerformAnswerCallAction body:@{ @"callUUID": [action.callUUID.UUIDString lowercaseString] }];
677+
[self sendEventWithNameWrapper:RNCallKeepPerformAnswerCallAction body:@{ @"callUUID": [action.callUUID.UUIDString lowercaseString] }];
666678
[action fulfill];
667679
}
668680

@@ -672,7 +684,7 @@ - (void)provider:(CXProvider *)provider performEndCallAction:(CXEndCallAction *)
672684
#ifdef DEBUG
673685
NSLog(@"[RNCallKeep][CXProviderDelegate][provider:performEndCallAction]");
674686
#endif
675-
[self sendEventWithName:RNCallKeepPerformEndCallAction body:@{ @"callUUID": [action.callUUID.UUIDString lowercaseString] }];
687+
[self sendEventWithNameWrapper:RNCallKeepPerformEndCallAction body:@{ @"callUUID": [action.callUUID.UUIDString lowercaseString] }];
676688
[action fulfill];
677689
}
678690

@@ -682,15 +694,15 @@ -(void)provider:(CXProvider *)provider performSetHeldCallAction:(CXSetHeldCallAc
682694
NSLog(@"[RNCallKeep][CXProviderDelegate][provider:performSetHeldCallAction]");
683695
#endif
684696

685-
[self sendEventWithName:RNCallKeepDidToggleHoldAction body:@{ @"hold": @(action.onHold), @"callUUID": [action.callUUID.UUIDString lowercaseString] }];
697+
[self sendEventWithNameWrapper:RNCallKeepDidToggleHoldAction body:@{ @"hold": @(action.onHold), @"callUUID": [action.callUUID.UUIDString lowercaseString] }];
686698
[action fulfill];
687699
}
688700

689701
- (void)provider:(CXProvider *)provider performPlayDTMFCallAction:(CXPlayDTMFCallAction *)action {
690702
#ifdef DEBUG
691703
NSLog(@"[RNCallKeep][CXProviderDelegate][provider:performPlayDTMFCallAction]");
692704
#endif
693-
[self sendEventWithName:RNCallKeepPerformPlayDTMFCallAction body:@{ @"digits": action.digits, @"callUUID": [action.callUUID.UUIDString lowercaseString] }];
705+
[self sendEventWithNameWrapper:RNCallKeepPerformPlayDTMFCallAction body:@{ @"digits": action.digits, @"callUUID": [action.callUUID.UUIDString lowercaseString] }];
694706
[action fulfill];
695707
}
696708

@@ -700,7 +712,7 @@ -(void)provider:(CXProvider *)provider performSetMutedCallAction:(CXSetMutedCall
700712
NSLog(@"[RNCallKeep][CXProviderDelegate][provider:performSetMutedCallAction]");
701713
#endif
702714

703-
[self sendEventWithName:RNCallKeepDidPerformSetMutedCallAction body:@{ @"muted": @(action.muted), @"callUUID": [action.callUUID.UUIDString lowercaseString] }];
715+
[self sendEventWithNameWrapper:RNCallKeepDidPerformSetMutedCallAction body:@{ @"muted": @(action.muted), @"callUUID": [action.callUUID.UUIDString lowercaseString] }];
704716
[action fulfill];
705717
}
706718

@@ -724,15 +736,15 @@ - (void)provider:(CXProvider *)provider didActivateAudioSession:(AVAudioSession
724736
[[NSNotificationCenter defaultCenter] postNotificationName:AVAudioSessionInterruptionNotification object:nil userInfo:userInfo];
725737

726738
[self configureAudioSession];
727-
[self sendEventWithName:RNCallKeepDidActivateAudioSession body:nil];
739+
[self sendEventWithNameWrapper:RNCallKeepDidActivateAudioSession body:nil];
728740
}
729741

730742
- (void)provider:(CXProvider *)provider didDeactivateAudioSession:(AVAudioSession *)audioSession
731743
{
732744
#ifdef DEBUG
733745
NSLog(@"[RNCallKeep][CXProviderDelegate][provider:didDeactivateAudioSession]");
734746
#endif
735-
[self sendEventWithName:RNCallKeepDidDeactivateAudioSession body:nil];
747+
[self sendEventWithNameWrapper:RNCallKeepDidDeactivateAudioSession body:nil];
736748
}
737749

738750
@end

0 commit comments

Comments
 (0)