Publicar e assinar

A API Nearby Messages é uma API de publicação-assinatura que permite que dispositivos próximos troquem pequenos payloads de dados. Quando 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 a trocar objetos maiores, como fotos e vídeos.

O conjunto de dispositivos próximos é determinado pela troca de pequenos tokens por Bluetooth e áudio quase ultrassônico (inaudível). Quando um dispositivo detecta um token de um dispositivo próximo, ele envia o token para o servidor do Nearby Messages para validá-lo e verificar se há mensagens a serem enviadas para o conjunto atual de assinaturas do aplicativo.

Um aplicativo pode controlar o conjunto de meios usados para a descoberta de dispositivos e se os meios são usados para transmitir e/ou verificar 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, é necessário transmitir 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.

Criação de 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. Você pode criar um 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")

Publicar uma mensagem

Este snippet de código demonstra a publicação de uma mensagem com 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 se inscrever para receber mensagens

Este snippet de código demonstra a inscrição em todos os nomes compartilhados pelo snippet de publicação anterior. A assinatura fica ativa enquanto os objetos de assinatura existirem. Para cancelar a assinatura, libere o objeto de assinatura.

O gerenciador de mensagens encontradas é chamado quando dispositivos próximos que estão publicando mensagens são descobertos. O gerenciador 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) são usados para descobrir dispositivos próximos, e ambos transmitem e fazem a busca. Em alguns casos, é necessário adicionar as seguintes entradas ao Info.plist do app:

  • Se o app fizer a verificação usando áudio, adicione NSMicrophoneUsageDescription, que é uma string que descreve por que você vai 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 por perto".

Em alguns casos, o app precisa usar apenas uma das mídias e não precisa transmitir e fazer a varredura nessa mídia.

Por exemplo, um app projetado para se conectar a uma caixa decodificadora que está transmitindo em áudio só precisa fazer a verificação em áudio para detectá-la. O snippet a seguir mostra como publicar uma mensagem na caixa usando apenas a detecçã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

O registro de depuração mostra eventos internos importantes no console que podem ser úteis para rastrear problemas que você pode encontrar ao integrar o app Mensagens do Google Meu Bairro. Vamos solicitar esses registros se você entrar em contato para receber suporte técnico.

Ative-o antes de criar um gerenciador de mensagens. Este snippet de código mostra como ativar o registro de depuração:

Objective-C

[GNSMessageManager setDebugLoggingEnabled:YES];

Swift

GNSMessageManager.setDebugLoggingEnabled(true)

Acompanhamento do estado da permissão do Nearby

O consentimento do usuário é necessário para ativar a descoberta de dispositivos. Isso é indicado pelo estado da permissão do recurso "Perto de você". Na primeira chamada para criar uma publicação ou assinatura, o usuário recebe uma caixa de diálogo de consentimento. 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 como se inscrever no estado de permissão. O gerenciador de alteração de estado de permissão é chamado sempre que o estado muda e não é chamado pela primeira vez até que o usuário conceda ou negue a permissão. Libere o objeto de permissão para interromper a inscrição.

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 oferecer uma maneira de o usuário mudar o estado da permissão, por exemplo, usando um botão de ativação 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

Rastreamento de configurações do usuário que afetam o recurso "Próximos"

Se o usuário negar a permissão de microfone, negar a permissão de Bluetooth ou desativar o Bluetooth, o recurso "Por perto" não vai funcionar tão bem ou pode não funcionar. Nesses casos, o app precisa mostrar uma mensagem alertando o usuário de que as operações do Nearby estão sendo prejudicadas. O snippet a seguir mostra como rastrear o status dessas configurações do usuário transmitindo manipuladores 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 do app "Perto de você"

Dependendo dos parâmetros transmitidos para suas publicações e assinaturas, o iOS pode solicitar várias permissões antes de permitir que o recurso "Perto de você" funcione. Por exemplo, a estratégia padrão detecta dados transmitidos em áudio quase ultrassônico, portanto, o iOS vai pedir permissão para usar o microfone. Nesses casos, o app Nearby vai mostrar uma caixa de diálogo "pré-voo" que explica por que o usuário está sendo solicitado a conceder a permissão.

Se você quiser fornecer uma caixa de diálogo "pré-voo" personalizada, defina o parâmetro permissionRequestHandler como um bloco personalizado nos parâmetros de publicação ou de assinatura. Seu 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

As publicações e assinaturas que usam BLE para descoberta de dispositivos podem funcionar em segundo plano. Confira alguns pontos a serem considerados ao decidir usar o modo em segundo plano:

  • As operações em segundo plano precisam usar apenas o BLE. O áudio não é compatível.
  • Há um custo de bateria extra para 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 de segundo plano a uma publicação ou assinatura, siga estas etapas adicionais:

  • Ative o modo de segundo plano e o BLE somente na sua publicação ou assinatura transmitindo um objeto GNSStrategy configurado corretamente. O snippet abaixo 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.plist do app:

    • UIBackgroundModes entradas:

      • bluetooth-central para a verificação de BLE em segundo plano. Só é necessário quando o modo de descoberta inclui a verificação, o que acontece por padrão.
      • bluetooth-peripheral para publicidade de BLE em segundo plano. Necessário somente quando o modo de descoberta inclui transmissão, o que acontece por padrão.
    • String NSBluetoothPeripheralUsageDescription que descreve por que você vai anunciar no BLE. Por exemplo, "Um token anônimo é anunciado por Bluetooth para descobrir dispositivos por perto". 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 de 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 de segundo plano em NSUserDefaults sempre que o usuário mudar.
    • Na inicialização, leia-o em NSUserDefaults e restaure as publicações e/ou assinaturas do app Nearby se o modo de segundo plano estiver ativado.

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 adicionar esses recursos 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 gerenciador de mensagens encontradas da sua 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...
    }