API Nearby Messages — это API с публикацией и подпиской, позволяющий устройствам поблизости обмениваться небольшими объёмами данных. После публикации сообщения устройство может его получить. Размер сообщения должен быть достаточно небольшим для поддержания высокой производительности. Этот сервис не предназначен для обмена большими объектами, такими как фотографии и видео.
Набор ближайших устройств определяется путём обмена небольшими токенами по Bluetooth и передачи звука на уровне, близком к ультразвуку (неслышимом). Когда устройство обнаруживает токен от ближайшего устройства, оно отправляет его на сервер Nearby Messages для проверки и поиска сообщений для доставки по текущему набору подписок приложения.
Приложение может управлять набором носителей, используемых для обнаружения устройств, а также тем, используются ли эти носители для трансляции токенов и/или сканирования. По умолчанию трансляция и сканирование выполняются на всех носителях. Для обнаружения на подмножестве носителей и управления трансляцией или сканированием необходимо передать дополнительные параметры при создании публикаций и подписок.
Эта библиотека работает на iOS 7 и выше и собирается с использованием iOS 8 SDK .
Создание менеджера сообщений
Этот код создаёт объект менеджера сообщений, позволяющий публиковать сообщения и подписываться на них. Обмен сообщениями не требует аутентификации, поэтому необходимо предоставить открытый ключ API для iOS. Вы можете создать его, используя запись в консоли разработчика Google для вашего проекта.
Objective-C
#import <GNSMessages.h>
GNSMessageManager *messageManager =
[[GNSMessageManager alloc] initWithAPIKey:@"API_KEY"];
Быстрый
let messageManager = GNSMessageManager(APIKey: "API_KEY")
Публикация сообщения
Этот фрагмент кода демонстрирует публикацию сообщения, содержащего имя. Публикация активна, пока существует объект публикации. Чтобы остановить публикацию, освободите объект публикации.
Objective-C
id<GNSPublication> publication =
[messageManager publicationWithMessage:[GNSMessage messageWithContent:[name dataUsingEncoding:NSUTF8StringEncoding]]];
Быстрый
let publication =
messageManager.publication(with: GNSMessage(content: name.data(using: .utf8)))
Подписка на сообщения
Этот фрагмент кода демонстрирует подписку на все имена, используемые в предыдущем фрагменте публикации. Подписка активна, пока существуют объекты подписки. Чтобы прекратить подписку, освободите объект подписки.
Обработчик найденных сообщений вызывается при обнаружении устройств, публикующих сообщения поблизости. Обработчик потерянных сообщений вызывается, когда сообщение больше не наблюдается (устройство вышло из зоны действия или перестало публиковать сообщение).
Objective-C
id<GNSSubscription> subscription =
[messageManager subscriptionWithMessageFoundHandler:^(GNSMessage *message) {
// Add the name to a list for display
}
messageLostHandler:^(GNSMessage *message) {
// Remove the name from the list
}];
Быстрый
let subscription =
messageManager.subscription(messageFoundHandler: { (message: GNSMessage?) in
// Add the name to a list for display
},
messageLostHandler: { (message: GNSMessage?) in
// Remove the name from the list
})
Средства обнаружения
По умолчанию оба канала (аудио и Bluetooth) будут использоваться для обнаружения устройств поблизости, и оба канала будут осуществлять трансляцию и сканирование. В некоторых случаях необходимо добавить следующие записи в Info.plist
вашего приложения:
Если ваше приложение использует аудиосканирование, добавьте
NSMicrophoneUsageDescription
— строку, описывающую цель использования микрофона. Например, «Микрофон прослушивает анонимные токены с устройств поблизости».Если ваше приложение использует BLE для трансляции, добавьте
NSBluetoothPeripheralUsageDescription
— строку, описывающую, почему вы будете использовать BLE для рекламы. Например, «Анонимный токен рекламируется через Bluetooth для обнаружения устройств поблизости».
В некоторых случаях вашему приложению может потребоваться использовать только один из носителей, и ему может не потребоваться выполнять и трансляцию, и сканирование на этом носителе.
Например, приложению, предназначенному для подключения к ТВ-приставке, транслирующей только аудио, достаточно выполнить сканирование аудио, чтобы обнаружить её. В следующем фрагменте кода показано, как опубликовать сообщение на этой ТВ-приставке, используя только сканирование аудио для обнаружения:
Objective-C
id<GNSPublication> publication = [messageManager publicationWithMessage:message
paramsBlock:^(GNSPublicationParams *params) {
params.strategy = [GNSStrategy strategyWithParamsBlock:^(GNSStrategyParams *params) {
params.discoveryMediums = kGNSDiscoveryMediumsAudio;
params.discoveryMode = kGNSDiscoveryModeScan;
}];
}];
Быстрый
let publication = messageManager.publication(with: message,
paramsBlock: { (params: GNSPublicationParams?) in
guard let params = params else { return }
params.strategy = GNSStrategy(paramsBlock: { (params: GNSStrategyParams?) in
guard let params = params else { return }
params.discoveryMediums = .audio
params.discoveryMode = .scan
})
})
Включение ведения журнала отладки
Журнал отладки выводит важные внутренние события в консоль, что может быть полезно для отслеживания проблем, с которыми вы можете столкнуться при интеграции Nearby Messages в ваше приложение. Мы запросим эти журналы, если вы обратитесь к нам за технической поддержкой.
Его следует включить перед созданием менеджера сообщений. Этот фрагмент кода показывает, как включить отладочное ведение журнала:
Objective-C
[GNSMessageManager setDebugLoggingEnabled:YES];
Быстрый
GNSMessageManager.setDebugLoggingEnabled(true)
Отслеживание состояния разрешения «Рядом»
Для включения обнаружения устройств требуется согласие пользователя. На это указывает состояние разрешения «Рядом». При первом вызове для создания публикации или подписки пользователю отображается диалоговое окно с запросом согласия. Если пользователь не даст согласия, обнаружение устройств работать не будет. В этом случае приложение должно отображать сообщение, напоминающее пользователю об отключении обнаружения устройств. Состояние разрешения хранится в NSUserDefaults
.
В следующем фрагменте кода показана подписка на состояние разрешения. Обработчик изменений состояния разрешения вызывается при каждом изменении состояния, и он не вызывается в первый раз, пока пользователь не предоставит или не отклонит разрешение. Чтобы прекратить подписку, отпустите объект разрешения.
Objective-C
GNSPermission *nearbyPermission = [[GNSPermission alloc] initWithChangedHandler:^(BOOL granted) {
// Update the UI here
}];
Быстрый
let nearbyPermission = GNSPermission(changedHandler: { (granted: Bool) in
// Update the UI here
})
Ваше приложение может предоставить пользователю возможность изменить состояние разрешения, например, с помощью переключателя на странице настроек.
Вот пример того, как получить и установить состояние разрешения.
Objective-C
BOOL permissionState = [GNSPermission isGranted];
[GNSPermission setGranted:!permissionState]; // toggle the state
Быстрый
let permissionState = GNSPermission.isGranted()
GNSPermission.setGranted(!permissionState) // toggle the state
Отслеживание пользовательских настроек, влияющих на функцию «Рядом»
Если пользователь запретил доступ к микрофону, Bluetooth или отключил Bluetooth, приложение Nearby не будет работать должным образом или может не работать вовсе. В таких случаях ваше приложение должно выводить сообщение, предупреждающее пользователя о том, что работа приложения Nearby затруднена. В следующем фрагменте кода показано, как отслеживать состояние этих пользовательских настроек, передавая обработчики при создании менеджера сообщений:
Objective-C
GNSMessageManager *messageManager = [[GNSMessageManager alloc]
initWithAPIKey:API_KEY
paramsBlock:^(GNSMessageManagerParams *params) {
params.microphonePermissionErrorHandler = ^(BOOL hasError) {
// Update the UI for microphone permission
};
params.bluetoothPowerErrorHandler = ^(BOOL hasError) {
// Update the UI for Bluetooth power
};
params.bluetoothPermissionErrorHandler = ^(BOOL hasError) {
// Update the UI for Bluetooth permission
};
}];
Быстрый
let messageManager = GNSMessageManager(
APIKey: API_KEY,
paramsBlock: { (params: GNSMessageManagerParams?) in
guard let params = params else { return }
params.microphonePermissionErrorHandler = { (hasError: Bool) in
// Update the UI for microphone permission
}
params.bluetoothPowerErrorHandler = { (hasError: Bool) in
// Update the UI for Bluetooth power
}
params.bluetoothPermissionErrorHandler = { (hasError: Bool) in
// Update the UI for Bluetooth permission
}
})
Переопределение диалогового окна разрешений «Рядом»
В зависимости от параметров, которые вы передаёте в публикации и подписки, iOS может запрашивать различные разрешения перед запуском Nearby. Например, стратегия по умолчанию предполагает прослушивание данных, передаваемых в диапазоне частот, близком к ультразвуковому, поэтому iOS запросит разрешение на использование микрофона. В этих случаях Nearby покажет «предварительное» диалоговое окно, объясняющее причину запроса разрешения.
Если вы хотите создать настраиваемый предварительный диалог, задайте параметр permissionRequestHandler
для настраиваемого блока в параметрах публикации или подписки. Ваш настраиваемый блок должен вызывать блок permissionHandler
после ответа пользователя. В следующем фрагменте кода показано, как это сделать для публикации:
Objective-C
id<GNSPublication> publication =
[messageManager publicationWithMessage:[GNSMessage messageWithContent:[name dataUsingEncoding:NSUTF8StringEncoding]]
paramsBlock:^(GNSPublicationParams *params) {
params.permissionRequestHandler = ^(GNSPermissionHandler permissionHandler) {
// Show your custom dialog here.
// Don't forget to call permissionHandler() with YES or NO when the user dismisses it.
};
}];
Быстрый
let publication =
messageManager.publication(with: GNSMessage(content: name.data(using: .utf8)),
paramsBlock: { (params: GNSPublicationParams?) in
guard let params = params else { return }
params.permissionRequestHandler = { (permissionHandler: GNSPermissionHandler?) in
// Show your custom dialog here.
// Don't forget to call permissionHandler() with true or false when the user dismisses it.
}
})
Фоновая операция
Публикации и подписки, использующие BLE для обнаружения устройств, могут работать в фоновом режиме. Вот несколько моментов, которые следует учитывать при выборе фонового режима:
- Фоновые операции должны использовать только среду BLE; аудио не поддерживается.
- Фоновый режим BLE влечет за собой дополнительную нагрузку на аккумулятор. Стоимость невелика, но перед использованием фонового режима следует оценить её.
- iOS запросит у пользователя разрешение на показ рекламы через BLE в фоновом режиме.
Чтобы добавить фоновый режим к публикации или подписке, выполните следующие дополнительные действия:
Включите фоновый режим и поддержку BLE-поддержки в вашей публикации или подписке, передав правильно настроенный объект
GNSStrategy
. В следующем фрагменте кода показано, как это сделать для подписки:Objective-C
id<GNSSubscription> subscription = [messageManager subscriptionWithMessageFoundHandler:^(GNSMessage *message) { // Add the name to a list for display } messageLostHandler:^(GNSMessage *message) { // Remove the name from the list } paramsBlock:^(GNSSubscriptionParams *params) { params.strategy = [GNSStrategy strategyWithParamsBlock:^(GNSStrategyParams *params) { params.allowInBackground = YES; params.discoveryMediums = kGNSDiscoveryMediumsBLE; }]; }];
Быстрый
let subscription = messageManager.subscription(messageFoundHandler: { (message: GNSMessage?) in // Add the name to a list for display }, messageLostHandler: { (message: GNSMessage?) in // Remove the name from the list }, paramsBlock:{ (params: GNSSubscriptionParams?) in guard let params = params else { return } params.strategy = GNSStrategy(paramsBlock: { (params: GNSStrategyParams?) in guard let params = params else { return } params.allowInBackground = true params.discoveryMediums = .BLE }) })
Добавьте эти записи в
Info.plist
вашего приложения:Записи
UIBackgroundModes
:-
bluetooth-central
для сканирования BLE в фоновом режиме. Требуется только в том случае, если режим обнаружения включает сканирование; по умолчанию оно включено. -
bluetooth-peripheral
для показа объявлений BLE в фоновом режиме. Требуется только в том случае, если режим обнаружения включает широковещательную передачу; по умолчанию она включена.
-
Строка
NSBluetoothPeripheralUsageDescription
, описывающая, почему вы будете рекламировать BLE. Например, «Анонимный токен рекламируется через Bluetooth для обнаружения устройств поблизости». Подробности см. в документации Apple .
Система может в любой момент завершить ваше приложение, пока оно находится в фоновом режиме. Если фоновый режим — это настройка, которую пользователь может включить или отключить, ваше приложение должно выполнять следующие действия:
- Сохраняйте значение фонового режима в
NSUserDefaults
всякий раз, когда пользователь его изменяет. - При запуске прочитайте его из
NSUserDefaults
и восстановите ближайшие публикации и/или подписки, если включен фоновый режим.
- Сохраняйте значение фонового режима в
Фоновые уведомления
Если вы хотите, чтобы ваше приложение уведомляло пользователя о получении подпиской сообщения в фоновом режиме, вы можете использовать локальные уведомления .
Чтобы добавить их в свое приложение, выполните следующие действия:
Зарегистрируйтесь для получения локальных уведомлений при запуске:
Objective-C
if ([UIApplication instancesRespondToSelector:@selector(registerUserNotificationSettings:)]) { [[UIApplication sharedApplication] registerUserNotificationSettings: [UIUserNotificationSettings settingsForTypes: UIUserNotificationTypeAlert | UIUserNotificationTypeBadge | UIUserNotificationTypeSound categories:nil]]; }
Быстрый
UIApplication.shared.registerUserNotificationSettings( UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil))
Отправьте локальное уведомление в обработчик найденных сообщений вашей подписки:
Objective-C
GNSMessageHandler myMessageFoundHandler = ^(GNSMessage *message) { // Send a local notification if not in the foreground. if ([UIApplication sharedApplication].applicationState != UIApplicationStateActive) { UILocalNotification *localNotification = [[UILocalNotification alloc] init]; localNotification.alertBody = @"Message received"; [[UIApplication sharedApplication] presentLocalNotificationNow:localNotification]; } // Process the new message... };
Быстрый
let myMessageFoundHandler: GNSMessageHandler = { (message: GNSMessage?) in // Send a local notification if not in the foreground. if UIApplication.shared.applicationState != .active { let localNotification = UILocalNotification() localNotification.alertBody = "Message received" UIApplication.shared.presentLocalNotificationNow(localNotification) } // Process the new message... }