Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Listeners not working when App is in Kill state #791

Open
1 task done
abdulahad96 opened this issue Jul 1, 2024 · 2 comments
Open
1 task done

Listeners not working when App is in Kill state #791

abdulahad96 opened this issue Jul 1, 2024 · 2 comments

Comments

@abdulahad96
Copy link

abdulahad96 commented Jul 1, 2024

Bug report

  • Hi
    I am facing an issue while integrating CallKeep in my React Native app. It works as expected in the foreground and background, but in the killed state, answering the call does not trigger the listener, preventing any action.

  • Reproduced on:

  • iOS

Description

This is AppDelegate.m

#import "AppDelegate.h"
#import <Firebase.h>
#import <React/RCTBridge.h>
#import <React/RCTBundleURLProvider.h>
#import <React/RCTRootView.h>
#import <GoogleMaps/GoogleMaps.h>
#import <UserNotifications/UserNotifications.h>
#import <RNCPushNotificationIOS.h>
#import "RNSplashScreen.h"
#import <PushKit/PushKit.h>
#import <CallKit/CallKit.h>
#import "RNVoipPushNotificationManager.h"
#import "RNCallKeep.h"
#import <AVFoundation/AVFoundation.h>

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];
}

@implementation AppDelegate {
    CXProvider *provider;
    BOOL hasActiveCall;
}

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
  [FIRApp configure];
  [self checkAndHandleActiveCall];
  RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions];

  [RNCallKeep setup:@{
       @"appName": @"callApp",
       @"maximumCallGroups": @1,
       @"maximumCallsPerCallGroup": @1,
       @"supportsVideo": @YES,
  }];

  RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge moduleName:@"callApp" initialProperties:nil];

  if (@available(iOS 13.0, *)) {
      rootView.backgroundColor = [UIColor systemBackgroundColor];
  } else {
      rootView.backgroundColor = [UIColor whiteColor];
  }

  [RNSplashScreen show];  // here

  self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
  UIViewController *rootViewController = [UIViewController new];
  rootViewController.view = rootView;
  self.window.rootViewController = rootViewController;
  [self.window makeKeyAndVisible];
  
  // Define UNUserNotificationCenter
  UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
  center.delegate = self;
  return YES;
}

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

#pragma mark - UNUserNotificationCenterDelegate

- (void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler {
  completionHandler(UNNotificationPresentationOptionSound | UNNotificationPresentationOptionAlert | UNNotificationPresentationOptionBadge);
}

#pragma mark - RCTBridgeDelegate

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

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

- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error {
  [RNCPushNotificationIOS didFailToRegisterForRemoteNotificationsWithError:error];
}

- (void)pushRegistry:(PKPushRegistry *)registry didUpdatePushCredentials:(PKPushCredentials *)credentials forType:(PKPushType)type {
  [RNVoipPushNotificationManager didUpdatePushCredentials:credentials forType:(NSString *)type];
}

- (void)pushRegistry:(PKPushRegistry *)registry
didReceiveIncomingPushWithPayload:(PKPushPayload *)payload
             forType:(PKPushType)type
withCompletionHandler:(void (^)(void))completion {
    NSLog(@"Received incoming VoIP push notification");

    if ([type isEqualToString:PKPushTypeVoIP]) {
       NSLog(@"Received incoming VoIP push notification: %@", payload);
       NSDictionary *payloadDictionary = payload.dictionaryPayload;
       NSDictionary *data = payloadDictionary[@"data"];
       NSString *guid;
       NSString *sourceName;
       NSString *callerID;

       if (data[@"guid"]) {
           guid = data[@"guid"];
       } else if (data[@"call"] && data[@"call"][@"guid"]) {
           guid = data[@"call"][@"guid"];
       }
       if (data[@"source"] && data[@"source"][@"name"]) {
           sourceName = data[@"source"][@"name"];
       } else if (data[@"call"] && data[@"call"][@"source"] && data[@"call"][@"source"][@"name"]) {
           sourceName = data[@"call"][@"source"][@"name"];
       }
       if (data[@"source"] && data[@"source"][@"id"]) {
           callerID = data[@"source"][@"id"];
       } else if (data[@"call"] && data[@"call"][@"source"] && data[@"call"][@"source"][@"id"]) {
           callerID = data[@"call"][@"source"][@"id"];
       }
       [[SwiftClass shared] checkGuid:guid completion:^(BOOL isNewGuid) {
           if (isNewGuid) {
               [RNCallKeep reportNewIncomingCall: guid
                                            handle: sourceName
                                        handleType: @"generic"
                                          hasVideo: YES
                               localizedCallerName: sourceName
                                   supportsHolding: YES
                                      supportsDTMF: YES
                                  supportsGrouping: YES
                                supportsUngrouping: YES
                                       fromPushKit: YES
                                           payload: payloadDictionary
                             withCompletionHandler: completion];
           } else {
               NSLog(@"Duplicate call, ignoring");
               completion();
           }
       }];

       [[SwiftClass shared] processCall:guid completion:^(NSArray *response) {
           NSLog(@"Response: %@", response);
           completion();
       }];
    }
}
@end

index.js

import React, { useEffect } from "react";
import { AppRegistry, NativeModules, Platform, NativeEventEmitter } from "react-native";
import App from "./App";
import { name as appName } from "./app.json";
import VoipPushNotification from "react-native-voip-push-notification";
import RNCallKeep from "react-native-callkeep";
import messaging from "@react-native-firebase/messaging";
import AsyncStorage from "@react-native-async-storage/async-storage";
import { extractGuid } from "./app/utilities/extractGuid";
import BackgroundTimer from "react-native-background-timer";
import PushNotificationIOS from '@react-native-community/push-notification-ios';
import { each, compact, last, get } from "lodash";

const callKeepEmitter = new NativeEventEmitter(RNCallKeep);

messaging().setBackgroundMessageHandler(async (remoteMessage) => {
  if (remoteMessage) {
    const notificationPayload = remoteMessage?.data;
    const guid = extractGuid(notificationPayload);
    if (guid) {
      if (Platform.OS === "android") {
        NativeModules.ButterFlyMX.processCall(guid, (error, result) => {});
      }
    } else {
      console.log("GUID not found in notification payload");
    }
  } else {
    console.log("No notification found in FCM message");
  }
});

const options = {
  ios: {
    appName: "callApp",
    supportsVideo: true,
    maximumCallGroups: "1",
    maximumCallsPerCallGroup: "1",
  },
  android: {
    alertTitle: "Permissions required",
    alertDescription: "This application needs to access your phone accounts",
    cancelButton: "Cancel",
    okButton: "OK",
  },
};

const AppWithCallKeep = ({ isHeadless }) => {
  const onDidLoadWithNativeEvents = (events) => {
    const validEvents = compact(events);
    let callDataToAdd = null;
    let callDataToAnswer = null;
    let callDataToReject = null;
    let callDataToInitiateCall = null;
    each(compact(validEvents), (event) => {
      const { name, data } = event;
      if (name === "RNCallKeepDidDisplayIncomingCall") {
        callDataToAdd = data;
        recieveCall(data);
        callDataToAnswer = null;
        callDataToReject = null;
      }
      if (name === "RNCallKeepPerformAnswerCallAction") {
        callDataToReject = null;
        callDataToAnswer = data;
        answerCall(data);
      }
      if (name === "RNCallKeepPerformEndCallAction") {
        callDataToAnswer = null;
        callDataToReject = data;
       
`

Steps to Reproduce

I have a scenario I am calling call UI from swift it works when I am in foreground,
but when ever I answer call from kill state it just open the app dont call UI as answeraction listener does not triggered

Versions

- Callkeep:^4.3.13"
- React Native:0.66.3
- iOS:17
- Android:nil
- Phone model: 13 pro 

Logs

Paste here
@abdulahad96
Copy link
Author

anyone please help me

@MichelNassarFC
Copy link

add something like this
RNCallKeep.addEventListener('answerCall', answerCallTrigger);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants