Управление подключениями

Инициировать соединение

При обнаружении близлежащих устройств программа обнаружения может инициировать подключение. В следующем примере запрашивается соединение с устройством, как только оно будет обнаружено.

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.
      }
    };

В зависимости от вашего варианта использования вы можете вместо этого отобразить пользователю список обнаруженных устройств, позволяя ему выбирать, к каким устройствам подключаться.

Принять или отклонить соединение

После того как исследователь запросил соединение с рекламодателем, обе стороны уведомляются о процессе инициации соединения через метод onConnectionInitiated() обратного вызова ConnectionLifecycleCallback . Обратите внимание, что этот обратный вызов передается в startAdvertising() на рекламодателе и requestConnection() на исследователе, но с этого момента API становится симметричным.

Теперь обе стороны должны выбрать, принять или отклонить соединение посредством вызова acceptConnection() или rejectConnection() соответственно. Соединение полностью устанавливается только тогда, когда обе стороны его приняли. Если один или оба отклоняются, соединение аннулируется. В любом случае результат доставляется в onConnectionResult() .

Следующий фрагмент кода показывает, как реализовать этот обратный вызов:

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.
      }
    };

Опять же, этот пример показывает, что соединение автоматически принимается обеими сторонами, но в зависимости от вашего варианта использования вы можете каким-то образом представить этот выбор пользователю.

Аутентификация соединения

Когда запрашивается соединение, ваше приложение может аутентифицировать соединение, используя токен аутентификации, предоставленный onConnectionInitiated() . Это позволяет пользователям подтвердить, что они подключаются к нужному устройству. Оба устройства получают один и тот же токен, который представляет собой короткую случайную строку; вам решать, как это проверить. Обычно это включает в себя показ токена на обоих устройствах и просьбу пользователей вручную сравнить и подтвердить, аналогично диалоговому окну сопряжения Bluetooth.

В этом примере кода демонстрируется один из способов аутентификации путем отображения токена аутентификации пользователю в 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();
}