在做一个电商项目过程中,需要获取设备地理信息,包括经纬度定位,附近地址等,于是写了一个工具类方便使用。
1.在使用百度地图API使,首先要获取官方授权,在http://lbsyun.baidu.com/index.php?title=androidsdk页面获取秘钥,然后按照要求申请即可,需要手机和百度账号及邮箱认证。激活后可看到后台页面,现在可以开始创建应用了,这里请求校验方式有两种,一种是白名单IP,另一种是SN校验(旁边有计算的说明),我选择SN校验:
**
* Description:获取百度地理编码的sn的工具类
**/
public class BaiDuGeocodingSnCalUtil {
private static final String HEADER = "/geocoder/v2/?";
public static String getSnCalString(String paramsStr) {
String tempStr = null;
try {
// 对paramsStr前面拼接上/geocoder/v2/?,后面直接拼接yoursk得到/geocoder/v2/?address=%E7%99%BE%E5%BA%A6%E5%A4%A7%E5%8E%A6&output=json&ak=yourakyoursk
String wholeStr = HEADER + paramsStr + Constants.BaiDu.SK;
// 对上面wholeStr再作utf8编码
tempStr = URLEncoder.encode(wholeStr, Constants.UTF_8);
tempStr = MD5(tempStr);
} catch (Exception e) {
Logger.debug(e.getMessage());
}
return tempStr;
}
/**
* 对Map内所有value作utf8编码,拼接返回结果
*/
public static String toQueryString(Map<?, ?> data)
throws UnsupportedEncodingException {
StringBuilder queryString = new StringBuilder();
for (Map.Entry<?, ?> pair : data.entrySet()) {
queryString.append(pair.getKey());
queryString.append("=");
queryString.append(URLEncoder.encode((String) pair.getValue(), Constants.UTF_8));
queryString.append("&");
}
if (queryString.length() > 0) {
queryString.deleteCharAt(queryString.length() - 1);
}
return queryString.toString();
}
/**
* 来自stackoverflow的MD5计算方法,调用了MessageDigest库函数,并把byte数组结果转换成16进制
*/
public static String MD5(String md5) {
try {
java.security.MessageDigest md = java.security.MessageDigest
.getInstance("MD5");
byte[] array = md.digest(md5.getBytes());
StringBuilder sb = new StringBuilder();
for (int i = 0; i < array.length; ++i) {
sb.append(Integer.toHexString((array[i] & 0xFF) | 0x100)
.substring(1, 3));
}
return sb.toString();
} catch (java.security.NoSuchAlgorithmException e) {
Logger.debug(e.getMessage());
}
return null;
}
}
public class SimulationRequestUtil {
public static final int SUCCESS = 200;
private SimulationRequestUtil() {
}
/**
* get请求
*
* @param url 请求路径
* @return 返回参数
*/
public static String doGet(String url) {
CloseableHttpClient client = null;
try {
client = HttpClients.createDefault();
//发送get请求
HttpResponse response = client.execute(new HttpGet(url));
//请求发送成功,并得到响应
if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
//读取服务器返回过来的json字符串数据
return EntityUtils.toString(response.getEntity());
}
} catch (IOException e) {
Logger.warn(e.getMessage());
} finally {
if (client != null) {
try {
client.close();
} catch (Exception e) {
Logger.warn(e.getMessage());
}
}
}
return null;
}
/**
* post请求(用于key-value格式的参数)
*
* @param url 请求路径
* @param params 参数
* @return 返回数据
*/
@SuppressWarnings("unchecked")
public static String doPost(String url, Map params) {
CloseableHttpClient client = null;
BufferedReader in = null;
try {
// 定义HttpClient
client = HttpClients.createDefault();
// 实例化HTTP方法
HttpPost request = new HttpPost();
request.setURI(new URI(url));
//设置参数
List<NameValuePair> nvps = new ArrayList<>();
for (Iterator<Map.Entry<Object, Object>> iterator = params.entrySet().iterator(); iterator.hasNext();) {
Map.Entry<Object, Object> entry = iterator.next();
String name = (String) entry.getKey();
String value = String.valueOf(entry.getValue());
nvps.add(new BasicNameValuePair(name, value));
}
request.setEntity(new UrlEncodedFormEntity(nvps, StandardCharsets.UTF_8));
HttpResponse response = client.execute(request);
int code = response.getStatusLine().getStatusCode();
if (code == SUCCESS) {
//请求成功
in = new BufferedReader(new InputStreamReader(response.getEntity()
.getContent(), StandardCharsets.UTF_8));
StringBuilder sb = new StringBuilder();
String line = "";
String nl = System.getProperty("line.separator");
while ((line = in.readLine()) != null) {
sb.append(line);
sb.append(nl);
}
return sb.toString();
} else {
return null;
}
} catch (Exception e) {
Logger.warn(e.getMessage());
return null;
} finally {
if (in != null) {
try {
in.close();
} catch (Exception e) {
Logger.warn(e.getMessage());
}
}
if (client != null) {
try {
client.close();
} catch (Exception e) {
Logger.warn(e.getMessage());
}
}
}
}
/**
* post请求(用于请求json格式的参数)
*
* @param url 请求路径
* @param params 参数
* @return 返回数据
*/
public static String doPost(String url, String params) throws Exception {
CloseableHttpClient httpclient = HttpClients.createDefault();
// 创建httpPost
HttpPost httpPost = new HttpPost(url);
httpPost.setHeader("Accept", "application/json");
httpPost.setHeader("Content-Type", "application/json");
String charSet = "UTF-8";
StringEntity entity = new StringEntity(params, charSet);
httpPost.setEntity(entity);
CloseableHttpResponse response = null;
try {
response = httpclient.execute(httpPost);
StatusLine status = response.getStatusLine();
int state = status.getStatusCode();
if (state == HttpStatus.SC_OK) {
HttpEntity responseEntity = response.getEntity();
return EntityUtils.toString(responseEntity);
} else {
Logger.warn("请求返回:" + state + "(" + url + ")");
}
} finally {
if (response != null) {
try {
response.close();
} catch (IOException e) {
Logger.warn(e.getMessage());
}
}
try {
httpclient.close();
} catch (IOException e) {
Logger.warn(e.getMessage());
}
}
return null;
}
}
2.准备就绪之后就是最重要的就是访问api接口获取想要的信息,可根据官方文档调整参数,http://lbsyun.baidu.com/index.php?title=webapi/guide/webservice-geocoding
public class CityLatitudeAndLongitudeUtil {
private static double EARTH_RADIUS = 6371.393;
private static double rad(double d) {
return d * Math.PI / 180.0;
}
/**
* 根据地址获取经纬度信息
* @param area 区域
* @param location 地址
* @return CityLatitudeAndLongitudeBean 城市经纬度信息
*/
public static CityLatitudeAndLongitudeBean getLatitudeAndLongitude(String area, String location) {
CityLatitudeAndLongitudeBean result = null;
try {
StringBuilder url = new StringBuilder("http://api.map.baidu.com/geocoder/v2/?");
LinkedHashMap<String, String> paramsMap = new LinkedHashMap<>();
paramsMap.put("address", area + (StringUtils.isNotEmpty(location) ? location : StringUtils.EMPTY));
paramsMap.put("output", "json");
paramsMap.put("ak", Constants.BaiDu.AK);
// 调用下面的toQueryString方法,对LinkedHashMap内所有value作utf8编码,拼接返回结果address=%E7%99%BE%E5%BA%A6%E5%A4%A7%E5%8E%A6&output=json&ak=yourak
String paramsStr = BaiDuGeocodingSnCalUtil.toQueryString(paramsMap);
url.append(paramsStr);
String sn = BaiDuGeocodingSnCalUtil.getSnCalString(paramsStr);
url.append("&sn=");
url.append(sn);
result = JSON.parseObject(SimulationRequestUtil.doGet(url.toString()), new TypeReference<CityLatitudeAndLongitudeBean>() {
});
if (result == null || result.getStatus() == null || result.getStatus() != 0) {
return null;
}
} catch (Exception e) {
Logger.debug(e.getMessage());
}
return result;
}
/**
* 根据经纬度获取地址及周边信息
* @param lat 纬度
* @param lng 经度
* @return ProvinceBean 城市信息
*/
public static ProvinceBean getProvince(String lat, String lng) {
ProvinceBean result = null;
try {
StringBuilder url = new StringBuilder("http://api.map.baidu.com/geocoder/v2/?");
LinkedHashMap<String, String> paramsMap = new LinkedHashMap<>();
paramsMap.put("location", lat+","+lng);
String put = paramsMap.put("output", "json");
paramsMap.put("pois", "1");
paramsMap.put("latest_admin", "1");
paramsMap.put("ak", Constants.BaiDu.AK);
String paramsStr = BaiDuGeocodingSnCalUtil.toQueryString(paramsMap);
url.append(paramsStr);
String sn = BaiDuGeocodingSnCalUtil.getSnCalString(paramsStr);
url.append("&sn=");
url.append(sn);
String json = SimulationRequestUtil.doGet(url.toString());
System.out.println(json);
result = JSON.parseObject(json, new TypeReference<ProvinceBean>() {
});
if (result == null || result.getStatus() == null || result.getStatus() != 0) {
return null;
}
} catch (Exception e) {
Logger.debug(e.getMessage());
}
return result;
}
/**
* 计算两个经纬度之间的距离
*
* @param lat1
* @param lng1
* @param lat2
* @param lng2
* @return
*/
public static double getDistance(double lat1, double lng1, double lat2, double lng2) {
double radLat1 = rad(lat1);
double radLat2 = rad(lat2);
double a = radLat1 - radLat2;
double b = rad(lng1) - rad(lng2);
double s = 2 * Math.asin(Math.sqrt(Math.abs(Math.pow(Math.sin(a / 2), 2) +
Math.cos(radLat1) * Math.cos(radLat2) * Math.pow(Math.sin(b / 2), 2))));
s = s * EARTH_RADIUS;
s = Math.round(s * 1000);
return s;
}
/**
* 测试
* @param args
*/
public static void main(String []args){
System.out.println(getLatitudeAndLongitude("福州","福州"));
System.out.println(getProvince("26.080429420698079","119.30346983854001"));
}
}
3.返回结果是json数据,可以自行封装需要的数据,在此附上我的信息封装类:
@Data是引入了lombok插件,简化开发,不理解的可自行百度。 其余是一些swagger注解。
/**
* Description:城市经纬度
**/
@Data
public class CityLatitudeAndLongitudeBean implements Serializable {
private static final long serialVersionUID = 9112556610655198188L;
private Integer status;
private Result result;
}
/**
* Description:城市经纬度的结果
**/
@Data
public class Result implements Serializable {
private static final long serialVersionUID = 5142442006448398929L;
private Location location;
private String precise;
private String confidence;
private String level;
}
/**
* Description:经纬度城市
**/
@Data
@ApiModel(value = "经纬度城市")
public class ProvinceBean implements Serializable {
private static final long serialVersionUID = 9112556610655198166L;
private Integer status;
private ProvinceLocation result;
}
/**
* Description:经纬度城市
**/
@Data
@ApiModel(value = "经纬度城市")
public class ProvinceLocation implements Serializable {
private static final long serialVersionUID = 1570896924286528777L;
@ApiModelProperty(value = "纬度")
private String lng;
@ApiModelProperty(value = "经度")
private String lat;
@ApiModelProperty(value = "地址信息")
private AddressComponent addressComponent;
@ApiModelProperty(value = "附近地址")
private List<AddressPois> pois;
}
**
* Description:城市
**/
@Data
public class AddressComponent implements Serializable {
private static final long serialVersionUID = 1570896924286528788L;
private String country;
private String province;
private String city;
private String district;
private String street;
}
/**
* Description:城市周边信息
**/
@Data
@ApiModel(value = "城市周边信息")
public class AddressPois implements Serializable {
private static final long serialVersionUID = 1570896924286528755L;
@ApiModelProperty(value = "地址")
private String addr;
@ApiModelProperty(value = "名称")
private String name;
@ApiModelProperty(value = "经纬度")
private ProvincePoint point;
@ApiModelProperty(value = "类型")
private String poiType;
@ApiModelProperty(value = "标签")
private String tag;
}
测试结果
CityLatitudeAndLongitudeBean(status=0, result=Result(location=Location(lng=119.30346983854001, lat=26.080429420698079), precise=0, confidence=10, level=城市))
ProvinceBean(status=0, result=ProvinceLocation(lng=null, lat=null, addressComponent=AddressComponent(country=中国, province=福建省, city=福州市, district=鼓楼区, street=乌山路), pois=[AddressPois(addr=福州市鼓楼区乌山路96号, name=福州市人民政府, point=ProvincePoint(x=119.30289474335273, y=26.0805464063163), poiType=政府机构, tag=政府机构;各级政府), AddressPois(addr=光禄新坊2座1楼16号店面, name=中国工商银行(福州灵响支行), point=ProvincePoint(x=119.30390084552356, y=26.080724886227349), poiType=金融, tag=金融;银行), AddressPois(addr=乌山路92, name=福州市机关事务管理局, point=ProvincePoint(x=119.30403559135002, y=26.08070866079226), poiType=政府机构, tag=政府机构;行政单位), AddressPois(addr=福建省福州市鼓楼区乌山路92号, name=市委大院, point=ProvincePoint(x=119.30382898108279, y=26.080789787944974), poiType=房地产, tag=房地产;住宅区), AddressPois(addr=乌山路59, name=福建移动通信大厦, point=ProvincePoint(x=119.30229287866124, y=26.079353828941117), poiType=房地产, tag=房地产;写字楼), AddressPois(addr=福州市鼓楼区加洋路26号, name=协和公寓, point=ProvincePoint(x=119.30431406605801, y=26.078940074737014), poiType=房地产, tag=房地产;住宅区), AddressPois(addr=福州市鼓楼区乌山路53号福建黎明大酒店, name=中国工商银行(福州南门支行营业室), point=ProvincePoint(x=119.30562559210215, y=26.0808790277473), poiType=金融, tag=金融;银行), AddressPois(addr=福州市鼓楼区加洋路23号, name=福建煤田地质博物馆, point=ProvincePoint(x=119.30494287991479, y=26.079004977455033), poiType=旅游景点, tag=旅游景点;博物馆), AddressPois(addr=福州市鼓楼区乌山路80号, name=山水知音, point=ProvincePoint(x=119.30537406655944, y=26.081665957572313), poiType=购物, tag=购物;商铺), AddressPois(addr=鼓楼区乌山路53号(市政府对面), name=海通商务酒店(斗西路), point=ProvincePoint(x=119.30562559210215, y=26.080294911429247), poiType=酒店, tag=酒店;二星级)]))