-
Notifications
You must be signed in to change notification settings - Fork 493
Description
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
}
}`