Skip to content

Library not working with Expo SDK 54 #869

@ICGVIP

Description

@ICGVIP

Hello. We have been constantly trying to work around this by using everything listed on here, but it is not working for some reason.
The app was initially built in Expo SDK 54 and has since been ejected. We have tried keeping the imports of RNCallkeep in swift file and that didn't work, as has been the case with everyone - "RNCallKeep not found" error. Also tried listing it in the Bridging-Header file and that's when these two errors arose-

1.) Failed to emit precompiled header '/Users/mc559/Library/Developer/Xcode/DerivedData/[AppName]-gthpjwqbmzgdepbcdzmuhlqwpyuk/Build/Intermediates.noindex/PrecompiledHeaders/[AppName]-Bridging-Header-swift_1LS8Z4CYI0BYD-clang_1MEDN0KIR5C77.pch' for bridging header '/Users/mc559/Desktop/[AppName]/ios/[AppName]/[AppName]-Bridging-Header.h'

2.) RNCallKeep - RNCallKeep.h:15:9 'React/RCTEventEmitter.h' file not found

Here is the package.json:

{ "main": "index.js", "version": "1.0.0", "scripts": { "start": "expo start", "reset-project": "node ./scripts/reset-project.js", "android": "expo run:android", "ios": "expo run:ios", "web": "expo start --web", "lint": "expo lint" }, "dependencies": { "@expo/vector-icons": "^15.0.3", "@gorhom/bottom-sheet": "^5.2.8", "@notifee/react-native": "^9.1.8", "@react-native-async-storage/async-storage": "^2.2.0", "@react-native-camera-roll/camera-roll": "^7.10.2", "@react-native-community/cli": "^20.0.2", "@react-native-community/datetimepicker": "^8.5.1", "@react-native-community/geolocation": "^3.4.0", "@react-native-community/netinfo": "^11.4.1", "@react-native-menu/menu": "^2.0.0", "@react-native-picker/picker": "^2.11.4", "@react-navigation/bottom-tabs": "^7.4.0", "@react-navigation/elements": "^2.6.3", "@react-navigation/material-top-tabs": "^7.4.10", "@react-navigation/native": "^7.1.8", "@react-navigation/native-stack": "^7.8.6", "@reduxjs/toolkit": "^2.11.2", "axios": "^1.13.2", "core-js": "^3.47.0", "dayjs": "^1.11.19", "event-target-shim": "^6.0.2", "expo": "~54.0.29", "expo-asset": "~12.0.11", "expo-audio": "~1.1.0", "expo-clipboard": "~8.0.8", "expo-constants": "~18.0.12", "expo-contacts": "~15.0.11", "expo-crypto": "~15.0.8", "expo-dev-client": "~6.0.20", "expo-device": "~8.0.10", "expo-document-picker": "~14.0.8", "expo-file-system": "~19.0.21", "expo-font": "~14.0.10", "expo-haptics": "~15.0.8", "expo-image": "~3.0.11", "expo-image-picker": "~17.0.10", "expo-linear-gradient": "~15.0.8", "expo-linking": "~8.0.10", "expo-notifications": "~0.32.15", "expo-router": "~6.0.19", "expo-screen-capture": "~8.0.9", "expo-splash-screen": "~31.0.12", "expo-status-bar": "~3.0.9", "expo-symbols": "~1.0.8", "expo-system-ui": "~6.0.9", "expo-video": "~3.0.15", "expo-web-browser": "~15.0.10", "jwt-decode": "^4.0.0", "mediasoup-client": "^3.18.3", "moment": "^2.30.1", "react": "19.1.0", "react-dom": "19.1.0", "react-native": "0.81.5", "react-native-appearance": "^0.3.4", "react-native-callkeep": "^4.3.16", "react-native-chart-kit": "^6.12.0", "react-native-circular-progress-indicator": "^4.4.2", "react-native-country-codes-picker": "^2.3.5", "react-native-device-info": "^15.0.1", "react-native-file-viewer": "^2.1.5", "react-native-fs": "^2.20.0", "react-native-gesture-handler": "~2.28.0", "react-native-get-random-values": "^2.0.0", "react-native-gifted-chat": "^3.2.2", "react-native-haptic-feedback": "^2.3.3", "react-native-image-modal": "^3.0.13", "react-native-incall-manager": "^4.2.1", "react-native-ios-context-menu": "^3.2.1", "react-native-ios-utilities": "^5.2.0", "react-native-keyboard-controller": "^1.20.2", "react-native-keychain": "^10.0.0", "react-native-pager-view": "^7.0.2", "react-native-paper": "^5.14.5", "react-native-permissions": "^5.4.4", "react-native-picker-select": "^9.3.1", "react-native-qr-svg": "^1.5.0", "react-native-reanimated": "~4.1.1", "react-native-safe-area-context": "~5.6.0", "react-native-screens": "~4.16.0", "react-native-share": "^12.2.1", "react-native-simple-biometrics": "^3.0.2", "react-native-svg": "^15.15.1", "react-native-tab-view": "^4.2.1", "react-native-uuid": "^2.0.3", "react-native-video": "^6.18.0", "react-native-virtualized-view": "^1.0.0", "react-native-voip-push-notification": "^3.3.3", "react-native-web": "~0.21.0", "react-native-webrtc": "^124.0.7", "react-native-webview": "^13.16.0", "react-native-worklets": "0.5.1", "react-redux": "^9.2.0", "redux-persist": "^6.0.0", "rn-emoji-keyboard": "^1.7.0", "socket.io-client": "^4.8.1", "zeego": "^3.0.6" }, "devDependencies": { "@types/react": "~19.1.0", "eslint": "^9.25.0", "eslint-config-expo": "~10.0.0", "typescript": "~5.9.2" }, "private": true }

And here is AppDelegate.swift:

`import Expo
import React
import ReactAppDependencyProvider
import PushKit
import WebRTC

@UIApplicationMain
public class AppDelegate: ExpoAppDelegate, PKPushRegistryDelegate, CXProviderDelegate {
var window: UIWindow?

var reactNativeDelegate: ExpoReactNativeFactoryDelegate?
var reactNativeFactory: RCTReactNativeFactory?

public override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil
) -> Bool {

let localizedAppName = Bundle.main.localizedInfoDictionary?["CFBundleDisplayName"] as? String
let appName = Bundle.main.infoDictionary?["CFBundleDisplayName"] as! String
RNCallKeep.setup([
"appName": localizedAppName ?? appName,
"supportsVideo": true,
"includesCallsInRecents": false,
])
RNVoipPushNotificationManager.voipRegistration()

let options = WebRTCModuleOptions.sharedInstance()
options.enableMultitaskingCameraAccess = true

let delegate = ReactNativeDelegate()
let factory = ExpoReactNativeFactory(delegate: delegate)
delegate.dependencyProvider = RCTAppDependencyProvider()

reactNativeDelegate = delegate
reactNativeFactory = factory
bindReactNativeFactory(factory)

#if os(iOS) || os(tvOS)
window = UIWindow(frame: UIScreen.main.bounds)
factory.startReactNative(
withModuleName: "main",
in: window,
launchOptions: launchOptions)
#endif

return super.application(application, didFinishLaunchingWithOptions: launchOptions)

}

// Linking API
public override func application(
_ app: UIApplication,
open url: URL,
options: [UIApplication.OpenURLOptionsKey: Any] = [:]
) -> Bool {
return super.application(app, open: url, options: options) || RCTLinkingManager.application(app, open: url, options: options)
}

// Universal Links
public override func application(
_ application: UIApplication,
continue userActivity: NSUserActivity,
restorationHandler: https://github.com/escaping ([UIUserActivityRestoring]?) -> Void
) -> Bool {
let result = RCTLinkingManager.application(application, continue: userActivity, restorationHandler: restorationHandler)
return super.application(application, continue: userActivity, restorationHandler: restorationHandler) || result
}

// handle updated push credentials
func provider(_ provider: CXProvider, didActivate audioSession: AVAudioSession) {
RTCAudioSession.sharedInstance().audioSessionDidActivate(AVAudioSession.sharedInstance())
}

func provider(_ provider: CXProvider, didDeactivate audioSession: AVAudioSession) {
RTCAudioSession.sharedInstance().audioSessionDidDeactivate(AVAudioSession.sharedInstance())
}

func provider(_ provider: CXProvider, performEndCall action: CXEndCallAction) {
print("🔴 System call ended: (action.callUUID.uuidString)")
RTCAudioSession.sharedInstance().audioSessionDidDeactivate(AVAudioSession.sharedInstance())
action.fulfill()
}

// handle updated push credentials
func pushRegistry(
_ registry: PKPushRegistry,
didUpdate credentials: PKPushCredentials,
for type: PKPushType
) {
RNVoipPushNotificationManager.didUpdate(credentials, forType: type.rawValue)
}

// handle incoming pushes
func pushRegistry(
_ registry: PKPushRegistry,
didReceiveIncomingPushWith payload: PKPushPayload,
for type: PKPushType,
completion: https://github.com/escaping () -> Void
) {

// process the payload
let uuid = payload.dictionaryPayload["uuid"]
let hasVideoValue = payload.dictionaryPayload["hasVideo"]
let handle = payload.dictionaryPayload["handle"]
let caller = payload.dictionaryPayload["callerName"]

RNVoipPushNotificationManager.addCompletionHandler(uuid, completionHandler: completion)

RNVoipPushNotificationManager.didReceiveIncomingPush(
with: payload,
forType: type.rawValue
)

// display the incoming call notification
RNCallKeep.reportNewIncomingCall(
uuid,
handle: handle,
handleType: "generic",
hasVideo: hasVideo,
localizedCallerName: caller,
supportsHolding: true,
supportsDTMF: true,
supportsGrouping: true,
supportsUngrouping: true,
fromPushKit: true,
payload: nil,
withCompletionHandler: completion
)

}
}

class ReactNativeDelegate: ExpoReactNativeFactoryDelegate {
// Extension point for config-plugins

override func sourceURL(for bridge: RCTBridge) -> URL? {
// needed to return the correct URL for expo-dev-client.
bridge.bundleURL ?? bundleURL()
}

override func bundleURL() -> URL? {
#if DEBUG
return RCTBundleURLProvider.sharedSettings().jsBundleURL(forBundleRoot: ".expo/.virtual-metro-entry")
#else
return Bundle.main.url(forResource: "main", withExtension: "jsbundle")
#endif
}
}`

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