Я создаю приложение, в котором хочу получить текущее время из Интернета.
Я знаю, как получить время с устройства с помощью System.currentTimeMillis
, и даже после многого поиска я не понял, как получить его из Интернета.
Я создаю приложение, в котором хочу получить текущее время из Интернета.
Я знаю, как получить время с устройства с помощью System.currentTimeMillis
, и даже после многого поиска я не понял, как получить его из Интернета.
Вы можете получить время от интернет-серверов времени, используя следующую программу
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("nist.time.nosc.us");
System.out.println(client.getDate());
} finally {
client.disconnect();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
1. Для этого вам понадобится Apache Commons Net. Загрузите библиотеку и добавьте в свой путь построения проекта.
(Или вы также можете использовать обрезанную Apache Commons Net Library здесь: https://www.dropbox.com/s/bjxjv7phkb8xfhh/commons-net-3.1.jar. Этого достаточно, чтобы получить время из Интернета)
2. Запустите программу. Вы получите время, напечатанное на консоли.
Вот метод, который я создал для вас вы можете использовать это в своем коде
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;
}
Вам понадобится доступ к веб-сервису, который предоставляет текущее время в формате XML или JSON.
Если вы не найдете такой тип сервиса, вы можете анализировать время с веб-страницы, например http://www.timeanddate.com/worldclock/, или хост ваш собственный сервис времени на сервере, используя, например, простую страницу PHP.
Проверьте JSoup для анализа HTML-страниц.
Я думаю, что лучшим решением является использование SNTP, в частности, код клиента SNTP от самого Android, например: http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.1.1_r1/android/net/SntpClient.java/
Я считаю, что Android использует SNTP для автоматического обновления даты и времени, когда сотовая сеть недоступна (например, wifi-планшеты).
Я думаю, что лучше, чем другие решения, потому что он использует SNTP/NTP, а не протокол Time (RFC 868), используемый Apache TimeTCPClient. Я не знаю ничего плохого о RFC 868, но NTP новее и, кажется, превзошел его и более широко используется. Я считаю, что устройства Android, у которых нет сотовой связи, используют NTP.
Кроме того, поскольку он использует сокеты. Некоторые из предлагаемых решений используют HTTP, чтобы они теряли что-то в своей точности.
Ничего из вышеизложенного не работало от меня. Это то, с чем я оказался (с Волей),
Этот пример также преобразуется в другой часовой пояс.
Long time = null;
RequestQueue queue = Volley.newRequestQueue(this);
String url ="http://www.timeapi.org/utc/now";
StringRequest stringRequest = new StringRequest(Request.Method.GET, url,
new Response.Listener<String>() {
@Override
public void onResponse(String response) {
try {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
simpleDateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
Date date = simpleDateFormat.parse(response);
TimeZone tz = TimeZone.getTimeZone("Israel");
SimpleDateFormat destFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
destFormat.setTimeZone(tz);
String result = destFormat.format(date);
Log.d(TAG, "onResponse: " + result.toString());
} catch (ParseException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Log.w(TAG, "onErrorResponse: "+ error.getMessage());
}
});
queue.add(stringRequest);
return time;
Импортировать волейбол в gradle:
compile 'com.android.volley:volley:1.0.0'
Если вам не нужна точность в миллисекундах, и если вы уже используете google firebase или не возражаете использовать его (они предоставляют бесплатный уровень), проверьте это: https://firebase.google.com/docs/database/android/offline-capabilities#clock-skew
В основном, база данных firebase имеет поле, которое обеспечивает значение смещения между временем устройства и временем сервера firebase. Вы можете использовать это смещение для получения текущего времени.
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");
}
});
Как я уже сказал, это будет неточно в зависимости от задержки сети.