我正在尝试开发一款应用程序,允许其他Android手机充当扬声器,从而创建一个像派对一样的派对。该应用程序类似于三星提供的群游功能。
为了实现此功能,我决定执行以下步骤 -
**面临的问题 - ** 在我实现这个之后,我注意到两个Android设备都有不同的系统时间,因此我使用使用NTP同步时间的ClockSync App同步系统时间。 我不希望我的用户使用需要root访问权限的第三方应用。那我怎么能同步两部Android手机的时钟呢? 我该如何解决这个问题呢?
编辑 -
我使用AsyncTask
类以下来计算NTP时钟和本地时钟之间的差异。
public class offSetAsyncTask extends AsyncTask<Void,Void,Double> {
private String serverName;
private double localClockOffset;
private double destinationTimestamp;
private double roundTripDelay;
double total = 0;
Context context;
double avg;
@Override
protected Double doInBackground(Void... params) {
getAllForMe();
getAllForMe();
getAllForMe();
getAllForMe();
getAllForMe();
System.out.println("!!!!!!!" + total);
avg = total/5;
System.out.println("~~~avg. Lag: " + avg);
response.processFinish(avg);
return avg;
}
public interface AsyncResponse{
void processFinish(double offSet);
}
public AsyncResponse response = null;
public offSetAsyncTask(AsyncResponse res, String name, Context c){
response = res;
serverName = name;
context = c;
}
private void getAllForMe(){
try{
DatagramSocket socket = new DatagramSocket();
InetAddress address = InetAddress.getByName(serverName);
byte[] buf = new NtpMessage().toByteArray();
DatagramPacket packet =
new DatagramPacket(buf, buf.length, address, 123);
// Set the transmit timestamp *just* before sending the packet
// ToDo: Does this actually improve performance or not?
NtpMessage.encodeTimestamp(packet.getData(), 40,
(System.currentTimeMillis()/1000.0) + 2208988800.0);
socket.send(packet);
// Get response
System.out.println("NTP request sent, waiting for response...\n");
packet = new DatagramPacket(buf, buf.length);
socket.receive(packet);
// Immediately record the incoming timestamp
destinationTimestamp =
(System.currentTimeMillis()/1000.0) + 2208988800.0;
// Process response
NtpMessage msg = new NtpMessage(packet.getData());
// Corrected, according to RFC2030 errata
roundTripDelay = (destinationTimestamp-msg.originateTimestamp) -
(msg.transmitTimestamp-msg.receiveTimestamp);
localClockOffset =
((msg.receiveTimestamp - msg.originateTimestamp) +
(msg.transmitTimestamp - destinationTimestamp)) / 2;
total+=localClockOffset;
// Display response
System.out.println("NTP server: " + serverName);
System.out.println(msg.toString());
System.out.println("Dest. timestamp: " +
NtpMessage.timestampToString(destinationTimestamp));
System.out.println("Round-trip delay: " +
new DecimalFormat("0.00").format(roundTripDelay*1000) + " ms");
System.out.println("Local clock offset: " +
new DecimalFormat("0.00").format(localClockOffset*1000) + " ms");
socket.close();
} catch (Exception e){
e.printStackTrace();
}
}
}
答案 0 :(得分:2)
那么如何同步两款Android手机的时钟呢?我该如何解决这个问题呢?
从概念上讲,您可以跳过同步系统时钟,并确定相对偏移和漂移。在论文Tiny-Sync: Tight Time Synchronization for Wireless Sensor Networks中,作者首先将节点 i 的时间描述为
t i (t)= a i t + b i
以UTC t 。
其中 i 和b i 是节点i时钟的漂移和偏移。
从此,您可以用节点2的时间t 2 表示节点1的时间t 1 ,如
t 1 (t)= a 12 t 2 (t)+ b 12 。
为了估计这些系数,发送消息,如下所示:
每个邮件发件人都添加一个时间戳。只需两个数据点,就可以估算两个节点的偏移量和漂移,使用基于树的方法来同步节点网络。
截至论文,
算法非常好 精度(微秒,如果精心制作)并在使用时限制精度 资源非常有限,[强调我的]
答案 1 :(得分:1)
如果可以接受,我认为我们应该切换视角 - 而不是将设备彼此同步,目标是A == B
(并且必须手动考虑偏移和延迟),我们可以让每个设备与外部设备同步源(服务器),因为A == C
和B == C
然后是A == B
。
您的用例类似于:
如果您只需要在一分钟内获得准确度,public api已经存在。否则服务器将是您自己创建的私有端点。
注意:由于您似乎的目标是同步播放,并且不同的设备将具有不同的性能,您需要在播放开始之前完全准备(加载/缓冲)媒体播放器。在收到歌曲之前,可能会在同步时间之前立即