地图导航算是一个比较鸡肋的功能(有这个需求的可以直接在百度网站上查看,还是比较好看懂的,
http://developer.baidu.com/map/index.php?title=android-navsdk),而且要集成百度地图并不是一件让人很愉快的事情(各种KEY的申请,超大的os文件,API升级),比较严重是为了兼容各种芯片,需要放5分os文件,让app的大小显著的增加(我们最初的app只有5M,集成后有20多),其次是导航界面和app本身的风格不和,显得不协调,修改起来也不容易。
今天研究了一下其他方法。
一、调用第三方地图
//调起地图(所有)try {//geo:latitude,longitude//geo:latitude,longitude?z=zoom,z表示zoom级别,值为数字1到23//geo:0,0?q=my+street+address//geo:0,0?q=business+near+city//"geo:39.940409,116.355257?q=西直门"Uri mUri = Uri . parse ( String . format ( "geo:%s,%s?q=%s" , entity . getLatitude (), entity . getLongitude (), entity . getPopContent ()));Intent mIntent = new Intent ( Intent . ACTION_VIEW , mUri );startActivity ( mIntent );}catch ( BaiduMapAppNotSupportNaviException e ) {e . printStackTrace ();}
执行上述代码,会弹出选择框,显示手机安装了的所有的地图软件,让用户选择,需要注意的是,如果用户一个地图软件都没有装,可能会报错,所以需要
try/catch一下,防止崩溃。
不过这个方法遇到了一些问题。
1)启动的app只是简单的打开了地图并定位,并没有进入导航模式。(其实这个无关紧要)
2)我们使用百度地图定位SDK获得的经纬度,当用其他的地图去打开时有比较明显的偏差,比如用高德地图打开,偏差大约有1公里,这个不能接受。
所以我们不能调用所有的地图,只能打开百度地图。
二、调用百度地图
//调起百度地图导航try {String url = String . format ( "intent://map/direction?origin=latlng:%s,%s|name:%s&destination=%s&mode=driving&src=%s|%s#Intent;scheme=bdapp;package=com.baidu.BaiduMap;end" , entity . getLongitude (), entity . getLatitude (), "我的位置" , merName , "合时代" , "com.heshidai.HSD" ) ;startActivity ( Intent . getIntent ( url )); //启动} catch ( Exception e ) {e . printStackTrace ();}
这里用到的方法其实和第一个没有很大的区别,主要是url不一样。
这个url可以百度开发者平台上面找到,专门用于开启百度地图的导航功能。
http://developer.baidu.com/map/wiki/index.php?title=uri/api/android
但是用户没有安百度地图app怎么办?
网页版百度地图!
开发者平台上面有用浏览器打开百度地图网页版,在catch方法中调用浏览器去打开百度地图就好了。
简单了实现了一下(应该加入跳转提示)
//调起百度地图导航try {String url = String . format ( "intent://map/direction?origin=latlng:%s,%s|name:%s&destination=%s&mode=driving&src=%s|%s#Intent;scheme=bdapp;package=com.baidu.BaiduMap;end" , entity . getLongitude (), entity . getLatitude (), "我的位置" , merName , "合时代" , "com.heshidai.HSD" );startActivity ( Intent . getIntent ( url )); //启动} catch ( Exception e ) {try {String url = String . format ( "http://api.map.baidu.com/mobile/direction?origin=latlng:%s,%s|name:%s&destination=%s &mode=driving&output=html&src=%s|%s" , entity . getLongitude (), entity . getLatitude (), "我的位置" , merName , "合时代" , "超嘀折" );Intent intent = new Intent ( Intent . ACTION_VIEW );intent . setData ( Uri . parse ( url ));startActivity ( intent );} catch ( Exception e1 ) {e . printStackTrace ();}}
注意,浏览器使用的url和地图app用的url不一样,浏览器中使用的在
http://developer.baidu.com/map/wiki/index.php?title=uri/api/web 中可以找到。
三、使用百度SDK
ios的同事说百度SDk中有方法可以调用百度地图,赶紧查一下,还真有。(上面的工作都白做了)
在
http://developer.baidu.com/map/index.php?title=androidsdk/guide/tool (
Android SDK
> 开发指南
> 计算工具)中找到了 “调启百度地图”
不过需要注意是这个文档有个地方会误导人(还真心坑啊,一开始整个组都没看出来) :公交线路规划调启百度地图 中的 setSupportWebRoute方法 对步行/骑行导航调启百度地图 不起作用 ,导航中应该使用
BaiduMapNavigation.setSupportWebNavi(false); 来设置设 步行/骑行导航调启百度地图 是否可以调用WebApp。
// 起始位置坐标double mLat1 = bdLocation . getLatitude ();double mLon1 = bdLocation . getLongitude ();// 目标位置坐标double mLat2 = Double . valueOf ( entity . getLatitude ());double mLon2 = Double . valueOf ( entity . getLongitude ());LatLng pt1 = new LatLng ( mLat1 , mLon1 );LatLng pt2 = new LatLng ( mLat2 , mLon2 );// 构建 导航参数NaviParaOption para = new NaviParaOption (). startPoint ( pt1 ). endPoint ( pt2 ). startName ( "我的位置" ). endName ( merName );try {// 调起百度地图导航BaiduMapNavigation . setSupportWebNavi ( true ); //设置如果没有安装百度地图或者百度地图版本太低,是否调用网页版BaiduMapNavigation . openBaiduMapWalkNavi ( para , this ); //调启百度地图} catch ( BaiduMapAppNotSupportNaviException e ) {e . printStackTrace ();}
这里再强调一遍:
公交线路规划调启百度地图 是
BaiduMapRoutePlan 其中设置是否调用网页版 是
setSupportWebRoute
而步行/骑行导航调启百度地图 是
BaiduMapNavigation 其中设置是否调用网页版 是
setSupportWebNavi
不要弄错了
百度的demo中还提供了另外一个思路,如果没有安装百度地图,让用户去下载百度地图,
/*** 提示未安装百度地图app或app版本过低*/public void showDialog () {AlertDialog . Builder builder = new AlertDialog . Builder ( this );builder . setMessage ( "您尚未安装百度地图app或app版本过低,点击确认安装?" );builder . setTitle ( "提示" );builder . setPositiveButton ( "确认" , new OnClickListener () {@Overridepublic void onClick ( DialogInterface dialog , int which ) {dialog . dismiss ();OpenClientUtil . getLatestBaiduMapApp ( OpenBaiduMap . this );}});builder . setNegativeButton ( "取消" , new OnClickListener () {@Overridepublic void onClick ( DialogInterface dialog , int which ) {dialog . dismiss ();}});builder . create (). show ();}
OpenClientUtil
.
getLatestBaiduMapApp
(
OpenBaiduMap
.
this
); 方法其实就是调用浏览器开启百度地图下载的网页。
四、其他
1、打开源码,可以发现,其实第二种方法和第三种方法是一样的,只是百度SDK将url的拼装封装了起来,做了一些限制判断。
/** @deprecated */@Deprecatedpublic static void openWebBaiduMapNavi ( NaviParaOption var0 , Context var1 ) throws IllegalNaviArgumentException {if ( var0 != null && var1 != null ) {if ( var0 . a != null && var0 . c != null ) {GeoPoint var7 = CoordUtil . ll2mc ( var0 . a );GeoPoint var8 = CoordUtil . ll2mc ( var0 . c );StringBuilder var9 = new StringBuilder ();var9 . append ( "http://daohang.map.baidu.com/mobile/#navi/naving/start=" );var9 . append ( var7 . getLongitudeE6 ());var9 . append ( "," );var9 . append ( var7 . getLatitudeE6 ());var9 . append ( "&endp=" );var9 . append ( var8 . getLongitudeE6 ());var9 . append ( "," );var9 . append ( var8 . getLatitudeE6 ());var9 . append ( "&fromprod=" );var9 . append ( a ( var1 ));var9 . append ( "/vt=map&state=entry" );Uri var5 = Uri . parse ( var9 . toString ());Intent var6 = new Intent ();var6 . setAction ( "android.intent.action.VIEW" );var6 . setFlags ( 268435456 );var6 . setData ( var5 );var1 . startActivity ( var6 );} else {if ( var0 . b == null || var0 . b . equals ( "" ) || var0 . d == null || var0 . d . equals ( "" )) {throw new IllegalNaviArgumentException ( "you must set start and end point or set the start and end name." );}StringBuilder var2 = new StringBuilder ();var2 . append ( "http://daohang.map.baidu.com/mobile/#search/search/qt=nav&sn=2$$$$$$" );var2 . append ( var0 . b );var2 . append ( "$$$$$$&en=2$$$$$$" );var2 . append ( var0 . d );var2 . append ( "$$$$$$&fromprod=" );var2 . append ( a ( var1 ));Uri var3 = Uri . parse ( var2 . toString ());Intent var4 = new Intent ();var4 . setAction ( "android.intent.action.VIEW" );var4 . setData ( var3 );var1 . startActivity ( var4 );}} else {throw new IllegalNaviArgumentException ( "para or context can not be null." );}}
2、关于不同地图软件获取的坐标有偏差的问题,
百度地图有将其他地图获取的坐标装换为百度地图自己的坐标的方法,但是没有将百度坐标转换为其他地图坐标的方法(艹)。
所以如果你的app中使用其他地位控件获取坐标的,可以通过util中的方法转换,然后在调用百度地图app,
如果你是用百度地图定位的,想传到其他地图app中,直接用有误差,想转换计算,得看其他app有没有提供这样的算法了。