歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> Android 通過NTP服務器自動獲取時間的方法

Android 通過NTP服務器自動獲取時間的方法

日期:2017/3/1 10:19:31   编辑:Linux編程

對於手機,如果有SIM卡支持的話,在設置時間時可以通過選擇自動從網絡獲取時間來取得當地的時間和時區:

但如果手機沒有SIM卡,此時如果有Wifi鏈接,手機依然可以通過網絡自動獲取時間(時區此時需要手動設置)。 查看Android源碼,在android.net 中有 SntpClient類,可以通過訪問NTP服務器來取得當前的GMT時間。pool.ntp.org為最常用的一個NTF服務器。修改SntpClient代碼,你也可以在自己的應用(包括非Android應用)中通過NTP服務器來取得當前GMT時間,代碼如下:

  1. import java.net.DatagramPacket;
  2. import java.net.DatagramSocket;
  3. import java.net.InetAddress;
  4. import java.util.Date;
  5. public class GetTime {
  6. public static void main(String[] args) {
  7. SntpClient client = new SntpClient();
  8. if (client.requestTime("pool.ntp.org", 30000)) {
  9. long now = client.getNtpTime() + System.nanoTime() / 1000
  10. - client.getNtpTimeReference();
  11. Date current = new Date(now);
  12. System.out.println(current.toString());
  13. }
  14. }
  15. }
  16. class SntpClient {
  17. private static final int ORIGINATE_TIME_OFFSET = 24;
  18. private static final int RECEIVE_TIME_OFFSET = 32;
  19. private static final int TRANSMIT_TIME_OFFSET = 40;
  20. private static final int NTP_PACKET_SIZE = 48;
  21. private static final int NTP_PORT = 123;
  22. private static final int NTP_MODE_CLIENT = 3;
  23. private static final int NTP_VERSION = 3;
  24. // Number of seconds between Jan 1, 1900 and Jan 1, 1970
  25. // 70 years plus 17 leap days
  26. private static final long OFFSET_1900_TO_1970 = ((365L * 70L) + 17L) * 24L * 60L * 60L;
  27. // system time computed from NTP server response
  28. private long mNtpTime;
  29. // value of SystemClock.elapsedRealtime() corresponding to mNtpTime
  30. private long mNtpTimeReference;
  31. // round trip time in milliseconds
  32. private long mRoundTripTime;
  33. /**
  34. * Sends an SNTP request to the given host and processes the response.
  35. *
  36. * @param host
  37. * host name of the server.
  38. * @param timeout
  39. * network timeout in milliseconds.
  40. * @return true if the transaction was successful.
  41. */
  42. public boolean requestTime(String host, int timeout) {
  43. try {
  44. DatagramSocket socket = new DatagramSocket();
  45. socket.setSoTimeout(timeout);
  46. InetAddress address = InetAddress.getByName(host);
  47. byte[] buffer = new byte[NTP_PACKET_SIZE];
  48. DatagramPacket request = new DatagramPacket(buffer, buffer.length,
  49. address, NTP_PORT);
  50. // set mode = 3 (client) and version = 3
  51. // mode is in low 3 bits of first byte
  52. // version is in bits 3-5 of first byte
  53. buffer[0] = NTP_MODE_CLIENT | (NTP_VERSION << 3);
  54. // get current time and write it to the request packet
  55. long requestTime = System.currentTimeMillis();
  56. long requestTicks = System.nanoTime() / 1000;
  57. writeTimeStamp(buffer, TRANSMIT_TIME_OFFSET, requestTime);
  58. socket.send(request);
  59. // read the response
  60. DatagramPacket response = new DatagramPacket(buffer, buffer.length);
  61. socket.receive(response);
  62. long responseTicks = System.nanoTime() / 1000;
  63. long responseTime = requestTime + (responseTicks - requestTicks);
  64. socket.close();
  65. // extract the results
  66. long originateTime = readTimeStamp(buffer, ORIGINATE_TIME_OFFSET);
  67. long receiveTime = readTimeStamp(buffer, RECEIVE_TIME_OFFSET);
  68. long transmitTime = readTimeStamp(buffer, TRANSMIT_TIME_OFFSET);
  69. long roundTripTime = responseTicks - requestTicks
  70. - (transmitTime - receiveTime);
  71. // receiveTime = originateTime + transit + skew
  72. // responseTime = transmitTime + transit - skew
  73. // clockOffset = ((receiveTime - originateTime) + (transmitTime -
  74. // responseTime))/2
  75. // = ((originateTime + transit + skew - originateTime) +
  76. // (transmitTime - (transmitTime + transit - skew)))/2
  77. // = ((transit + skew) + (transmitTime - transmitTime - transit +
  78. // skew))/2
  79. // = (transit + skew - transit + skew)/2
  80. // = (2 * skew)/2 = skew
  81. long clockOffset = ((receiveTime - originateTime) + (transmitTime - responseTime)) / 2;
  82. // if (Config.LOGD) Log.d(TAG, "round trip: " + roundTripTime +
  83. // " ms");
  84. // if (Config.LOGD) Log.d(TAG, "clock offset: " + clockOffset +
  85. // " ms");
  86. // save our results - use the times on this side of the network
  87. // latency
  88. // (response rather than request time)
  89. mNtpTime = responseTime + clockOffset;
  90. mNtpTimeReference = responseTicks;
  91. mRoundTripTime = roundTripTime;
  92. } catch (Exception e) {
  93. return false;
  94. }
  95. return true;
  96. }
  97. /**
  98. * Returns the time computed from the NTP transaction.
  99. *
  100. * @return time value computed from NTP server response.
  101. */
  102. public long getNtpTime() {
  103. return mNtpTime;
  104. }
  105. /**
  106. * Returns the reference clock value (value of
  107. * SystemClock.elapsedRealtime()) corresponding to the NTP time.
  108. *
  109. * @return reference clock corresponding to the NTP time.
  110. */
  111. public long getNtpTimeReference() {
  112. return mNtpTimeReference;
  113. }
  114. /**
  115. * Returns the round trip time of the NTP transaction
  116. *
  117. * @return round trip time in milliseconds.
  118. */
  119. public long getRoundTripTime() {
  120. return mRoundTripTime;
  121. }
  122. /**
  123. * Reads an unsigned 32 bit big endian number from the given offset in the
  124. * buffer.
  125. */
  126. private long read32(byte[] buffer, int offset) {
  127. byte b0 = buffer[offset];
  128. byte b1 = buffer[offset + 1];
  129. byte b2 = buffer[offset + 2];
  130. byte b3 = buffer[offset + 3];
  131. // convert signed bytes to unsigned values
  132. int i0 = ((b0 & 0x80) == 0x80 ? (b0 & 0x7F) + 0x80 : b0);
  133. int i1 = ((b1 & 0x80) == 0x80 ? (b1 & 0x7F) + 0x80 : b1);
  134. int i2 = ((b2 & 0x80) == 0x80 ? (b2 & 0x7F) + 0x80 : b2);
  135. int i3 = ((b3 & 0x80) == 0x80 ? (b3 & 0x7F) + 0x80 : b3);
  136. return ((long) i0 << 24) + ((long) i1 << 16) + ((long) i2 << <img class="wp-smiley" alt="8)" src="http://www.imobilebbs.com/wordpress/wp-includes/images/smilies/icon_cool.gif">
  137. + (long) i3;
  138. }
  139. /**
  140. * Reads the NTP time stamp at the given offset in the buffer and returns it
  141. * as a system time (milliseconds since January 1, 1970).
  142. */
  143. private long readTimeStamp(byte[] buffer, int offset) {
  144. long seconds = read32(buffer, offset);
  145. long fraction = read32(buffer, offset + 4);
  146. return ((seconds - OFFSET_1900_TO_1970) * 1000)
  147. + ((fraction * 1000L) / 0x100000000L);
  148. }
  149. /**
  150. * Writes system time (milliseconds since January 1, 1970) as an NTP time
  151. * stamp at the given offset in the buffer.
  152. */
  153. private void writeTimeStamp(byte[] buffer, int offset, long time) {
  154. long seconds = time / 1000L;
  155. long milliseconds = time - seconds * 1000L;
  156. seconds += OFFSET_1900_TO_1970;
  157. // write seconds in big endian format
  158. buffer[offset++] = (byte) (seconds >> 24);
  159. buffer[offset++] = (byte) (seconds >> 16);
  160. buffer[offset++] = (byte) (seconds >> 8);
  161. buffer[offset++] = (byte) (seconds >> 0);
  162. long fraction = milliseconds * 0x100000000L / 1000L;
  163. // write fraction in big endian format
  164. buffer[offset++] = (byte) (fraction >> 24);
  165. buffer[offset++] = (byte) (fraction >> 16);
  166. buffer[offset++] = (byte) (fraction >> 8);
  167. // low order bits should be random data
  168. buffer[offset++] = (byte) (Math.random() * 255.0);
  169. }
  170. }

運行這個Java應用,可以得到當前GMT時間,如:Sat Jun 16 10:52:19 BST 2012

更多Android相關信息見Android 專題頁面 http://www.linuxidc.com/topicnews.aspx?tid=11

Copyright © Linux教程網 All Rights Reserved