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”這個屬性。
    添加該屬性後,由於權限衝突,程序無法直接安裝,必須重新簽名。

    <?xml version="1.0" encoding="utf-8"?>
    <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/

    發表評論
    所有評論
    還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
    相關文章