1. 程式人生 > 實用技巧 >Android : 基於公網IP和第三方資料庫進行時區自動同步

Android : 基於公網IP和第三方資料庫進行時區自動同步

一、前言

  電子移動裝置在區域變更時需要根據地區座標進行時間、時區的同步,目前普遍使用的手機可以利用網路同步時間,進一步通過運營商資訊、GPS等獲取位置資訊來進行時區同步。而有的電子裝置,如:智慧TV、教育機 雖然可以聯網,但沒有GPS模組,無法獲取位置資訊,只能手動設定時區。

  本文介紹一種通過第三方伺服器獲取公網IP和資料庫查詢進行時區定位及自動更新。

二、公網IP獲取

  通過HttpURL訪問某些企業伺服器,如:

  String[] platforms = {
    "http://pv.sohu.com/cityjson",
    "http://pv.sohu.com/cityjson?ie=utf-8",

    "http://ip.chinaz.com/getip.aspx",
  };

 1.Android Java程式碼 - 獲取公網IP

   String[] platforms = {
            "http://pv.sohu.com/cityjson",
            "http://pv.sohu.com/cityjson?ie=utf-8",
            "http://ip.chinaz.com/getip.aspx",
    };
private String getOutNetIP(Context context, int index) {
        
if (index < platforms.length) { BufferedReader buff = null; HttpURLConnection urlConnection = null; try { URL url = new URL(platforms[index]); urlConnection = (HttpURLConnection) url.openConnection(); urlConnection.setRequestMethod(
"GET"); urlConnection.setReadTimeout(5000);//讀取超時 urlConnection.setConnectTimeout(5000);//連線超時 urlConnection.setDoInput(true); urlConnection.setUseCaches(false); int responseCode = urlConnection.getResponseCode(); if (responseCode == HttpURLConnection.HTTP_OK) {//找到伺服器的情況下,可能還會找到別的網站返回html格式的資料 InputStream is = urlConnection.getInputStream(); buff = new BufferedReader(new InputStreamReader(is, "UTF-8"));//注意編碼,會出現亂碼 StringBuilder builder = new StringBuilder(); String line = null; while ((line = buff.readLine()) != null) { PlatformLogUtil.at(TAG, "line : " + line); builder.append(line); } buff.close();//內部會關閉 InputStream urlConnection.disconnect(); Log.e(TAG, builder.toString()); if (index == 0 || index == 1) { //擷取字串 int satrtIndex = builder.indexOf("{");//包含[ int endIndex = builder.indexOf("}");//包含] String json = builder.substring(satrtIndex, endIndex + 1);//包含[satrtIndex,endIndex) JSONObject jo = new JSONObject(json); String ip = jo.getString("cip"); return ip; } else if (index == 2) { JSONObject jo = new JSONObject(builder.toString()); return jo.getString("ip"); } } } catch (Exception e) { e.printStackTrace(); } } return getOutNetIP(context, ++index); } 

 2.Linux下通過curl 指令可以直接網址獲取公網IP資訊

curl icanhazip.com
curl http://pv.sohu.com/cityjson?ie=utf-8

三、通過ip2region(IP地址定位庫)進行查詢

  ip2region是第三方準確率99.9%的離線庫,體積小隻有幾MB,在國內可以準確定位到城市及運營商資訊,通過客製化存放到系統目錄,如"/data/system/ip2region.db"

   /**
     * 解析Ip地址工具類,傳入IP地址,返回省、市、城市、執行商,以\t分割
     */
    private String parseIP(String ip) {
        String result = "";
        // 關聯下載的id2region.db 離線庫
        String dbFile = "/data/system/ip2region.db";
        try {
            DbSearcher search = new DbSearcher(new DbConfig(), dbFile);
            // 傳入ip進行解析
            DataBlock dataBlock = search.btreeSearch(ip);
            // 獲取解析後的資料  
            
            String region = dataBlock.getRegion();
            Log.d(TAG, "region : " + region);
            String replace = region.replace("|", ",");
            String[] splits = replace.split(",");
            if (splits.length == 5) {
                String country = splits[0];
                String province = splits[2];
                String city = splits[3];
                String operator = splits[4];
                // 拼接資料
                result = country + "\t" + province + "\t" + city + "\t" + operator;
            }
            return result;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

  Ip2region專案詳細參考https://gitee.com/lionsoul/ip2region

  注:Android 4.0 之後不能在主執行緒中請求HTTP請求,需要放到子執行緒中:
    try {
        new Thread(new Runnable(){
            @Override
            public void run() {
                String curIp = getOutNetIP(mContext,1);
                String region = parseIP(curIp);
                Log.d(TAG, "IP :" + curIp + " | 地區: " + region);
                Toast.makeText(mContext, "IP :" + curIp +" | 地區: " + region, Toast.LENGTH_SHORT).show();
            }
        }).start();
    } catch (RemoteException e) {
        e.printStackTrace();
    }