高德地图开发文档入口
info
public enum AMapAPIDevAccountInfo {
//企业开发者key
KEY("7beb6ccxxxxxxxxxxxx108ade8"),
//服务ID
SID("77XXX8");
public final String value;
AMapAPIDevAccountInfo(String value) {
this.value = value;
}
}
Util
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.winsky.carhailing.common.util.PageUtil;
import com.winsky.carhailing.common.util.amap.enums.AMapAPIAddress;
import com.winsky.carhailing.common.util.amap.enums.AMapAPIDevAccountInfo;
import com.winsky.carhailing.common.util.amap.model.bo.AmapBatchBO;
import com.winsky.carhailing.common.util.amap.model.bo.AmapResPathData;
import com.winsky.carhailing.common.util.amap.model.bo.AmapResTrackingData;
import com.winsky.carhailing.common.util.amap.model.res.ReGeoRes;
import com.winsky.carhailing.common.util.amap.model.res.TrackTraceSearchRes;
import com.winsky.carhailing.common.util.amap.model.res.WeatherInfoRes;
import com.winsky.carhailing.common.util.gps.CoordinateConversionUtil;
import com.winsky.carhailing.common.util.gps.GPSPoint;
import com.winsky.carhailing.common.util.httpClient.HttpClientUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.math.BigDecimal;
import java.util.*;
/**
* 高德API https://lbs.amap.com/api/webservice/guide/api/direction
* @date create in
*/
public class AmapApi {
private static final Logger logger = LoggerFactory.getLogger(AmapApi.class);
/**
* 获取驾车规划 -- 起点与终点的驾车规划
*/
public static AmapResPathData getDriverNavPathData(GPSPoint startPoint, GPSPoint endPoint) {
AmapResPathData amapResPathData = new AmapResPathData();
try {
Map filter = new HashMap();
//起始经纬度
filter.put("origin", startPoint.getLng() + "," + startPoint.getLat());
filter.put("destination", endPoint.getLng() + "," + endPoint.getLat());
//駕車選擇策略 2:距离优先,不考虑路况,仅走距离最短的路线,但是可能存在穿越小路/小区的情况
filter.put("strategy", "2");
//返回结果控制 base:返回基本信息;all:返回全部信息
filter.put("extensions", "base");
//返回数据格式类型 可选值:JSON,XML
filter.put("output", "JSON");
//高德用户唯一标识 用户在高德地图官网申请
filter.put("key", AMapAPIDevAccountInfo.KEY.value);
//https://lbs.amap.com/api/webservice/guide/api/direction 驾车路径规划接口
String response = HttpClientUtil.getInstance().sendHttpPost(AMapAPIAddress.DRIVER_NAV_API_URL.ADDRESS, filter);
//高德放回的json
JSONObject jb = JSON.parseObject(response);
//结果状态值,0:请求失败;1:请求成功
if (jb.getIntValue("status") == 1) {
//route 驾车路径规划信息列表
if (null != jb && jb.getJSONObject("route") != null) {
//paths 驾车换乘方案 distance :行驶距离 单位:米; duration : 预计行驶时间 单位:秒
amapResPathData = jb.getJSONObject("route").getJSONArray("paths").getJSONObject(0).toJavaObject(AmapResPathData.class);
} else {
amapResPathData.setDistance(0L);
amapResPathData.setDuration(0L);
}
} else {
logger.error("高德接口请求失败:{}", response);
}
} catch (Exception e) {
logger.error("获取驾车规划", e);
}
return amapResPathData;
}
/**
* 获取拼车订单原始驾车规划
* 订单的起点终点,剩余进行中行程的未接到的起点和未送到的目的地,与订单起点直线距离排序,在起点终点距离范围内的是途经点
*/
public static AmapResPathData getDriverNavPathData(GPSPoint startPoint, GPSPoint endPoint, List<GPSPoint> waypoints) {
AmapResPathData amapResPathData = new AmapResPathData();
try {
Map filter = new HashMap();
filter.put("origin", startPoint.getLng() + "," + startPoint.getLat());
filter.put("extensions", "base");
filter.put("output", "JSON");
//排序
gpsPointsSort(startPoint, waypoints);
StringBuilder waypointsVal = new StringBuilder();
StringBuilder endpointVal = new StringBuilder();
Iterator<GPSPoint> itr = waypoints.iterator();
Double distance = CoordinateConversionUtil.getDistance(startPoint.getLng(), startPoint.getLat(), endPoint.getLng(), endPoint.getLat());
while (itr.hasNext()) {
GPSPoint point = itr.next();
//重复的点去除
if(startPoint.equals(point)){
continue;
}
//按距离排序,途经点算到订单重点为止
if(endPoint.equals(point)){
break;
}
//超出起点终点距离范围内的去除
// if(distance<CoordinateConversionUtil.getDistance(startPoint.getLng(),startPoint.getLat(),point.getLng(),point.getLat())
// || distance<CoordinateConversionUtil.getDistance(endPoint.getLng(),endPoint.getLat(),point.getLng(),point.getLat())){
// continue;
// }
if(itr.hasNext()){
waypointsVal.append(point.getLng() + "," + point.getLat()).append(";");
} else {
endpointVal.append(point.getLng() + "," + point.getLat());
}
}
filter.put("waypoints", waypointsVal.toString());
filter.put("destination", endPoint.getLng() + "," + endPoint.getLat());
filter.put("key", AMapAPIDevAccountInfo.KEY.value);
String response = HttpClientUtil.getInstance().sendHttpPost(AMapAPIAddress.DRIVER_NAV_API_URL.ADDRESS, filter);
JSONObject jb = JSON.parseObject(response);
if (jb.getIntValue("status") == 1) {
if (null != jb && jb.getJSONObject("route") != null) {
amapResPathData = jb.getJSONObject("route").getJSONArray("paths").getJSONObject(0).toJavaObject(AmapResPathData.class);
} else {
amapResPathData.setDistance(0L);
amapResPathData.setDuration(0L);
}
} else {
logger.error("高德接口请求失败:{}", response);
}
} catch (Exception e) {
logger.error("获取驾车规划", e);
}
return amapResPathData;
}
/**
* 与起点直线距离由近到远排序
*
* @param startPoint
* @param waypoints
* @return
*/
public static List<GPSPoint> gpsPointsSort(GPSPoint startPoint, List<GPSPoint> waypoints) {
Collections.sort(waypoints, new Comparator<GPSPoint>() {
@Override
public int compare(GPSPoint o1, GPSPoint o2) {
Double distance1 = CoordinateConversionUtil.getDistance(startPoint.getLng(), startPoint.getLat(), o1.getLng(), o1.getLat());
Double distance2 = CoordinateConversionUtil.getDistance(startPoint.getLng(), startPoint.getLat(), o2.getLng(), o2.getLat());
return distance1.compareTo(distance2);
}
});
return waypoints;
}
/**
* 轨迹纠偏接口,获取驾驶轨迹路线,里程
*/
public static AmapResTrackingData getDrivingTracks(List<Map> locDates) {
AmapResTrackingData resTrackingData = new AmapResTrackingData();
try {
JSONArray jsonArray = new JSONArray();
locDates.stream().forEach(locDate -> {
JSONObject jsonObject = new JSONObject();
jsonObject.put("x", locDate.get("lgt")); //经度
jsonObject.put("y", locDate.get("lat")); //纬度
jsonObject.put("ag", locDate.get("direction")); //角度
jsonObject.put("tm", locDate.get("time")); //时间
jsonObject.put("sp", locDate.get("speed")); //速度
jsonArray.add(jsonObject);
});
String response = HttpClientUtil.getInstance().postJSON(AMapAPIAddress.GRASP_ROAD_API_URL.ADDRESS + "?key=" + AMapAPIDevAccountInfo.KEY.value, jsonArray.toJSONString());
JSONObject jb = JSON.parseObject(response);
if (null != jb && jb.getJSONObject("data") != null) {
resTrackingData = jb.getJSONObject("data").getJSONArray("distance").getJSONObject(0).toJavaObject(AmapResTrackingData.class);
} else {
logger.error("高德接口请求抓路失败:{}", response);
resTrackingData.setDistance(0L);
}
// resTrackingData.setPoints(locDates);
} catch (Exception e) {
logger.error("获取轨迹纠偏", e);
}
return resTrackingData;
}
/**
* 批量获取驾车规划
*/
public static List<AmapResPathData> getPathData(List<AmapBatchBO> batchBOS) {
List<AmapResPathData> amapResPathDataList = new ArrayList<>();
try {
JSONObject batchReq = new JSONObject();
int count = batchBOS.size();
int index = 0;
int step = 20;
while (index < count) {
List<AmapBatchBO> temp = batchBOS.subList(index, index + step <= count ? index + step : count);
batchReq.put("ops", temp);
String res = HttpClientUtil.getInstance().postJSON(AMapAPIAddress.BATCH_API_URL.ADDRESS, batchReq.toJSONString());
JSONArray jsonArray = JSONObject.parseArray(res);
Iterator itr = jsonArray.iterator();
while (itr.hasNext()) {
JSONObject jb = ((JSONObject) itr.next()).getJSONObject("body");
if (null != jb && jb.getJSONObject("route") != null) {
AmapResPathData amapResPathData = jb.getJSONObject("route").getJSONArray("paths").getJSONObject(0).toJavaObject(AmapResPathData.class);
amapResPathDataList.add(amapResPathData);
} else {
AmapResPathData amapResPathData = new AmapResPathData();
amapResPathData.setDistance(0L);
amapResPathData.setDuration(0L);
amapResPathDataList.add(amapResPathData);
}
}
index += step;
}
} catch (Exception e) {
logger.error("批量获取驾车规划", e);
}
return amapResPathDataList;
}
/**
* 创建终端
*
* @param key 请求服务权限标识
* @param sid 服务的唯一编号
* @param name 终端名称
* @param desc 终端描述
* @param props 自定义字段
*/
public static String terminalAdd(String key, String sid, String name, String desc, String props) {
Map<String, Object> params = new HashMap<>();
params.put("key", key);
params.put("sid", sid);
params.put("name", name);
params.put("desc", desc);
params.put("props", props);
return HttpClientUtil.getInstance().post(AMapAPIAddress.TERMINAL_ADD.ADDRESS, params);
}
/**
* 创建轨迹, 创建一条轨迹,一个终端下最多可创建500000条轨迹。
*
* @param key 请求服务权限标识
* @param sid 查询的服务ID
* @param tid 设备唯一编号
*/
public static String trackTraceAdd(String key, String sid, String tid) {
Map<String, Object> params = new HashMap<>();
params.put("key", key);
params.put("sid", sid);
params.put("tid", tid);
return HttpClientUtil.getInstance().post(AMapAPIAddress.TRACK_TRACE_ADD.ADDRESS, params);
}
/**
* 获取轨迹全部数据
*
* @param tid 设备唯一编号(即t_car表里的Trid)
* @param trid 轨迹唯一编号(即t_order表里的Trid)
* @param startTime 起始时间, Unix时间戳(轨迹点的定位时间),需要精准到毫秒
* @param endTime 结束时间, Unix时间戳(轨迹点的定位时间),需要精准到毫秒
* @return
*/
public static TrackTraceSearchRes.Track getAllTrackTrace(String tid, String trid, Long startTime, Long endTime) {
int pageNum = 1;
int pageSize = 500;
TrackTraceSearchRes res = trackTraceSearch(tid, trid, startTime, endTime, null, null, null, null, pageNum, pageSize);
if (null == res || null == res.getData()) {
logger.error("未查询到轨迹数据");
return null;
} else {
TrackTraceSearchRes.Track track = res.getData().getTracks().get(0);
if (track != null && track.getCounts() > 0) {
int totalPage = PageUtil.getTotalPage(pageSize, track.getCounts());
for (int i = 1; i < totalPage; i++) {
++pageNum;
TrackTraceSearchRes res1 = trackTraceSearch(tid, trid, startTime, endTime, null, null, null, null, pageNum, pageSize);
if (null == res1 || null == res1.getData()) {
break;
} else {
TrackTraceSearchRes.Track track1 = res1.getData().getTracks().get(0);
track.getPoints().addAll(track1.getPoints());
}
}
}
return track;
}
}
/**
* 查询轨迹信息(里程、时间等)
*
* @param key 请求服务权限标识
* @param sid 查询的服务ID
* @param tid 设备唯一编号
* @param trid 轨迹唯一编号
* @param startTime 起始时间, Unix时间戳(轨迹点的定位时间),需要精准到毫秒
* @param endTime 结束时间, Unix时间戳(轨迹点的定位时间),需要精准到毫秒, 结束时间不能大于当前时间,且距离开始时间不能超过24小时。 若轨迹较多,建议将时间段进行拆分。
* @param correction 对轨迹进行处理
* @param recoup 对轨迹进行补点 缺省值0, 0:代表用直线连接方式进行补点计算; 1:代表用correction的mode方式进行补点计算,当前只开放了driving。
* @param gap 补点间距 缺省值为5公里,最小50米,最大10公里,单位:米。
* @param isPoints 是否返回轨迹点信息 默认为返回(1),可以设置为不返回(0)
* @param page 查询页数 缺省值1
* @param pageSize 每页点数 缺省值20,当page=1的时候起点、终点的个数不计算在内,pagesize最大值为1000。
*/
public static TrackTraceSearchRes trackTraceSearch(String tid, String trid, Long startTime, Long endTime, String correction,
Integer recoup, Integer gap, Integer isPoints, Integer page, Integer pageSize) {
Map<String, Object> params = new HashMap<>();
params.put("key", AMapAPIDevAccountInfo.KEY.value);
params.put("sid", AMapAPIDevAccountInfo.SID.value);
params.put("tid", tid);
params.put("trid", trid);
params.put("starttime", startTime);
params.put("endtime", endTime);
params.put("correction", correction);
params.put("recoup", recoup);
params.put("gap", gap);
params.put("ispoints", isPoints);
params.put("page", page);
params.put("pagesize", pageSize);
String result = HttpClientUtil.getInstance().get(AMapAPIAddress.TRACK_TRACE_SEARCH.ADDRESS, params);
return JSONObject.parseObject(result, TrackTraceSearchRes.class);
}
/**
* 天气接口 https://lbs.amap.com/api/webservice/guide/tools/weather-code/
*
* @param key 请求服务权限标识
* @param city 城市编码 输入城市的adcode,adcode信息可参考城市编码表
* @param extensions 气象类型 可选值:base/all base:返回实况天气 all:返回预报天气
* @param output 返回格式 可选值:JSON(默认),XML
*/
public static WeatherInfoRes getWeatherInfo(String key, String city, String extensions, String output) {
Map<String, Object> params = new HashMap<>();
params.put("key", key);
params.put("city", city);
params.put("extensions", extensions);
params.put("output", output);
String result = HttpClientUtil.getInstance().get(AMapAPIAddress.WEATHER_INFO.ADDRESS, params);
return JSONObject.parseObject(result, WeatherInfoRes.class);
}
/**
* 逆地理编码
*
* @param key 高德Key
* @param location 经纬度坐标 传入内容规则:经度在前,纬度在后,经纬度间以“,”分割,经纬度小数点后不要超过 6 位。如果需要解析多个经纬度的话,请用"|"进行间隔,并且将 batch 参数设置为 true,最多支持传入 20 对坐标点。每对点坐标之间用"|"分割。
* @param other 其他非必填参数,参考文档:https://lbs.amap.com/api/webservice/guide/api/georegeo
* @return
*/
public static ReGeoRes getLocationReGeo(String key, String location, Map<String, Object> other) {
Map<String, Object> params = new HashMap<>();
params.put("key", key);
params.put("location", location);
if (null != other) {
other.forEach((keys, values) -> {
params.put(keys, values);
});
}
String result = HttpClientUtil.getInstance().get(AMapAPIAddress.GEOCODE_REGEO_API_URL.ADDRESS, params);
return JSONObject.parseObject(result, ReGeoRes.class);
}
public static void main(String[] args) {
GPSPoint a1 = new GPSPoint(Double.valueOf("117.130525"), Double.valueOf("29.258724"));
GPSPoint a2 = new GPSPoint(Double.valueOf("117.214981"), Double.valueOf("29.293871"));
GPSPoint b1 = new GPSPoint(Double.valueOf("117.1304215"), Double.valueOf("29.2585618"));
GPSPoint b2 = new GPSPoint(Double.valueOf("117.216467"), Double.valueOf("29.289589"));
List<GPSPoint> waypoints = new ArrayList<>();
waypoints.add(a1);
waypoints.add(a2);
waypoints.add(b1);
waypoints.add(b2);
//自己加入行程后绕路里程
AmapResPathData beforeJoin = AmapApi.getDriverNavPathData(a1,a2);
AmapResPathData afterJoin = AmapApi.getDriverNavPathData(a1,a2, waypoints);
BigDecimal detourMileagePec= BigDecimal.valueOf(afterJoin.getDistance() - beforeJoin.getDistance()).divide(BigDecimal.valueOf(beforeJoin.getDistance()),2,BigDecimal.ROUND_HALF_UP).multiply(BigDecimal.valueOf(100));
if (detourMileagePec.compareTo(BigDecimal.ZERO)==-1 ||detourMileagePec.compareTo(BigDecimal.valueOf(20))==1) {
System.out.println("false");
return;
}
//加入行程后对其他乘客的绕路里程
beforeJoin = AmapApi.getDriverNavPathData(b1,b2);
afterJoin = AmapApi.getDriverNavPathData(b1,b2, waypoints);
if (BigDecimal.valueOf(afterJoin.getDistance() - beforeJoin.getDistance()).divide(BigDecimal.valueOf(beforeJoin.getDistance()),2,BigDecimal.ROUND_HALF_UP).multiply(BigDecimal.valueOf(100)).compareTo(BigDecimal.valueOf(20))==1) {
System.out.println("false1");
return;
}
}
}