Nima
Nima

Reputation: 6563

How to execute code on 2 devices almost simultaneously?

I'm trying to play a beep sound on 2 devices at roughly the same time (with maximum 50ms difference between the two). What I've done so far is get the network time by SNTP and then use a handler.postDelayed(runnable, difference of network time and phone time + delay) to execute the runnable but this seems to work only sometimes and other times devices beep with difference as high as 3-4 seconds.

In short, here is the scenario: we have 2 devices, we want both of them to play a beep every 10 seconds together.

Is there any better way to do this that I'm not aware of?

Upvotes: 2

Views: 106

Answers (2)

hasan
hasan

Reputation: 24185

Assumption

Both devices reaches the minute ticks simultaneously.

Steps:

  1. Let one of the devices lead the process.

  2. Gets the current time on the other device. (Let the other device respond on the minute tick).

  3. Suggest a time to the other device (ex. 19:34 sharp) considering a safe window to confirm that the suggested time msg. will receive the other device before it past.

  4. Implement a fail mechanism. Asume that the time sent to the other device has been past. device will send a failure msg to the first device informing a failure. the first device that already started beeping. Beeping process will cancel at that device and steps starts again.

  5. Otherwise, keep playing sound every 10 seconds. SUCCESS.

Based on the assumption this will work from first time. fail mechanism will work only if the connection is too slow that made the communication take almost 1 minute or less.

Upvotes: 2

CommonsWare
CommonsWare

Reputation: 1006944

I'm trying to play a beep sound on 2 devices at roughly the same time (with maximum 50ms difference between the two).

Quoting Google's Scott Barta, on his answer to a suspiciously similar question:

I don't know what your overall goals are, but don't get your hopes up for being able to achieve simultaneity within too tight a tolerance -- a lot of things are working against you. Android isn't designed as a real-time OS, and even in places where latency is important like live audio, it's got some catching up to do. The OS may not give you the scheduling latency you want with your process, and Java on Android can be a little unpredictable unless you're very careful about memory allocation and such (a garbage collection at the wrong time and everything is out the window). Your process can get bumped around at any time if something else occurs. Even your NTP synchronization at the beginning can be a little fraught, especially if you're synchronizing over a mobile network connection and not WiFi (though having said that, I don't know how good the protocol is at dealing with that). Getting things to within a half-second should be feasible, maybe, I think, getting things to less than 10ms is likely to be extremely tough, and somewhere in between will be...somewhere in between.

I would encourage you to reconsider the approach. If the two devices are close enough that both their beeps can be heard, those devices can be interconnected via Bluetooth or WiFiDirect. Have one device serve as the master. It sends a signal to the other device to indicate when to play the sound, as an offset in milliseconds from when the signal is received. Now you only have one clock. Through experimentation, you can determine a "fudge factor" to apply to deal with the latency of sending the message.

and then use a handler.postDelayed(runnable, difference of network time and phone time + delay) to execute the runnable

postDelayed() is not designed for accurate timing, and postDelayed() specifically ties you to the main application thread. Audio playback APIs generally work fine on a background thread. Hence, I'd use ScheduledExecutorService.

Upvotes: 3

Related Questions