A API Nearby Messages é uma API de publicação/assinatura que permite que dispositivos próximos troquem pequenos payloads de dados. Depois que um dispositivo publica uma mensagem, os dispositivos próximos podem recebê-la. O tamanho da mensagem precisa ser pequeno para manter um bom desempenho. Esse serviço não é destinado à troca de objetos maiores, como fotos e vídeos.
O conjunto de dispositivos próximos é determinado pela troca de pequenos tokens por áudio Bluetooth e quase ultrassônico (inaudível). Quando um dispositivo detecta um token de um dispositivo por perto, ele envia o token para o servidor da API Nearby Messages para validá-lo e verificar se há mensagens a serem entregues para o conjunto atual de assinaturas do aplicativo.
Um aplicativo pode controlar o conjunto de mídias usadas para a descoberta de dispositivos e se as mídias são usadas para transmitir tokens e/ou procurar tokens. Por padrão, a transmissão e a verificação são feitas em todos os meios. Para fazer a descoberta em um subconjunto ou meios e controlar se a transmissão ou a verificação será feita, transmita parâmetros adicionais ao criar publicações e assinaturas.
Essa biblioteca é executada no iOS 7 e versões mais recentes e é criada com o SDK do iOS 8.
Como criar um gerenciador de mensagens
Esse código cria um objeto de gerenciador de mensagens, que permite publicar e assinar. A troca de mensagens não é autenticada. Portanto, você precisa fornecer uma chave de API pública para iOS. É possível criar uma usando a entrada do Google Developers Console para seu projeto.
Objective-C
#import <GNSMessages.h>
GNSMessageManager *messageManager =
[[GNSMessageManager alloc] initWithAPIKey:@"API_KEY"];
Swift
let messageManager = GNSMessageManager(APIKey: "API_KEY")
Como publicar uma mensagem
Esse snippet de código demonstra a publicação de uma mensagem que contém um nome. A publicação fica ativa enquanto o objeto de publicação existir. Para interromper a publicação, libere o objeto de publicação.
Objective-C
id<GNSPublication> publication =
[messageManager publicationWithMessage:[GNSMessage messageWithContent:[name dataUsingEncoding:NSUTF8StringEncoding]]];
Swift
let publication =
messageManager.publication(with: GNSMessage(content: name.data(using: .utf8)))
Como assinar mensagens
Esse snippet de código demonstra a assinatura de todos os nomes compartilhados pelo snippet de publicação anterior. A assinatura fica ativa enquanto os objetos de assinatura existirem. Para interromper a assinatura, libere o objeto de assinatura.
O handler de mensagens encontradas é chamado quando dispositivos próximos que estão publicando mensagens são descobertos. O handler de mensagens perdidas é chamado quando uma mensagem não é mais observada (o dispositivo saiu do alcance ou não está mais publicando a mensagem).
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
}];
Swift
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
})
Meios de descoberta
Por padrão, os dois meios (áudio e Bluetooth) serão usados para descobrir dispositivos por perto, e os dois meios vão transmitir e verificar. Em alguns casos, é necessário adicionar as seguintes entradas ao Info.plist do app:
Se o app verificar usando áudio, adicione
NSMicrophoneUsageDescription, que é uma string que descreve por que você usará o microfone. Por exemplo, "O microfone ouve tokens anônimos de dispositivos próximos".Se o app transmitir usando BLE, adicione
NSBluetoothPeripheralUsageDescription, que é uma string que descreve por que você vai anunciar no BLE. Por exemplo, "Um token anônimo é anunciado via Bluetooth para descobrir dispositivos próximos".
Em alguns casos, o app pode precisar usar apenas um dos meios e não precisa fazer a transmissão e a verificação nesse meio.
Por exemplo, um app projetado para se conectar a um conversor que está transmitindo apenas áudio precisa verificar o áudio para descobri-lo. O snippet a seguir mostra como publicar uma mensagem nesse conversor usando apenas a verificação de áudio para descoberta:
Objective-C
id<GNSPublication> publication = [messageManager publicationWithMessage:message
paramsBlock:^(GNSPublicationParams *params) {
params.strategy = [GNSStrategy strategyWithParamsBlock:^(GNSStrategyParams *params) {
params.discoveryMediums = kGNSDiscoveryMediumsAudio;
params.discoveryMode = kGNSDiscoveryModeScan;
}];
}];
Swift
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
})
})
Como ativar a geração de registros de depuração
A geração de registros de depuração imprime eventos internos significativos no console que podem ser úteis para rastrear problemas que você pode encontrar ao integrar a API Nearby Messages ao seu app. Vamos pedir esses registros se você entrar em contato conosco para receber suporte técnico.
Ative-o antes de criar um gerenciador de mensagens. Este snippet de código mostra como ativar a geração de registros de depuração:
Objective-C
[GNSMessageManager setDebugLoggingEnabled:YES];
Swift
GNSMessageManager.setDebugLoggingEnabled(true)
Como acompanhar o estado da permissão "Dispositivos por perto"
O consentimento do usuário é necessário para ativar a descoberta de dispositivos. Isso é indicado pelo estado da permissão "Dispositivos por perto". Na primeira chamada para criar uma publicação ou assinatura, uma caixa de diálogo de consentimento é apresentada ao usuário. Se o usuário não consentir, a descoberta de dispositivos não vai funcionar. Nesse caso, o app precisa mostrar uma mensagem para lembrar o usuário de que a descoberta de dispositivos está desativada. O estado da permissão é armazenado em NSUserDefaults.
O snippet a seguir demonstra a assinatura do estado da permissão. O handler de estado de permissão alterado é chamado sempre que o estado muda e não é chamado pela primeira vez até que o usuário tenha concedido ou negado a permissão. Libere o objeto de permissão para interromper a assinatura.
Objective-C
GNSPermission *nearbyPermission = [[GNSPermission alloc] initWithChangedHandler:^(BOOL granted) {
// Update the UI here
}];
Swift
let nearbyPermission = GNSPermission(changedHandler: { (granted: Bool) in
// Update the UI here
})
O app pode fornecer uma maneira para o usuário mudar o estado da permissão, por exemplo, usando um botão de alternância em uma página de configurações.
Confira um exemplo de como receber e definir o estado da permissão.
Objective-C
BOOL permissionState = [GNSPermission isGranted];
[GNSPermission setGranted:!permissionState]; // toggle the state
Swift
let permissionState = GNSPermission.isGranted()
GNSPermission.setGranted(!permissionState) // toggle the state
Como acompanhar as configurações do usuário que afetam a permissão "Dispositivos por perto"
Se o usuário tiver negado a permissão do microfone, negado a permissão do Bluetooth ou desativado o Bluetooth, a permissão "Dispositivos por perto" não vai funcionar bem ou não vai funcionar. Nesses casos, o app precisa mostrar uma mensagem alertando o usuário de que as operações da permissão "Dispositivos por perto" estão sendo prejudicadas. O snippet a seguir mostra como acompanhar o status dessas configurações do usuário transmitindo handlers ao criar o gerenciador de mensagens:
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
};
}];
Swift
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
}
})
Como substituir a caixa de diálogo de permissão "Dispositivos por perto"
Dependendo dos parâmetros transmitidos às publicações e assinaturas, o iOS pode pedir várias permissões antes de permitir que a permissão "Dispositivos por perto" funcione. Por exemplo, a estratégia padrão ouve dados transmitidos em áudio quase ultrassônico. Portanto, o iOS vai pedir permissão para usar o microfone. Nesses casos, o Compartilhar por proximidade vai mostrar uma caixa de diálogo de "pré-voo" que explica por que o usuário está sendo solicitado a conceder permissão.
Se você quiser fornecer uma caixa de diálogo de "pré-voo" personalizada, defina o parâmetro permissionRequestHandler como um bloco personalizado nos parâmetros de publicação ou assinatura. O bloco personalizado precisa chamar o bloco permissionHandler depois que o usuário responder. O snippet a seguir mostra como fazer isso para uma publicação:
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.
};
}];
Swift
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.
}
})
Operação em segundo plano
Publicações e assinaturas que usam BLE para descoberta de dispositivos podem funcionar em segundo plano. Confira algumas coisas que você precisa saber ao decidir usar o modo em segundo plano:
- As operações em segundo plano precisam usar apenas o meio BLE. O áudio não é compatível.
- Há um custo de bateria adicional para o BLE em segundo plano. O custo é baixo, mas você precisa medi-lo antes de decidir usar o modo em segundo plano.
- O iOS vai pedir permissão ao usuário para anunciar via BLE em segundo plano.
Para adicionar o modo em segundo plano a uma publicação ou assinatura, siga estas etapas adicionais:
Ative o modo em segundo plano e somente BLE na publicação ou assinatura transmitindo um objeto
GNSStrategyconfigurado corretamente. O snippet a seguir mostra como fazer isso para uma assinatura: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; }]; }];Swift
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 }) })Adicione estas entradas ao
Info.plistdo app:Entradas
UIBackgroundModes:bluetooth-centralpara verificação de BLE em segundo plano. Necessário apenas quando o modo de descoberta inclui a verificação. Ele faz isso por padrão.bluetooth-peripheralpara publicidade BLE em segundo plano. Necessário apenas quando o modo de descoberta inclui a transmissão. Ele faz isso por padrão.
String
NSBluetoothPeripheralUsageDescriptionque descreve por que você vai anunciar no BLE. Por exemplo, "Um token anônimo é anunciado via Bluetooth para descobrir dispositivos próximos". Consulte a documentação da Apple para mais detalhes.
O app pode ser encerrado a qualquer momento pelo sistema enquanto estiver em segundo plano. Se o modo em segundo plano for uma configuração que pode ser ativada ou desativada pelo usuário, o app precisará fazer o seguinte:
- Salve o valor do modo em segundo plano em
NSUserDefaultssempre que o usuário o mudar. - Na inicialização, leia o valor de
NSUserDefaultse restaure as publicações e/ou assinaturas da permissão "Dispositivos por perto" se o modo em segundo plano estiver ativado.
- Salve o valor do modo em segundo plano em
Notificações em segundo plano
Se você quiser que o app notifique o usuário quando uma assinatura receber uma mensagem em segundo plano, use notificações locais.
Siga estas etapas para adicioná-las ao app:
Registre-se para receber notificações locais na inicialização:
Objective-C
if ([UIApplication instancesRespondToSelector:@selector(registerUserNotificationSettings:)]) { [[UIApplication sharedApplication] registerUserNotificationSettings: [UIUserNotificationSettings settingsForTypes: UIUserNotificationTypeAlert | UIUserNotificationTypeBadge | UIUserNotificationTypeSound categories:nil]]; }Swift
UIApplication.shared.registerUserNotificationSettings( UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil))Envie uma notificação local no handler de mensagens encontradas da assinatura:
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... };Swift
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... }