Android使用REAL unix时间

问题描述:

我想获得真正的unix时间戳。因此,即使您手动将设备的时间更改为将来,我也能获得实时。我已经在这里搜索,发现System.CurrentTimeMillis,但它并没有解决我的问题。Android使用REAL unix时间

如果无法做到这一点,我该如何检查它与时间服务器?

+0

哇非常快的答案。我会看看它Thx :) – Tester

通过这种SntpClient类

class GetNTPAsynctask extends AsyncTask<String, Void, Boolean> { 
    SntpClient sntpClient = new SntpClient(); 
    @Override 
    protected Boolean doInBackground(String... params) { 
     boolean success = false; 
     try { 
      success = sntpClient.requestTime("pool.ntp.org", 30000); 
     } 
     catch (Exception e) { 
      Log.d(TAG, "doInBackground: Exception" + e.getMessage()); 
      success = false; 
     } 
     return success; 
    } 

    @Override 
    protected void onPostExecute(Boolean aBoolean) { 
     super.onPostExecute(aBoolean); 

     if(aBoolean) { 
      long currentTimeMiliseconds = sntpClient.getNtpTime(); 
      // use it... 
     } 
     else { 
      Toast.makeText(context, "Connection to device not possible.", Toast.LENGTH_SHORT).show(); 
     } 
    } 
} 

只是调用这个AsyncTask

GetNTPAsynctask asyncTask = new GetNTPAsynctask(); 
asyncTask.execute(); 

使用此sntpclient类

import android.net.TrafficStats; 
import android.os.SystemClock; 
import android.util.Log; 
import java.net.DatagramPacket; 
import java.net.DatagramSocket; 
import java.net.InetAddress; 
import java.util.Arrays; 
public class SntpClient { 
private static final String TAG = "SntpClient"; 
private static final boolean DBG = true; 
private static final int REFERENCE_TIME_OFFSET = 16; 
private static final int ORIGINATE_TIME_OFFSET = 24; 
private static final int RECEIVE_TIME_OFFSET = 32; 
private static final int TRANSMIT_TIME_OFFSET = 40; 
private static final int NTP_PACKET_SIZE = 48; 
private static final int NTP_PORT = 123; 
private static final int NTP_MODE_CLIENT = 3; 
private static final int NTP_MODE_SERVER = 4; 
private static final int NTP_MODE_BROADCAST = 5; 
private static final int NTP_VERSION = 3; 
private static final int NTP_LEAP_NOSYNC = 3; 
private static final int NTP_STRATUM_DEATH = 0; 
private static final int NTP_STRATUM_MAX = 15; 
// Number of seconds between Jan 1, 1900 and Jan 1, 1970 
// 70 years plus 17 leap days 
private static final long OFFSET_1900_TO_1970 = ((365L * 70L) + 17L) * 24L * 60L * 60L; 
// system time computed from NTP server response 
private long mNtpTime; 
// value of SystemClock.elapsedRealtime() corresponding to mNtpTime 
private long mNtpTimeReference; 
// round trip time in milliseconds 
private long mRoundTripTime; 
private static class InvalidServerReplyException extends Exception { 
    public InvalidServerReplyException(String message) { 
     super(message); 
    } 
} 
/** 
* Sends an SNTP request to the given host and processes the response. 
* 
* @param host host name of the server. 
* @param timeout network timeout in milliseconds. 
* @return true if the transaction was successful. 
*/ 
public boolean requestTime(String host, int timeout) { 
    InetAddress address = null; 
    try { 
     address = InetAddress.getByName(host); 
    } catch (Exception e) { 
     if (DBG) Log.d(TAG, "request time failed: " + e); 
     return false; 
    } 
    return requestTime(address, NTP_PORT, timeout); 
} 
public boolean requestTime(InetAddress address, int port, int timeout) { 
    DatagramSocket socket = null; 
    try { 
     socket = new DatagramSocket(); 
     socket.setSoTimeout(timeout); 
     byte[] buffer = new byte[NTP_PACKET_SIZE]; 
     DatagramPacket request = new DatagramPacket(buffer, buffer.length, address, port); 
     // set mode = 3 (client) and version = 3 
     // mode is in low 3 bits of first byte 
     // version is in bits 3-5 of first byte 
     buffer[0] = (byte) (NTP_MODE_CLIENT | (NTP_VERSION << 3)); 
     // get current time and write it to the request packet 
     final long requestTime = System.currentTimeMillis(); 
     final long requestTicks = SystemClock.elapsedRealtime(); 
     writeTimeStamp(buffer, TRANSMIT_TIME_OFFSET, requestTime); 
     socket.send(request); 
     // read the response 
     DatagramPacket response = new DatagramPacket(buffer, buffer.length); 
     socket.receive(response); 
     final long responseTicks = SystemClock.elapsedRealtime(); 
     final long responseTime = requestTime + (responseTicks - requestTicks); 
     // extract the results 
     final byte leap = (byte) ((buffer[0] >> 6) & 0x3); 
     final byte mode = (byte) (buffer[0] & 0x7); 
     final int stratum = (int) (buffer[1] & 0xff); 
     final long originateTime = readTimeStamp(buffer, ORIGINATE_TIME_OFFSET); 
     final long receiveTime = readTimeStamp(buffer, RECEIVE_TIME_OFFSET); 
     final long transmitTime = readTimeStamp(buffer, TRANSMIT_TIME_OFFSET); 
     /* do sanity check according to RFC */ 
     // TODO: validate originateTime == requestTime. 
     checkValidServerReply(leap, mode, stratum, transmitTime); 
     long roundTripTime = responseTicks - requestTicks - (transmitTime - receiveTime); 
     // receiveTime = originateTime + transit + skew 
     // responseTime = transmitTime + transit - skew 
     // clockOffset = ((receiveTime - originateTime) + (transmitTime - responseTime))/2 
     //    = ((originateTime + transit + skew - originateTime) + 
     //    (transmitTime - (transmitTime + transit - skew)))/2 
     //    = ((transit + skew) + (transmitTime - transmitTime - transit + skew))/2 
     //    = (transit + skew - transit + skew)/2 
     //    = (2 * skew)/2 = skew 
     long clockOffset = ((receiveTime - originateTime) + (transmitTime - responseTime))/2; 
     if (DBG) { 
      Log.d(TAG, "round trip: " + roundTripTime + "ms, " + 
        "clock offset: " + clockOffset + "ms"); 
     } 
     // save our results - use the times on this side of the network latency 
     // (response rather than request time) 
     mNtpTime = responseTime + clockOffset; 
     mNtpTimeReference = responseTicks; 
     mRoundTripTime = roundTripTime; 
    } catch (Exception e) { 

     if (DBG) Log.d(TAG, "request time failed: " + e); 
     return false; 
    } finally { 
     if (socket != null) { 
      socket.close(); 
     } 
    } 
    return true; 
} 
/** 
* Returns the time computed from the NTP transaction. 
* 
* @return time value computed from NTP server response. 
*/ 
public long getNtpTime() { 
    return mNtpTime; 
} 
/** 
* Returns the reference clock value (value of SystemClock.elapsedRealtime()) 
* corresponding to the NTP time. 
* 
* @return reference clock corresponding to the NTP time. 
*/ 
public long getNtpTimeReference() { 
    return mNtpTimeReference; 
} 
/** 
* Returns the round trip time of the NTP transaction 
* 
* @return round trip time in milliseconds. 
*/ 
public long getRoundTripTime() { 
    return mRoundTripTime; 
} 
private static void checkValidServerReply(
     byte leap, byte mode, int stratum, long transmitTime) 
     throws InvalidServerReplyException { 
    if (leap == NTP_LEAP_NOSYNC) { 
     throw new InvalidServerReplyException("unsynchronized server"); 
    } 
    if ((mode != NTP_MODE_SERVER) && (mode != NTP_MODE_BROADCAST)) { 
     throw new InvalidServerReplyException("untrusted mode: " + mode); 
    } 
    if ((stratum == NTP_STRATUM_DEATH) || (stratum > NTP_STRATUM_MAX)) { 
     throw new InvalidServerReplyException("untrusted stratum: " + stratum); 
    } 
    if (transmitTime == 0) { 
     throw new InvalidServerReplyException("zero transmitTime"); 
    } 
} 
/** 
* Reads an unsigned 32 bit big endian number from the given offset in the buffer. 
*/ 
private long read32(byte[] buffer, int offset) { 
    byte b0 = buffer[offset]; 
    byte b1 = buffer[offset+1]; 
    byte b2 = buffer[offset+2]; 
    byte b3 = buffer[offset+3]; 
    // convert signed bytes to unsigned values 
    int i0 = ((b0 & 0x80) == 0x80 ? (b0 & 0x7F) + 0x80 : b0); 
    int i1 = ((b1 & 0x80) == 0x80 ? (b1 & 0x7F) + 0x80 : b1); 
    int i2 = ((b2 & 0x80) == 0x80 ? (b2 & 0x7F) + 0x80 : b2); 
    int i3 = ((b3 & 0x80) == 0x80 ? (b3 & 0x7F) + 0x80 : b3); 
    return ((long)i0 << 24) + ((long)i1 << 16) + ((long)i2 << 8) + (long)i3; 
} 
/** 
* Reads the NTP time stamp at the given offset in the buffer and returns 
* it as a system time (milliseconds since January 1, 1970). 
*/ 
private long readTimeStamp(byte[] buffer, int offset) { 
    long seconds = read32(buffer, offset); 
    long fraction = read32(buffer, offset + 4); 
    // Special case: zero means zero. 
    if (seconds == 0 && fraction == 0) { 
     return 0; 
    } 
    return ((seconds - OFFSET_1900_TO_1970) * 1000) + ((fraction * 1000L)/0x100000000L); 
} 
/** 
* Writes system time (milliseconds since January 1, 1970) as an NTP time stamp 
* at the given offset in the buffer. 
*/ 
private void writeTimeStamp(byte[] buffer, int offset, long time) { 
    // Special case: zero means zero. 
    if (time == 0) { 
     Arrays.fill(buffer, offset, offset + 8, (byte) 0x00); 
     return; 
    } 
    long seconds = time/1000L; 
    long milliseconds = time - seconds * 1000L; 
    seconds += OFFSET_1900_TO_1970; 
    // write seconds in big endian format 
    buffer[offset++] = (byte)(seconds >> 24); 
    buffer[offset++] = (byte)(seconds >> 16); 
    buffer[offset++] = (byte)(seconds >> 8); 
    buffer[offset++] = (byte)(seconds >> 0); 
    long fraction = milliseconds * 0x100000000L/1000L; 
    // write fraction in big endian format 
    buffer[offset++] = (byte)(fraction >> 24); 
    buffer[offset++] = (byte)(fraction >> 16); 
    buffer[offset++] = (byte)(fraction >> 8); 
    // low order bits should be random data 
    buffer[offset++] = (byte)(Math.random() * 255.0); 
} 
} 
+0

感谢@Omer Hayat我已经使用此代码。它的工作。 –

+0

@Tester如果这解决了你的问题,请接受我的答案。 –

+0

@Omer Hayat首先非常感谢您的快速响应。我仍然有这个类的问题:https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/net/SntpClient.java http://prntscr.com/gw1ran如果你能帮助我,这将是很好的:)再次感谢你的努力。 – Tester