最近项目中需要添加一个对于目的地的导航功能,查阅了不少资料发现都是比较老的内容于是准备自己写个地图功能,下面直接开始,用到的几个链接:
百度调起app传送门:http://lbsyun.baidu.com/index.php?title=uri
百度网页调起地图传送门:http://lbsyun.baidu.com/index.php?title=uri/api/web
高德调起pp传送门:http://lbs.amap.com/api/amap-mobile/summary/
本文只展示了打点地址的功能,其他功能读者可以自行参考api文档自己研究,首先为了能够调起第三方地图app必须得先判断是否安装了地图app代码如下:
/** * 地图应用是否安装 * @return */ public static boolean isGdMapInstalled(){ return isInstallPackage("com.autonavi.minimap"); } public static boolean isBaiduMapInstalled(){ return isInstallPackage("com.baidu.BaiduMap"); } private static boolean isInstallPackage(String packageName) { return new File("/data/data/" + packageName).exists(); }
这里如果存在就进行跳转,百度跳转如下:
/** * 打开百度地图 */ /** * * @param slat 纬度 * @param slon 经度 * @param content 内容 */ private void openBaiduMap(double slat, double slon, String content) { if (OpenLocalMapUtil.isBaiduMapInstalled()) { try { String uri = OpenLocalMapUtil.getBaiduMapUri(String.valueOf(slat), String.valueOf(slon), content); Intent intent = new Intent(); intent.setData(Uri.parse(uri)); startActivity(intent); //启动调用 isOpened = true; } catch (Exception e) { isOpened = false; e.printStackTrace(); } } else { isOpened = false; } }
高德跳转如下:
/** * 打开高德地图 */ /** * * @param dlat 纬度 * @param dlon 纬度 * @param content 终点 */ private void openGaoDeMap(double dlat, double dlon, String content) { if (OpenLocalMapUtil.isGdMapInstalled()) { try { //百度地图定位坐标转换成高德地图可识别坐标 double[] loca = new double[2]; loca = OpenLocalMapUtil.gcj02_To_Bd09(dlat, dlon); String uri = OpenLocalMapUtil.getGdMapUri(APP_NAME, String.valueOf(loca[0]), String.valueOf(loca[1]), content); Intent intent = new Intent(); intent.setAction(Intent.ACTION_VIEW); intent.addCategory(Intent.CATEGORY_DEFAULT); intent.setPackage("com.autonavi.minimap"); intent.setData(Uri.parse(uri)); startActivity(intent); //启动调用 isOpened = true; } catch (Exception e) { isOpened = false; e.printStackTrace(); } } else { isOpened = false; } }
浏览器打开百度地图:
/** * 打开浏览器进行百度地图导航 */ /** * * @param dlat 纬度 * @param dlon 经度 * @param dname 终点 * @param content 地点内容 */ private void openWebMap(double dlat, double dlon, String dname, String content) { Uri mapUri = Uri.parse(OpenLocalMapUtil.getWebBaiduMapUri( String.valueOf(dlat), String.valueOf(dlon), dname, content, APP_NAME)); Intent loction = new Intent(Intent.ACTION_VIEW, mapUri); startActivity(loction); }
上面我OpenLocalMapUtil是我创建的一个工具类:
public class OpenLocalMapUtil { public static double pi = 3.1415926535897932384626; public static double x_pi = 3.14159265358979324 * 3000.0 / 180.0; public static double a = 6378245.0; public static double ee = 0.00669342162296594323; /** * 地图应用是否安装 * @return */ public static boolean isGdMapInstalled(){ return isInstallPackage("com.autonavi.minimap"); } public static boolean isBaiduMapInstalled(){ return isInstallPackage("com.baidu.BaiduMap"); } private static boolean isInstallPackage(String packageName) { return new File("/data/data/" + packageName).exists(); } public static double transformLat(double x, double y) { double ret = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y + 0.2 * Math.sqrt(Math.abs(x)); ret += (20.0 * Math.sin(6.0 * x * pi) + 20.0 * Math.sin(2.0 * x * pi)) * 2.0 / 3.0; ret += (20.0 * Math.sin(y * pi) + 40.0 * Math.sin(y / 3.0 * pi)) * 2.0 / 3.0; ret += (160.0 * Math.sin(y / 12.0 * pi) + 320 * Math.sin(y * pi / 30.0)) * 2.0 / 3.0; return ret; } public static double transformLon(double x, double y) { double ret = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * Math.sqrt(Math.abs(x)); ret += (20.0 * Math.sin(6.0 * x * pi) + 20.0 * Math.sin(2.0 * x * pi)) * 2.0 / 3.0; ret += (20.0 * Math.sin(x * pi) + 40.0 * Math.sin(x / 3.0 * pi)) * 2.0 / 3.0; ret += (150.0 * Math.sin(x / 12.0 * pi) + 300.0 * Math.sin(x / 30.0 * pi)) * 2.0 / 3.0; return ret; } public static double[] transform(double lat, double lon) { if (outOfChina(lat, lon)) { return new double[]{lat,lon}; } double dLat = transformLat(lon - 105.0, lat - 35.0); double dLon = transformLon(lon - 105.0, lat - 35.0); double radLat = lat / 180.0 * pi; double magic = Math.sin(radLat); magic = 1 - ee * magic * magic; double sqrtMagic = Math.sqrt(magic); dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * pi); dLon = (dLon * 180.0) / (a / sqrtMagic * Math.cos(radLat) * pi); double mgLat = lat + dLat; double mgLon = lon + dLon; return new double[]{mgLat,mgLon}; } //是不是超出中国境内 public static boolean outOfChina(double lat, double lon) { if (lon < 72.004 || lon > 137.8347) return true; if (lat < 0.8293 || lat > 55.8271) return true; return false; } /** * 84 to 火星坐标系 (GCJ-02) World Geodetic System ==> Mars Geodetic System * * @param lat * @param lon * @return */ public static double[] gps84_To_Gcj02(double lat, double lon) { if (outOfChina(lat, lon)) { return new double[]{lat,lon}; } double dLat = transformLat(lon - 105.0, lat - 35.0); double dLon = transformLon(lon - 105.0, lat - 35.0); double radLat = lat / 180.0 * pi; double magic = Math.sin(radLat); magic = 1 - ee * magic * magic; double sqrtMagic = Math.sqrt(magic); dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * pi); dLon = (dLon * 180.0) / (a / sqrtMagic * Math.cos(radLat) * pi); double mgLat = lat + dLat; double mgLon = lon + dLon; return new double[]{mgLat, mgLon}; } /** * * 火星坐标系 (GCJ-02) to 84 * * @param lon * @param lat * @return * */ public static double[] gcj02_To_Gps84(double lat, double lon) { double[] gps = transform(lat, lon); double lontitude = lon * 2 - gps[1]; double latitude = lat * 2 - gps[0]; return new double[]{latitude, lontitude}; } /** * 火星坐标系 (GCJ-02) 与百度坐标系 (BD-09) 的转换算法 将 GCJ-02 坐标转换成 BD-09 坐标 * * @param lat * @param lon */ public static double[] gcj02_To_Bd09(double lat, double lon) { double x = lon, y = lat; 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 tempLon = z * Math.cos(theta) + 0.0065; double tempLat = z * Math.sin(theta) + 0.006; double[] gps = {tempLat,tempLon}; return gps; } /** * * 火星坐标系 (GCJ-02) 与百度坐标系 (BD-09) 的转换算法 * * 将 BD-09 坐标转换成GCJ-02 坐标 * * @param * bd_lat * @param bd_lon * @return */ public static double[] bd09_To_Gcj02(double lat, double lon) { double x = lon - 0.0065, y = lat - 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 tempLon = z * Math.cos(theta); double tempLat = z * Math.sin(theta); double[] gps = {tempLat,tempLon}; return gps; } /**将gps84转为bd09 * @param lat * @param lon * @return */ public static double[] gps84_To_bd09(double lat,double lon){ double[] gcj02 = gps84_To_Gcj02(lat,lon); double[] bd09 = gcj02_To_Bd09(gcj02[0],gcj02[1]); return bd09; } public static double[] bd09_To_gps84(double lat,double lon){ double[] gcj02 = bd09_To_Gcj02(lat, lon); double[] gps84 = gcj02_To_Gps84(gcj02[0], gcj02[1]); //保留小数点后六位 gps84[0] = retain6(gps84[0]); gps84[1] = retain6(gps84[1]); return gps84; } /**保留小数点后六位 * @param num * @return */ private static double retain6(double num){ String result = String .format("%.6f", num); return Double.valueOf(result); } /** *自定义打点 百度 * @param desLat 纬度 * @param desLon 经度 * @param destination 地点名字 * @return */ public static String getBaiduMapUri( String desLat, String desLon, String destination){ String uri = "baidumap://map/marker?location=%1$s,%2$s&title=%3$s&traffic=on"; return String.format(uri,desLat,desLon,destination); } /** * 自定义打点 高德 * @param appname 应用名字 * @param dlat 纬度 * @param dlon 经度 * @param dname 终点名字 * @return */ public static String getGdMapUri(String appname,String dlat, String dlon, String dname){ String uri = "androidamap://navi?sourceApplication=%1$s&poiname=%2$s&lat=%3$s&lon=%4$s&dev=1&style=2"; // return "androidamap://navi?sourceApplication="+appname+"&poiname="+dname+"&lat="+dlat+"&lon="+dlon+"&dev=1&style=2"; return String.format(uri,appname,dname,dlat,dlon); } /** * 自自定义打点 网页百度地图 * @param desLat 纬度 * @param desLon 经度 * @param destination 终点名字 * @param content 终点内容 * @param appName 应用名字 * @return */ public static String getWebBaiduMapUri(String desLat, String desLon, String destination, String content, String appName) { String uri = "http://api.map.baidu.com/marker?location=%1$s,%2$s&title=%3$s&content=%4$s&output=html&src=%5$s"; return String.format(uri, desLat, desLon, destination, content, appName); } }
因为百度和高德坐标不能通用所以在使用前必须进行转换。
demo地址:https://github.com/jiujiu1314/ThirdAppMap