I am trying to use Google Nearby Connections API to connect two Android devices to exchange data but no success. The devices can found eachother none of them can connect to the other. It always fails at onConnectionInitiated()
with STATUS_ENDPOINT_UNKNOWN when I try to accept the connection.
I tried it with Strategy.P2P_POINT_TO_POINT
Strategy.CLUSTER
and Strategy.STAR
but I get the same result.
Anyone can help me what do I miss?
Both devices are physical and running on Android 9.0
This is the code:
public static ConnectionLifecycleCallback connectionLifecycleCallback;
public static EndpointDiscoveryCallback endpointDiscoveryCallback;
public static PayloadCallback payloadCallback;
public static String SERVICE_ID;
public Context ctx;
public static Strategy STRATEGY;
public NearbyHandler(Context ctx,Strategy STRATEGY){
this.ctx = ctx;
this.STRATEGY = STRATEGY;
SERVICE_ID = ctx.getPackageName();
payloadCallback = new PayloadCallback() {
@Override
public void onPayloadReceived(@NonNull String s, @NonNull Payload payload) {
Log.d("NEARBY_", "PAYLOAD RECEIVED " + s);
}
@Override
public void onPayloadTransferUpdate(@NonNull String s, @NonNull PayloadTransferUpdate payloadTransferUpdate) {
Log.d("NEARBY_", "PAYLOAD TRANSFER UPDATE " + s);
}
};
connectionLifecycleCallback = new ConnectionLifecycleCallback() {
@Override
public void onConnectionInitiated(@NonNull String s, @NonNull ConnectionInfo connectionInfo) {
Nearby.getConnectionsClient(ctx)
.acceptConnection(s, payloadCallback)
.addOnSuccessListener(new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void aVoid) {
Log.d("NEARBY_", "SUCCESSFULLY CONNECTED");
}
})
.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
e.printStackTrace();
}
});
}
@Override
public void onConnectionResult(@NonNull String s, @NonNull ConnectionResolution connectionResolution) {
switch (connectionResolution.getStatus().getStatusCode()) {
case ConnectionsStatusCodes.STATUS_OK:
Nearby.getConnectionsClient(ctx).stopAdvertising();
Nearby.getConnectionsClient(ctx).stopDiscovery();
break;
case ConnectionsStatusCodes.STATUS_CONNECTION_REJECTED:
break;
case ConnectionsStatusCodes.STATUS_ERROR:
break;
}
}
@Override
public void onDisconnected(@NonNull String s) {
Log.d("NEARBY_", "DISCONNECTED " + s);
}
};
endpointDiscoveryCallback = new EndpointDiscoveryCallback() {
@Override
public void onEndpointFound(@NonNull String s, @NonNull DiscoveredEndpointInfo discoveredEndpointInfo) {
Nearby.getConnectionsClient(ctx)
.requestConnection(
s,
ctx.getPackageName(),
connectionLifecycleCallback)
.addOnSuccessListener(new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void aVoid) {
Log.d("NEARBY_", "ENDPOINT CONNECTED");
}
})
.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
Log.d("NEARBY_", "FAILED TO CONNECT ENDPOINT " + e.getMessage());
e.printStackTrace();
}
});
}
@Override
public void onEndpointLost(@NonNull String s) {
Log.d("NEARBY_", "ENDPOINT LOST: " + s);
}
};
}
public void startDiscovering() {
Nearby.getConnectionsClient(ctx)
.startDiscovery(
SERVICE_ID,
endpointDiscoveryCallback,
new DiscoveryOptions.Builder()
.setStrategy(CONSTANTS.PEERTOPEER_STRATEGY).build())
.addOnSuccessListener(new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void aVoid) {
Log.d("NEARBY_DISCOVERER_", "onSuccess");
}
})
.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
e.printStackTrace();
}
});
}
public void startAdvertising() {
Nearby.getConnectionsClient(ctx)
.startAdvertising(
Build.MODEL,
SERVICE_ID,
connectionLifecycleCallback,
new AdvertisingOptions.Builder()
.setStrategy(CONSTANTS.PEERTOPEER_STRATEGY).build())
.addOnSuccessListener(new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void aVoid) {
}
})
.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
e.printStackTrace();
}
});
}
}
NearbyHandler nearby = new NearbyHandler(getApplicationContext(), Strategy.P2P_POINT_TO_POINT);
if (IS_DEVICE_A) {
nearby.startAdvertising();
} else {
nearby.startDiscovering();
}
Update: Google's walkietalkie demo app works fine on both phones.
Finally I've managed to get it working but not sure about the problem. I managed the connection lifecycle a bit different way than in the API Docs.
So I created a private helper class
class Endpoint {
@NonNull
private final String id;
@NonNull
private final String name;
public Endpoint(@NonNull String id, @NonNull String name) {
this.id = id;
this.name = name;
}
@NonNull
public String getId() {
return id;
}
@NonNull
public String getName() {
return name;
}
@Override
public boolean equals(Object obj) {
if (obj instanceof Endpoint) {
Endpoint other = (Endpoint) obj;
return id.equals(other.id);
}
return false;
}
@Override
public int hashCode() {
return id.hashCode();
}
@Override
public String toString() {
return String.format("Endpoint{id=%s, name=%s}", id, name);
}
}
The ConnectionLifecycleCallback()
and EndpointDiscoveryCallback()
should look like this:
endpointDiscoveryCallback = new EndpointDiscoveryCallback() {
@Override
public void onEndpointFound(@NonNull String s, @NonNull DiscoveredEndpointInfo discoveredEndpointInfo) {
Endpoint endpoint = new Endpoint(s, discoveredEndpointInfo.getEndpointName());
ConnectionsClient c = Nearby.getConnectionsClient(ctx);
c.requestConnection(endpoint.getName(), endpoint.getId(), connectionLifecycleCallback).addOnSuccessListener(new OnSuccessListener < Void > () {
@Override
public void onSuccess(Void aVoid) {}
});
}
@Override
public void onEndpointLost(@NonNull String s) {}
};
connectionLifecycleCallback = new ConnectionLifecycleCallback() {
@Override
public void onConnectionInitiated(@NonNull String s, @NonNull ConnectionInfo connectionInfo) {
Nearby.getConnectionsClient(ctx).stopAdvertising();
Nearby.getConnectionsClient(ctx).stopDiscovery();
Endpoint endpoint = new Endpoint(s, connectionInfo.getEndpointName());
ConnectionsClient c = Nearby.getConnectionsClient(ctx);
c.acceptConnection(endpoint.getId(), payloadCallback).addOnSuccessListener(new OnSuccessListener < Void > () {
@Override
public void onSuccess(Void aVoid) {}
});
}
@Override
public void onConnectionResult(@NonNull String s, @NonNull ConnectionResolution connectionResolution) {
switch (connectionResolution.getStatus().getStatusCode()) {
case ConnectionsStatusCodes.STATUS_OK:
Nearby.getConnectionsClient(ctx).stopAdvertising();
Nearby.getConnectionsClient(ctx).stopDiscovery();
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;
}
}
@Override
public void onDisconnected(@NonNull String s) {}
};
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.