前言:
我的应用程序是基于颤振的--但是要使FCM消息正常工作,需要本机代码实现,有关更多详细信息,请参阅下面
GitHub发布 #154以供参考。
我很难让FCM通知在iOS上运行,特别是在我的应用程序上发布到Testflight上。我在这个问题上已经被困了一个星期了,我完全不知道该怎么做。
问题
当在我的设备上使用Xcode/Android在本地运行调试/发布版本时,会在后台、前台等接收通知。当将完全相同的应用上传到测试飞行时,没有一个通知会通过FCM发出。
这是至关重要的,因为FCM交付VoIP通知,这些通知没有在测试飞行中收到,这是非常令人苦恼的。
问题和解决方案?
我发现了两个问题(这里和这里),这两个问题似乎都表明这是一个APNS证书问题(APNS -> Firebase)。我重新创建了我的证书并将它添加到Firebase控制台(在所有证书生成操作中使用相同的.csr文件)
Setup/Configuration:
试过:
<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>Tutorials/sources:
Swift代码:(针对>=10.0)
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;
}颤振 main.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个物理iPhones (6s & 8)上进行。当使用(调试和发布)模式直接从Mac (Android & XCode)构建时,两者都与Firebase一起工作。从TestFlight下载相同的内容时,这两种方法都不起作用。
如果有人能洞察错误配置、安装错误或缺少/不正确的Swift代码,或者只是一个错误或遗漏,我们将不胜感激。
发布于 2021-10-17 22:07:44
前言:这个问题是我的。
TL;博士仅改变了CubeEnvironment对PRODUCTION的1次引用。
有多个位置可以更改CubeEnvironment
建议使用,更好的是将其添加到“CallManagerService”的init()方法中:
bool isProduction = bool.fromEnvironment('dart.vm.product');
parameters.environment = isProduction ? CubeEnvironment.PRODUCTION : CubeEnvironment.DEVELOPMENT;调试( 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环境通知--这需要修复。
回顾我的代码,我终于发现了这个问题(并修复了上面提到的)。
发布于 2021-10-16 20:45:59
这个问题有时会让人们抓狂,即使他们把所有的东西都应用在正确的场景中,所以请试着检查以下内容:
1-在你的苹果开发者帐户中,确保你只有一个Apple Push Services Certificate分配给应用标识符(捆绑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被认为是发布(生产)模式,而不是沙箱模式。
发布于 2022-10-31 02:18:11
我什么都试过了,但对我起作用的是发现App阻止了我的推送通知。把这个从公共场合拿出来帮我解决了问题。结束了30小时的调试过程。
https://stackoverflow.com/questions/69592491
复制相似问题