Flutter iOS中APN后台/终止状态推送处理问题求助
iOS Flutter应用后台/终止状态下APN推送处理问题
在iOS平台的Flutter应用中,无法处理后台及终止状态下的APN推送通知。尝试使用FCM后台处理服务,但通过APN Token发送推送时,_firebaseBackgroundHandler()方法未被调用;使用flutter_apns库也无法处理后台推送,不清楚遗漏了什么配置或代码。
AppDelegate.swift
@UIApplicationMain @objc class AppDelegate: FlutterAppDelegate, PKPushRegistryDelegate { override func application( _ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? ) -> Bool { GeneratedPluginRegistrant.register(with: self) //Setup VOIP let mainQueue = DispatchQueue.main let voipRegistry: PKPushRegistry = PKPushRegistry(queue: mainQueue) voipRegistry.delegate = self voipRegistry.desiredPushTypes = [PKPushType.voIP] if #available(iOS 10.0, *) { // For iOS 10 display notification (sent via APNS) UNUserNotificationCenter.current().delegate = self let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound] UNUserNotificationCenter.current().requestAuthorization( options: authOptions, completionHandler: {_, _ in }) } else { let settings: UIUserNotificationSettings = UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil) application.registerUserNotificationSettings(settings) } application.registerForRemoteNotifications() return super.application(application, didFinishLaunchingWithOptions: launchOptions) } // Call back from Recent history override func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool { guard let handleObj = userActivity.handle else { return false } guard let isVideo = userActivity.isVideo else { return false } let nameCaller = handleObj.getDecryptHandle()["nameCaller"] as? String ?? "" let handle = handleObj.getDecryptHandle()["handle"] as? String ?? "" let data = flutter_callkit_incoming.Data(id: UUID().uuidString, nameCaller: nameCaller, handle: handle, type: isVideo ? 1 : 0) //set more data... data.nameCaller = "Johnny" SwiftFlutterCallkitIncomingPlugin.sharedInstance?.startCall(data, fromPushKit: true) return super.application(application, continue: userActivity, restorationHandler: restorationHandler) } // Handle updated push credentials func pushRegistry(_ registry: PKPushRegistry, didUpdate credentials: PKPushCredentials, for type: PKPushType) { print(credentials.token) let deviceToken = credentials.token.map { String(format: "%02x", $0) }.joined() print(deviceToken) //Save deviceToken to your server SwiftFlutterCallkitIncomingPlugin.sharedInstance?.setDevicePushTokenVoIP(deviceToken) } func pushRegistry(_ registry: PKPushRegistry, didInvalidatePushTokenFor type: PKPushType) { print("didInvalidatePushTokenFor") SwiftFlutterCallkitIncomingPlugin.sharedInstance?.setDevicePushTokenVoIP("") } func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject], fetchCompletionHandler completionHandler: (UIBackgroundFetchResult) -> Void) { print("Recived: \(userInfo)") } // Handle incoming pushes func pushRegistry(_ registry: PKPushRegistry, didReceiveIncomingPushWith payload: PKPushPayload, for type: PKPushType, completion: @escaping () -> Void) { print("didReceiveIncomingPushWith") guard type == .voIP else { return } let id = payload.dictionaryPayload["id"] as? String ?? "" let nameCaller = payload.dictionaryPayload["nameCaller"] as? String ?? "" let handle = payload.dictionaryPayload["handle"] as? String ?? "" let isVideo = payload.dictionaryPayload["isVideo"] as? Bool ?? false let data = flutter_callkit_incoming.Data(id: id, nameCaller: nameCaller, handle: handle, type: isVideo ? 1 : 0) //set more data data.extra = ["user": "abc@123", "platform": "ios"] //data.iconName = ... //data..... SwiftFlutterCallkitIncomingPlugin.sharedInstance?.showCallkitIncoming(data,fromPushKit: true) }}
flutter_apn库在main.dart中的register()方法
final PushConnector connector = createPushConnector(); Future<void> _register() async { final connector = this.connector; connector.configure( onLaunch: (onLaunch) async { print("on1 ==> ${onLaunch.data.toString()}"); return await null; }, onResume: (data) async { var responce = await onPush('onResumess', data);print("responce data ${responce}");}, onMessage: (onLaunch) async { print("on3 ==> ${onLaunch.data.length}"); return await null; }, onBackgroundMessage: _onBackgroundMessage, ); connector.token.addListener(() { print('Token ${connector.token.value}'); }); connector.requestNotificationPermissions(); if (connector is ApnsPushConnector) { connector.shouldPresent = (x) async { final remote = RemoteMessage.fromMap(x.payload); return remote.category == 'MEETING_INVITATION'; }; connector.setNotificationCategories([ UNNotificationCategory( identifier: 'MEETING_INVITATION', actions: [ UNNotificationAction( identifier: 'ACCEPT_ACTION', title: 'Accept', options: UNNotificationActionOptions.values, ), UNNotificationAction( identifier: 'DECLINE_ACTION', title: 'Decline', options: [], ), ], intentIdentifiers: [], options: UNNotificationCategoryOptions.values, ), ]); }}
期望onPush()方法在应用处于后台或终止状态时能被调用。
main中的onPush()方法
Future<dynamic> onPush(String name, RemoteMessage payload) async { await FlutterCallkitIncoming.endAllCalls(); SharedPreferences prefs = await SharedPreferences.getInstance(); var data = GetStorage(); storage.append('$name: ${payload.notification?.title}'); final action = UNNotificationAction.getIdentifier(payload.data); print("Payload Data1 ${payload.notification!.title.toString()}"); print("Payload Data2 ${payload.notification!.body.toString()}"); print("Payload ${payload.notification!.toMap()}"); if(payload.notification!.title!.contains('from')){ prefs.setBool('incomingCall', true); data.write('callingName', payload.notification!.title.toString()); showCallkitIncoming(Uuid().v4(), payload.notification!.title.toString(), payload.notification!.body.toString() ); } else { print('NOT IOS BG CALLING'); } if (action != null && action != UNNotificationAction.defaultIdentifier) { storage.append('Action: $action'); } return Future.value(true);}
main.dart中的_onBackgroundMessage()方法
Future<dynamic> _onBackgroundMessage(RemoteMessage data) async { await FlutterCallkitIncoming.endAllCalls(); var responce = await onPush('onBackgroundMessage', data); print("BG responce data ${responce}"); if(data.notification!.title!.contains('from')){ showCallkitIncoming(Uuid().v4(), data.notification!.title.toString(), data.notification!.body.toString() ); }else{ print('NOT IOS BG CALLING'); } }
内容的提问来源于stack exchange,提问作者Nayeem Sama
相关产品推荐
相关产品推荐

