使用第三方百度地图根据城市名称计算两地之间的实际驾车距离

  大概思路是这样的,我们需要首先根据两地之间的城市名称获取到两地的经纬度,在网上查到的很多方法都是根据经纬度计算两地之间的球面距离或者是直线距离,而不是实际的驾车距离,百度地图第三方API实际上有提供计算驾车距离的方法,除此之外,还有骑行距离,步行距离等,并且规划了几条不同的路线,下面具体详解功能实现的核心代码。

  1.使用第三方平台首要的是导入相应第三方的SDK。这个自行去百度开发平台下载。

  2.申请appKey,这里需要提到的一点是我在使用eclipse开发过程中遇到的坑。申请appKey需要SHA1和packegName,其中packegName肯定是没有问题的,在清单文件就可以找到,但是项目打包完成以后的SHA1值却和eclipse自带的SHA1值不一样,测试时,我们的SHA1值可以在Window-preferences-Android-build目录下找到,使用这个SHA1值申请的appKey也仅仅是测试的时候可以使用,如果需要上线使用,也就是使用keyStoer进行打包,就不能使用这个SHA1申请的appKey,有一个最简单的办法可以找到与keyStor对应的SHA1。在用keyStor进行打包的时候到了最后一步finish的时候就会看到一个SHA1值,那就是这个了。用这个SHA1申请的appKey就可以上线使用了。在清单文件中配置appKey。


<!-- meta-data需要写在application中 -->
<meta-data
android:name="com.baidu.lbsapi.API_KEY"
android:value="VEDGD3GLpdvRgKkYTb2yBvQg385kdRoC" />
<!-- 线上:VEDGD3GLpdvRgKkYTb2yBvQg385kdRoC -->
<!-- 测试:qYBH9YBopFAY3CsBaG3B4mftkKvhg0xI -->

   3.在application中进行初始化

SDKInitializer.initialize(this);
mLocationClient = new LocationClient(this.getApplicationContext());
mGeofenceClient = new GeofenceClient(getApplicationContext());

  4.下面是针对这一需求写的工具类

public class GetInstence implements OnGetRoutePlanResultListener {
// private double d1;
// private double d2;
// private double d3;
// private double d4;
TextView textView;
RoutePlanSearch mSearch = null; // 路径规划,可独立使用该模块
private static final double EARTH_RADIUS = 6378137.0;
private GeoCoder mySearch;
private String str=null;
Context context;
boolean flag;
static LatLng latLng1=null;
static LatLng latlng2=null;
public GetInstence(String str, Context context, boolean flag,TextView textView) {
this.str = str;
this.context = context;
this.flag = flag;
this.textView=textView;
}
public static LatLng Getlat1(){

return latLng1;
}
public static LatLng Getlat2(){

return latlng2;
}

public void cal(){
// 初始化搜索模块,注册事件监听
mSearch = RoutePlanSearch.newInstance();
mSearch.setOnGetRoutePlanResultListener(this);

mySearch = GeoCoder.newInstance();
mySearch.geocode(new GeoCodeOption().city("").address(str));
mySearch.setOnGetGeoCodeResultListener(new OnGetGeoCoderResultListener() {
@Override
public void onGetReverseGeoCodeResult(ReverseGeoCodeResult arg0) {
}
@Override
public void onGetGeoCodeResult(GeoCodeResult result) {
if (result == null || result.error != SearchResult.ERRORNO.NO_ERROR) {
return;
}
double latitude;
double longitude;
LatLng l1;
LatLng l2;
// //拿到经纬度
// String strInfo = String.format("纬度:%f 经度:%f",
// result.getLocation().latitude, result.getLocation().longitude);

latitude=result.getLocation().latitude;
longitude= result.getLocation().longitude;
if(flag){
PrefUtils.putString(context, "a1", String.valueOf(latitude));
PrefUtils.putString(context, "a2", String.valueOf(longitude));
}else{
PrefUtils.putString(context, "b1", String.valueOf(latitude));
PrefUtils.putString(context, "b2", String.valueOf(longitude));
}
if(!flag){
double d1=Double.parseDouble(PrefUtils.getString(context, "a1", null));
double d2=Double.parseDouble(PrefUtils.getString(context, "a2", null));
double d3=Double.parseDouble(PrefUtils.getString(context, "b1", null));
double d4=Double.parseDouble(PrefUtils.getString(context, "b2", null));
latLng1=new LatLng(d1, d2);
latlng2=new LatLng(d3, d4);
PlanNode stNode = PlanNode.withLocation(latLng1);
PlanNode enNode = PlanNode.withLocation(latlng2);
mSearch.drivingSearch((new DrivingRoutePlanOption())
.from(stNode).to(enNode));
textView.setText("计算中...");

double s=getDistance(d2,d1,d4,d3);

double a=s/1000;
DecimalFormat df = new DecimalFormat("0.00");
String num = df.format(a);

}
}
});
}

public double getDistance(double longitude1, double latitude1,
double longitude2, double latitude2) {
double Lat1 = rad(latitude1);
double Lat2 = rad(latitude2);
double a = Lat1 - Lat2;
double b = rad(longitude1) - rad(longitude2);
double s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2)
+ Math.cos(Lat1) * Math.cos(Lat2)
* Math.pow(Math.sin(b / 2), 2)));
s = s * EARTH_RADIUS;
s = Math.round(s * 10000) / 10000;
return s;
}
private double rad(double d) {
return d * Math.PI / 180.0;
}
@Override
public void onGetDrivingRouteResult(DrivingRouteResult result) {
// TODO Auto-generated method stub
if (result == null || result.error != SearchResult.ERRORNO.NO_ERROR) {
//Toast.makeText(, "抱歉,未找到结果", Toast.LENGTH_SHORT).show();
textView.setText("");
}
if (result.error == SearchResult.ERRORNO.AMBIGUOUS_ROURE_ADDR) {
// 起终点或途经点地址有岐义,通过以下接口获取建议查询信息
// result.getSuggestAddrInfo()
return;
}
if (result.error == SearchResult.ERRORNO.NO_ERROR) {
result.getRouteLines();
result.getRouteLines();
//instence.setText("计算中。。。");
double object=result.getRouteLines().get(0).getDistance();
DecimalFormat df = new DecimalFormat("0.00");
String num = df.format(object/1000);
textView.setText(num+"km");
//mSearch = null;
}
}
@Override
public void onGetTransitRouteResult(TransitRouteResult arg0) {
// TODO Auto-generated method stub

}
@Override
public void onGetWalkingRouteResult(WalkingRouteResult arg0) {
// TODO Auto-generated method stub

}
}

上面代码很多都是和我们工程相关的,因此我做一下代码提取

  首先需要去实现OnGetRoutePlanResultListener这个接口,重写方法onGetDrivingRouteResult,onGetTransitRouteResult,onGetWalkingRouteResult。需要的驾车距离会在onGetDrivingRouteResult这个方法中回调。拿到这个回调有两种方法,一种是直接用地点名称计算,另外一种是用经纬度来计算,所以我是先通过地点名称拿到经纬度,再利用经纬度进行计算。cal()  这个方法就是计算经纬度的。拿到经纬度的同时会接收到onGetDrivingRouteResult方法的回调值。