Skip to content
This repository was archived by the owner on May 26, 2019. It is now read-only.

Commit f20efaf

Browse files
committed
the start call event can be delivered to JS when app is launched via user activity
1 parent 84ef004 commit f20efaf

File tree

3 files changed

+77
-31
lines changed

3 files changed

+77
-31
lines changed

README.md

Lines changed: 35 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77

88
For more information about **CallKit**, please see [Official CallKit Framework Document][1] or [Introduction to CallKit by Xamarin][2]
99

10+
**Note**: Since CallKit is quite new, this module will be updated frequently so be careful with the version you are using.
11+
1012
## Installation
1113

1214
### NPM module
@@ -27,23 +29,43 @@ In `Xcode` -> `Build Phases` -> `Link Binary With Libraries`, add `CallKit.frame
2729

2830
### AppDelegate.m
2931

32+
#### - Import Library
33+
3034
```obj-c
3135
#import "RNCallKit.h"
36+
```
3237

33-
.
34-
.
35-
.
38+
#### - Change the way you initialise React Root View
3639

40+
Initialise **RNCallKit** first, since we need our custom `observer` of `NSNotificationCenter` to be started as soon as the app is initialising
3741

38-
- (BOOL)application:(UIApplication *)application
39-
openURL:(NSURL *)url
40-
options:(NSDictionary<UIApplicationOpenURLOptionsKey, id> *)options NS_AVAILABLE_IOS(9_0)
41-
{
42+
```diff
4243

43-
return [RNCallKit application:application
44-
openURL:url
45-
options:options];
46-
}
44+
// This is how you normally initialise React Root View, delete it
45+
-RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation
46+
- moduleName:@"MyApp"
47+
- initialProperties:nil
48+
- launchOptions:launchOptions];
49+
50+
// Initialise RNCallKit
51+
+RNCallKit *rncallkit = [[RNCallKit alloc] init];
52+
53+
// Initialise React Bridge with RNCallKit
54+
+RCTBridge *bridge = [[RCTBridge alloc] initWithBundleURL:jsCodeLocation
55+
+ moduleProvider:^{ return @[rncallkit]; }
56+
+ launchOptions:launchOptions];
57+
58+
// Initialise React Root View with React Bridge you've just created
59+
+RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge
60+
+ moduleName:@"MyApp"
61+
+ initialProperties:nil];
62+
```
63+
64+
#### - Handling User Activity
65+
66+
This delegate will be called when the user tries to start a call from native Phone App
67+
68+
```obj-c
4769

4870
- (BOOL)application:(UIApplication *)application
4971
continueUserActivity:(NSUserActivity *)userActivity
@@ -174,7 +196,7 @@ class RNCallKitExample extends React.Component {
174196
*/
175197

176198
let _uuid = uuid.v4();
177-
RNCallKit.startCall(_uuid, data.handle);
199+
RNCallKit.startCall(_uuid, data.handle);
178200
}
179201

180202
onRNCallKitPerformAnswerCallAction() {
@@ -187,7 +209,7 @@ class RNCallKitExample extends React.Component {
187209
}
188210

189211
onRNCallKitPerformEndCallAction() {
190-
/* You will get this event when the user finish the incoming/outgoing call
212+
/* You will get this event when the user finish the incoming/outgoing call
191213
*
192214
* Try to do your normal Hang Up actions here
193215
*

index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ export default class RNCallKit {
2525
RNCallKitDidReceiveStartCallAction,
2626
(data) => { handler(data);}
2727
);
28+
_RNCallKit._startCallActionEventListenerAdded();
2829
} else if (type === 'answerCall') {
2930
listener = _RNCallKitEmitter.addListener(
3031
RNCallKitPerformAnswerCallAction,

ios/RNCallKit/RNCallKit.m

Lines changed: 41 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -15,37 +15,43 @@
1515

1616
#import <AVFoundation/AVAudioSession.h>
1717

18-
NSString *const RNCallKitHandleStartCallNotification = @"RNCallKitHandleStartCallNotification";
19-
NSString *const RNCallKitDidReceiveStartCallAction = @"RNCallKitDidReceiveStartCallAction";
20-
NSString *const RNCallKitPerformAnswerCallAction = @"RNCallKitPerformAnswerCallAction";
21-
NSString *const RNCallKitPerformEndCallAction = @"RNCallKitPerformEndCallAction";
22-
NSString *const RNCallKitDidActivateAudioSession = @"RNCallKitDidActivateAudioSession";
18+
static int const DelayInSeconds = 2;
19+
20+
static NSString *const RNCallKitHandleStartCallNotification = @"RNCallKitHandleStartCallNotification";
21+
static NSString *const RNCallKitDidReceiveStartCallAction = @"RNCallKitDidReceiveStartCallAction";
22+
static NSString *const RNCallKitPerformAnswerCallAction = @"RNCallKitPerformAnswerCallAction";
23+
static NSString *const RNCallKitPerformEndCallAction = @"RNCallKitPerformEndCallAction";
24+
static NSString *const RNCallKitDidActivateAudioSession = @"RNCallKitDidActivateAudioSession";
2325

2426
@implementation RNCallKit
2527
{
2628
NSMutableDictionary *_settings;
2729
NSOperatingSystemVersion _version;
30+
BOOL _isStartCallActionEventListenerAdded;
2831
}
2932

30-
RCT_EXPORT_MODULE()
33+
// should initialise in AppDelegate.m
34+
//RCT_EXPORT_MODULE()
3135

32-
// Override method of RCTEventEmitter
33-
- (void)startObserving
36+
- (instancetype)init
3437
{
3538
#ifdef DEBUG
36-
NSLog(@"[RNCallKit][startObserving]");
39+
NSLog(@"[RNCallKit][init]");
3740
#endif
38-
[[NSNotificationCenter defaultCenter] addObserver:self
39-
selector:@selector(handleStartCallNotification:)
40-
name:RNCallKitHandleStartCallNotification
41-
object:nil];
41+
if (self = [super init]) {
42+
[[NSNotificationCenter defaultCenter] addObserver:self
43+
selector:@selector(handleStartCallNotification:)
44+
name:RNCallKitHandleStartCallNotification
45+
object:nil];
46+
_isStartCallActionEventListenerAdded = NO;
47+
}
48+
return self;
4249
}
4350

44-
// Override method of RCTEventEmitter
45-
- (void)stopObserving
51+
- (void)dealloc
4652
{
4753
#ifdef DEBUG
48-
NSLog(@"[RNCallKit][stopObserving]");
54+
NSLog(@"[RNCallKit][dealloc]");
4955
#endif
5056
[[NSNotificationCenter defaultCenter] removeObserver:self];
5157
}
@@ -149,6 +155,11 @@ - (void)stopObserving
149155
[self requestTransaction:transaction];
150156
}
151157

158+
RCT_EXPORT_METHOD(_startCallActionEventListenerAdded)
159+
{
160+
_isStartCallActionEventListenerAdded = YES;
161+
}
162+
152163
- (void)requestTransaction:(CXTransaction *)transaction
153164
{
154165
#ifdef DEBUG
@@ -272,7 +283,7 @@ + (BOOL)application:(UIApplication *)application
272283
#ifdef DEBUG
273284
NSLog(@"[RNCallKit][application:continueUserActivity]");
274285
#endif
275-
INInteraction *interaction = userActivity.interaction;
286+
INInteraction *interaction = userActivity.interaction;
276287
INPerson *contact;
277288
NSString *handle;
278289

@@ -290,9 +301,11 @@ + (BOOL)application:(UIApplication *)application
290301
@"handle": handle,
291302
@"video": @NO
292303
};
304+
293305
[[NSNotificationCenter defaultCenter] postNotificationName:RNCallKitHandleStartCallNotification
294306
object:self
295307
userInfo:userInfo];
308+
296309
return YES;
297310
}
298311
return NO;
@@ -303,7 +316,17 @@ - (void)handleStartCallNotification:(NSNotification *)notification
303316
#ifdef DEBUG
304317
NSLog(@"[RNCallKit][handleStartCallNotification] userInfo = %@", notification.userInfo);
305318
#endif
306-
[self sendEventWithName:RNCallKitDidReceiveStartCallAction body:notification.userInfo];
319+
int delayInSeconds;
320+
if (!_isStartCallActionEventListenerAdded) {
321+
// Workaround for when app is just launched and JS side hasn't registered to the event properly
322+
delayInSeconds = DelayInSeconds;
323+
} else {
324+
delayInSeconds = 0;
325+
}
326+
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
327+
dispatch_after(popTime, dispatch_get_main_queue(), ^{
328+
[self sendEventWithName:RNCallKitDidReceiveStartCallAction body:notification.userInfo];
329+
});
307330
}
308331

309332
#pragma mark - CXProviderDelegate

0 commit comments

Comments
 (0)