【声明:】本文是作者(蘑菇v5)原创,版权归作者 蘑菇v5所有,侵权必究。本文首发在简书。如若转发,请注明作者和来源地址!未经授权,严禁私自转载!
在项目的开发过程中,项目要求无论终端是什么时区设置、地处何方,终端的时间是否正确,终端的时间始终要求与服务器同步,也就是说,用户买来一部新手机、新平板,不做任何日期时间、时区方面的设置,装了App
就显示当前时间。
原理:
现在服务器时间 = 以前服务器时间 + 现在手机开机时间 – 以前服务器时间的获取时刻的手机开机时间
开始之前,先认识两个时间,分别是System.currentTimeMillis()
和SystemClock.elapsedRealtime()
。System.currentTimeMillis()
获取的是系统时间,是距离1970
年1
月1
日开始计算的一个值。获取当前日期,如当前是xxxx
年xx
月xx
时xx
分xx
秒xxx
毫秒,这个值在系统设置中可以更改的。
而SystemClock.elapsedRealtime()
获取从设备boot
后经历的时间值,是系统从启动到现在的时间(包含休眠时间),这个值在系统设置中是不可以被更改的。
思路:
使用elapsedRealtime
同步服务端时间,就是说在必要的时刻获取一下服务器时间,然后记录这个时刻的手机开机时间(elapsedRealtime)
,两者作差,获取到设置服务器时间的时候与手机本地当前elapsedRealtime
的绝对的时间差。即获取到的服务器时间- 当时手机的elapsedRealtime
。 这个差值是固定的,只要请求一次服务器接口后,就可以根据本地时间推算出服务器时间,实现本地时间与服务器时间同步。
代码如下:
/**
* 获取服务器时间
* @param response
*/
public static void getServerTimeDelta(Response response){
if (response != null) {
Headers headers = response.headers();
String strServerDate = headers.get("Date");
if (!TextUtils.isEmpty(strServerDate)){
//Thu, 29 Sep 2016 07:57:42 GMT
final SimpleDateFormat simpleDateFormat = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss z",
Locale.ENGLISH);
TimeZone.setDefault(TimeZone.getTimeZone("GMT+8"));
try {
Date serverDate = simpleDateFormat.parse(strServerDate);
//在必要的时刻获取一下服务器时间
MyApplication.ResponseTime = serverDate.getTime();
//记录这个时刻的手机开机时间
MyApplication.ResponseCurrentTime = SystemClock.elapsedRealtime();
}catch(Exception exception){
exception.printStackTrace();
}
}
}
}
获取当前时间:
//获取当前手机时间,即远程服务器的时间
long currentTime = MyApplication.ResponseTime + SystemClock.elapsedRealtime()
-MyApplication.ResponseCurrentTime;
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String dateString = formatter.format(currentTime);
效果如下:
- 第一次请求到的服务器时间:
第一次请求到的服务器时间
- 故意手机调错后,获取的手机本地时间,和获取的同步的服务器时间format
手机调错后,获取的手机本地时间
- 两分钟后,效果依旧。
两分钟后,效果依旧