Android 同步网络时间
分析这个功能点之前先了解一下相关概念:
网络时间协议(英语: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 threadmHandler.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);}@Overridepublic 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 timeif (mLastNtpFetchTime == NOT_SET || refTime >= mLastNtpFetchTime + mPollingIntervalMs|| event == EVENT_AUTO_TIME_CHANGED) {if (DBG) Log.d(TAG, "Before Ntp fetch");// force refresh NTP cache when outdatedif (mTime.getCacheAge() >= mPollingIntervalMs) {mTime.forceRefresh();}// only update when NTP time is freshif (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 timeif (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 intif (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 shortlymTryAgainCounter++;if (mTryAgainTimesMax < 0 || mTryAgainCounter <= mTryAgainTimesMax) {resetAlarm(mPollingIntervalShorterMs);} else {// Try much latermTryAgainCounter = 0;resetAlarm(mPollingIntervalMs);}return;}}resetAlarm(mPollingIntervalMs);}
onPollNetworkTime就干了同步的事情。
其中 final long ntp = mTime.currentTimeMillis(); 就是获取网络时间。
private TrustedTime mTime;mTime = NtpTrustedTime.getInstance(context);
中NtpTrustedTime这类就起了同步的功能。其中
@Overridepublic 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 bytebuffer[0] = NTP_MODE_CLIENT | (NTP_VERSION << 3);// get current time and write it to the request packetlong requestTime = System.currentTimeMillis();long requestTicks = SystemClock.elapsedRealtime();writeTimeStamp(buffer, TRANSMIT_TIME_OFFSET, requestTime);socket.send(request);// read the responseDatagramPacket response = new DatagramPacket(buffer, buffer.length);socket.receive(response);long responseTicks = SystemClock.elapsedRealtime();long responseTime = requestTime + (responseTicks - requestTicks);// extract the resultslong 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 = skewlong 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>
Android 同步网络时间相关推荐
- Android6.0 禁止自动同步网络时间
点击打开链接 配置文件在:frameworks/base/packages/SettingsProvider/res/values/defaults.xml <bool name="d ...
- ubuntu 修改时区、时间、同步网络时间、将时间写入硬件
查看系统当前的时间状态 $ timedatectl statusLocal time: 六 2021-10-30 09:33:37 CSTUniversal time: 六 2021-10-30 01 ...
- Windows自动同步网络时间
同步脚本如下: 创建"自动同步网络时间.bat",键入如下内容: @echo off w32tm /config /manualpeerlist:"time.nist.g ...
- Esp8266 进阶之路36【外设篇】乐鑫esp8266芯片SDK编程驱动时间芯片 ds1302,同步网络时间到本地,再也不怕掉电断网也可以同步时间了!(附带Demo)
本系列博客学习由非官方人员 半颗心脏 潜心所力所写,仅仅做个人技术交流分享,不做任何商业用途.如有不对之处,请留言,本人及时更改. 1. Esp8266之 搭建开发环境,开始一个"hello ...
- Linux - 自动同步网络时间
Linux - 查看.修改.更新系统时间 本文以 CentOS 为例,演示如何查看.设置系统时间,以及自动从互联网更新系统时间. 查看系统时间 执行 date 命令可以查看当前系统的时间: 原文:Li ...
- 实现嵌入式linux自动同步网络时间---NTP
因为ARM板断电重启问题,为保证能获取到准确的实时时间,所以需要实现自动从网络上获取时间,这就需要用到NTP.NTP是网络时间协议(Network Time Protocol)的简称,它是用来同步网络 ...
- Linux一条命令----同步网络时间
同步网络时间 [root@allen ~]# ntpdate cn.pool.ntp.org 如下图:成功! 如提示命令不存在,直接输入:yum install ntp -y 安装ntp软件包
- centos7 同步网络时间
安装ntpdate sudo yum install -y ntpdate 然后使用命令同步网络时间 sudo ntpdate pool.ntp.org 重新查看时间如下: 此处还不能完全解决掉这个问 ...
- 【STM32F767】使用RTThread和TouchGFX实现DIY数字仪表(四)——同步网络时间
目录: [STM32F767]使用RTThread和TouchGFX实现DIY数字仪表(一)--使用STM32CUBMX5.6移植touchGFX4.13 [STM32F767]使用RTThread和 ...
最新文章
- 安卓手机python开发环境_「学习」人工智能开发宝典:第四讲 Python开发环境安装(一)...
- java instanceof运算符_java的instanceof运算符
- ASP.NET Core 系列视频完结,新项目实战课程发布。
- Airbnb 弃用之后,我们还应该用 React Native 吗?
- 【NOIP2001】【Luogu1029】最大公约数和最小公倍数问题(GCD,枚举)
- 《Spring揭秘》知识点总结
- 佳能IP7250打印机6000错误
- 塞班S40手机内存出现乱码无法删除的解决办法
- android ios mp4格式转换,ios 开发 视频格式转换、mov转MP4
- 关于from scipy.misc import comb ImportError: cannot import name 'comb'的问题
- DXP中关于PCB及原理绘制那些高级玩意总结
- can总线隔离中继器、canbridge、CanRepeater的can波特率和滤波设置
- Spark论文思想之-基于RDD构建的模型(Shark的来龙去脉)
- 【积水成渊-逐步定制自己的Emacs神器】1:Emacs入门
- A slap on the back 祝贺一下
- 【指纹识别】基于模板匹配实现指纹识别门禁系统含Matlab源码
- with(), within() 和 transform()的简单比较
- 车辆违章查询演示示例
- 【AXU3EG】UltraScale+ MPSoC以及开发板介绍
- 【Deno】极简入门
热门文章
- 了解iPhone OS框架
- Windows系统的命令窗口
- UML 之 UML中的关系
- 1046 mysql_mysql 1046 错误解决实例_MySQL
- LS1046A 启动流程分析
- 常用的加密有哪些?在Java中如何实现?(MD5、AES、RSA)
- ios html js调用陀螺仪,Js 获取手机陀螺仪
- surface pen未接触屏幕就有反应 解决办法
- K8s安装 遇到错误:docker-ce conflicts with 2:docker-1.13.1-208.git7d71120.el7_9.x86_64
- 《跟我学习AI量化投资》通过chatgpt进行选股,简单易懂,降低人为操作风险