Ios 颤振推送通知:无法在后台或应用程序关闭时接收通知

Ios 颤振推送通知:无法在后台或应用程序关闭时接收通知,ios,firebase,flutter,firebase-cloud-messaging,apple-push-notifications,Ios,Firebase,Flutter,Firebase Cloud Messaging,Apple Push Notifications,我正在为Android和iOS开发一款颤振应用程序。它有通知,所以我实现了API。我通过设备ID向某些设备发送通知,同时也向主题发送通知 我正在测试主题通知发送,它在Android中100%正常工作。我遵循上面提供的链接中的指南,也实现了iOS设置。但在iOS中,当发送通知时,应用程序仅在前台接收通知。也就是说,只能通过onMessage。如果应用程序在后台或已关闭,我看不到任何通知(我正在控制台中打印)。但当我重新打开应用程序时,通知会打印出来 下面是我的通知注册码 FirebaseM

我正在为Android和iOS开发一款颤振应用程序。它有通知,所以我实现了API。我通过设备ID向某些设备发送通知,同时也向
主题
发送通知

我正在测试
主题
通知发送,它在Android中100%正常工作。我遵循上面提供的链接中的指南,也实现了iOS设置。但在iOS中,当发送通知时,应用程序仅在前台接收通知。也就是说,只能通过
onMessage
。如果应用程序在后台或已关闭,我看不到任何通知(我正在控制台中打印)。但当我重新打开应用程序时,通知会打印出来

下面是我的通知注册码

    FirebaseMessagesImpl msg = FirebaseMessagesImpl();
         msg.requestPermissions();
    
    //Get configured with firebase messaging to recieve messages
    msg.getMessage().then((_) {
     msg.register().then((String token) {
     print(token);
    
     //Register to the `topic` so we get messages sent to the topic
     msg.topicRegister();
.........
}
FirebaseMessageSimple

  import 'package:firebase_messaging/firebase_messaging.dart';

  import 'package:http/http.dart' as http;
  import 'dart:convert' as convert;

  class FirebaseMessagesImpl {
    final FirebaseMessaging _firebaseMessaging = FirebaseMessaging();

    String serverToken =
        "AAAAAAA:XXXXXXXXX-YYYYYYYY-ZZZZ-BBBBBBBB";

    Future<String> register() async {
      String token = "";
      _firebaseMessaging.getToken().then((t) {
        token = t;
        print("ha: " + t);
      });

      return token;
    }

    Future<void> getMessage() async {
      _firebaseMessaging.configure(
          onMessage: (Map<String, dynamic> message) async {
        print('on message $message');
        //setState(() => _message = message["notification"]["title"]);
      }, onResume: (Map<String, dynamic> message) async {
        print('on resume $message');
        // setState(() => _message = message["notification"]["title"]);
      }, onLaunch: (Map<String, dynamic> message) async {
        print('on launch $message');
        //setState(() => _message = message["notification"]["title"]);
      });
    }

    void topicRegister() {
    // _firebaseMessaging.subscribeToTopic("mobile_admin");
      _firebaseMessaging.subscribeToTopic("puppies");
    }



    void requestPermissions() async
    {
      await _firebaseMessaging.requestNotificationPermissions(
        const IosNotificationSettings(sound:true, badge:true, alert:true, provisional:false)
      );
    }
正如一些人在其他SO答案中建议的那样,我从AppDelegate.swift代码中删除了以下部分并尝试了,但仍然存在相同的问题

if #available(iOS 10.0, *) {
      UNUserNotificationCenter.current().delegate = self as? UNUserNotificationCenterDelegate
    }
我已经将apple key文件上传到Firebase项目
云消息
部分,正如在指南中一样

下面是我发送通知的JSon代码

{
           "notification": {
              "body": "body",
              "title": "title"
           },
           "priority": "high",
           "data": {
            "body": "body",
              "title": "title",
              "click_action": "FLUTTER_NOTIFICATION_CLICK",
              "id": "1",
              "status": "done",
              "image": "https://ibin.co/2t1lLdpfS06F.png"
           },
           "to": "/topics/puppies"
        }
我的签名能力如下

我是iOS新手,不知道发生了什么。我想就像Android一样,当应用程序处于后台或关闭时,通知会自动出现在通知栏中

更新

根据@nandish的建议,我将
AppDelegate.swift
文件更改如下

import UIKit
import Flutter
import Firebase

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate, UNUserNotificationCenterDelegate {
  override func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
  ) -> Bool {
    FirebaseApp.configure()
    GeneratedPluginRegistrant.register(with: self)
    UNUserNotificationCenter.current().delegate = self
    
    return super.application(application, didFinishLaunchingWithOptions: launchOptions)
  }
    
    override func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {

      Messaging.messaging().apnsToken = deviceToken
      super.application(application, didRegisterForRemoteNotificationsWithDeviceToken: deviceToken)
    }
    
    // MARK: - UNUserNotificationCenterDelegate Method
    func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
        completionHandler([.alert])
    }

    func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {

     }
}
然后我出现了以下错误

UNUserNotificationCenter' is only available in iOS 10.0 or newer
        func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
更新

在前台,当发出通知时,我从应用程序收到以下响应。这也只是在iPhone模拟器中,而不是在真实设备中

{from: /topics/puppies, status: done, id: 1, notification: {body: body, title: title, e: 1, tag: topic_key_9204266xxxxxxx535}, title: title, image: https://ibin.co/2t1lLdpfS06F.png, collapse_key: com.aaa.xxx, body: body, click_action: FLUTTER_NOTIFICATION_CLICK}

首先,如果您使用Firebase云消息进行通知,android将在应用程序打开或关闭时收到通知。 但在iOS方面,iOS使用的是APN(苹果推送通知)

*-你应该试一试真正的设备。在iOS模拟器上,获取通知是不稳定的。在*

在firebase控制台上,进入
设置>云消息>iOS应用程序配置
,然后从Apple开发者面板添加APN标识密钥。你可以在电视上看到

此外,您还应该在通知负载上添加
“content\u available”:true

这里有一个例子:

{
  "to": "/topics/topic_name",
  "content_available": true,
  "notification": {
    "title": "TITLE TEXT",
    "body": "BODY TEXT",
    "content_available": true
  },
  "data": {
    "body": "BODY TEXT",
    "title": "TITLE TEXT",
    "click_action": "FLUTTER_NOTIFICATION_CLICK"
  }
}

对于后台通知,您可以尝试在中添加“后台模式”功能,方法是单击目标项目的“签名与功能”选项卡下的“+capability”,并按照以下apple文档中的建议启用远程通知

在AppDelegate.swift中,还应添加以下内容:

class AppDelegate: FlutterAppDelegate , UNUserNotificationCenterDelegate {
      override func application(_ application: UIApplication,
          didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
       ....
       UNUserNotificationCenter.current().delegate = self
       ....
    }
    ....

    // MARK: - UNUserNotificationCenterDelegate Method
    func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
        completionHandler([.alert])
    }

    func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {

     }
}

当他们在firebase_messaging 6.0.16中发现一个问题时,我遇到了一个非常类似的问题,现在它已更新为7.0.0

我调整了我的info.plist并更改了

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

它与您的有所不同。

您是否尝试强制转换传递给onMessage回调的消息数据

data = Map<String, dynamic>.from(message['data']);
data=Map.from(message['data']);

谢谢您的回复。嗯,我只是试着用真正的设备,然后注意到我根本没有收到任何通知。然而昨天我收到了真实设备的通知,当它在前台时。然后我使用了
content\u available=true
和no good。我想我已经正确上传了APN,否则我根本就不会收到任何通知,不是吗?当应用程序在前台时,我会收到模拟器的通知。好吧,我明白了,实际上我不知道为什么。我在手机上试过,但当应用程序关闭时,我也无法收到通知。可能问题出在firebase消息包上。“content\u available”:true表示它是无声通知。请拿掉那个标签。谢谢你,贾斯米特,我不知道。抱歉提供了不好的信息。你能截图一下你添加到目标中的功能吗?@Honey:很抱歉延迟回复。我已经添加了截图。请检查。@Honey:看来我没有收到真正设备的通知。我的测试设备是iPhone6。看起来不错。有时只要取消选中并再次检查它们就可以解决问题。您何时注销设备令牌?也许你正在做一些在后台注销用户的事情顺便问一下,你没有收到真实设备的通知是什么意思?推送通知仅传送到真实设备。模拟器无法使用APN创建令牌…所以只能使用真实设备测试你的回复,但这会产生错误。基本上它说你的方法只适用于iOS 10及以上版本。我已经用这个更新了我的问题。而且我似乎没有收到真正设备的通知。我的测试设备是iPhone 6。你是否在调试模式下通过连接测试通知?它工作正常,非常感谢!!。我更改info.plist与您的相同,并更改firebase_消息版本6.0.9及其工作状态。在此之前,我使用的是版本7.0.3
<key>FirebaseAppDelegateProxyEnabled</key><false/>
<key>FirebaseAppDelegateProxyEnabled</key>
<string>false</string>
@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
  override func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
  ) -> Bool {
    GeneratedPluginRegistrant.register(with: self)
    //FirebaseApp.configure()
    if #available(iOS 10.0, *) {
      UNUserNotificationCenter.current().delegate = self as? UNUserNotificationCenterDelegate
    }
    return super.application(application, didFinishLaunchingWithOptions: launchOptions)
  }
  }
data = Map<String, dynamic>.from(message['data']);