Nearby Connections is a peer-to-peer networking API that allows apps to easily
discover, connect to, and exchange data with nearby devices in real-time,
regardless of network connectivity. The API is located in the
com.google.android.gms.nearby.connection
package.
Some example use cases:
- Collaborative whiteboard: Jot ideas down with nearby participants on a shared virtual whiteboard.
- Local multiplayer gaming: Set up a multiplayer game and invite other users nearby to join.
- Multi-screen gaming: Use a phone or tablet as a game controller to play games displayed on a nearby large-screen Android device, such as Android TV.
- Offline file transfers: Share photos, videos, or any other type of data quickly and without requiring a network connection.
Introduction
Nearby Connections enables advertising, discovery, and connections between nearby devices in a fully-offline peer-to-peer manner. Connections between devices are high-bandwidth, low-latency, and fully encrypted to enable fast, secure data transfers.
A primary goal of this API is to provide a platform that is simple, reliable, and performant. Under the hood, the API uses a combination of Bluetooth, BLE, and Wifi hotspots, leveraging the strengths of each while circumventing their respective weaknesses. This effectively abstracts the vagaries of Bluetooth and Wifi across a range of Android OS versions and hardware, allowing developers to focus on the features that matter to their users.
As a convenience, users are not prompted to turn on Bluetooth or Wi-Fi — Nearby Connections enables these features as they are required, and restores the device to its prior state once the app is done using the API, ensuring a smooth user experience.
API overview
Usage of the API falls into two phases: pre-connection, and post-connection.
In the pre-connection phase, Advertisers advertise themselves, while Discoverers discover nearby Advertisers and send connection requests. A connection request from a Discoverer to an Advertiser initiates a symmetric authentication flow that results in both sides independently accepting (or rejecting) the connection request.
After a connection request is accepted by both sides, the connection is considered to be established and the devices enter the post-connection phase, during which both sides can exchange data.
Advertising and discovery
Advertisers begin by invoking startAdvertising()
, passing in a
ConnectionLifecycleCallback
which will be notified whenever a Discoverer wants
to connect via the onConnectionInitiated()
callback.
Discoverers begin by invoking startDiscovery()
, passing in an
EndpointDiscoveryCallback
which will be notified whenever a nearby Advertiser
is found via the onEndpointFound()
callback.
Establishing connections
When a Discoverer wishes to connect to a nearby Advertiser, the Discoverer
invokes requestConnection()
, passing in a ConnectionLifecycleCallback
of its
own.
Both sides are then notified of the connection initiation process via the
ConnectionLifecycleCallback.onConnectionInitiated()
callback, and both must
now choose whether to accept or reject the connection via a call to
acceptConnection()
or rejectConnection()
, respectively.
At this point, apps can optionally prompt the user to accept the connection. See Authenticate a connection to learn more.
Once both sides have responded, each will be notified of the result via the
ConnectionLifecycleCallback.onConnectionResult()
callback. If both sides
accepted the connection, then the ConnectionResolution
provided in the
callback will be successful, the connection is considered established, and the
transfer of Payloads can then begin.
Exchanging data
After a connection is established, further API usage is symmetrical, so there’s no longer a distinction between Advertiser and Discoverer.
Both sides can now exchange data as Payload
objects. There are 3 types of
supported Payloads:
BYTES
Byte arrays limited to 32k; these are good for sending things such as metadata or control messages.FILE
Files of any size; these are transferred from the app to the network interface with minimal copying across process boundaries.STREAM
A stream of data that is generated on the fly, as in the case of recorded audio/video, with no final size known beforehand.
Senders use the sendPayload()
method to send a Payload. This method can be
invoked multiple times, but since we guarantee in-order delivery, the second
Payload onwards will be queued for sending until the first Payload is done.
Receivers can expect the PayloadCallback.onPayloadReceived()
callback to be
invoked when a new incoming Payload is received.
Senders and Receivers both can expect the
PayloadCallback.onPayloadTransferUpdate()
callback to be invoked to update
them about the progress of outgoing and incoming Payloads, respectively.
The connections established are full-duplex, which means that Advertisers and Discoverers can simultaneously send and receive Payloads.
Disconnecting
Finally, disconnectFromEndpoint()
disconnects from a particular remote
endpoint, and stopAllEndpoints()
disconnects from all connected endpoints.
Remote endpoints are notified of disconnection via the
ConnectionLifecycleCallback.onDisconnected()
.
Data Collection
When using the Google Play services Nearby SDK, usage analytics are collected to improve the experience.
- Performance metrics: Discovery and connection latency, reliability and throughput are collected when scanning for and connecting to devices using the Nearby SDK.
- Device information: Device model, country, build version and the application package name are collected and associated with the performance metrics to identify regional and device-specific slices.
End users can allow or deny this collection by navigating to Settings > Google > Usage & diagnostics.