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)
Отслеживание состояния разрешения Nearby
Для включения обнаружения устройств требуется согласие пользователя. Это указано в состоянии разрешения Nearby. При первом вызове для создания публикации или подписки пользователю предоставляется диалоговое окно согласия. Если пользователь не дает согласия, обнаружение устройств работать не будет. В этом случае ваше приложение должно отображать сообщение, напоминающее пользователю о том, что обнаружение устройств отключено. Состояние разрешения хранится в 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
Отслеживание пользовательских настроек, влияющих на Nearby
Если пользователь отклонил разрешение на микрофон, отклонил разрешение на 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 покажет диалоговое окно «preflight», в котором объясняется, почему пользователя просят дать разрешение.
Если вы хотите предоставить пользовательский диалог "preflight", установите параметр 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-only в вашей публикации или подписке, передав правильно настроенный объект
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
и восстановите публикации и/или подписки Nearby, если включен фоновый режим.
- Сохраняйте значение фонового режима в
Фоновые уведомления
Если вы хотите, чтобы ваше приложение уведомляло пользователя о получении подпиской сообщения в фоновом режиме, вы можете использовать локальные уведомления .
Чтобы добавить их в свое приложение, выполните следующие действия:
Зарегистрируйтесь для получения локальных уведомлений при запуске:
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... }