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

Pur*_*lia 5 networking android ntp android-mediaplayer

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

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

  1. 主机创建热点并在热点上发布参与方名称并等待连接。
  2. 客户端现在可以在列表视图中查看可用方名称并选择要连接的方。
  3. 一旦建立了主机和客户端之间的连接,主机就会被引导至出现歌曲列表的活动。主持人选择其中一首歌曲。
  4. 使用套接字编程将所选歌曲传输到客户端并保存在文件夹中。
  5. 之后,主机获取当前系统时间并增加 5 秒,并将此秒发送给客户端。例如 - 10:35 - 当前时间。嗯,我们10点40分玩
  6. 一旦主机发送完时间并且客户端收到时间,它们都会创建一个警报,触发它们开始使用媒体播放器播放 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();
    }
    }

}
Run Code Online (Sandbox Code Playgroud)

ser*_*inc 3

\n

那么如何同步两部安卓手机的时钟呢?我该如何解决这个问题?

\n
\n\n

从概念上讲,您可以跳过同步系统时钟,而只确定相对偏移和漂移。在Tiny-Sync: Tight Time Synchronization for Wireless Sensor Networks论文中,作者首先将节点i的时间描述为

\n\n

t i (t) = a i t + b i

\n\n

以 UTC t表示。

\n\n
\n

其中 a i和 b i是节点 i\xe2\x80\x99s 时钟的漂移和偏移。

\n
\n\n

由此,您可以用节点 2 的时间 t 2来表示节点 1 的时间 t 1,如下所示

\n\n

t 1 (t) = a 12 t 2 (t) + b 12

\n\n

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

\n\n

消息从 1 发送到 2,然后返回到 1

\n\n

每个消息发送者都会添加一个时间戳。只需两个数据点,就可以估计两个节点的偏移和漂移,并使用基于树的方法来同步节点网络。

\n\n

截至该论文,

\n\n
\n

该算法提供了非常好的\n精度(如果精心设计的话为微秒),并且在使用\n非常有限的资源时限制了精度,[强调我的]

\n
\n