2

I'm trying to use Nearby Connections 2.0 with the P2P_CLUSTER connection strategy, and I'm having problems getting my devices to connect and stay connected. According to my trace logs, it looks like the devices are successfully connecting and then getting instantly disconnected.

Note that it also sometimes runs through the same code successfully, and then stays connected. I don't know what makes it work sometimes and fail other times, and I don't know why the nodes are getting automatically disconnected. However, I'm certain that the "disconnect" isn't being issued in my code. It's coming from something at a lower level.

Here's the sequence of events that I'm currently seeing:

  • we discover another node (ie, hit the onEndpointFound callback) and then issue requestConnection
  • we hit onConnectionInitiated for that endpoint. (Checking info.isIncomingConnection() here, it doesn't seem to matter whether this was a response to our own request, or a request initiated elsewhere.)
  • we issue acceptConnection (and move our status to PENDING)
  • we hit onConnectionResult with "success" status. Everything's good (and both sides briefly think they're connected).
  • immediately afterward, we hit onDisconnected (and both sides go to unknown status)

Update: Added 200ms delay before acceptConnection

This was a big improvement, and the devices almost always establish a successful (and lasting) connection now. However, sometimes it takes 2-3 tries.

For example, here's what happened when running a simple test case (with one advertising device and one discovering device, and no complicating factors). From the Discoverer's point of view, it looked like this:

  • we hit onEndpointFound and requestConnection
  • we hit onConnectionInitiated for the connection we requested, and accept it
  • we hit onConnectionResult with successful connection.
  • very soon afterwards, we hit onDisconnected
  • we stop discovery, wait 3 seconds, restart discovery
  • we run through all of the above a second time, getting disconnected again

But running through the connection process a third time, we got a good persistent connection, and were able to send and receive data reliably.

Update: Exception on Advertiser side causing disconnect?

I caught a long series of these auto-disconnects. Each time, the Advertiser had this exception just before they got disconnected.

10-09 19:17:26.365 29232-29232/? E/SearchServiceStarter: Task 174 failed or timed out. Client 128565203126930423 disconnecting from SearchService!
                                                     java.util.concurrent.CancellationException: Task was cancelled.
                                                         at com.google.common.util.concurrent.d.cp(SourceFile:75)
                                                         at com.google.common.util.concurrent.d.get(SourceFile:57)
                                                         at com.google.common.util.concurrent.cj.n(SourceFile:2)
                                                         at com.google.common.util.concurrent.ay.l(SourceFile:50)
                                                         at com.google.common.util.concurrent.ba.run(SourceFile:5)
                                                         at com.google.android.apps.gsa.shared.util.concurrent.a.bc.run(SourceFile:2)
                                                         at android.os.Handler.handleCallback(Handler.java:808)
                                                         at android.os.Handler.dispatchMessage(Handler.java:103)
                                                         at android.os.Looper.loop(Looper.java:193)
                                                         at android.app.ActivityThread.main(ActivityThread.java:5299)
                                                         at java.lang.reflect.Method.invokeNative(Native Method)
                                                         at java.lang.reflect.Method.invoke(Method.java:515)
                                                         at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:831)
                                                         at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:647)
                                                         at dalvik.system.NativeStart.main(Native Method)

Does this help you diagnose the problem?

Rapunzel Van Winkle
  • 5,380
  • 6
  • 31
  • 48

1 Answers1

2

Oops! This is a race condition in Nearby Connections. It's fixed in the next upcoming release. As a temporary fix, delay your accept connection by a small amount (~100ms?).

Edit: This should be fixed as of Google Play Services 11.6.0

Xlythe
  • 1,958
  • 1
  • 8
  • 12
  • The auto-disconnects seem to be happening much less often (and recovering better on the retry) with a 100ms delay, but they still happen sometimes. Should I try a longer delay? Or might there be some other problem? – Rapunzel Van Winkle Oct 04 '17 at 01:03
  • If you're still seeing it, yes, a longer delay should help. – Xlythe Oct 04 '17 at 21:24
  • Increased delay to 200ms. See the updated post for more details. – Rapunzel Van Winkle Oct 05 '17 at 04:58
  • I'm glad the delay helped out! As for the few remaining disconnections, check logcat for errors. There should be one consistent "failed to parse" exception that exposes the race condition as the cause of the disconnection. If you're seeing other exceptions instead, let me know :) By the way, we have a beta program where you can get the latest Play Services update (with all the fixes) before it's released publicly. If you're interested, I just need a Gmail address tied to the phone. (Does StackOverflow have a PM system?) – Xlythe Oct 06 '17 at 00:32
  • WRT the disconnects: I was only monitoring the discoverer's side of that failed handshake, and didn't see any exceptions in the log. Would the exceptions you mentioned be on the advertiser's side? Is there anything I can do to smooth out the process, besides installing the Google Play beta? – Rapunzel Van Winkle Oct 06 '17 at 02:06
  • Exceptions could be from either side. Unfortunately you have to collect both sides. – Xlythe Oct 06 '17 at 02:14
  • 1
    Is there a way to get notified of lower-level exceptions and error messages in my program? I can display a log of my own messages, but only see the lower-level NearbyConnections messages on the side that I'm monitoring with Android Monitor (and I only have one copy of Android Studio.) – Rapunzel Van Winkle Oct 06 '17 at 02:21
  • If you grab a bug report, it generally has the most recent logcat logs. You can enable bug reports in dev settings. Alternatively, you can plug in both devices and use "adb -s device_id logcat" in the command prompt to get logs for each device. There's no way to get logcat from an app. – Xlythe Oct 06 '17 at 05:42
  • Good to know. Maybe I'll try that. For sure I didn't see any exceptions on the discoverer's side, but it would be nice to know for sure what's causing the problem. (Or, I could just increase the delay to a whole second and see if that fixes it?) – Rapunzel Van Winkle Oct 06 '17 at 05:44
  • See the last update in my post for an exception that seems to occur on the Advertiser side just before the disconnect. Maybe relevant? – Rapunzel Van Winkle Oct 09 '17 at 08:51
  • Shouldn't be relevant. That's from a different API in Play Services. But given the exception, it might be a hint that Google Play Services has crashed/updated/restarted/etc, which would explain why there's a disconnection; Nearby is a part of Play Services. – Xlythe Oct 09 '17 at 15:52
  • We can test that theory. See if onConnectionSuspended triggers for your app at around the same time. – Xlythe Oct 09 '17 at 16:31
  • I've moved on to other projects, but hope to get back to my Nearby Connections prototype early next year. Meanwhile, I'll mark this question as answered, since you say it's been fixed. – Rapunzel Van Winkle Dec 06 '17 at 07:23