swift Flutter - firebase FCM消息根本不适用于Testflight发布版本

gmxoilav  于 2023-06-04  发布在  Swift
关注(0)|答案(4)|浏览(361)

前言:

我的应用程序是基于Flutter的-但需要本机代码实现才能使FCM消息工作,请参阅下文了解更多详细信息

GitHub issue#154供参考。

我在iOS上获得FCM通知时遇到了巨大的麻烦,特别是在我发布到Testflight的应用程序上。我在这个问题上被卡住了一个星期,完全不知道该怎么办。

问题

当使用Xcode/Android Studio在我的设备上使用调试/发布构建在本地运行时,会在后台、前台等接收到通知。当上传完全相同的应用程序到Testflight时,没有一个通知会通过FCM。

  • 这是至关重要的,因为FCM提供VoIP通知,这些在Testflight上没有收到,这非常令人沮丧 *
    问题和解决方案?

我发现了两个问题(herehere),这两个问题似乎都表明这是一个APNS证书问题(APNS -> Firebase)。我已经重新创建了我的证书并将其添加到Firebase控制台(所有证书生成操作都使用相同的.csr文件)

设置/配置:
*APNS生成密钥并添加到Firebase
*功能:

尝试:

<key>FirebaseAppDelegateProxyEnabled</key>
<string>NO</string>

其中:

<key>FirebaseAppDelegateProxyEnabled</key>
<string>0</string>

并具有:

<key>FirebaseAppDelegateProxyEnabled</key>
<boolean>false</boolean>

*后台模式:

<key>UIBackgroundModes</key>
    <array>
        <string>audio</string>
        <string>bluetooth-central</string>
        <string>external-accessory</string>
        <string>fetch</string>
        <string>location</string>
        <string>processing</string>
        <string>remote-notification</string>
        <string>voip</string>
        <string>remote-notification</string>
    </array>

教程/来源:

import UIKit
import CallKit
import Flutter
import Firebase
import UserNotifications
import GoogleMaps
import PushKit
import flutter_voip_push_notification
import flutter_call_kit

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate, PKPushRegistryDelegate {
    override func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
    ) -> Bool {
        
        // run firebase app
        FirebaseApp.configure()
        
        // setup Google Maps
        GMSServices.provideAPIKey("google-maps-api-key")
        
        // register notification delegate
        UNUserNotificationCenter.current().delegate = self as UNUserNotificationCenterDelegate
        
        GeneratedPluginRegistrant.register(with: self)
        
        // register VOIP
        self.voipRegistration()
        
        // register notifications
        application.registerForRemoteNotifications();
        return super.application(application, didFinishLaunchingWithOptions: launchOptions)
    }
    
    // Handle updated push credentials
    public func pushRegistry(_ registry: PKPushRegistry, didUpdate pushCredentials: PKPushCredentials, for type: PKPushType) {
        // Process the received pushCredentials
        FlutterVoipPushNotificationPlugin.didUpdate(pushCredentials, forType: type.rawValue);
    }
    
    // Handle incoming pushes
    public func pushRegistry(_ registry: PKPushRegistry,
                             didReceiveIncomingPushWith payload: PKPushPayload,
                             for type: PKPushType,
                             completion: @escaping () -> Swift.Void){
        
        FlutterVoipPushNotificationPlugin.didReceiveIncomingPush(with: payload, forType: type.rawValue)
        
        let signalType = payload.dictionaryPayload["signal_type"] as! String
        if(signalType == "endCall" || signalType == "rejectCall"){
            return
        }
        
        let uuid = payload.dictionaryPayload["session_id"] as! String
        let uID = payload.dictionaryPayload["caller_id"] as! Int
        let callerName = payload.dictionaryPayload["caller_name"] as! String
        let isVideo = payload.dictionaryPayload["call_type"] as! Int == 1;
        FlutterCallKitPlugin.reportNewIncomingCall(
            uuid,
            handle: String(uID),
            handleType: "generic",
            hasVideo: isVideo,
            localizedCallerName: callerName,
            fromPushKit: true
        )
        completion()
    }
    
    // Register for VoIP notifications
    func voipRegistration(){
        // Create a push registry object
        let voipRegistry: PKPushRegistry = PKPushRegistry(queue: DispatchQueue.main)
        // Set the registry's delegate to self
        voipRegistry.delegate = self
        // Set the push type to VoIP
        voipRegistry.desiredPushTypes = [PKPushType.voIP]
    }
}

public func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
    if #available(iOS 14.0, *) {
        completionHandler([ .banner, .alert, .sound, .badge])
    } else {
        completionHandler([.alert, .sound, .badge])
    }
}

func application(application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
    print(deviceToken)
    Messaging.messaging().apnsToken = deviceToken;
}

Fluttermain.dart

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();
  await initializeDateFormatting();
  setupLocator();
  var fcmService = locator<FCMService>();

  FirebaseMessaging.onBackgroundMessage(FCMService.handleFirebaseBackgroundMessage);
  FirebaseMessaging.onMessage.listen((event) {
    print("Foreground message");
    Fluttertoast.showToast(msg: "Received onMessage event");
    FCMService.processCallNotification(event.data);
  });
  FirebaseMessaging.onMessageOpenedApp.listen((event) {
    print("On message opened app");
    Fluttertoast.showToast(msg: "Received onMessageOpenedAppEvent");
    FCMService.handleInitialMessage(event);
  });
  FirebaseMessaging.instance.getInitialMessage().then((value) {
    Fluttertoast.showToast(msg: "Received onLaunch event");
    if (value != null) {
      FCMService.handleInitialMessage(value);
    }
  });

  initConnectyCube();
  runApp(AppProviders());
}

FCMService.dart

// handle any firebase message
  static Future<void> handleFirebaseBackgroundMessage(RemoteMessage message) async {
    print("Received background message");
    Fluttertoast.showToast(msg: "Received Firebase background message");
    await Firebase.initializeApp();
    setupLocator();
    var fcmService = locator<FCMService>();
    fcmService.init();

    _handleMessage(message, launchMessage: true);
  }

测试:

测试是在2个物理iPhone(6s和8)上完成的。当使用(调试和发布)模式直接从Mac(Android Studio和XCode)构建时,两者都可以使用Firebase FCM。当从TestFlight下载相同的内容时,两者都不起作用。
如果任何人可以提供对错误配置,设置错误或缺少/不正确的Swift代码的洞察,或者只是错误或遗漏,我们将不胜感激。

xdyibdwo

xdyibdwo1#

这个问题有时会让人发疯,即使他们在正确的情况下应用一切,所以请尝试检查以下内容:
1-在您的苹果开发者帐户中,请确保您只有一个Apple Push Services Certificate分配给应用程序标识符(Bundle ID),请避免重复。
2-如果你使用APNs键来接收通知,你必须确保当你的应用上传到TestFlight或AppStore时,它设置在生产模式

func application(_ application: UIApplication,
didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
    let token = deviceToken.map { String(format: "%02.2hhx", $0) }.joined()
    
    print("APNs Device Token: \(token)")
    Messaging.messaging().apnsToken = deviceToken
    Messaging.messaging().setAPNSToken(deviceToken, type: .prod)
    
}

注:TestFlight被视为发布(生产)模式,而不是沙盒模式

toiithl6

toiithl62#

**问题是我的。
TL;DR仅将CubeEnvironment的1个引用更改为PRODUCTION

有多个位置可以更改CubeEnvironment

  • push_notifications_manager.dart#111
  • push_notifications_manager.dart#111
  • call_manager.dart#111

建议使用,甚至更好地将其添加到“CallManagerService”的init()方法中:

bool isProduction = bool.fromEnvironment('dart.vm.product');
    parameters.environment = isProduction ? CubeEnvironment.PRODUCTION : CubeEnvironment.DEVELOPMENT;

**Debugging(process):**调试过程(对Swift和XCode有些不熟悉)可以更好。我考虑了各种配置文件、aps-environment设置等。
*由于该问题仅发生在Testflight上,这使得调试更具挑战性和耗时,因为上传调试版本有其自己的一组问题 *

最后,我添加了一堆日志记录,其中最重要的是CB-SDK调试条目(当收到通知时):

[
  {
    "subscription": {
      "id": sub id,
      "_id": "insert sub id",
      "user_id": cube_user_id,
      "bundle_identifier": "insert bundle id",
      "client_identification_sequence": "insert client id",
      "notification_channel_id": 6,
      "udid": "insert-uuid",
      "platform_id": 1,
      "environment": "development",
      "notification_channel": {
        "name": "apns_voip"
      },
      "device": {
        "udid": "insert-uuid",
        "platform": {
          "name": "ios"
        }
      }
    }
  }
]

具体来说,下面的条目。

environment": "development

这是由于APS使用了2个不同的推送通知环境,每个环境都有自己的证书(证书被分配给推送通知可以来自的唯一URL)。这个,aps-environment被设置为'production(在开始上传之前请参阅上传存档屏幕),但我收到了development环境通知-需要修复。
回顾我的代码,我终于找到了问题(并修复了上面提到的问题)。

ckocjqey

ckocjqey3#

我尝试了所有的方法,但对我有效的是发现App Flyer SDK阻止了我的推送通知。从pubspec中删除这个为我解决了这个问题。30小时调试之旅的结束。

qrjkbowd

qrjkbowd4#

刚刚解决了。
该修复需要在“Runner.entitlements”文件中将“aps-environment”设置为“production”。在开发/测试期间,将其设置为“开发”。
请注意- TestFlight被视为“生产”。

相关问题