Cómo obtener la hora actual de Internet en Android
Estoy creando una aplicación en la que quiero obtener la hora actual de Internet.
Sé cómo obtener la hora del dispositivo usando System.currentTimeMillis
, e incluso después de buscar mucho, no obtuve ninguna idea sobre cómo obtenerla de Internet.
Puede obtener la hora de los servidores de hora de Internet utilizando el siguiente programa
import java.io.IOException;
import org.apache.commons.net.time.TimeTCPClient;
public final class GetTime {
public static final void main(String[] args) {
try {
TimeTCPClient client = new TimeTCPClient();
try {
// Set timeout of 60 seconds
client.setDefaultTimeout(60000);
// Connecting to time server
// Other time servers can be found at : http://tf.nist.gov/tf-cgi/servers.cgi#
// Make sure that your program NEVER queries a server more frequently than once every 4 seconds
client.connect("time.nist.gov");
System.out.println(client.getDate());
} finally {
client.disconnect();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
1. Necesitaría la biblioteca Apache Commons Net para que esto funcione. Descargue la biblioteca y agréguela a la ruta de compilación de su proyecto.
(O también puede utilizar la biblioteca Apache Commons Net recortada aquí: https://www-us.apache.org/dist//commons/net/binaries/commons-net-3.6-bin.tar.gz Esto es suficiente para obtener tiempo de internet)
2.Ejecute el programa. Obtendrás la hora impresa en tu consola.
Aquí hay un método que he creado para ti. Puedes usarlo en tu código.
public String getTime() {
try{
//Make the Http connection so we can retrieve the time
HttpClient httpclient = new DefaultHttpClient();
// I am using yahoos api to get the time
HttpResponse response = httpclient.execute(new
HttpGet("http://developer.yahooapis.com/TimeService/V1/getTime?appid=YahooDemo"));
StatusLine statusLine = response.getStatusLine();
if(statusLine.getStatusCode() == HttpStatus.SC_OK){
ByteArrayOutputStream out = new ByteArrayOutputStream();
response.getEntity().writeTo(out);
out.close();
// The response is an xml file and i have stored it in a string
String responseString = out.toString();
Log.d("Response", responseString);
//We have to parse the xml file using any parser, but since i have to
//take just one value i have deviced a shortcut to retrieve it
int x = responseString.indexOf("<Timestamp>");
int y = responseString.indexOf("</Timestamp>");
//I am using the x + "<Timestamp>" because x alone gives only the start value
Log.d("Response", responseString.substring(x + "<Timestamp>".length(),y) );
String timestamp = responseString.substring(x + "<Timestamp>".length(),y);
// The time returned is in UNIX format so i need to multiply it by 1000 to use it
Date d = new Date(Long.parseLong(timestamp) * 1000);
Log.d("Response", d.toString() );
return d.toString() ;
} else{
//Closes the connection.
response.getEntity().getContent().close();
throw new IOException(statusLine.getReasonPhrase());
}
}catch (ClientProtocolException e) {
Log.d("Response", e.getMessage());
}catch (IOException e) {
Log.d("Response", e.getMessage());
}
return null;
}
Si no le importa la precisión de milisegundos y ya está usando Google Firebase o no le importa usarlo (proporcionan un nivel gratuito), consulte esto: https://firebase.google.com/docs/database /android/offline-capabilities#clock-skew
Básicamente, la base de datos de Firebase tiene un campo que proporciona un valor de compensación entre la hora del dispositivo y la hora del servidor de Firebase. Puede utilizar este desplazamiento para obtener la hora actual.
DatabaseReference offsetRef = FirebaseDatabase.getInstance().getReference(".info/serverTimeOffset");
offsetRef.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot snapshot) {
double offset = snapshot.getValue(Double.class);
double estimatedServerTimeMs = System.currentTimeMillis() + offset;
}
@Override
public void onCancelled(DatabaseError error) {
System.err.println("Listener was cancelled");
}
});
Como dije, será inexacto según la latencia de la red.
Creo que la mejor solución es utilizar SNTP, en particular el código de cliente SNTP del propio Android, por ejemplo: http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/ 4.1.1_r1/android/net/SntpClient.java/
Creo que Android usa SNTP para actualizaciones automáticas de fecha/hora cuando una red celular no está disponible (por ejemplo, tabletas wifi).
Creo que es mejor que las otras soluciones porque utiliza SNTP/NTP en lugar del protocolo de tiempo (RFC 868) utilizado por Apache TimeTCPClient. No sé nada malo sobre RFC 868, pero NTP es más nuevo y parece haberlo reemplazado y se usa más ampliamente. Creo que los dispositivos Android que no tienen celular usan NTP.
Además, porque utiliza enchufes. Algunas de las soluciones propuestas utilizan HTTP, por lo que perderán algo de precisión.