I am using the react-native-callkeep library in a React Native project to handle displaying incoming calls on receiving notification from firebase. The library works perfectly when the app is active, but fails to display incoming calls or wake up the app when it's in the background or terminated on iOS.
PS: firebase notification works fine for both android and ios
Here's the relevant part of my code:
AppDelegate.m:
#import "AppDelegate.h"#import "Adjust.h"#import "Firebase.h"#import <UserNotifications/UserNotifications.h>#import <FirebaseMessaging/FirebaseMessaging.h>#import "FirebaseCore.h"#import <React/RCTBundleURLProvider.h>#import <React/RCTRootView.h>#import "RNCallKeep.h"#import <React/RCTLinkingManager.h>#import <PushKit/PushKit.h>#import "RNVoipPushNotificationManager.h"#import <RNCPushNotificationIOS.h>@implementation AppDelegate- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { [FIRApp configure]; [RNCallKeep setup:@{@"appName": @"DocMoonlight", @"maximumCallGroups": @3, @"maximumCallsPerCallGroup": @1, @"supportsVideo": @YES}]; [RNVoipPushNotificationManager voipRegistration]; // other initialization code}- (void)pushRegistry:(PKPushRegistry *)registry didReceiveIncomingPushWithPayload:(PKPushPayload *)payload forType:(PKPushType)type withCompletionHandler:(void (^)(void))completion { [RNVoipPushNotificationManager didReceiveIncomingPushWithPayload:payload forType:(NSString *)type]; NSString *uuid = [[[NSUUID UUID] UUIDString] lowercaseString]; [RNCallKeep reportNewIncomingCall:uuid handle:@"unknown" handleType:@"generic" hasVideo:NO localizedCallerName:@"Unknown" supportsHolding:YES supportsDTMF:YES supportsGrouping:YES supportsUngrouping:YES fromPushKit:YES payload:nil withCompletionHandler:completion];}
React Native Side (App.js):
const options = { ios: { appName: 'DocMoonlight', }, android: { alertTitle: 'Permissions required', alertDescription: 'This application needs to access your phone accounts', cancelButton: 'Cancel', okButton: 'ok', imageName: '', additionalPermissions: [], foregroundService: { channelId: 'com.docmoonlight', channelName: 'Foreground service for my app', notificationTitle: 'My app is running on background', notificationIcon: 'ic_notification', }, },};CallKeep.setup(options).then(() => {});CallKeep.setAvailable(true);
this is the code used to handle display calls or normal notifications
async function onMessageReceived(remoteMessage) { if (remoteMessage.data?.type === 'video_call') { const callUUID = uuidv4(); CallKeep.displayIncomingCall( callUUID, remoteMessage.data?.location,'Docmoonlight','generic', true, ); // Listen to the CallKeep events CallKeep.addEventListener('answerCall', async ({callUUID}) => { bringAppToForeground(); CallKeep.endCall(callUUID); setTimeout(async () => { if (remoteMessage.data) { const zoomLink = remoteMessage.data; try { const jwtToken = generateSignature(zoomLink.meetingNumber); await ZoomUs.initialize({ jwtToken, }) .then(result => { console.log(result); try { ZoomUs.joinMeeting({ userName: zoomLink.name, meetingNumber: zoomLink.meetingNumber, password: zoomLink.password, }); } catch (error) { console.error('Failed to join the meeting', error); } }) .catch(error => console.log('Failed to initialize', error)); } catch (error) { console.log(error); } } }, 1000); }); CallKeep.addEventListener('endCall', ({callUUID}) => { console.log('Call ended:', callUUID); CallKeep.endCall(callUUID); }); } else { onDisplayNotification( remoteMessage.notification?.title, remoteMessage.notification?.body, remoteMessage.messageId, ); }}
and this is my pod file
require_relative '../node_modules/react-native/scripts/react_native_pods'require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules'platform :ios, min_ios_version_supportedprepare_react_native_project!source 'https://github.com/CocoaPods/Specs.git'# Disable Flipper temporarilyflipper_config = FlipperConfiguration.disabledlinkage = ENV['USE_FRAMEWORKS']if linkage != nil Pod::UI.puts "Configuring Pod with #{linkage}ally linked Frameworks".green use_frameworks! :linkage => linkage.to_symendtarget 'DocMoonlight' do config = use_native_modules! pod 'Firebase', :modular_headers => true pod 'FirebaseCoreInternal', :modular_headers => true pod 'GoogleUtilities', :modular_headers => true pod 'FirebaseCore', :modular_headers => true pod 'RNPermissions', :path => '../node_modules/react-native-permissions' permissions_path = '../node_modules/react-native-permissions/ios' pod 'FirebaseInstallations', :modular_headers => true pod 'FirebaseCoreExtension', :modular_headers => true pod 'GoogleDataTransport', :modular_headers => true pod 'nanopb', :modular_headers => true pod 'RNCallKeep', :path => '../node_modules/react-native-callkeep' # Flags change depending on the env values. flags = get_default_flags() use_react_native!( :path => config[:reactNativePath], :hermes_enabled => flags[:hermes_enabled], :fabric_enabled => flags[:fabric_enabled], :flipper_configuration => flipper_config, :app_path => "#{Pod::Config.instance.installation_root}/.." ) target 'DocMoonlightTests' do inherit! :complete end post_install do |installer| react_native_post_install( installer, :mac_catalyst_enabled => false ) endend
and this is info.plist
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"><plist version="1.0"><dict><key>BGTaskSchedulerPermittedIdentifiers</key><array><string>com.docmoonlight.app.fetch-updates</string></array><key>CFBundleDevelopmentRegion</key><string>en</string><key>CFBundleDisplayName</key><string>Docmoonlight</string><key>CFBundleExecutable</key><string>$(EXECUTABLE_NAME)</string><key>CFBundleIdentifier</key><string>$(PRODUCT_BUNDLE_IDENTIFIER)</string><key>CFBundleInfoDictionaryVersion</key><string>6.0</string><key>CFBundleName</key><string>$(PRODUCT_NAME)</string><key>CFBundlePackageType</key><string>APPL</string><key>CFBundleShortVersionString</key><string>$(MARKETING_VERSION)</string><key>CFBundleSignature</key><string>????</string><key>CFBundleVersion</key><string>$(CURRENT_PROJECT_VERSION)</string><key>LSRequiresIPhoneOS</key><true/><key>NSAppTransportSecurity</key><dict><key>NSExceptionDomains</key><dict><key>localhost</key><dict><key>NSExceptionAllowsInsecureHTTPLoads</key><true/></dict></dict></dict><key>NSBluetoothPeripheralUsageDescription</key><string>We will use your Bluetooth to access your Bluetooth headphones.</string><key>NSCameraUsageDescription</key><string>For people to see you during meetings, we need access to your camera.</string><key>NSDocumentsFolderUsageDescription</key><string>Docmoonlight's app requires access to your Documents Folder to allow you to upload necessary documents and files, such as proof of medical licensing or certifications, during the registration process</string><key>NSLocationWhenInUseUsageDescription</key><string>Docmoonlight's app requires access to your location while in use to provide accurate clock-in and clock-out times for payment purposes. </string><key>NSMicrophoneUsageDescription</key><string>For people to hear you during meetings, we need access to your microphone.</string><key>NSPhotoLibraryUsageDescription</key><string>Docmoonlight's app requires access to your Photo Library and file storage to allow you to upload necessary documents and files, such as proof of medical licensing or certifications, during the registration process</string><key>UIAppFonts</key><array><string>Poppins-Medium.ttf</string><string>Poppins-Regular.ttf</string><string>Poppins-SemiBold.ttf</string><string>AntDesign.ttf</string><string>Entypo.ttf</string><string>EvilIcons.ttf</string><string>Feather.ttf</string><string>FontAwesome.ttf</string><string>FontAwesome5_Brands.ttf</string><string>FontAwesome5_Regular.ttf</string><string>FontAwesome5_Solid.ttf</string><string>Foundation.ttf</string><string>Ionicons.ttf</string><string>MaterialIcons.ttf</string><string>MaterialCommunityIcons.ttf</string><string>SimpleLineIcons.ttf</string><string>Octicons.ttf</string><string>Zocial.ttf</string><string>FontAwesome6_Regular.ttf</string><string>FontAwesome6_Solid.ttf</string><string>FontAwesome6_Brands.ttf</string></array><key>UIBackgroundModes</key><array><string>audio</string><string>fetch</string><string>remote-notification</string><string>voip</string></array><key>UILaunchStoryboardName</key><string>LaunchScreen</string><key>UIRequiredDeviceCapabilities</key><array><string>armv7</string></array><key>UISupportedInterfaceOrientations</key><array><string>UIInterfaceOrientationPortrait</string></array><key>UISupportedInterfaceOrientations~ipad</key><array><string>UIInterfaceOrientationLandscapeLeft</string><string>UIInterfaceOrientationLandscapeRight</string><string>UIInterfaceOrientationPortrait</string></array><key>UIViewControllerBasedStatusBarAppearance</key><false/></dict></plist>
i have tried so many tries on this but it doesnt work