接続を管理する

接続を開始する

付近のデバイスが検出されると、検出者が接続を開始できます。次の例では、デバイスが検出されるとすぐに接続をリクエストします。

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

ユースケースによっては、検出されたデバイスのリストをユーザーに表示し、ユーザーが接続するデバイスを選択できるようにすることもできます。

接続を承認または拒否する

調査者が広告主への接続をリクエストすると、ConnectionLifecycleCallback コールバックの onConnectionInitiated() メソッドを使用して、両者に接続開始プロセスが通知されます。このコールバックは、広告主の startAdvertising() と Discoverer の 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();
}