Skip to content

iOS app does not open when the app is in background mode and an incoming call is answered. How can this be resolved? #860

@agam-phppoets

Description

@agam-phppoets

Here is my code

callkeep.js

import {Linking, PermissionsAndroid} from 'react-native';
import {endpoints, httpRequestPost} from './function';
import renderToast from './renderToast';

export const options = {
ios: {
appName: 'app',
supportsVideo: false,
},
android: {
alertTitle: 'Permissions Required',
alertDescription:
'This application needs to access your phone calling accounts to make calls',
cancelButton: 'Cancel',
okButton: 'ok',
imageName: 'sim_icon',
// additionalPermissions: [PermissionsAndroid.PERMISSIONS.READ_CONTACTS],
foregroundService: {
channelId: 'com.yourapp.channelId',
channelName: 'YourApp Call Channel',
notificationTitle: 'Incoming Call',
notificationIcon: 'ic_launcher', // Your notification icon
},
},
};

export const reOpenApp = async () => {
try {
await Linking.openURL('app://open');
} catch (error) {
// Handle the error, possibly log it, or alert the user
console.log('Failed to open URL:', error);
// Alert.alert('Error', 'Failed to open app');
}
};

export const handleOnCallInitiate = async (
user_id,
setLoader,
userData,
navigation,
toast,
) => {
setLoader(user_id);

const response = await httpRequestPost(
endpoints.VOICE_CALL_INITIATE,
{
receiver_id: user_id,
},
userData?.token,
);
const {status} = response;

setLoader(false);

if (status) {
navigation?.navigate('Video Call', {
token: response.data?.data?.token,
onVoice: true,
});
} else {
renderToast(toast, response?.data?.message ?? response?.message, 'danger');
}
};


Appdelegate.mm

#import "AppDelegate.h"

#import <React/RCTBundleURLProvider.h>
#import <Firebase.h>
#import <React/RCTLinkingManager.h> // <- Add This Import
#import <UIKit/UIKit.h>
#import <AuthenticationServices/AuthenticationServices.h>
#import <SafariServices/SafariServices.h>
#import <FBSDKCoreKit/FBSDKCoreKit-Swift.h>

#import "RNCallKeep.h"

#import <PushKit/PushKit.h>
#import "RNVoipPushNotificationManager.h"
#import <GoogleMaps/GoogleMaps.h>
#import "Orientation.h"

#import <TSBackgroundFetch/TSBackgroundFetch.h>

@implementation AppDelegate

  • (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    {
    [FIRApp configure];
    [GMSServices provideAPIKey:@"AXXXXXXXXXXXXXXXXXXXXXXXXXXAHQ"]; // add this line using the api key obtained from Google Console

    [RNCallKeep setup:@{
    @"appName": @"App",
    @"maximumCallGroups": @3,
    @"maximumCallsPerCallGroup": @1,
    @"supportsVideo": @no,
    }];

    [RNVoipPushNotificationManager voipRegistration];

    self.moduleName = @"app";
    // You can add your custom initial props in the dictionary below.
    // They will be passed down to the ViewController used by React Native.
    self.initialProps = @{};
    [[FBSDKApplicationDelegate sharedInstance] application:application
    didFinishLaunchingWithOptions:launchOptions];

    // [REQUIRED] Register BackgroundFetch
    [[TSBackgroundFetch sharedInstance] didFinishLaunching];

    return [super application:application didFinishLaunchingWithOptions:launchOptions];
    }

  • (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
    {
    return [self bundleURL];
    }

  • (BOOL)application:(UIApplication *)application
    openURL:(NSURL *)url
    options:(NSDictionary<UIApplicationOpenURLOptionsKey, id> *)options
    {
    // Handle the URL with the React Native Linking Manager
    BOOL handledByReactNative = [RCTLinkingManager application:application openURL:url options:options];

    // Handle the URL with the Facebook SDK
    BOOL handledByFacebookSDK = [[FBSDKApplicationDelegate sharedInstance] application:application openURL:url options:options];

    // Return YES if either the React Native or Facebook handler succeeded
    return handledByReactNative || handledByFacebookSDK;
    }

  • (NSURL *)bundleURL
    {
    #if DEBUG
    return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index"];
    #else
    return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
    #endif
    }

// Handle updated push credentials

  • (void)pushRegistry:(PKPushRegistry *)registry didUpdatePushCredentials:(PKPushCredentials *)credentials forType:(NSString *)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.
    }

  • (void)pushRegistry:(PKPushRegistry *)registry didReceiveIncomingPushWithPayload:(PKPushPayload *)payload forType:(PKPushType)type withCompletionHandler:(void (^)(void))completion {
    NSString *uuid = [[[NSUUID UUID] UUIDString] lowercaseString];
    NSString *callerName = @"Caller Name";
    NSString *handle = @"Caller Handle";

    [RNVoipPushNotificationManager addCompletionHandler:uuid completionHandler:completion];
    [RNVoipPushNotificationManager didReceiveIncomingPushWithPayload:payload forType:(NSString *)type];

    [RNCallKeep reportNewIncomingCall: uuid
    handle: handle
    handleType: @"generic"
    hasVideo: NO
    localizedCallerName: callerName
    supportsHolding: YES
    supportsDTMF: YES
    supportsGrouping: YES
    supportsUngrouping: YES
    fromPushKit: YES
    payload: nil
    withCompletionHandler: completion];

    // completion();
    }

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

}

  • (UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window {
    return [Orientation getOrientation];
    }

@EnD


App.js code

async function onDisplayNotification(d) {
if (d?.data?.type === 'HIDDEN_OFFLINE_USER') return;
if (Platform.OS === 'ios') {
await notifee.requestPermission();
}

saveCount(count + 1);
dispatch(updateNotificationCount(count + 1));

if (d?.notification) {
  // Display a notification
  const channelId = await notifee.createChannel({
    id: 'onMessage',
    name: 'onMessage Channel',
    importance: AndroidImportance.HIGH,
    sound: 'notification',
  });
  await notifee.displayNotification({
    id: 'onMessage',
    title: d?.notification?.title,
    body: d?.notification?.body,
    data: d?.data,
    android: {
      channelId,
      // largeIcon: require('./src/assets/images/icon.png'),
      importance: AndroidImportance.HIGH,
      sound: 'notification',
      pressAction: {
        launchActivity: 'default',
        id: 'default',
      },
    },
  });
}

}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions