Android : 基于公网IP和第三方数据库进行时区自动同步
一、前言
电子移动设备在区域变更时需要根据地区坐标进行时间、时区的同步,目前普遍使用的手机可以利用网络同步时间,进一步通过运营商信息、GPS等获取位置信息来进行时区同步。而有的电子设备,如:智能TV、教育机 虽然可以联网,但没有GPS模块,无法获取位置信息,只能手动设置时区。
本文介绍一种通过第三方服务器获取公网IP和数据库查询进行时区定位及自动更新的方法。
二、公网IP获取
通过HttpURL访问某些企业服务器,如:
"http://pv.sohu.com/cityjson",
"http://pv.sohu.com/cityjson?ie=utf-8",
"http://ip.chinaz.com/getip.aspx",
Android Java代码参考如下:
1.获取公网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"
ip2region.db 已上传到百度:
链接:https://pan.baidu.com/s/1sO9zcjJTzrvvFILquPLzzQ
提取码:lqed
/** * 解析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();
}
获取结果如下:
定位城市后可以通过主要城市对照列表进行时区转换和设定。
posted on 2020-09-07 17:08 sheldon_blogs 阅读(921) 评论(0) 编辑 收藏 举报