【发布时间】:2017-03-13 08:14:45
【问题描述】:
我正在尝试开发一个应用程序,它允许其他安卓手机充当扬声器,从而创建一个类似派对的东西。该应用程序将类似于三星提供的群组游戏功能。
为了实现这个功能,我决定执行以下步骤 -
- 主机创建热点并在热点上发布党名并等待连接。
- 客户端现在可以在列表视图中查看可用的参与方名称并选择要连接的参与方。
- 一旦主机和客户端之间的连接建立,主机将被定向到出现歌曲列表的活动。主持人选择其中一首歌曲。
- 使用套接字编程将所选歌曲传输到客户端并保存在文件夹中。
- 之后,主机获取当前系统时间并将其增加 5 秒,并将此秒数发送给客户端。例如 - 10:35 - 当前时间。嗯,我们会在 10:40 玩
- 主机发送完时间并且客户端收到时间后,它们都会创建一个警报,触发它们开始使用媒体播放器播放 MP3 文件。
**面临的问题 - ** 实现此功能后,我注意到两个 Android 设备的系统时间不同,因此我使用 ClockSync 应用程序同步系统时间,该应用程序使用 NTP 同步时间。 我不希望我的用户使用需要 root 访问权限的第三方应用程序。那么如何同步两部安卓手机的时钟呢? 我该如何解决这个问题?
编辑 -
我使用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();
}
}
}
【问题讨论】:
-
我认为你最初关于音频播放同步的问题实际上更好的是不是XY problem。从您的问题中仍然不清楚您当前在代码中的方法到底有什么问题。您似乎在每台设备上都有
localClockOffset。 -
是的。我们在每个设备上都有本地偏移量。但我们仍然会延迟 0.3-0.5 秒。
-
@SergGr 你有更好的方法来同步两部手机之间的播放吗?
-
对不起,我还是不明白。您在什么和什么之间“仍然有 0.3-0.5 秒的延迟”?你到底是怎么使用
localClockOffset的? -
@SergGr 我们正在使用警报管理器来触发媒体播放器开始在每台设备上播放歌曲。由于每个设备都有不同的系统时间,我们使用偏移量和它们的系统时间让设备等待某个时间,例如晚上 10:45,然后当闹钟响起时,媒体播放开始。
标签: android networking android-mediaplayer ntp