Android中的网络时间同步

http://blog.csdn.net/absurd/archive/2011/01/09/6125588.aspx
在 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
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值