iOS后台/终止状态下react-native-callkeep无法正常工作
iOS后台/终止状态下react-native-callkeep无法触发来电显示问题
我在React Native项目中使用react-native-callkeep库结合Firebase通知实现来电显示功能,应用处于前台时功能完全正常,但在iOS设备上,当应用处于后台或被终止状态时,无法显示来电界面,也无法唤醒应用。
注:Firebase通知本身在Android和iOS平台均能正常接收。
相关代码文件
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]; } @end
React Native端(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);
通知处理逻辑代码
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, ); } }
Podfile
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_supported prepare_react_native_project! source 'https://github.com/CocoaPods/Specs.git' # Disable Flipper temporarily flipper_config = FlipperConfiguration.disabled linkage = ENV['USE_FRAMEWORKS'] if linkage != nil Pod::UI.puts "Configuring Pod with #{linkage}ally linked Frameworks".green use_frameworks! :linkage => linkage.to_sym end target '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 ) end end
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>
我已经尝试了多种方法,但问题仍未解决。
内容的提问来源于stack exchange,提问作者Kero Fawzy
相关产品推荐
相关产品推荐

