Android : 基於公網IP和第三方資料庫進行時區自動同步
阿新 • • 發佈:2020-09-07
一、前言
電子移動裝置在區域變更時需要根據地區座標進行時間、時區的同步,目前普遍使用的手機可以利用網路同步時間,進一步通過運營商資訊、GPS等獲取位置資訊來進行時區同步。而有的電子裝置,如:智慧TV、教育機 雖然可以聯網,但沒有GPS模組,無法獲取位置資訊,只能手動設定時區。
本文介紹一種通過第三方伺服器獲取公網IP和資料庫查詢進行時區定位及自動更新。
二、公網IP獲取
通過HttpURL訪問某些企業伺服器,如:
String[] platforms = {
"http://pv.sohu.com/cityjson",
"http://pv.sohu.com/cityjson?ie=utf-8",
};
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();
}