Manage Connections

Initiate a connection

When nearby devices are found, the discoverer can initiate connections. The following example shows initiating a connection with a discovered device.

@Override
public void onEndpointFound(
    String endpointId, DiscoveredEndpointInfo discoveredEndpointInfo) {
  String name = getUserNickname();
  Nearby.Connections.requestConnection(
          mGoogleApiClient,
          name,
          endpointId,
          mConnectionLifecycleCallback)
      .setResultCallback(
          new ResultCallback<Status>() {
            @Override
            public void onResult(@NonNull Status status) {
              if (status.isSuccess()) {
                // We successfully requested a connection. Now both sides
                // must accept before the connection is established.
              } else {
                // Nearby Connections failed to request the connection.
              }
            }
          });
}

Depending on your use case, you may wish to instead display a list of discovered devices to the user, allowing them to choose which devices to connect to.

Accept or reject a connection

After the discoverer has requested a connection to an advertiser, both sides are notified of the connection initiation process via the onConnectionInitiated() method of the ConnectionLifecycleCallback callback. Note that this callback is passed in to startAdvertising() on the advertiser and requestConnection() on the discoverer, but from this point forward, the API is symmetric.

Now both sides must choose whether to accept or reject the connection via a call to acceptConnection() or rejectConnection(), respectively. The connection is fully established only when both sides have accepted. If one or both reject, the connection is discarded. Either way, the result is delivered to onConnectionResult().

The following code snippet shows how to implement this callback:

private final ConnectionLifecycleCallback mConnectionLifecycleCallback =
  new ConnectionLifecycleCallback() {

    @Override
    public void onConnectionInitiated(
        String endpointId, ConnectionInfo connectionInfo) {
      // Automatically accept the connection on both sides.
      Nearby.Connections.acceptConnection(
          mGoogleApiClient, endpointId, mPayloadCallback);
    }

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

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

Authenticate a connection

When a connection is requested, your app can authenticate the connection by using the authentication token provided to onConnectionInitiated(). This provides a way to let users confirm that they are connecting to the intended device. Both devices are given the same token, which is a short random string; it's up to you to decide how to verify it. Typically this involves showing the token on both devices and asking the users to manually compare and confirm, similar to a bluetooth pairing dialog.

Note that authentication is an optional step, and that Nearby Connections will encrypt the connection regardless of whether or not the authentication token is used by your app. However, since encryption without authentication is essentially meaningless, it is highly recommended that you use authentication to secure your connections.

This sample code demonstrates one way to authenticate by displaying the authentication token to the user in an AlertDialog:

@Override
public void onConnectionInitiated(String endpointId, ConnectionInfo connectionInfo) {
  new AlertDialog.Builder(context)
    .setTitle("Accept connection to " + connectionInfo.getEndpointName())
    .setMessage("Confirm if the code " + connectionInfo.getAuthenticationToken() + " is also displayed on the other device")
    .setPositiveButton("Accept", new DialogInterface.OnClickListener() {
        public void onClick(DialogInterface dialog, int which) {
          // The user confirmed, so we can accept the connection.
          Nearby.Connections.acceptConnection(mGoogleApiClient, endpointId, mPayloadCallback);
        }
     })
    .setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
        public void onClick(DialogInterface dialog, int which) {
          // The user canceled, so we should reject the connection.
          Nearby.Connections.rejectConnection(mGoogleApiClient, mPayloadCallback);
        }
     })
    .setIcon(android.R.drawable.ic_dialog_alert)
    .show();
}

Run in the background

If you are disconnecting your GoogleApiClient in your Activity's onStop() method, any active connections at that time will be disconnected. To enable background usage of the Nearby Connections API, you must instead use a foreground service and connect and disconnect your GoogleApiClient in your service's onCreate() and onDestroy() methods, respectively. This allows the user to exit your app while remaining connected to the API.