Gerenciar conexões

Iniciar uma conexão

Quando dispositivos próximos são encontrados, o Discover pode iniciar conexões. A exemplo a seguir solicita uma conexão com um dispositivo assim que ele é descoberto.

private final EndpointDiscoveryCallback endpointDiscoveryCallback =
    new EndpointDiscoveryCallback() {
      @Override
      public void onEndpointFound(String endpointId, DiscoveredEndpointInfo info) {
        // An endpoint was found. We request a connection to it.
        Nearby.getConnectionsClient(context)
            .requestConnection(getLocalUserName(), endpointId, connectionLifecycleCallback)
            .addOnSuccessListener(
                (Void unused) -> {
                  // We successfully requested a connection. Now both sides
                  // must accept before the connection is established.
                })
            .addOnFailureListener(
                (Exception e) -> {
                  // Nearby Connections failed to request the connection.
                });
      }

      @Override
      public void onEndpointLost(String endpointId) {
        // A previously discovered endpoint has gone away.
      }
    };

Dependendo do caso de uso, uma lista de descobertas de dispositivos para o usuário, permitindo escolher a quais dispositivos se conectar.

Aceitar ou recusar uma conexão

Após o descobridor solicitar uma conexão com um anunciante, ambos os lados serão notificado sobre o processo de início da conexão pelo onConnectionInitiated() da classe ConnectionLifecycleCallback o retorno de chamada. Esse callback é transmitido para startAdvertising() no anunciante e requestConnection() no Discover, mas a partir desse ponto para a frente, a API é simétrica.

Agora os dois lados precisam escolher se vão aceitar ou rejeitar a conexão em uma ligação como acceptConnection() ou rejectConnection(), respectivamente. A conexão é está totalmente estabelecido somente quando ambos os lados o aceitarem. Se uma ou ambas forem rejeitadas, o será descartada. De qualquer forma, o resultado é entregue onConnectionResult():

O snippet de código abaixo mostra como implementar esse callback:

private final ConnectionLifecycleCallback connectionLifecycleCallback =
    new ConnectionLifecycleCallback() {
      @Override
      public void onConnectionInitiated(String endpointId, ConnectionInfo connectionInfo) {
        // Automatically accept the connection on both sides.
        Nearby.getConnectionsClient(context).acceptConnection(endpointId, payloadCallback);
      }

      @Override
      public void onConnectionResult(String endpointId, ConnectionResolution result) {
        switch (result.getStatus().getStatusCode()) {
          case ConnectionsStatusCodes.STATUS_OK:
            // We're connected! Can now start sending and receiving data.
            break;
          case ConnectionsStatusCodes.STATUS_CONNECTION_REJECTED:
            // The connection was rejected by one or both sides.
            break;
          case ConnectionsStatusCodes.STATUS_ERROR:
            // The connection broke before it was able to be accepted.
            break;
          default:
            // Unknown status code
        }
      }

      @Override
      public void onDisconnected(String endpointId) {
        // We've been disconnected from this endpoint. No more data can be
        // sent or received.
      }
    };

Mais uma vez, este exemplo mostra a conexão sendo aceita automaticamente por ambos os lados, mas, dependendo do seu caso de uso, talvez você queira apresentar essa opção ao usuário de alguma forma.

Autenticar uma conexão

Quando uma conexão é solicitada, seu app pode autenticar a conexão: usando o token de autenticação fornecido para onConnectionInitiated(). Isso oferece uma maneira de permitir que os usuários confirmem que estão se conectando ao dispositivo. Os dois dispositivos recebem o mesmo token, que é uma string curta aleatória. cabe a você decidir como verificá-la. Normalmente, isso envolve mostrar token nos dois dispositivos e pedindo que os usuários comparem e confirmem manualmente, semelhante a uma caixa de diálogo de pareamento do Bluetooth.

Este exemplo de código demonstra uma forma de autenticação exibindo o token de autenticação ao usuário em uma AlertDialog:

@Override
public void onConnectionInitiated(String endpointId, ConnectionInfo info) {
  new AlertDialog.Builder(context)
      .setTitle("Accept connection to " + info.getEndpointName())
      .setMessage("Confirm the code matches on both devices: " + info.getAuthenticationDigits())
      .setPositiveButton(
          "Accept",
          (DialogInterface dialog, int which) ->
              // The user confirmed, so we can accept the connection.
              Nearby.getConnectionsClient(context)
                  .acceptConnection(endpointId, payloadCallback))
      .setNegativeButton(
          android.R.string.cancel,
          (DialogInterface dialog, int which) ->
              // The user canceled, so we should reject the connection.
              Nearby.getConnectionsClient(context).rejectConnection(endpointId))
      .setIcon(android.R.drawable.ic_dialog_alert)
      .show();
}