我正试图在两台设备上大致同时发出哔哔声(两者之间的差异最大为50ms)。到目前为止我所做的是通过 SNTP 获取网络时间,然后使用handler.postDelayed(runnable, difference of network time and phone time + delay)
执行runnable但这似乎只在某些时候工作,而其他时候设备发出哔声,差异很高为3-4秒。
简而言之,这就是场景:我们有2个设备,我们希望它们两个一起每隔10秒发出一次哔声。
有没有更好的方法可以做到这一点,我不知道?
答案 0 :(得分:3)
我正试图在两台设备上大致同时发出哔哔声(两者之间的差异最大为50ms)。
引用Google的Scott Barta,answer至a suspiciously similar question:
我不知道你的总体目标是什么,但是不要因为能够在过于宽容的情况下实现同时性而抱有希望 - 很多事情都在对你不利。 Android并非设计为实时操作系统,即使在像现场音频那样重要的延迟的地方,也有一些赶上来做。操作系统可能无法为您提供所需的进程调度延迟,并且Android上的Java可能有点不可预测,除非您非常小心内存分配等(在错误的时间进行垃圾收集,一切都在窗外) 。如果发生其他事情,您的流程可能会随时出现。即使您在开始时的NTP同步也可能有点令人担忧,特别是如果您通过移动网络连接同步而不是WiFi(尽管如此,我不知道协议在处理时有多好)。让事情在半秒内完成应该是可行的,也许,我认为,将事情变得不到10毫秒可能会非常艰难,介于两者之间的某个地方将介于两者之间。
我鼓励你重新考虑这个方法。如果两个设备足够接近以至于可以听到它们的嘟嘟声,那么这些设备可以通过蓝牙或WiFiDirect进行互连。让一台设备作为主设备。它向另一个设备发送信号以指示何时播放声音,作为从接收到信号时起的毫秒偏移量。现在你只有一个时钟。通过实验,您可以确定应用“软糖因子”来处理发送消息的延迟。
然后使用handler.postDelayed(可运行,网络时间和电话时间的差异+延迟)来执行runnable
postDelayed()
不是为精确计时而设计的,postDelayed()
专门将您绑定到主应用程序线程。音频回放API通常在后台线程上正常工作。因此,我会使用ScheduledExecutorService
。
答案 1 :(得分:2)
<强>假设强>
两台设备同时达到分钟刻度。
<强>步骤:强>
让其中一个设备领导这个过程。
获取其他设备上的当前时间。 (让其他设备按分钟响应)。
建议到其他设备的时间(例如19:34),考虑一个安全窗口来确认建议的时间消息。将在收到之前收到其他设备。
实施失败机制。假设发送到其他设备的时间已经过去。设备将向第一个设备发送故障消息,通知故障。第一个已经开始发出哔哔声的设备。哔哔声过程将在该设备上取消,并且步骤将再次开始。
否则,每隔10秒钟继续播放声音。 SUCCESS。
基于这个假设,这将从第一次起作用。只有当连接速度太慢导致通信耗时差不多1分钟时,失败机制才会起作用。