如何同步两部或更多Android手机的系统时钟?

时间:2017-02-24 12:36:02

标签: android networking android-mediaplayer ntp

我正在尝试开发一款应用程序,允许其他Android手机充当扬声器,从而创建一个像派对一样的派对。该应用程序类似于三星提供的群游功能。

为了实现此功能,我决定执行以下步骤 -

  1. 主机创建热点并在热点上发布聚会名称并等待连接。
  2. 客户端现在可以在列表视图中查看可用的聚会名称,并选择要连接的一方。
  3. 一旦建立了主机和客户端之间的连接,主机就会转到显示歌曲列表的活动。主持人选择其中一首歌曲。
  4. 使用套接字编程将选定的歌曲传送到客户端并保存在文件夹中。
  5. 之后,主机获取当前系统时间并向其添加5秒并将此秒发送给客户端。对于前 - 10:35 - 当前时间。嗯,我们将在10:40
  6. 上演
  7. 一旦主机完成发送时间并且客户端已经收到时间,他们都会创建一个警报,触发他们开始使用媒体播放器播放MP3文件。
  8. **面临的问题 - ** 在我实现这个之后,我注意到两个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();
        }
        }
    
    }
    

2 个答案:

答案 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

为了估计这些系数,发送消息,如下所示:

message from 1 to 2 and back to 1

每个邮件发件人都添加一个时间戳。只需两个数据点,就可以估算两个节点的偏移量和漂移,使用基于树的方法来同步节点网络。

截至论文,

  

算法非常好   精度(微秒,如果精心制作)并在使用时限制精度   资源非常有限,[强调我的]

答案 1 :(得分:1)

如果可以接受,我认为我们应该切换视角 - 而不是将设备彼此同步,目标是A == B(并且必须手动考虑偏移和延迟),我们可以让每个设备与外部设备同步源(服务器),因为A == CB == C然后是A == B

您的用例类似于:

  1. 主持人创建热点并发布(...)
  2. 客户现在可以看到可用的聚会(...)
  3. 建立主机与客户端之间的连接后(...)
  4. 所选歌曲将传输到客户端(...)
  5. 每个客户端/主机联系服务器以获得“正确”的时间
  6. 存储接收时间和设备时间之间的偏移
  7. 客户端向主持人广播时间已对齐
  8. 当所有客户都标记时间对齐时,主机会广播所需的开始时间
  9. 当客户收到请求的开始时间时,他们会使用他们存储的偏移量来根据设备系统时间计算开始时间
  10. 在计算的时间开始播放
  11. 如果您只需要在一分钟内获得准确度,public api已经存在。否则服务器将是您自己创建的私有端点。

    注意:由于您似乎的目标是同步播放,并且不同的设备将具有不同的性能,您需要在播放开始之前完全准备(加载/缓冲)媒体播放器。在收到歌曲之前,可能会在同步时间之前立即