Android 校正系统时间的三种解决方案

前言

在开发过程中我们常常需要获取系统时间。
Android系统的自动确认时间,是由系统通过访问厂家的NTP服务器的时间,然后修改后得到的。
所以当没有网络或者在内网环境下的时候,系统无法访问到NTP服务器,便会造成系统时间错误。
所以这个时候我们就需要程序去修改系统的时间,或者获取一个正确的时间来代替系统时间。

NTP服务器

【Network Time Protocol(NTP)】是用来使计算机时间同步化的一种协议,它可以使计算机对其服务器或时钟源(如石英钟,GPS等等)做同步化,它可以提供高精准度的时间校正(LAN上与标准间差小于1毫秒,WAN上几十毫秒),且可介由加密确认的方式来防止恶毒的协议攻击。时间按NTP服务器的等级传播。按照离外部UTC源的远近把所有服务器归入不同的Stratum(层)中。

解决方案

根据不同的情况,我实现了如下三种解决方案:

  1. 修改系统时间。
    优点:程序启动时执行一次即可,一劳永逸。
    缺点:只能在原生系统中使用,非原生系统无法安装。(具体后面会解释)。

  2. 获取NTP服务器时间代替系统时间。
    优点:无需Root,适用于任何手机及系统。
    缺点:需要可以访问外部网络,内网环境下则需要一台自己的NTP服务器。

  3. 获取网页时间代替系统时间。
    优点:无需Root,适用于任何手机及系统,适用于任何网络环境。
    缺点:需要一条额外的线程,去维护时间准确,容易造成误差。

代码及目录

GitHub: https://github.com/Demo-DeMon/ChangeTime

这里写图片描述

1.修改系统时间

1.配置系统JDK环境变量

这个就不细说了,自行百度。
由于签名工具用到的sun.misc.BASE64Encoder类已从Java SE 9中删除。所以只能在Java 1.8及以下环境下使用。
具体可以查看:JDK从1.8升级到9.0.1后sun.misc.BASE64Decoder和sun.misc.BASE64Encoder不可用

2.修改系统时间,一行代码如下:

SystemClock.setCurrentTimeMillis(long millis);
   
   
   
   

    3.修改AndroidManifest.xml

    在应用程序的AndroidManifest.xml中的manifest节点中加入android:sharedUserId=”android.uid.system”这个属性。
    添加该属性后,由于权限冲突,程序无法直接安装,必须重新签名。

    
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
         package="com.demon.setsystemtime"
        android:sharedUserId="android.uid.system"  >
    manifest>

    4.编译apk,重新签名

    Android Studio编译生成apk,然后将apk复制到上述目录的sign文件夹(重新签名的文件夹)下,将apk的名字与bat脚本中的一致。
    用压缩软件打开apk文件,删掉META-INF目录下的CERT.SF和CERT.RSA两个文件。
    双击运行bat脚本,脚本代码如下:

    @echo off
    java -jar signapk.jar platform.x509.pem platform.pk8 demo.apk test.apk
    pause
    

    signapk.jar: Android提供的签名工具。
    platform.x509.pem&platform.pk8: Android源码目录中”build/target/product/security”,下面的两个文件。
    demo.apk:程序编译生成的apk。
    test.apk:重新签名后的apk。

    这也有一个问题,就是这样生成的程序只有在原始的Android系统或者是自己编译的系统中才可以用,因为这样的系统才可以拿到platform.pk8和platform.x509.pem两个文件。要是别家公司做的Android上连安装都安装不了。

    安装重新签名的apk,运行即可修改系统时间。

    二、获取NTP服务器时间代替系统时间

    直接使用truetime-android框架即可同步NTP服务器时间,调取框架内的方法便可以实时获取最新时间。
    GitHub:https://github.com/instacart/truetime-android
    具体的使用可以参考代码,或者GitHub文档。

    ### 阿里云提供了7个NTP服务器
    ntp1.aliyun.com
    ntp2.aliyun.com
    ntp3.aliyun.com
    ntp4.aliyun.com
    ntp5.aliyun.com
    ntp6.aliyun.com
    ntp7.aliyun.com
    
    
    ### 中国科学技术大学NTP服务器
    time.ustc.edu.cn
    

    三、获取网页时间代替系统时间

    根据下列代码,我们就可以获取任何一个网址的时间(内网服务器地址)。
    拿到这个时间后,可以开启一个线程,做定时任务,不断更新该时间,以到达时间时间同步的效果。
    具体实现方法不再阐述。

    /**
         * 网址访问
         * @param url  网址
         * @return urlDate 对象网址时间
         */
        public static String VisitURL(String url){
            String urlDate = null;
            try {
                URL url1 = new URL(url);
                URLConnection  conn = url1.openConnection();  //生成连接对象
                conn.connect();  //连接对象网页
                Date date = new Date(conn.getDate());  //获取对象网址时间
                SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  //设置日期格式
                urlDate = df.format(date);
            } catch (Exception e) {
                e.printStackTrace();
            }
            return urlDate;
        }
    
    

    效果

    这里写图片描述

    参考

    http://www.programgo.com/article/54422482620/

    文章来源

    https://blog.csdn.net/DeMonliuhui/article/details/82226601/

    你可能感兴趣的:(Android,笔记相关,android,系统时间)