Android中的网络时间同步

转载 2012年03月26日 20:46:39

在 Android的系统设置中,有自动同步网络时间的选项。因为Broncho A1移植到froyo版本之后,我们发现时间同步选项无效了。所以我花了一点时间去研究 Android的网络时间同步的流程。研究的结果让我感到惊讶,Android的网络时间同步居然与SNTP协议无关,甚至与TCP/IP协议也毫无关系。

从设置的应用程序中可以了解到,自动同步网络时间的选项只是修改了Settings.System.AUTO_TIME这个设置:

private void setAutoState(boolean isEnabled, boolean autotimeStatus) { if (isEnabled == false) { mAutoPref.setChecked(autotimeStatus); mAutoPref.setEnabled(isEnabled); } else { Settings.System.putInt(getContentResolver(), Settings.System.AUTO_TIME, autotimeStatus ? 1 : 0); } mTimePref.setEnabled(!autotimeStatus); mDatePref.setEnabled(!autotimeStatus); mTimeZone.setEnabled(!autotimeStatus); }

谁会用这个设置呢?然后从代码中查找Settings.System.AUTO_TIME,主要有下面两处:

telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java

GSM和CDMA的实现应该是类似的,这里只是看看GSM: 1. reference-ril/reference-ril.c处理主动上报消息。

if (strStartsWith(s, "%CTZV:")) { /* TI specific -- NITZ time */ char *response; line = p = strdup(s); at_tok_start(&p); err = at_tok_nextstr(&p, &response); free(line); if (err != 0) { LOGE("invalid NITZ line %s/n", s); } else { RIL_onUnsolicitedResponse ( RIL_UNSOL_NITZ_TIME_RECEIVED, response, strlen(response)); } } 这里是处理模组主动上报的消息,如果是时间和时区消息,则调用RIL_onUnsolicitedResponse。 2.	RIL_onUnsolicitedResponse会把消息发送给RIL的客户端。
ret = sendResponse(p, client_id);
时间和时区信息的格式在RIL_UNSOL_NITZ_TIME_RECEIVED消息的定义处有说明: "data" is const char * pointing to NITZ time string in the form "yy/mm/dd,hh:mm:ss(+/-)tz,dt" 3. RIL客户端处理RIL_UNSOL_NITZ_TIME_RECEIVED消息(telephony/java/com/android/internal/telephony/RIL.java: processUnsolicited)
case RIL_UNSOL_NITZ_TIME_RECEIVED: if (RILJ_LOGD) unsljLogRet(response, ret); // has bonus long containing milliseconds since boot that the NITZ // time was received long nitzReceiveTime = p.readLong(); Object[] result = new Object[2]; result[0] = ret; result[1] = Long.valueOf(nitzReceiveTime); if (mNITZTimeRegistrant != null) { mNITZTimeRegistrant .notifyRegistrant(new AsyncResult (null, result, null)); } else { // in case NITZ time registrant isnt registered yet mLastNITZTimeInfo = result; }
是GsmServiceStateTracker向RIL注册的,所以事件会由GsmServiceStateTracker来处理。 4. GsmServiceStateTracker 处理EVENT_NITZ_TIME事件:
case EVENT_NITZ_TIME: ar = (AsyncResult) msg.obj; String nitzString = (String)((Object[])ar.result)[0]; long nitzReceiveTime = ((Long)((Object[])ar.result)[1]).longValue(); setTimeFromNITZString(nitzString, nitzReceiveTime); break;
这里nitzString是时间字符串,由setTimeFromNITZString负责解析。
private void setTimeFromNITZString (String nitz, long nitzReceiveTime) { String[] nitzSubs = nitz.split("[/:,+-]"); int year = 2000 + Integer.parseInt(nitzSubs[0]); c.set(Calendar.YEAR, year); // month is 0 based! int month = Integer.parseInt(nitzSubs[1]) - 1; c.set(Calendar.MONTH, month); int date = Integer.parseInt(nitzSubs[2]); c.set(Calendar.DATE, date); int hour = Integer.parseInt(nitzSubs[3]); c.set(Calendar.HOUR, hour); int minute = Integer.parseInt(nitzSubs[4]); c.set(Calendar.MINUTE, minute);
如果在系统设置中,用户选择了自动同步网络时间,才会去设置系统时间。
if (getAutoTime()) { setAndBroadcastNetworkSetTimeZone(zone.getID()); } if (getAutoTime()) { setAndBroadcastNetworkSetTime(c.getTimeInMillis()); }
关于NITZ在WIKI上有说明: NITZ, or Network Identity and Time Zone[1], is a mechanism for provisioning local time and date, as well as network provider identity information to mobile devices via a wireless network[2]. NITZ has been part of the official GSM standard since phase 2+ release 96[3]. NITZ is often used to automatically update the system clock of mobile phones. 由于NITZ的实现是可选的,如果运营商不支持它,Android手机就无法使用此功能了。此时用最好用SNTP来代替,否则用户会感到迷惑。但Android目前好像并没有这样做,我只找到两处地方调用SntpClient,但它们都没有去设置系统时间。

---------------------------------------------------------------------------------------------

整体描述:

android网络时间同步使用NITZ(Network identity and Time Zone)运营商可选服务。

由Ril层主动上报RIL_UNSOL_NITZ_TIME_RECEIVED消息;通知(notify)给CdmaServiceStateTracker和GsmServiceStateTracker;CdmaServiceStateTracker获得网络同步时间,根据DateTimeSetting中自动同步设置,决定是否同步和发送(ACTION_NETWORK_SET_TIMEZONE、ACTION_NETWORK_SET_TIME)广播。

 

其中

/** if time between NITZ updates is less than mNitzUpdateSpacing the update may be ignored. */

private static final int NITZ_UPDATE_SPACING_DEFAULT = 1000 * 60 * 10;
    private int mNitzUpdateSpacing = SystemProperties.getInt("ro.nitz_update_spacing",
            NITZ_UPDATE_SPACING_DEFAULT);

决定同步的时间间隔,如果网络主动上报间隔小于此时间间隔,则忽略该次消息

 

/** If mNitzUpdateSpacing hasn't been exceeded but update is > mNitzUpdate do the update */
    private static final int NITZ_UPDATE_DIFF_DEFAULT = 2000;
    private int mNitzUpdateDiff = SystemProperties.getInt("ro.nitz_update_diff",
            NITZ_UPDATE_DIFF_DEFAULT);

上报的NITZ同步时间与当前处理时间的默认间隔,如果实际间隔大于此间隔,则同步该次时间。

 

同步判断条件

if ((mSavedAtTime == 0) || (timeSinceLastUpdate > nitzUpdateSpacing)
                            || (Math.abs(gained) > nitzUpdateDiff)) {
                        Log.i(LOG_TAG, "NITZ: Auto updating time of day to " + c.getTime()
                                + " NITZ receive delay=" + millisSinceNitzReceived
                                + "ms gained=" + gained + "ms from " + nitz);

                        setAndBroadcastNetworkSetTime(c.getTimeInMillis());

} else {
                        Log.i(LOG_TAG, "NITZ: ignore, a previous update was "
                                + timeSinceLastUpdate + "ms ago and gained=" + gained + "ms");
                        return;
}

 

另,上层Setting App中,DateTimeSetting设置了AutoTime is True,则CdmaServiceStateTracker和GsmServiceStateTracker的监听,根据当前

if (mSavedTimeZone != null && mSavedTime != 0 && mSavedAtTime != 0) {
            setAndBroadcastNetworkSetTimeZone(mSavedTimeZone);
            setAndBroadcastNetworkSetTime(mSavedTime
                    + (SystemClock.elapsedRealtime() - mSavedAtTime));
}

广播时间和Time Zone


Android 时间更新机制之网络更新时间

综述:Android网络时间更新,大体分两类。1、moderm相关更新,2、网络更新。本次主要介绍android设备网路时间同步。...
  • hailushijie
  • hailushijie
  • 2015年05月13日 22:36
  • 3409

Android网络时间同步

转自 http://blog.csdn.net/shy1987shy/article/details/22822995 起因:有时候android盒子起来了,半天都没有获取到时...
  • skykingf
  • skykingf
  • 2016年01月13日 15:26
  • 2056

Android 同步网络时间

android 网络时间同步
  • autumn_xl
  • autumn_xl
  • 2016年05月25日 17:10
  • 4715

Android时间同步流程

对时概述 Android的自动对时有好几种,基本的是通过ntp网络服务器对时和通过手机sim卡运营商网络对时,国内如果是电信cdma手机的话,按照运营商需求是强制通过第二种对时的,手机设置中不可选择取...
  • firedancer0089
  • firedancer0089
  • 2017年03月02日 15:30
  • 886

Linux同步网络时间

Linux服务器运行久时,系统时间就会存在一定的误差,一般情况下可以使用date命令进行时间设置,但在做数据库集群分片等操作时对多台机器的时间差是有要求的,此时就需要使用ntpdate进行时间同步 ...
  • weiyuefei
  • weiyuefei
  • 2017年05月10日 09:07
  • 3427

android-获取网络时间、获取特定时区时间、时间同步的方法

最近整理出android-获取网络时间、获取特定时区时间、时间同步的方法。具体如下: 方法一: ? 1 2 3 Simple...
  • u010083695
  • u010083695
  • 2017年04月20日 13:51
  • 999

嵌入式linux自动更新网络时间NTP移植

有些嵌入式设备中为了节省成本或者体积原因都没有配备掉电保存电池,每次上电之后就需要人为手动的更新系统时间,而且系统时间也不准确。有些需要得到实时的比较准确的时间,以和服务器或是设备之间进行时间同步,但...
  • andylauren
  • andylauren
  • 2016年12月05日 22:50
  • 1364

CentOS设置系统时间与网络时间同步

Linux的时间分为System Clock(系统时间)和Real Time Clock (硬件时间,简称RTC)。 系统时间:指当前Linux Kernel中的时间。 硬件时间:主板上有电池供电...
  • u011391839
  • u011391839
  • 2017年03月17日 17:08
  • 7516

获取网络时间(即获取网络时间同步服务器的时间)

要获取
  • wwkaven
  • wwkaven
  • 2014年06月21日 14:07
  • 7666

Linux ntpdate同步网络时间

自己的Linux服务器的时间和PC机上的时间不太对,打log的时间对不上,不太方便调式信息的判断,因此需要同步一下Linux服务器的时间和自己Windows的时间,两者一致,才方便调式的查看呢。 ...
  • u013207877
  • u013207877
  • 2016年09月22日 20:15
  • 3751
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Android中的网络时间同步
举报原因:
原因补充:

(最多只允许输入30个字)