¿Cómo puedo sincronizar los relojes del sistema de dos o más teléfonos android?

Estoy tratando de desarrollar una aplicación que permite a otros teléfonos Android para actuar como altavoces y, por tanto, crear una fiesta como cosa. La aplicación sería similar a la función de reproducción en grupo proporcionada por Samsung.

Para implementar esta característica, decidí realizar los siguientes pasos:

  1. El host crea un hotspot y publica un nombre de parte en el hotspot y espera las conexiones.
  2. El cliente ahora puede ver los nombres de las partes disponibles en una vista de lista y selecciona una parte para conectarse.
  3. Una vez establecida la conexión entre el host y el cliente, el host se dirige a una actividad donde aparece una lista de canciones. El anfitrión selecciona una de las canciones.
  4. La canción seleccionada se transfiere al cliente mediante la programación de socket y se guarda en una carpeta.
  5. Después de eso, el host recibe el tiempo del sistema actual y agrega 5 segundos a él y envía este segundo al cliente. Por ex – 10:35 – hora actual. Hmm, jugaremos a las 10:40
  6. Una vez que el anfitrión se hace el envío de la hora y el cliente ha recibido el tiempo, ambos crean una alarma que los desencadena para comenzar a reproducir el archivo MP3 con un reproductor de medios.

** Problemas enfrentados – ** Después de implementar esto, me di cuenta de que los dos dispositivos Android tenía tiempo del sistema diferente, por lo tanto, sincronizó el sistema veces utilizando la aplicación ClockSync que utiliza NTP para sincronizar el tiempo. No quiero que mis usuarios utilicen una aplicación de terceros que requiera acceso root. Entonces, ¿cómo puedo sincronizar los relojes de dos teléfonos Android? ¿Cómo puedo solucionar el problema?

EDIT – Estoy usando por debajo de AsyncTask Clase para calcular la diferencia entre el reloj NTP y el reloj local.

 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(); } } } 

Entonces, ¿cómo puedo sincronizar los relojes de dos teléfonos Android? ¿Cómo puedo solucionar el problema?

Conceptualmente, puede saltar la sincronización de los relojes del sistema, y ​​sólo determinar el desplazamiento relativo y la deriva. En el documento Tiny-Sync: Sincronización de tiempo estrecho para redes de sensores inalámbricos , los autores describen primero el tiempo del nodo i como

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

En términos de UTC t .

Donde a i y b i son la deriva y el desplazamiento del reloj del nodo i.

A partir de esto, puede expresar el tiempo t 1 del nodo 1 en términos del tiempo t 2 del nodo 2 , como

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

Para estimar estos coeficientes, se envían mensajes, como se muestra aquí:

Mensaje de 1 a 2 y de nuevo a 1

Cada remitente de mensajes agrega una marca de tiempo. Con tan sólo dos puntos de datos, se puede estimar el desplazamiento y la deriva de los dos nodos, con un método basado en árbol para sincronizar una red de nodos.

En el documento,

Los algoritmos proporcionan una precisión muy buena ( microsecond si se trabajan cuidadosamente ) y los límites de la precisión, mientras que el uso de recursos muy limitados, [énfasis mío]

Si es aceptable, creo que probablemente deberíamos cambiar la perspectiva – en lugar de sincronizar dispositivos con el objetivo de A == B (y tener que contabilizar manualmente las compensaciones y los retrasos), podemos sincronizar cada dispositivo con una fuente externa (servidor) Ya que si A == C y B == C entonces A == B

Su caso de uso se verá así:

  1. El host crea un hotspot y publica (…)
  2. El cliente puede ver ahora la parte disponible (…)
  3. Una vez establecida la conexión entre el host y el cliente (…)
  4. La canción seleccionada se transfiere al cliente (…)
  5. Cada cliente / anfitrión se pone en contacto con el servidor para obtener el tiempo "correcto"
  6. El desplazamiento entre el tiempo recibido y el tiempo del dispositivo se almacena
  7. Las transmisiones de cliente al host que el tiempo está alineado
  8. Cuando todos los clientes han alineado el tiempo marcado el anfitrión transmite la hora de inicio requerida
  9. Cuando los clientes reciben la hora de inicio solicitada, usan la compensación que almacenan para calcular la hora de inicio de acuerdo con la hora del sistema de sus dispositivos
  10. A la hora calculada comienza la reproducción

Si sólo necesita precisión en un minuto, ya existe una api pública . De lo contrario, el servidor será un punto final privado que creará usted mismo.

Nota: Como parezca estar apuntando a la reproducción sincronizada y diferentes dispositivos tendrán diferentes prestaciones que usted necesita para preparar completamente (cargar / buffer) su reproductor de medios antes de que comience la reproducción. Probablemente inmediatamente cuando se recibe la canción, antes de sincronizar el tiempo

FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.