Android时区问题

       最近做外销机,在实现设置时区的功能中,遇到了一些问题,特此记录。

       1,如何获取到时区列表?如何设置时区?

       2,默认时区怎么设置?

       3,自动时区是怎么回事?

      一,设置时区问题 

      首先我们看一下android的原生设置中的逻辑,代码位置在原生设置setting中的com.android.tv.settings.system.DateTimeActivity.java中。在这个类中,很容易找到其中的setTimeZone方法。而其中的alarm.setTimeZone(tzId);正是设置时区的关键代码,其中tzId是String类型的,其实就是时区id。

时区示例:(

//    KEY_DISPLAYNAME 中国标准时间

//    KEY_OFFSET 28800000

//    KEY_ID Asia/Shanghai

//    KEY_GMT GMT+08:00)

       很好,设置时区的关键方法有了,但是如何获取时区列表?如何获取到时区名称和时区ID(tzId)之间的关系呢?在DateTimeActivity.java中继续查找。

mTimeZones = ZoneGetter.getZonesList(this);

其中:private List<Map<String, Object>> mTimeZones;

我们继续进行,找到ZoneGetter的文件位置。

./frameworks/base/packages/SettingsLib/src/com/android/settingslib/datetime/ZoneGetter.java. 通过查找其对应的mk文件(./frameworks/base/packages/SettingsLib/Android.mk),我们知道对应的LOCAL_MODULE := SettingsLib. 它对应的编译后jar位置是:out/target/common/obj/JAVA_LIBRARIES/SettingsLib_intermediates。

       但是如果直接将这个jar包导入到AndroidStudio中,由于在ZoneGetter.java有依赖R,import com.android.settingslib.R; 而jar中是不包含资源文件R的,虽然编译能过,但是运行时报如下错误,这个跟之前eclipse直接集成带有资源的jar包一样的错误,比如很多初学者在第一次使用Recycleview的时候会直接导入它的jar,而不做模块依赖。

 Caused by: java.lang.ClassNotFoundException: Didn't find class "com.android.settingslib.R$xml" on path:DexPathList[[。。。。。。

        分析代码发现,这里的R正是为了获取时区列表:

context.getResources().getXml(R.xml.timezones). 似乎Android并未为我们提供一种很方便的方式,将资源文件一起打包进来。无非就是再AndroidStudio中新建一个Module,在这个Module中导入jar包和对应的xml,在我们主工程中依赖这个Module。

         这里我们用另一种更加简单的方案解决此问题,观察发现,ZoneGetter.java这个类import的包除了java,android的以外,还有一个特别的,那就是import libcore.icu.TimeZoneNames;这个类的位置:./libcore/luni/src/main/java/libcore/icu/TimeZoneNames.java. 同样的方法,找到其mk文件(./libcore/JavaLibrary.mk)。找到对应的Module名字。

它编译后对应的jar包是:out/target/common/obj/JAVA_LIBRARIES/core-libart_intermediates。经过上面的分析,问题的最终解决方案如下:

步骤1:将libcore的jar包导入到AndroidStudio中,导入方式为CompileOnly;

步骤2:将xml(frameworks/base/packages/SettingsLib/res/xml/timezones.xml)拷贝到自己工程,如需要定制可修改。

步骤3:将ZoneGetter.java直接拷贝到自己的工程,修改packagename和R的依赖即可。

二,设置默认时区

        这就比较简单了,只是设置一个系统属性即可,可以在机型的device.mk(比如device/mstar/synsepalum/device.mk)中设置。

 

三,自动时区是怎么回事?

1,先简单介绍一下自动时间问题:

       Android的时间更新分成2种,一种是走运营商协议的NITZ,另外一种是走网络时钟的SNTP。 SNTP是简单网络时间协议(Simple Network Time protocol)的简称。 

       在Android系统中,Settings->Date & time->Automatic项打上后,时间会通过网络进行同步,而Android默认使用的是NITZ来获取移动网络时间,需要有移动网络服务商的支持才能使用,而有些Android产品只支持WIFI等无线网络,而不支持移动网络,此时就需要采用SNTP方式来获取网络时间进行同步了。

        当不支持NITZ获取时间同步时就使用SNTP方式获取时间进行同步。不过使用SNTP方式进行时间同步时不能同步时区(后面我们会重点关注这一点),需要自己先去掉自动同步并设置时区后再设置自动同步,这样才能进行网络时间的同步更新。

        2,NITZ:NetworkIdentityandTimeZone(网络标识和时区) 依赖基站发出的消息的回调更新时间。

        NITZ更新时间依赖运营商,当运营商基站发出更新时间的消息,基站附近的手机接收到对应消息后,会通过RIL层上报UNSOL_NITZ_TIME_RECEIVED事件,此时ServiceStateTracker便会处理相关时间更新流程。

由于NITZ主要依赖于运营商,但在国内移动和联通貌似不怎么好用,在这里就不在详细说了,简单总结下如下:1、在ServiceStateTracker构造方法里调用setOnNITZTime注册RIL事件RIL_UNSOL_NITZ_TIME_RECEIVED2、RIL层上报RIL_UNSOL_NITZ_TIME_RECEIVED,在ServiceStateTracker的handleMessage里处理3、调用ServiceStateTracker的setTimeFromNITZString设置时间和时区,在setAndBroadcastNetworkSetTime里调用setCurrentTimeMillis设置系统时间,并发送广播通知NetworkTimeUpdateService。

        3,SNTP:(Simple Network Time protocol) 

   相关的类有下面几个,这里简单介绍一下,深入了解还是需要看代码:

其中:NetworkTimeUpdateService.java 这是控制时间的逻辑,设计时间更新的策略,机制等等。

 NteTrustedTime.java这里封装了几个方法比如foreceRefresh给NetworkTimeUpdateService调用。

 SntpClient.java是实际的与网络交互的类,这个类可以单独拿出来跑。

 通过Settings.java, DatabaseHelper.java Config.xml找到了服务器地址等,服务器等的配置再Config.xml中:

自己写demo打印了时间的数据返回值如下类型是byte[] ,从中能解析出时间出来。

Arrays.toString(buffer):

12-11 07:49:42.061 3640-3686/com.xgimi.home D/SntpClient: buffer = [28, 2, 0, -24, 0, 0, 0, 10, 0, 0, 0, 69, 10, -119, 53, 7, -31, -101, 1, -56, 107, 119, 35, -59, -31, -101, 1, -10, 1, 71, -82, 73, -31, -101, 1, -10, 8, -100, 90, 31, -31, -101, 1, -10, 8, -96, 62, 11]

12-11 07:49:42.061 3640-3686/com.xgimi.home D/SntpClient: mNtpTime = 1576043382061        mNtpTimeReference = 209944         mRoundTripTime = 56

       4,AUTO_TIME_ZONE是否只在NITZ下面有效?

       在SNTP的相关文档中没有找到能够更新时区的相关代码,我们猜测时区无法通过SNTP更新。从上面NTP返回的数据来看,也确实是不包括时区信息的。

我们在Setting中找到了下面的代码:

这里特别标明了NITZ,是否也暗示了只有NITZ方式能够获取到时区。

为了验证我的猜测,用手机做了一些实现:

a,魅族note2,打开飞行模式,时间时区调错乱;

b,连接wifi的瞬间自动校时,但是无法自动设置时区,;

c,关闭飞行模式的瞬间,时区立即校准。

d,插拔sim2卡测试。sim在即可更新时区,sim卡不在就不能更新时区。

        这可能是某个规范或者标准,Android目前不能通过SNTP更新时区。我目前在Android6上做的这些工作,或许后面能够更新也未可知。总之,目前来说,如果是电视机型开发,无法插入sim卡,就不会有自动时区的功能。

  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
### 回答1: Android时区列表是由操作系统提供的,用于设置设备当前所在时区的功能。Android操作系统提供了一个包含世界各地主要城市的时区列表。用户可以根据自己的所在位置或需要选择合适的时区Android时区列表包含了全球大多数的时区,包括主要的城市和国家。用户可以通过进入设备的设置界面,打开日期和时间设置,然后选择时区选项来修改设备的当前时区Android时区列表不仅可以根据用户选择的城市或国家自动调整时间,还可以根据夏令时的变化自动调整时间。Android会根据全球各地的夏令时规则来自动更新时区信息,确保设备的时间始终准确。 时区列表还可以帮助用户在不同的时区之间快速切换,例如当用户出差或旅行到不同的国家或地区时,可以根据目的地的时区设置来调整设备时间。 总之,Android时区列表是为了方便用户设置设备的当前时区而提供的功能。它可以根据用户选择的城市或国家自动调整时间,也可以根据夏令时的变化自动更新时区信息,确保设备时间的准确性。 ### 回答2: Android系统提供了一个完整的时区列表,用于方便设置设备的时区时区是用来标识地理区域在时间上的差异,不同国家和地区有不同的时区,主要影响到了常用的时间显示、日期计算和日历功能等。 Android时区列表包括世界上所有主要的国家和地区,以及它们的主要城市。用户可以通过进入设备的设置界面,在日期和时间设置中进行时区的选择和修改。在选择时区时,Android会根据用户所在的地理位置以及设备的网络连接情况,提供一个默认的时区选项,用户还可以手动滚动列表,查找并选择他们所在的国家或地理位置来进行时区的设置。 Android时区列表是按照国家和地区的字母顺序排列的。用户可以根据他们所在的国家或地区的名称来查找并选择相应的时区。例如,如果用户位于中国,则可以选择“中国标准时间”,如果用户位于美国纽约,则可以选择“美国东部时间”。 时区列表中的每个时区都有一个标准时间和可能的夏令时时间,用户可以根据自己所在的地理位置来选择合适的时区。在选择并设置好时区后,设备上的时间将会根据选择的时区自动调整,并确保显示的时间是准确的。 总之,Android提供了一个全面的时区列表,用户可以根据自己所在的国家或地区,选择合适的时区来设置设备的时间,确保时间的显示和计算准确无误。 ### 回答3: Android时区列表是一组标准的时区名称和偏移量,用于在Android设备上设置和调整时间。Android时区列表是根据世界各个地区的时差和夏令时政策而形成的。 Android时区列表中包含了全球的各个时区,从东至西覆盖了大部分地球表面。例如,亚洲地区的时区有北京时间、东京时间等;欧洲地区的时区有伦敦时间、柏林时间等;美洲地区的时区有纽约时间、洛杉矶时间等。 在Android设备上,可以根据所在地区和时区的选择来设置时间显示方式。例如,如果用户位于北京,就可以选择北京时间,这样设备上的时间就会自动根据北京时间进行调整。此外,Android还提供了自动时间和时区选项,可以通过与移动网络或GPS连接来自动获取设备所在地的时区信息。 Android时区列表不仅可以用于设置设备上的时间显示,还可以在开发应用程序时使用。开发者可以借助Android提供的时区列表来实现在不同时区下正确显示和处理时间相关的功能。 总之,Android时区列表是一组标准的时区名称和偏移量,用于在Android设备上设置和调整时间,涵盖了全球各个地区,方便用户选择所在地的时区,并可以在开发应用程序时使用。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值