Reputation: 681
I am trying to develop an app which allows other android phones to act as speakers and thus creating a party like thing. The app would be similar to the group play feature provided by Samsung.
To implement this feature, I decided to perform the following steps -
**Problems faced - ** After I implemented this, I noticed that both the Android devices had different system time, hence I synced the system times using the ClockSync App which uses NTP for synchronising the time. I do not want my users to use a third party app which requires root access. So how can I sync the clocks of two android phones? How can I solve the problem?
EDIT -
I am using below AsyncTask
Class to calculate the difference between NTP clock and local Clock.
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();
}
}
}
Upvotes: 6
Views: 3082
Reputation: 21783
If it's acceptable I think we should probably switch the perspective - instead of syncing devices with each other aiming for A == B
(and having to manually account for offsets and delays), we can have each device sync with an external source (server) since if A == C
and B == C
then A == B
.
Your use case will look something like:
If you only need accuracy to within one minute a public api already exists. Otherwise the server will be a private endpoint you create yourself.
Note: As you appear to be aiming for synchronised playback and different devices will have different performance you need to completely prepare (load/buffer) your media player before playback begins. Probably immediately when the song is received, before synchronising time
Upvotes: 1
Reputation: 38307
So how can I sync the clocks of two android phones? How can I solve the problem?
Conceptually, you can skip synchronizing the system clocks, and just determine the relative offset and drift. In the paper Tiny-Sync: Tight Time Synchronization for Wireless Sensor Networks, the authors first describe node i's time as
ti (t) = ai t + bi
in terms of UTC t.
where ai and bi are the drift and the offset of node i’s clock.
From this, you can express node 1's time t1 in terms of node 2's time t2, as
t1 (t) = a12 t2 (t) + b12.
To estimate these coefficients, messages are sent, as depicted here:
Each message sender adds a timestamp. With as few as two data points, the offset, and the drift of the two nodes can be estimated, with a tree-based method to synchronize a network of nodes.
As of the paper,
the algorithms provide very good precision (microsecond if crafted carefully) and bounds on the precision while using very limited resources, [emphasis mine]
Upvotes: 3