Отправляйте сообщения на несколько устройств на платформах Apple.

Чтобы нацелить сообщение на несколько устройств, используйте Обмен сообщениями по темам . Эта функция позволяет отправлять сообщения на несколько устройств, которые выбрали определенную тему.

В этом руководстве основное внимание уделяется отправке тематических сообщений с вашего сервера приложений с помощью Admin SDK или REST API для FCM, а также их получению и обработке в приложении Apple. На этой странице перечислены все шаги для достижения этой цели, от настройки до проверки, поэтому она может охватывать шаги, которые вы уже выполнили, если вы настроили клиентское приложение Apple для FCM или выполнили шаги для отправки вашего первого сообщения .

Добавьте Firebase в свой проект Apple

В этом разделе описаны задачи, которые вы могли выполнить, если уже включили другие функции Firebase для своего приложения. В частности, для FCM вам потребуется загрузить ключ аутентификации APN и зарегистрироваться для получения удаленных уведомлений .

Предпосылки

  • Установите следующее:

    • Xcode 14.1 или новее
  • Убедитесь, что ваш проект соответствует следующим требованиям:

    • Ваш проект должен быть ориентирован на эти версии платформы или более поздние версии:
      • iOS 11
      • макОС 10.13
      • твОС 12
      • смотретьОС 6
  • Настройте физическое устройство Apple для запуска вашего приложения и выполните следующие задачи:

    • Получите ключ аутентификации Apple Push Notification для своей учетной записи Apple Developer .
    • Включите push-уведомления в XCode в разделе «Приложение» > «Возможности» .

Если у вас еще нет проекта Xcode и вы просто хотите попробовать продукт Firebase, вы можете загрузить один из наших кратких примеров .

Создайте проект Firebase

Прежде чем вы сможете добавить Firebase в свое приложение Apple, вам необходимо создать проект Firebase для подключения к вашему приложению. Посетите страницу Understand Firebase Projects , чтобы узнать больше о проектах Firebase.

Зарегистрируйте свое приложение в Firebase

Чтобы использовать Firebase в своем приложении Apple, вам необходимо зарегистрировать свое приложение в проекте Firebase. Регистрация вашего приложения часто называется «добавлением» вашего приложения в ваш проект.

  1. Перейдите в консоль Firebase .

  2. В центре страницы обзора проекта щелкните значок iOS+ , чтобы запустить рабочий процесс установки.

    Если вы уже добавили приложение в свой проект Firebase, нажмите «Добавить приложение» , чтобы отобразить параметры платформы.

  3. Введите идентификатор пакета вашего приложения в поле идентификатора пакета .

  4. (Необязательно) Введите другую информацию о приложении: псевдоним приложения и идентификатор App Store .

  5. Щелкните Зарегистрировать приложение .

Добавьте файл конфигурации Firebase

  1. Нажмите «Загрузить GoogleService-Info.plist» , чтобы получить файл конфигурации Firebase для платформ Apple ( GoogleService-Info.plist ).

  2. Переместите файл конфигурации в корень вашего проекта Xcode. При появлении запроса выберите, чтобы добавить файл конфигурации ко всем целям.

Если в вашем проекте есть несколько идентификаторов пакетов, вы должны связать каждый идентификатор пакета с зарегистрированным приложением в консоли Firebase, чтобы каждое приложение могло иметь свой собственный файл GoogleService-Info.plist .

Добавьте Firebase SDK в свое приложение

Используйте диспетчер пакетов Swift для установки и управления зависимостями Firebase.

  1. В Xcode при открытом проекте приложения перейдите в File > Add Packages .
  2. При появлении запроса добавьте репозиторий SDK Firebase для платформ Apple:
  3.   https://github.com/firebase/firebase-ios-sdk
  4. Выберите библиотеку Firebase Cloud Messaging.
  5. Для оптимальной работы с Firebase Cloud Messaging мы рекомендуем включить Google Analytics в вашем проекте Firebase и добавить Firebase SDK для Google Analytics в ваше приложение. Вы можете выбрать библиотеку без коллекции IDFA или с коллекцией IDFA.
  6. Когда закончите, Xcode автоматически начнет разрешать и загружать ваши зависимости в фоновом режиме.

Загрузите свой ключ аутентификации APNs

Загрузите свой ключ аутентификации APNs в Firebase. Если у вас еще нет ключа аутентификации APN, обязательно создайте его в Apple Developer Member Center .

  1. Внутри вашего проекта в консоли Firebase щелкните значок шестеренки, выберите «Настройки проекта» , а затем выберите вкладку «Облачные сообщения» .

  2. В разделе «Ключ аутентификации APNs» в разделе «Конфигурация приложения iOS» нажмите кнопку «Загрузить» .

  3. Перейдите к месту, где вы сохранили свой ключ, выберите его и нажмите «Открыть» . Добавьте идентификатор ключа для ключа (доступен в Apple Developer Member Center ) и нажмите «Загрузить» .

Инициализируйте Firebase в своем приложении

Вам нужно будет добавить код инициализации Firebase в ваше приложение. Импортируйте модуль Firebase и настройте общий экземпляр, как показано ниже:

  1. Импортируйте модуль FirebaseCore в свой UIApplicationDelegate , а также любые другие модули Firebase, которые использует ваш делегат приложения. Например, чтобы использовать Cloud Firestore и аутентификацию:

    SwiftUI

    import SwiftUI
    import FirebaseCore
    import FirebaseFirestore
    import FirebaseAuth
    // ...
          

    Быстрый

    import FirebaseCore
    import FirebaseFirestore
    import FirebaseAuth
    // ...
          

    Цель-C

    @import FirebaseCore;
    @import FirebaseFirestore;
    @import FirebaseAuth;
    // ...
          
  2. Настройте общий экземпляр FirebaseApp в методе application application(_:didFinishLaunchingWithOptions:) вашего делегата приложения:

    SwiftUI

    // Use Firebase library to configure APIs
    FirebaseApp.configure()

    Быстрый

    // Use Firebase library to configure APIs
    FirebaseApp.configure()

    Цель-C

    // Use Firebase library to configure APIs
    [FIRApp configure];
  3. Если вы используете SwiftUI, вы должны создать делегат приложения и прикрепить его к своей структуре App через UIApplicationDelegateAdaptor или NSApplicationDelegateAdaptor . Вы также должны отключить swizzling делегата приложения. Дополнительные сведения см. в инструкциях SwiftUI .

    SwiftUI

    @main
    struct YourApp: App {
      // register app delegate for Firebase setup
      @UIApplicationDelegateAdaptor(AppDelegate.self) var delegate
    
      var body: some Scene {
        WindowGroup {
          NavigationView {
            ContentView()
          }
        }
      }
    }
          

Зарегистрируйтесь для получения удаленных уведомлений

Либо при запуске, либо в желаемой точке потока вашего приложения зарегистрируйте свое приложение для удаленных уведомлений. Вызовите registerForRemoteNotifications , как показано ниже:

Быстрый


UNUserNotificationCenter.current().delegate = self

let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
UNUserNotificationCenter.current().requestAuthorization(
  options: authOptions,
  completionHandler: { _, _ in }
)

application.registerForRemoteNotifications()

Цель-C


[UNUserNotificationCenter currentNotificationCenter].delegate = self;
UNAuthorizationOptions authOptions = UNAuthorizationOptionAlert |
    UNAuthorizationOptionSound | UNAuthorizationOptionBadge;
[[UNUserNotificationCenter currentNotificationCenter]
    requestAuthorizationWithOptions:authOptions
    completionHandler:^(BOOL granted, NSError * _Nullable error) {
      // ...
    }];

[application registerForRemoteNotifications];

Подпишите клиентское приложение на тему

Клиентские приложения могут подписаться на любую существующую тему или создать новую тему. Когда клиентское приложение подписывается на новую тему (которая еще не существует для вашего проекта Firebase), в FCM создается новая тема с таким именем, и впоследствии любой клиент может подписаться на нее.

Чтобы подписаться на тему, вызовите метод подписки из основного потока вашего приложения (FCM не является потокобезопасным). Если запрос на подписку изначально завершается ошибкой, FCM повторяет попытку автоматически. В случаях, когда подписка не может быть завершена, подписка выдает ошибку, которую можно перехватить в обработчике завершения, как показано ниже:

Быстрый

Messaging.messaging().subscribe(toTopic: "weather") { error in
  print("Subscribed to weather topic")
}

Цель-C

[[FIRMessaging messaging] subscribeToTopic:@"weather"
                                completion:^(NSError * _Nullable error) {
  NSLog(@"Subscribed to weather topic");
}];

Этот вызов делает асинхронный запрос к серверной части FCM и подписывается клиента на данную тему. Перед вызовом subscribeToTopic:topic убедитесь, что экземпляр клиентского приложения уже получил токен регистрации с помощью обратного вызова didReceiveRegistrationToken .

Каждый раз, когда приложение запускается, FCM проверяет, подписаны ли все запрошенные темы. Чтобы отказаться от подписки, вызовите unsubscribeFromTopic:topic , и FCM отпишется от темы в фоновом режиме.

Получение и обработка тематических сообщений

FCM доставляет тематические сообщения так же, как и другие нижестоящие сообщения.

Реализуйте application(_:didReceiveRemoteNotification:fetchCompletionHandler:) , как показано ниже:

Быстрый

func application(_ application: UIApplication,
                 didReceiveRemoteNotification userInfo: [AnyHashable: Any]) async
  -> UIBackgroundFetchResult {
  // If you are receiving a notification message while your app is in the background,
  // this callback will not be fired till the user taps on the notification launching the application.
  // TODO: Handle data of notification

  // With swizzling disabled you must let Messaging know about the message, for Analytics
  // Messaging.messaging().appDidReceiveMessage(userInfo)

  // Print message ID.
  if let messageID = userInfo[gcmMessageIDKey] {
    print("Message ID: \(messageID)")
  }

  // Print full message.
  print(userInfo)

  return UIBackgroundFetchResult.newData
}

Цель-C

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
    fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
  // If you are receiving a notification message while your app is in the background,
  // this callback will not be fired till the user taps on the notification launching the application.
  // TODO: Handle data of notification

  // With swizzling disabled you must let Messaging know about the message, for Analytics
  // [[FIRMessaging messaging] appDidReceiveMessage:userInfo];

  // ...

  // Print full message.
  NSLog(@"%@", userInfo);

  completionHandler(UIBackgroundFetchResultNewData);
}

Создание запросов на отправку

После того, как вы создали тему, либо подписав экземпляры клиентского приложения на тему на стороне клиента, либо через API сервера , вы можете отправлять сообщения в тему. Если вы впервые создаете запросы на отправку для FCM, см. руководство по вашей серверной среде и FCM , где содержится важная справочная информация и информация по настройке.

В логике отправки на серверной части укажите желаемое имя темы, как показано ниже:

Node.js

// The topic name can be optionally prefixed with "/topics/".
const topic = 'highScores';

const message = {
  data: {
    score: '850',
    time: '2:45'
  },
  topic: topic
};

// Send a message to devices subscribed to the provided topic.
getMessaging().send(message)
  .then((response) => {
    // Response is a message ID string.
    console.log('Successfully sent message:', response);
  })
  .catch((error) => {
    console.log('Error sending message:', error);
  });

Джава

// The topic name can be optionally prefixed with "/topics/".
String topic = "highScores";

// See documentation on defining a message payload.
Message message = Message.builder()
    .putData("score", "850")
    .putData("time", "2:45")
    .setTopic(topic)
    .build();

// Send a message to the devices subscribed to the provided topic.
String response = FirebaseMessaging.getInstance().send(message);
// Response is a message ID string.
System.out.println("Successfully sent message: " + response);

Питон

# The topic name can be optionally prefixed with "/topics/".
topic = 'highScores'

# See documentation on defining a message payload.
message = messaging.Message(
    data={
        'score': '850',
        'time': '2:45',
    },
    topic=topic,
)

# Send a message to the devices subscribed to the provided topic.
response = messaging.send(message)
# Response is a message ID string.
print('Successfully sent message:', response)

Идти

// The topic name can be optionally prefixed with "/topics/".
topic := "highScores"

// See documentation on defining a message payload.
message := &messaging.Message{
	Data: map[string]string{
		"score": "850",
		"time":  "2:45",
	},
	Topic: topic,
}

// Send a message to the devices subscribed to the provided topic.
response, err := client.Send(ctx, message)
if err != nil {
	log.Fatalln(err)
}
// Response is a message ID string.
fmt.Println("Successfully sent message:", response)

С#

// The topic name can be optionally prefixed with "/topics/".
var topic = "highScores";

// See documentation on defining a message payload.
var message = new Message()
{
    Data = new Dictionary<string, string>()
    {
        { "score", "850" },
        { "time", "2:45" },
    },
    Topic = topic,
};

// Send a message to the devices subscribed to the provided topic.
string response = await FirebaseMessaging.DefaultInstance.SendAsync(message);
// Response is a message ID string.
Console.WriteLine("Successfully sent message: " + response);

ОТДЫХ

POST https://fcm.googleapis.com/v1/projects/myproject-b5ae1/messages:send HTTP/1.1

Content-Type: application/json
Authorization: Bearer ya29.ElqKBGN2Ri_Uz...HnS_uNreA
{
  "message":{
    "topic" : "foo-bar",
    "notification" : {
      "body" : "This is a Firebase Cloud Messaging Topic Message!",
      "title" : "FCM Message"
      }
   }
}

URL-команда:

curl -X POST -H "Authorization: Bearer ya29.ElqKBGN2Ri_Uz...HnS_uNreA" -H "Content-Type: application/json" -d '{
  "message": {
    "topic" : "foo-bar",
    "notification": {
      "body": "This is a Firebase Cloud Messaging Topic Message!",
      "title": "FCM Message"
    }
  }
}' https://fcm.googleapis.com/v1/projects/myproject-b5ae1/messages:send HTTP/1.1

Чтобы отправить сообщение в комбинацию тем, укажите условие , которое представляет собой логическое выражение, задающее целевые темы. Например, следующее условие будет отправлять сообщения на устройства, которые подписаны на TopicA и TopicB или TopicC :

"'TopicA' in topics && ('TopicB' in topics || 'TopicC' in topics)"

FCM сначала оценивает любые условия в круглых скобках, а затем вычисляет выражение слева направо. В приведенном выше выражении пользователь, подписанный на какую-либо отдельную тему, не получает сообщение. Точно так же пользователь, не подписанный на TopicA , не получит сообщение. Эти комбинации действительно получают его:

  • TopicA и TopicB
  • TopicA и TopicC

В условное выражение можно включить до пяти тем.

Для отправки в состояние:

Node.js

// Define a condition which will send to devices which are subscribed
// to either the Google stock or the tech industry topics.
const condition = '\'stock-GOOG\' in topics || \'industry-tech\' in topics';

// See documentation on defining a message payload.
const message = {
  notification: {
    title: '$FooCorp up 1.43% on the day',
    body: '$FooCorp gained 11.80 points to close at 835.67, up 1.43% on the day.'
  },
  condition: condition
};

// Send a message to devices subscribed to the combination of topics
// specified by the provided condition.
getMessaging().send(message)
  .then((response) => {
    // Response is a message ID string.
    console.log('Successfully sent message:', response);
  })
  .catch((error) => {
    console.log('Error sending message:', error);
  });

Джава

// Define a condition which will send to devices which are subscribed
// to either the Google stock or the tech industry topics.
String condition = "'stock-GOOG' in topics || 'industry-tech' in topics";

// See documentation on defining a message payload.
Message message = Message.builder()
    .setNotification(Notification.builder()
        .setTitle("$GOOG up 1.43% on the day")
        .setBody("$GOOG gained 11.80 points to close at 835.67, up 1.43% on the day.")
        .build())
    .setCondition(condition)
    .build();

// Send a message to devices subscribed to the combination of topics
// specified by the provided condition.
String response = FirebaseMessaging.getInstance().send(message);
// Response is a message ID string.
System.out.println("Successfully sent message: " + response);

Питон

# Define a condition which will send to devices which are subscribed
# to either the Google stock or the tech industry topics.
condition = "'stock-GOOG' in topics || 'industry-tech' in topics"

# See documentation on defining a message payload.
message = messaging.Message(
    notification=messaging.Notification(
        title='$GOOG up 1.43% on the day',
        body='$GOOG gained 11.80 points to close at 835.67, up 1.43% on the day.',
    ),
    condition=condition,
)

# Send a message to devices subscribed to the combination of topics
# specified by the provided condition.
response = messaging.send(message)
# Response is a message ID string.
print('Successfully sent message:', response)

Идти

// Define a condition which will send to devices which are subscribed
// to either the Google stock or the tech industry topics.
condition := "'stock-GOOG' in topics || 'industry-tech' in topics"

// See documentation on defining a message payload.
message := &messaging.Message{
	Data: map[string]string{
		"score": "850",
		"time":  "2:45",
	},
	Condition: condition,
}

// Send a message to devices subscribed to the combination of topics
// specified by the provided condition.
response, err := client.Send(ctx, message)
if err != nil {
	log.Fatalln(err)
}
// Response is a message ID string.
fmt.Println("Successfully sent message:", response)

С#

// Define a condition which will send to devices which are subscribed
// to either the Google stock or the tech industry topics.
var condition = "'stock-GOOG' in topics || 'industry-tech' in topics";

// See documentation on defining a message payload.
var message = new Message()
{
    Notification = new Notification()
    {
        Title = "$GOOG up 1.43% on the day",
        Body = "$GOOG gained 11.80 points to close at 835.67, up 1.43% on the day.",
    },
    Condition = condition,
};

// Send a message to devices subscribed to the combination of topics
// specified by the provided condition.
string response = await FirebaseMessaging.DefaultInstance.SendAsync(message);
// Response is a message ID string.
Console.WriteLine("Successfully sent message: " + response);

ОТДЫХ

POST https://fcm.googleapis.com/v1/projects/myproject-b5ae1/messages:send HTTP/1.1

Content-Type: application/json
Authorization: Bearer ya29.ElqKBGN2Ri_Uz...HnS_uNreA
{
   "message":{
    "condition": "'dogs' in topics || 'cats' in topics",
    "notification" : {
      "body" : "This is a Firebase Cloud Messaging Topic Message!",
      "title" : "FCM Message",
    }
  }
}

URL-команда:

curl -X POST -H "Authorization: Bearer ya29.ElqKBGN2Ri_Uz...HnS_uNreA" -H "Content-Type: application/json" -d '{
  "notification": {
    "title": "FCM Message",
    "body": "This is a Firebase Cloud Messaging Topic Message!",
  },
  "condition": "'dogs' in topics || 'cats' in topics"
}' https://fcm.googleapis.com/v1/projects/myproject-b5ae1/messages:send HTTP/1.1

Следующие шаги