Nearby connections is a peer-to-peer networking API that allows apps to easily connect, discover and exchange data with the nearby device in real-time, regardless of network connectivity. In other words, we can say that Nearby connections enable advertising, discovery and connection between nearby devices in a fully offline peer-to-peer manner. The connection between devices is high-bandwidth, low-latency and fully encrypted to enable fast, secure data transfers. Nearby connections API uses a combination of Bluetooth, BLE and wifi hotspots.
Nearby Connection API implementations
We implement nearby connections API in two phases:
- Pre-Connection
- Post-Connection
In the pre-connection phase, the Advertiser device advertises itself, while discovers devices search the nearby advertiser devices 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.
How to advertise the device?
Advertisers begin by invoking startAdvertising(), passing in a ConnectionLifecycleCallback which will be notified whenever a Discoverer wants to connect via the onConnectionInitiated() callback.
How to discover devices?
Discoverers begin by invoking startDiscovery(), passing in an EndpointDiscoveryCallback which will be notified whenever a nearby Advertiser is found via the onEndpointFound() callback.
Steps for implementing Nearby Connection API:
There are following steps for implementing nearby connection API as follows:
1. Add dependency for nearby connections
dependencies {
implementation 'com.google.android.gms:play-services-nearby:17.0.0'
}
2. Add permission in Manifest.xml
<!-- Required for Nearby Connections --> <uses-permission android:name="android.permission.BLUETOOTH" /> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" /> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <!-- Optional: only required for FILE payloads --> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
3. Advertise the advertiser devices
Task<Void> startAdvertisingResultPendingResult =
Nearby.getConnectionsClient(context)
.startAdvertising(userName, AppConstant.SERVICE_ID,
connectionLifeCycleCallback, new AdvertisingOptions.Builder().setStrategy(Strategy.P2P_STAR).build());
startAdvertisingResultPendingResult.addOnSuccessListener(new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void aVoid) {
}
});
startAdvertisingResultPendingResult.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
}
});
4. Discover the advertiser devices
Task<Void> statusPendingResult =
Nearby.getConnectionsClient(context).
startDiscovery(AppConstant.SERVICE_ID,
new endPointDiscoverCallback,
new DiscoveryOptions.Builder().setStrategy(Strategy.P2P_STAR).build());
statusPendingResult.addOnSuccessListener(new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void aVoid) {
}
});
statusPendingResult.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
}
});
5. Create a connectionLifecycleCallback class
private final ConnectionLifecycleCallback connectionLifecycleCallback =
new ConnectionLifecycleCallback () {
@Override
public void onConnectionInitiated(final String endpointId, final ConnectionInfo connectionInfo) {
}
@Override
public void onConnectionResult(String endpointId, ConnectionResolution connectionResolution) {
switch (connectionResolution.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) {
}
}
6. Create a EndPointDiscoveryCallback
private final EndpointDiscoveryCallbacks endPointDiscoverCallback =
new EndpointDiscoveryCallback() {
@Override
public void onEndpointFound(final String endpointId, final DiscoveredEndpointInfo discoveredEndpointInfo) {
// An endpoint was found!
Task<Void> statusPendingResult =
Nearby.getConnectionsClient(context).
requestConnection(userName, endpointId
, connectionLifecycleCallback);
}
@Override
public void onEndpointLost(String endpointId) {
}
}
7. Requesting to create a connection
Task<Void> statusPendingResult = Nearby.getConnectionsClient(context). requestConnection(userName, endpointId , connectionLifecycleCallback);
8. Accepting a connection request
Nearby.getConnectionsClient(CachingManager.getAppContext())
.acceptConnection(endpointId, genericPayloadCallback)
.addOnSuccessListener(new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void aVoid) {
}
})
.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
}
});
9. For rejecting the connection request
Nearby.getConnectionsClient(context).rejectConnection(endpointId))
10. For sending the data to the endpoint
Nearby.getConnectionsClient(context) .sendPayload(endPoints,payload) .addOnSuccessListener(resultCallback) .addOnFailureListener(failureListener);
11. For receiving the data
protected class ReceiveBytesPayloadListener extends PayloadCallback {
@Override
public void onPayloadReceived(String endpointId, Payload payload) {
// This always gets the full data of the payload. Will be null if it's not a BYTES
// payload. You can check the payload type with payload.getType().
byte[] receivedBytes = payload.asBytes();
}
@Override
public void onPayloadTransferUpdate(String endpointId, PayloadTransferUpdate update) {
// Bytes payloads are sent as a single chunk, so you'll receive a SUCCESS update immediately
// after the call to onPayloadReceived().
}
}
12. To stop all endpoints
Nearby.getConnectionsClient(context).stopAllEndpoints();
13. To disconnect from the endpoint
Nearby.getConnectionsClient(context).disconnectFromEndpoint(endpoint);
14. For stop advertising
Nearby.getConnectionsClient(context).stopAdvertising();
15. To stop discovering
Nearby.getConnectionsClient(context).stopDiscovery();
End to End Technology Solutions