一:国内主流坐标系类型
来自百度地图的介绍: https://lbsyun.baidu.com/index.php?title=androidsdk/guide/coordtrans
主要有以下三种
1. WGS84:为一种大地坐标系,也是目前广泛使用的GPS全球卫星定位系统使用的坐标系;
2. GCJ02:是由中国国家测绘局制订的地理信息系统的坐标系统,是由WGS84坐标系经加密后的坐标系;
3. BD09:百度坐标系,在GCJ02坐标系基础上再次加密。其中BD09ll表示百度经纬度坐标,BD09mc表示百度墨卡托米制坐标。
百度地图在国内(包括港澳台)使用的是BD09坐标;在海外地区,统一使用WGS84坐标。开发者在使用百度地图相关服务时,请注意选择。
百度地图SDK使用什么坐标类型?
1. 国内(包括港澳台),输入、输出默认使用BD09坐标。自Android v4.3起,支持一次声明为GCJ02坐标类型,全应用支持输入GCJ02坐标,返回GCJ02坐标。
2. 海外地区,输入为WGS84坐标。
为什么需要转换坐标?
百度地图的服务,国内(包括港澳台)使用BD09坐标,国外使用WGS84坐标。若使用非BD09坐标直接叠加在百度地图上,因坐标值不同,展示位置就会偏移。
举例:
1)在国内(包括港澳台):POI使用WGS84或GCJ02坐标数值,直接显示在百度地图上,POI展示位置就会偏移,因此通过其他坐标(WGS84、GCJ02)调用服务时,需先将其他坐标转换为BD09,再访问百度地图数据。
2)在国外:POI使用WGS84坐标数值,则无需转换,百度地图国外即使用WGS84坐标。
非百度坐标系,如何转换成百度坐标系?
1. 通用坐标转换方法: 手动将输入的WGS84、GCJ02坐标转换为BD09。适用于所有使用百度地图的开发者,是转换为百度BD09坐标的官方基础算法。
2. 自动坐标转换方法: 自Android v4.3起,支持一次声明GCJ02坐标类型,全应用内自动执行GCJ02到BD09的坐标转换,即直接输入GCJ02坐标,返回GCJ02坐标。
二:了解完坐标系,开始正式开发
以下地图链接是代码中参数设置的依据,找到对应的
1:高德地图
高德开放平台地址:https://lbs.amap.com/
高德地图手机版API地址:https://lbs.amap.com/api/amap-mobile/summary/
2:百度地图:
百度地图开放平台:http://lbsyun.baidu.com/
百度地图地图调起API:http://lbsyun.baidu.com/index.php?title=uri
3:腾讯地图
腾讯地图开放平台:https://lbs.qq.com/index.html
腾讯地图调起API:https://lbs.qq.com/uri_v1/guide-mobile-navAndRoute.html
4:经纬度的查询
可以在这个在线地图经度纬度查询获取地理位置的经纬度信息
三:具体代码
MainActivity.java的代码
package com.example.myMap;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private Button gaode_map, baidu_map, tencent_map;
//这里的经纬度是直接获取的,在实际开发中从应用的地图中获取经纬度,这里的经纬度用的是高德和腾讯的,在百度地图中进行了转换;
private double latx = 24.8738900000;
private double laty = 118.6758700000;
private String mAddress = "泉州市政府";
// private double latx = 39.9037448095;
// private double laty = 116.3980007172;
// private String mAddress = "北京天安门";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
gaode_map = (Button) findViewById(R.id.gaode_map);
baidu_map = (Button) findViewById(R.id.baidu_map);
tencent_map = (Button) findViewById(R.id.tencent_map);
gaode_map.setOnClickListener(this);
baidu_map.setOnClickListener(this);
tencent_map.setOnClickListener(this);
}
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.gaode_map:
if (MapUtil.isGdMapInstalled()) {
MapUtil.openGaoDeNavi(MainActivity.this, 0, 0, null, latx, laty, mAddress);
} else {
//这里必须要写逻辑,不然如果手机没安装该应用,程序会闪退,这里可以实现下载安装该地图应用
Toast.makeText(MainActivity.this, "尚未安装高德地图", Toast.LENGTH_SHORT).show();
}
break;
case R.id.baidu_map:
if (MapUtil.isBaiduMapInstalled()){
MapUtil.openBaiDuNavi(MainActivity.this, 0, 0, null, latx, laty, mAddress);
} else {
Toast.makeText(MainActivity.this, "尚未安装百度地图", Toast.LENGTH_SHORT).show();
}
break;
case R.id.tencent_map:
if (MapUtil.isTencentMapInstalled()){
MapUtil.openTencentMap(MainActivity.this, 0, 0, null, latx, laty, mAddress);
} else {
Toast.makeText(MainActivity.this, "尚未安装腾讯地图", Toast.LENGTH_SHORT).show();
}
break;
default:
break;
}
}
}
MapUtil.java工具类
package com.example.myMap;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import java.io.File;
public class MapUtil {
public static final String PN_GAODE_MAP = "com.autonavi.minimap";// 高德地图包名
public static final String PN_BAIDU_MAP = "com.baidu.BaiduMap"; // 百度地图包名
public static final String PN_TENCENT_MAP = "com.tencent.map"; // 腾讯地图包名
/**
* 检查地图应用是否安装
* @return
*/
public static boolean isGdMapInstalled(){
return isInstallPackage(PN_GAODE_MAP);
}
public static boolean isBaiduMapInstalled(){
return isInstallPackage(PN_BAIDU_MAP);
}
public static boolean isTencentMapInstalled(){
return isInstallPackage(PN_TENCENT_MAP);
}
private static boolean isInstallPackage(String packageName) {
return new File("/data/data/" + packageName).exists();
}
/**
* 百度转高德
* @param bd_lat
* @param bd_lon
* @return
*/
public static double[] bdToGaoDe(double bd_lat, double bd_lon) {
double[] gd_lat_lon = new double[2];
double PI = 3.14159265358979324 * 3000.0 / 180.0;
double x = bd_lon - 0.0065, y = bd_lat - 0.006;
double z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * PI);
double theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * PI);
gd_lat_lon[0] = z * Math.cos(theta);
gd_lat_lon[1] = z * Math.sin(theta);
return gd_lat_lon;
}
/**
* 高德、腾讯转百度
* @param gd_lon
* @param gd_lat
* @return
*/
private static double[] gaoDeToBaidu(double gd_lon, double gd_lat) {
double[] bd_lat_lon = new double[2];
double PI = 3.14159265358979324 * 3000.0 / 180.0;
double x = gd_lon, y = gd_lat;
double z = Math.sqrt(x * x + y * y) + 0.00002 * Math.sin(y * PI);
double theta = Math.atan2(y, x) + 0.000003 * Math.cos(x * PI);
bd_lat_lon[0] = z * Math.cos(theta) + 0.0065;
bd_lat_lon[1] = z * Math.sin(theta) + 0.006;
return bd_lat_lon;
}
// /**
// * 百度坐标系 (BD-09) 与 火星坐标系 (GCJ-02)的转换
// * 即 百度 转 谷歌、高德
// *
// * @param latLng
// * @returns
// *
// * 使用此方法需要下载导入百度地图的BaiduLBS_Android.jar包
// */
// public static LatLng BD09ToGCJ02(LatLng latLng) {
// double x_pi = 3.14159265358979324 * 3000.0 / 180.0;
// double x = latLng.longitude - 0.0065;
// double y = latLng.latitude - 0.006;
// double z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * x_pi);
// double theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * x_pi);
// double gg_lat = z * Math.sin(theta);
// double gg_lng = z * Math.cos(theta);
// return new LatLng(gg_lat, gg_lng);
// }
//
// /**
// * 火星坐标系 (GCJ-02) 与百度坐标系 (BD-09) 的转换
// * 即谷歌、高德 转 百度
// *
// * @param latLng
// * @returns
// *
// * 需要百度地图的BaiduLBS_Android.jar包
// */
// public static LatLng GCJ02ToBD09(LatLng latLng) {
// double x_pi = 3.14159265358979324 * 3000.0 / 180.0;
// double z = Math.sqrt(latLng.longitude * latLng.longitude + latLng.latitude * latLng.latitude) + 0.00002 * Math.sin(latLng.latitude * x_pi);
// double theta = Math.atan2(latLng.latitude, latLng.longitude) + 0.000003 * Math.cos(latLng.longitude * x_pi);
// double bd_lat = z * Math.sin(theta) + 0.006;
// double bd_lng = z * Math.cos(theta) + 0.0065;
// return new LatLng(bd_lat, bd_lng);
// }
/**
* 打开高德地图导航功能
* @param context
* @param slat 起点纬度
* @param slon 起点经度
* @param sname 起点名称 可不填(0,0,null)
* @param dlat 终点纬度
* @param dlon 终点经度
* @param dname 终点名称 必填
*/
public static void openGaoDeNavi(Context context,double slat, double slon, String sname, double dlat, double dlon, String dname){
String uriString = null;
StringBuilder builder = new StringBuilder("amapuri://route/plan?");
if (slat != 0) {
builder.append("sname=").append(sname)
.append("&slat=").append(slat)
.append("&slon=").append(slon);
}
builder.append("&dlat=").append(dlat)
.append("&dlon=").append(dlon)
.append("&dname=").append(dname)
.append("&dev=0")
.append("&t=0");
uriString = builder.toString();
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setPackage(PN_GAODE_MAP);
intent.setData(Uri.parse(uriString));
context.startActivity(intent);
}
/**
* 打开腾讯地图
* params 参考http://lbs.qq.com/uri_v1/guide-route.html
*
* @param context
* @param slat 起点纬度
* @param slon 起点经度
* @param sname 起点名称 可不填(0,0,null)
* @param dlat 终点纬度
* @param dlon 终点经度
* @param dname 终点名称 必填
* 驾车:type=drive,policy有以下取值
0:较快捷
1:无高速
2:距离
policy的取值缺省为0
* &from=" + dqAddress + "&fromcoord=" + dqLatitude + "," + dqLongitude + "
*/
public static void openTencentMap(Context context, double slat, double slon, String sname, double dlat, double dlon, String dname) {
String uriString = null;
StringBuilder builder = new StringBuilder("qqmap://map/routeplan?type=drive&policy=0&referer=wuczh");
if (slat != 0) {
builder.append("&from=").append(sname)
.append("&fromcoord=").append(slat)
.append(",")
.append(slon);
}
builder.append("&to=").append(dname)
.append("&tocoord=").append(dlat)
.append(",")
.append(dlon);
uriString = builder.toString();
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setPackage(PN_TENCENT_MAP);
intent.setData(Uri.parse(uriString));
context.startActivity(intent);
}
/**
* 打开百度地图导航功能(默认坐标点是高德地图,需要转换)
* @param context
* @param slat 起点纬度
* @param slon 起点经度
* @param sname 起点名称 可不填(0,0,null)
* @param dlat 终点纬度
* @param dlon 终点经度
* @param dname 终点名称 必填
*/
public static void openBaiDuNavi(Context context,double slat, double slon, String sname, double dlat, double dlon, String dname){
String uriString = null;
//终点坐标转换
// 此方法需要百度地图的BaiduLBS_Android.jar包
// LatLng destination = new LatLng(dlat,dlon);
// LatLng destinationLatLng = GCJ02ToBD09(destination);
// dlat = destinationLatLng.latitude;
// dlon = destinationLatLng.longitude;
double destination[] = gaoDeToBaidu(dlat, dlon);
dlat = destination[0];
dlon = destination[1];
StringBuilder builder = new StringBuilder("baidumap://map/direction?mode=driving&");
if (slat != 0){
//起点坐标转换
// LatLng origin = new LatLng(slat,slon);
// LatLng originLatLng = GCJ02ToBD09(origin);
// slat = originLatLng.latitude;
// slon = originLatLng.longitude;
double[] origin = gaoDeToBaidu(slat, slon);
slat = origin[0];
slon = origin[1];
builder.append("origin=latlng:")
.append(slat)
.append(",")
.append(slon)
.append("|name:")
.append(sname);
}
builder.append("&destination=latlng:")
.append(dlat)
.append(",")
.append(dlon)
.append("|name:")
.append(dname);
uriString = builder.toString();
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setPackage(PN_BAIDU_MAP);
intent.setData(Uri.parse(uriString));
context.startActivity(intent);
}
}
主要的代码就是在MapUtil.java这个工具类中,其中的跳转参数,来至于各个平台的不同类型的地图api的调用,详情可到相应的平台查看。
最后把具体的代码上传,供大家测试。本想直接上传代码,好像不能直接吧工程上传到文末,还要积分下载。
还是把activity_main.xml类的代码也传了,大家自己复制到工程中:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="5dp">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="18sp"
android:text="目的地:泉州市政府"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="18sp"
android:text="经度:118.6758700000"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="18sp"
android:text="纬度:24.8738900000"/>
</LinearLayout>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_above="@id/gaode_map"
android:text="请选择第三方地图导航!"/>
<Button
android:id="@+id/gaode_map"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_above="@id/baidu_map"
android:text="高德地图"/>
<Button
android:id="@+id/baidu_map"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_above="@id/tencent_map"
android:text="百度地图"/>
<Button
android:id="@+id/tencent_map"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:text="腾讯地图"/>
</RelativeLayout>
OK,到此就结束啦!有兴趣的愿意下载的,可以在此下载demo