开发app时发现APP显示的时间不准,或者说APP时间与服务器时间不一致,会导致数据请求、数据显示等各种问题。这时候我们就需要一种机制来解决时间不一致的问题。
第一个解决方法:
- 服务器端永远使用UTC时间,包括参数和返回值,不要使用Date格式,而是使用UTC时间1970年1月1日的差值,即long类型的长整数。
- APP端将服务器返回的long型时间转换为GMT8时区的时间,额外加上8小时,这样就保证了无论使用者在哪个时区,他们看到的时间都是同一个时间,也就是GMT8的时间。
- APP本地时间会不准,少则差几分钟,多则十几分钟,要解决这个问题,我们可以使用HTTP Response头的Date属性,每次调用服务器接口时就取出HTTP Response头的Date值,转换为GMT时间,再减去本地取出的时间,得到一个差值d,我们将这个差值d保存下来。每次获取本地时间的时候,额外加上这个差值d,就得到了服务器的GMT8时间,就保证了任何人看见的时间都是一样的。
public static void getServerTimeDelta(Header header){ if (header != null) { String strServerDate = header.getValue(); 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); delta = serverDate.getTime()-System.currentTimeMillis(); } catch (ParseException e) { e.printStackTrace(); } catch (java.text.ParseException e) { e.printStackTrace(); } } } }
使用时加上差值:
Date serverTime = new Date(System.currentTimeMillis()+<span style="font-family: 'microsoft yahei';">delta</span>);
但这个解决办法有几个问题:
1、用户使用过程中修改了时间,这时就坑了,时间完全不正确了
2、server时间到客户端交互需要时间,最后换算出的时间也不是非常准确
第二种解决办法:
使用第一种方法时,用户修改了手机本地的时间,时间肯定会出错,这种情况确实比较坑爹。但是Android还比较友好,就是如果用户修改了时间和修改了时区都会发广播,我们可以 设置一个receiver来监听几个广播,然后重新设置服务器时间。
Intent.ACTION_TIME_CHANGED Intent.ACTION_DATE_CHANGED
但是因为这个广播就算有了,我们也不知道用户修改了多少时间,除非重新去服务器拉取服务器 时间,但是在服务器拉取失败或者在服务器拉取时间的这个请求内需要使用服务器时间的情况处 理就比较麻烦了。
其实我们弄这么多,这么复杂其实只是需要知道手机本地当前时间与设置服务器时间的时候的绝对的时间差。
使用SystemClock.elapsedRealtime() :Returns milliseconds since boot, including time spent in sleep. 同步服务端时间
public static void getServerTimeDelta(ResponseInfo<String> responseInfo){ if (responseInfo != null) { Header headers = responseInfo.getFirstHeader("Date"); String strServerDate = headers.getValue(); 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); GeexekApplication.ResponseTime = serverDate.getTime(); GeexekApplication.ResponseCurrentTime =SystemClock.elapsedRealtime(); }catch(Exception exception){ exception.printStackTrace(); } } } }
获取当前时间:long currentMilliseconds = GeexekApplication.ResponseTime + SystemClock.elapsedRealtime()-GeexekApplication.ResponseCurrentTime;
评论:这种方法计较准确,本人就选择了这种办法。
相关文章: