Android 同步网络时间
来源:互联网 发布:高分少女 知乎: 编辑:程序博客网 时间:2024/05/18 11:11
分析这个功能点之前先了解一下相关概念:
网络时间协议(英语:Network Time Protocol,NTP)是以分组交换把两台电脑的时钟同步化的网络传输协议。NTP使用UDP端口123作为传输层。它是用作抵销可变延迟的影响。
NTP是仍在使用中的最古老的网络传输协议之一(在1985年前开始)。NTP最初由特拉华大学的Dave Mills 设计,他与一群志愿者仍在维护NTP。
NTP与更简单的DAYTIME(RFC 867)和TIME(RFC 868)网络传输协议没有关连。
android 系统在设置中有同步网络时间的功能。
Settings.System.putString(getContentResolver(), Settings.System.TIME_12_24, is24Hour? HOURS_24 : HOURS_12);
抽取设置中该代码片段,从代码片段来看仅仅是往数据库中存入了一个数值标识为要同步网络时间。具体怎么实现呢?
在源码中有NetworkTimeUpdateService.java这么一个类来负责这个事情,这个类监控这个值的变化。其中
/** Initialize the receivers and initiate the first NTP request */ public void systemRunning() { registerForTelephonyIntents(); registerForAlarms(); registerForConnectivityIntents(); HandlerThread thread = new HandlerThread(TAG); thread.start(); mHandler = new MyHandler(thread.getLooper()); // Check the network time on the new thread mHandler.obtainMessage(EVENT_POLL_NETWORK_TIME).sendToTarget(); mSettingsObserver = new SettingsObserver(mHandler, EVENT_AUTO_TIME_CHANGED); mSettingsObserver.observe(mContext); } /** Handler to do the network accesses on */ private class MyHandler extends Handler { public MyHandler(Looper l) { super(l); } @Override public void handleMessage(Message msg) { switch (msg.what) { case EVENT_AUTO_TIME_CHANGED: case EVENT_POLL_NETWORK_TIME: case EVENT_NETWORK_CHANGED: onPollNetworkTime(msg.what); break; } } } private void onPollNetworkTime(int event) { // If Automatic time is not set, don't bother. if (!isAutomaticTimeRequested()) return; final long refTime = SystemClock.elapsedRealtime(); // If NITZ time was received less than mPollingIntervalMs time ago, // no need to sync to NTP. if (mNitzTimeSetTime != NOT_SET && refTime - mNitzTimeSetTime < mPollingIntervalMs) { resetAlarm(mPollingIntervalMs); return; } final long currentTime = System.currentTimeMillis(); if (DBG) Log.d(TAG, "System time = " + currentTime); // Get the NTP time if (mLastNtpFetchTime == NOT_SET || refTime >= mLastNtpFetchTime + mPollingIntervalMs || event == EVENT_AUTO_TIME_CHANGED) { if (DBG) Log.d(TAG, "Before Ntp fetch"); // force refresh NTP cache when outdated if (mTime.getCacheAge() >= mPollingIntervalMs) { mTime.forceRefresh(); } // only update when NTP time is fresh if (mTime.getCacheAge() < mPollingIntervalMs) { final long ntp = mTime.currentTimeMillis(); mTryAgainCounter = 0; // If the clock is more than N seconds off or this is the first time it's been // fetched since boot, set the current time. if (Math.abs(ntp - currentTime) > mTimeErrorThresholdMs || mLastNtpFetchTime == NOT_SET) { // Set the system time if (DBG && mLastNtpFetchTime == NOT_SET && Math.abs(ntp - currentTime) <= mTimeErrorThresholdMs) { Log.d(TAG, "For initial setup, rtc = " + currentTime); } if (DBG) Log.d(TAG, "Ntp time to be set = " + ntp); // Make sure we don't overflow, since it's going to be converted to an int if (ntp / 1000 < Integer.MAX_VALUE) { SystemClock.setCurrentTimeMillis(ntp); } } else { if (DBG) Log.d(TAG, "Ntp time is close enough = " + ntp); } mLastNtpFetchTime = SystemClock.elapsedRealtime(); } else { // Try again shortly mTryAgainCounter++; if (mTryAgainTimesMax < 0 || mTryAgainCounter <= mTryAgainTimesMax) { resetAlarm(mPollingIntervalShorterMs); } else { // Try much later mTryAgainCounter = 0; resetAlarm(mPollingIntervalMs); } return; } } resetAlarm(mPollingIntervalMs); }
onPollNetworkTime就干了同步的事情。
其中 final long ntp = mTime.currentTimeMillis(); 就是获取网络时间。
private TrustedTime mTime; mTime = NtpTrustedTime.getInstance(context);
中NtpTrustedTime这类就起了同步的功能。其中
@Override public long currentTimeMillis() { if (!mHasCache) { throw new IllegalStateException("Missing authoritative time source"); } if (LOGD) Log.d(TAG, "currentTimeMillis() cache hit"); // current time is age after the last ntp cache; callers who // want fresh values will hit makeAuthoritative() first. return mCachedNtpTime + getCacheAge(); }
中mCachedNtpTime
final SntpClient client = new SntpClient(); if (client.requestTime(mServer, (int) mTimeout)) { mHasCache = true; mCachedNtpTime = client.getNtpTime(); mCachedNtpElapsedRealtime = client.getNtpTimeReference(); mCachedNtpCertainty = client.getRoundTripTime() / 2; return true; } else { return false; }
通过requestTime获取的,这个
/** * 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) { DatagramSocket socket = null; try { socket = new DatagramSocket(); socket.setSoTimeout(timeout); InetAddress address = InetAddress.getByName(host); byte[] buffer = new byte[NTP_PACKET_SIZE]; DatagramPacket request = new DatagramPacket(buffer, buffer.length, address, NTP_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] = NTP_MODE_CLIENT | (NTP_VERSION << 3); // get current time and write it to the request packet long requestTime = System.currentTimeMillis(); 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); long responseTicks = SystemClock.elapsedRealtime(); long responseTime = requestTime + (responseTicks - requestTicks); // extract the results long originateTime = readTimeStamp(buffer, ORIGINATE_TIME_OFFSET); long receiveTime = readTimeStamp(buffer, RECEIVE_TIME_OFFSET); long transmitTime = readTimeStamp(buffer, TRANSMIT_TIME_OFFSET); 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 (false) Log.d(TAG, "round trip: " + roundTripTime + " ms"); // if (false) Log.d(TAG, "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 (false) Log.d(TAG, "request time failed: " + e); return false; } finally { if (socket != null) { socket.close(); } } return true; }
其中这个host是在实例化NtpTrustedTime这个类的时候赋予的:
public static synchronized NtpTrustedTime getInstance(Context context) { if (sSingleton == null) { final Resources res = context.getResources(); final ContentResolver resolver = context.getContentResolver(); final String defaultServer = res.getString( com.android.internal.R.string.config_ntpServer); final long defaultTimeout = res.getInteger( com.android.internal.R.integer.config_ntpTimeout); final String secureServer = Settings.Global.getString( resolver, Settings.Global.NTP_SERVER); final long timeout = Settings.Global.getLong( resolver, Settings.Global.NTP_TIMEOUT, defaultTimeout); final String server = secureServer != null ? secureServer : defaultServer; sSingleton = new NtpTrustedTime(server, timeout); sContext = context; } return sSingleton; }
/frameworks/base/core/res/res/values/config.xml
其中com.android.internal.R.string.config_ntpServer 这个数值就是要访问的服务器地址。5.1.1源码中的值是:
<string translatable="false" name="config_ntpServer">2.android.pool.ntp.org</string>
0 3
- Android网络时间同步
- Android 同步网络时间
- Android中的网络时间同步
- Android中的网络时间同步
- Android中的网络时间同步
- Android中的网络时间同步 !!!!!!!!
- Android中的网络时间同步
- android网络时间同步总结
- android命令行网络时间同步
- android-获取网络时间、获取特定时区时间、时间同步
- Android增加SNTP网络时间同步功能
- Android增加SNTP网络时间同步功能
- android 手机的网络时间同步
- 网络时间同步
- C#同步网络时间
- C#同步网络时间
- C#同步网络时间
- C#同步网络时间
- Leetcode no. 344
- 牛客网算法学习记录-链表2
- 请求编码与响应编码
- MQ基础
- SVN出现!和!M问题
- Android 同步网络时间
- 多重背包
- BOBSLEDDING
- 高通平台进FFBM的三种模式
- 《Head First C#》学习 ---第一个实例中遇到的问题
- ayoutSubviews layoutIfNeeded setNeedsLayout 的区别
- libcocos2dx 已停止运行
- 网络流
- 如何学习 Javascript