react-native-webrtc / react-native-webrtc/react-native-callkeep

didLoadWithEvents always getting RNCallKeepDidDisplayIncomingCall

Open
#330 60 comments 2 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Java
Stars
1.1k
Forks
511
Avg merge
9h 12m
Merged PRs (30d)
2

Description

Bug report

  • I've checked the example to reproduce the issue.

  • Reproduced on:

  • iOS

Description

I have tried to register didLoadWithEvents in index.js and as well as App.js which is my first component. Both are returning RNCallKeepDidDisplayIncomingCall even if i press accept button right when callkit ui appears, i don't get acll accept event name here and if i press accept, i don't get answercall event either

Steps to Reproduce

Versions

- Callkeep: 4.0
- React Native: 0.63.3
- iOS: 14
- Phone model: iPhone 7 

Logs

[Thu Nov 26 2020 15:51:10.950] LOG didLoadWithEvents -> events {"data": {"callUUID": "f7f3f338-4c65-416a-893e-522ce1f3de68", "error": "", "fromPushKit": "1", "handle": "Task: Adnana", "hasVideo": "1", "localizedCallerName": "Adnan guild2 (Connecting...)", "payload": {"35video": true, "53video": true, "callId": "rymTxN91PDVWQIcCOp8q", "callUUID": "f7f3f338-4c65-416a-893e-522ce1f3de68", "callerAvatar": "", "callerId": 53, "callerName": "Adnan guild2", "channelId": "...", "recieverId": 35, "status": "incomingCall", "taskId": 711, "title": "Adnana", "type": "video"}, "supportsDTMF": "0", "supportsGrouping": "0", "supportsHolding": "0", "supportsUngrouping": "0"}, "name": "RNCallKeepDidDisplayIncomingCall"}

#import "AppDelegate.h"

#import <React/RCTBridge.h>
#import <React/RCTBundleURLProvider.h>
#import <React/RCTRootView.h>
#import <Firebase.h>
#import "RNFirebaseNotifications.h"
#import "RNFirebaseMessaging.h"
#import "RNSplashScreen.h"

#import "RNCallKeep.h"

//VOIP
#import <PushKit/PushKit.h>                    /* <------ add this line */
#import "RNVoipPushNotificationManager.h"      /* <------ add this line */

#ifdef FB_SONARKIT_ENABLED
#import <FlipperKit/FlipperClient.h>
#import <FlipperKitLayoutPlugin/FlipperKitLayoutPlugin.h>
#import <FlipperKitUserDefaultsPlugin/FKUserDefaultsPlugin.h>
#import <FlipperKitNetworkPlugin/FlipperKitNetworkPlugin.h>
#import <SKIOSNetworkPlugin/SKIOSNetworkAdapter.h>
#import <FlipperKitReactPlugin/FlipperKitReactPlugin.h>

//VOIP

static void InitializeFlipper(UIApplication *application) {
  FlipperClient *client = [FlipperClient sharedClient];
  SKDescriptorMapper *layoutDescriptorMapper = [[SKDescriptorMapper alloc] initWithDefaults];
  [client addPlugin:[[FlipperKitLayoutPlugin alloc] initWithRootNode:application withDescriptorMapper:layoutDescriptorMapper]];
  [client addPlugin:[[FKUserDefaultsPlugin alloc] initWithSuiteName:nil]];
  [client addPlugin:[FlipperKitReactPlugin new]];
  [client addPlugin:[[FlipperKitNetworkPlugin alloc] initWithNetworkAdapter:[SKIOSNetworkAdapter new]]];
  [client start];
}
#endif

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
  [FIRApp configure];
  [RNFirebaseNotifications configure];
#ifdef FB_SONARKIT_ENABLED
  InitializeFlipper(application);
#endif
  
  

  RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions];
  
  RNVoipPushNotificationManager* voipModule = [bridge moduleForClass:[RNVoipPushNotificationManager class]];
  [voipModule voipRegistration];
  
  
  RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge
                                                   moduleName:@"Artisan"
                                            initialProperties:nil];

  rootView.backgroundColor = [[UIColor alloc] initWithRed:1.0f green:1.0f blue:1.0f alpha:1];

  self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
  UIViewController *rootViewController = [UIViewController new];
  rootViewController.view = rootView;
  self.window.rootViewController = rootViewController;
  [self.window makeKeyAndVisible];
  [RNSplashScreen show]; 
  return YES;
}

- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification {
  [[RNFirebaseNotifications instance] didReceiveLocalNotification:notification];
}

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(nonnull NSDictionary *)userInfo
                                                       fetchCompletionHandler:(nonnull void (^)(UIBackgroundFetchResult))completionHandler{
  [[RNFirebaseNotifications instance] didReceiveRemoteNotification:userInfo fetchCompletionHandler:completionHandler];
}

- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings {
  [[RNFirebaseMessaging instance] didRegisterUserNotificationSettings:notificationSettings];
}

- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
{
#if DEBUG
  return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil];
#else
  return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
#endif
}



 - (BOOL)application:(UIApplication *)application
 continueUserActivity:(NSUserActivity *)userActivity
   restorationHandler:(void(^)(NSArray * __nullable restorableObjects))restorationHandler
 {
   return [RNCallKeep application:application
            continueUserActivity:userActivity
              restorationHandler:restorationHandler];
 }


//VOIP
/* Add PushKit delegate method */

// --- Handle updated push credentials
- (void)pushRegistry:(PKPushRegistry *)registry didUpdatePushCredentials:(PKPushCredentials *)credentials forType:(PKPushType)type {
  // Register VoIP push token (a property of PKPushCredentials) with server
  [RNVoipPushNotificationManager didUpdatePushCredentials:credentials forType:(NSString *)type];
}

- (void)pushRegistry:(PKPushRegistry *)registry didInvalidatePushTokenForType:(PKPushType)type
{
  // --- The system calls this method when a previously provided push token is no longer valid for use. No action is necessary on your part to reregister the push type. Instead, use this method to notify your server not to send push notifications using the matching push token.
}


// --- Handle incoming pushes (for ios <= 10)
- (void)pushRegistry:(PKPushRegistry *)registry didReceiveIncomingPushWithPayload:(PKPushPayload *)payload forType:(PKPushType)type {
  [RNVoipPushNotificationManager didReceiveIncomingPushWithPayload:payload forType:(NSString *)type];
}

// --- Handle incoming pushes (for ios >= 11)
- (void)pushRegistry:(PKPushRegistry *)registry didReceiveIncomingPushWithPayload:(PKPushPayload *)payload forType:(PKPushType)type withCompletionHandler:(void (^)(void))completion {
  

  // --- NOTE: apple forced us to invoke callkit ASAP when we receive voip push
  // --- see: react-native-callkeep

  // --- Retrieve information from your voip push payload
  NSString *uuid = payload.dictionaryPayload[@"uuid"];
  NSString *callerName = [NSString stringWithFormat:@"%@ (Connecting...)", payload.dictionaryPayload[@"callerName"]];
  NSString *handle = payload.dictionaryPayload[@"handle"];
  NSString *callData = payload.dictionaryPayload[@"callData"];
  

  // --- this is optional, only required if you want to call `completion()` on the js side
  [RNVoipPushNotificationManager addCompletionHandler:uuid completionHandler:completion];

  // --- Process the received push
  [RNVoipPushNotificationManager didReceiveIncomingPushWithPayload:payload forType:(NSString *)type];

  // --- You should make sure to report to callkit BEFORE execute `completion()`
//  [RNCallKeep reportNewIncomingCall:uuid
//                             handle:handle
//                         handleType:@"generic"
//                           hasVideo:true
//                localizedCallerName:callerName
//                        fromPushKit: YES
//                            payload:callData];
//
  [RNCallKeep reportNewIncomingCall: uuid
                 handle: handle
             handleType: @"generic"
               hasVideo: true
    localizedCallerName: callerName
        supportsHolding: false
           supportsDTMF: false
       supportsGrouping: false
     supportsUngrouping: false
            fromPushKit: YES
                payload: callData
  withCompletionHandler: nil];
  // --- You don't need to call it if you stored `completion()` and will call it on the js side.
  completion();
}
//VOIP
@end

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the iOS AppDelegate code shown in the report, including the PushKit and RNCallKeep callbacks, and compare it with the didLoadWithEvents registration in index.js or App.js. Reproduce the incoming-call flow on the listed iOS and React Native versions, then verify that accepting the CallKit UI produces the expected event rather than only RNCallKeepDidDisplayIncomingCall.

Written by the indexing model from the issue text.

Assessment

Tech stack
objective-c, react-native
Domain
mobile
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.