Gerenciar conexões

Iniciar uma conexão

Quando dispositivos por perto forem encontrados, o descobridor poderá iniciar conexões. O exemplo abaixo 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 seu caso de uso, você pode mostrar uma lista de dispositivos descobertos para o usuário, permitindo que ele escolha a quais dispositivos se conectar.

Aceitar ou recusar uma conexão

Ambas as partes recebem uma notificação do processo de iniciação da conexão com o método onConnectionInitiated() do callback ConnectionLifecycleCallback quando o solicitante solicita uma conexão com ele. Esse callback é transmitido para startAdvertising() no anunciante e requestConnection() no descobridor, mas a partir desse ponto a API é simétrica.

Agora, os dois lados precisam aceitar ou rejeitar a conexão usando acceptConnection() ou rejectConnection(), respectivamente. A conexão só será integrada quando os dois lados forem aceitos. Se uma ou ambas forem rejeitadas, a conexão será descartada. De qualquer forma, o resultado é entregue a 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.
      }
    };

Novamente, esse exemplo mostra a conexão sendo aceita automaticamente pelos dois lados, mas dependendo do seu caso de uso, você pode 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 desejado. Os dois dispositivos recebem o mesmo token, que é uma string aleatória curta. Cabe a você decidir como verificá-lo. Normalmente, isso envolve mostrar o token em ambos os dispositivos e solicitar 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 maneira de autenticação exibindo o token de autenticação para o usuário em um 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();
}