Android集成百度地图SDK

本Demo中所含功能
1:定位,显示当前位置
2:地图多覆盖物(地图描点,弹出该点的详细信息)
3:坐标地址互相换算
4:POI兴趣点检索
5:线路查询(步行,驾车,公交)
6:绘制线路(OpenGL和地图SDK绘制)


百度地图的api:http://lbsyun.baidu.com/

在上述所有的功能中,先完成如下工作:
1、在百度地图API控制台创建AK, 请参考:http://lbsyun.baidu.com/index.php?title=androidsdk/guide/key
2、下载百度地图的SDK。下载链接:http://lbsyun.baidu.com/sdk/download
      根据个人的需要下载相对应的sdk
3、将上面下载的sdk放到自己项目中的对应的Lib下 ,可参考链接:http://lbsyun.baidu.com/index.php?title=androidsdk/guide/buildproject

4、配置AndroidMainfest.xml文件:

  1. < uses-permission android:name ="android.permission.ACCESS_NETWORK_STATE" />  
  2.     <uses-permission android:name ="android.permission.INTERNET" />  
  3.     <uses-permission android:name"com.android.launcher.permission.READ_SETTINGS" />  
  4.     <uses-permission android:name ="android.permission.WAKE_LOCK" />  
  5.     <uses-permission android:name ="android.permission.CHANGE_WIFI_STATE" />  
  6.     <uses-permission android:name ="android.permission.ACCESS_WIFI_STATE" />  
  7.     <uses-permission android:name ="android.permission.GET_TASKS" />  
  8.     <uses-permission android:name"android.permission.WRITE_EXTERNAL_STORAGE" />  
  9.     <uses-permission android:name ="android.permission.WRITE_SETTINGS" />  
  10.   
  11.     <!-- 这个权限用于进行网络定位 -->  
  12.     <uses-permission android:name"android.permission.ACCESS_COARSE_LOCATION" />  
  13.     <!-- 这个权限用于访问GPS定位 -->  
  14.     <uses-permission android:name"android.permission.ACCESS_FINE_LOCATION" />  
  15.     <!-- 用于读取手机当前的状态 -->  
  16.     <uses-permission android:name ="android.permission.READ_PHONE_STATE" />  
  17.     <!-- SD卡读取权限,用户写入离线定位数据 -->  
  18.     <uses-permission android:name"android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />  
  19.     <uses-permission android:name"android.permission.BAIDU_LOCATION_SERVICE" />  
  20.     <uses-permission android:name"android.permission.ACCES_MOCK_LOCATION" />  
  21.     <uses-permission android:name ="android.permission.ACCESS_GPS" />  
  22.     <uses-permission android:name ="android.permission.BROADCAST_STICKY" />  
  23.     <!-- 来电消音 -->  
  24.     <uses-permission android:name"android.permission.PROCESS_OUTGOING_CALLS" />  
  25.     <uses-permission android:name"android.permission.MODIFY_AUDIO_SETTINGS" />  
  26.     <uses-permission android:name ="android.permission.RECORD_AUDIO" />  
  27.     <!-- 摄影机 -->  
  28.     <uses-permission android:name ="android.permission.CAMERA" />  
注:上面的权限是我的项目中所有用到的权限,具体可参考百度地图和定位地图所需要的权限。

还需要配置地图的AK以及定位service:
  1. < meta-data  
  2.     android:name"com.baidu.lbsapi.API_KEY"  
  3.     android:value"API控制台申请到的AK" />  
  4.   
  5. ; service  
  6.     android:name"com.baidu.location.f"  
  7.     android:enabled"true"  
  8.     android:process":remote" >  
  9. </service >  

5、在Application中初始化地图SDK
      SDKInitializer. initialize (getApplicationContext());



1、定位并且显示当前位置
    步骤:1、初始化LocationClient 类 ,并设置定位回调类(通过registerLocationListener()方法
              2、设置定位参数
              3、发起定位
              4、在回调接口中获取定位的信息
代码如下:

  1. import com.baidu.location.BDLocation;  
  2. import com.baidu.location.BDLocationListener;  
  3. import com.baidu.location.LocationClient;  
  4. import com.baidu.location.LocationClientOption;  
  5. import com.baidu.location.LocationClientOption.LocationMode;  
  6. import com.lb.baidumapdemo.db.DBConstants;  
  7. import com.lb.baidumapdemo.db.ShareDB;  
  8. import com.lb.baidumapdemo.face.LocationFace;  
  9.   
  10. import android.content.Context;  
  11.   
  12. /** 
  13.  * @ClassName: LocationFaceUtil 
  14.  * @Description: 定位帮助类,这个类只用来做定位用 
  15.  * @author libiao 
  16.  * @date 2015 -8 -20 下午2:48:07 
  17.  * 
  18.  */  
  19. public class LocationFaceUtil implements BDLocationListener {  
  20.       private LocationFace locationFace; // 这个为自己写的一个接口,用来回调给外部处理  
  21.       public LocationClient mLocationClient = null;  
  22.       private Context context;  
  23.   
  24.       public LocationFaceUtil(Context context, LocationFace locationFace) {  
  25.              super();  
  26.              this. locationFace = locationFace;  
  27.              this. context = context;  
  28.              mLocationClient = new LocationClient(context);  
  29.              mLocationClient.registerLocationListener(LocationFaceUtil. this);  
  30.             startLocation();  
  31.       }  
  32.   
  33.       private void startLocation() {  
  34.             LocationClientOption option = new LocationClientOption();  
  35.             option.setLocationMode(LocationMode. Hight_Accuracy); // 可选,默认高精度,设置定位模式,高精度,低功耗,仅设备  
  36.             option.setCoorType( "bd09ll"); // 可选,默认gcj02,设置返回的定位结果坐标系  
  37.             option.setScanSpan(0); // 可选,默认0,即仅定位一次,设置发起定位请求的间隔需要大于等于1000ms才是有效的  
  38.             option.setIsNeedAddress( true); // 可选,设置是否需要地址信息,默认不需要  
  39.             option.setOpenGps( true); // 可选,默认false,设置是否使用 gps  
  40.             option.setLocationNotify( true); // 可选,默认false,设置是否当 gps有效时按照1S1次频率输出GPS结果  
  41.             option.setIsNeedLocationDescribe( true); // 可选,默认false,设置是否需要位置语义化结果,可以在BDLocation.getLocationDescribe里得到,结果类似于“在北京天安门附近”  
  42.             option.setIsNeedLocationPoiList( true); // 可选,默认false,设置是否需要POI结果,可以在BDLocation.getPoiList里得到  
  43.             option.setIgnoreKillProcess( false); // 可选,默认false,定位SDK内部是一个SERVICE,并放到了独立进程,设置是否在stop的时候杀死这个进程,默认杀死  
  44.             option.SetIgnoreCacheException( false); // 可选,默认false,设置是否收集CRASH信息,默认收集  
  45.             option.setEnableSimulateGps( false); // 可选,默认false,设置是否需要过滤 gps仿真结果,默认需要  
  46.              mLocationClient.setLocOption(option);  
  47.              mLocationClient.start();  
  48.       }  
  49.   
  50.       @Override  
  51.       public void onReceiveLocation(BDLocation arg0) {  
  52.              //注意这里,一定要判断BdLocation的返回值,只有在getLocType()==61或者161的情况下才表示定位成功,具体返回的错误码可参考http://lbsyun.baidu.com/index.php?title=android-locsdk/guide/ermsg  
  53.              if (arg0.getLocType() == 61 || arg0.getLocType() == 161 && arg0.getLatitude() != 0.0) {  
  54.                    //将城市的名字存到SharedPreferences里面  
  55.                    new ShareDB( context).save(DBConstants. CITY_NAME, arg0.getCity());  
  56.                    //将定位结果回调给locationFace的locationResult()方法  
  57.                    locationFace.locationResult(arg0);  
  58.             }  
  59.       }  
  60.   
  61. }  

在调用这个类的时候,我们只需要

  1. new LocationFaceUtil(getApplicationContext(), new LocationFace() {  
  2.   
  3.              @Override  
  4.              public void locationResult(BDLocation location) {  
  5.                    bdLocation = location;  
  6.                   addMarker();  
  7.             }  
  8.       });  


然后回调的信息就全部在这个bdLocation里面了,接着标注当前自己的位置,就是调用的  addMarker()方法
下面代码中的:mBaiduMap= (MapView) findViewById(R.id.  basemap ) .getMap();
  1. private void addMarker() {  
  2.              // 设置地图类型 MAP_TYPE_NORMAL 普通图; MAP_TYPE_SATELLITE 卫星图  
  3.              mBaiduMap.setMapType(BaiduMap. MAP_TYPE_NORMAL);  
  4.              // 开启交通图  
  5.              mBaiduMap.setTrafficEnabled( true);  
  6.              // 设置地图当前级别  
  7.             MapStatusUpdate statusUpdate = MapStatusUpdateFactory.zoomTo(19);  
  8.              mBaiduMap.setMapStatus(statusUpdate);  
  9.              // 构建覆盖物的经纬度  
  10.             LatLng latLng = new LatLng( bdLocation.getLatitude(), bdLocation.getLongitude());  
  11.              //覆盖物显示的图标  
  12.             BitmapDescriptor descriptor = BitmapDescriptorFactory.fromResource(R.drawable. icon_gcoding);  
  13.             OverlayOptions option = new MarkerOptions().position(latLng).icon(descriptor).draggable(true);  
  14.              // 清除地图上所有的覆盖物  
  15.              mBaiduMap.clear();  
  16.              // 将覆盖物添加到地图上  
  17.              mBaiduMap.addOverlay(option);  
  18.              // 将覆盖物设置为地图中心  
  19.             MapStatusUpdate u = MapStatusUpdateFactory.newLatLng(latLng);  
  20.              // 以动画方式更新地图状态,动画耗时 300 ms  
  21.              mBaiduMap.animateMapStatus(u);  
  22.              mBaiduMap.setOnMarkerClickListener(BaseMapActivity. this);  
  23.              mBaiduMap.setOnMarkerDragListener(BaseMapActivity. this);  
  24.       }  

OK,到这里定位显示当前自己的位置的功能就已经完成了


2:地图多覆盖物(地图描点,弹出该点的详细信息
     首先,我构建了四个经纬度的点(实际中需要通过POI检索得到),然后循环将这些点添加到地图界面上,并给这些点设置额外的数据。 最后给覆盖物设置点击事件,在点击事件中弹出弹框
     代码如下:
  1. import android.graphics.Point;  
  2. import android.os.Bundle;  
  3. import android.view.View;  
  4. import android.view.View.OnClickListener;  
  5. import android.widget.TextView;  
  6. import android.widget.Toast;  
  7.   
  8. import com.baidu.mapapi.map.BaiduMap;  
  9. import com.baidu.mapapi.map.BaiduMap.OnMapClickListener;  
  10. import com.baidu.mapapi.map.BaiduMap.OnMarkerClickListener;  
  11. import com.baidu.mapapi.map.BitmapDescriptor;  
  12. import com.baidu.mapapi.map.BitmapDescriptorFactory;  
  13. import com.baidu.mapapi.map.InfoWindow;  
  14. import com.baidu.mapapi.map.MapPoi;  
  15. import com.baidu.mapapi.map.MapStatusUpdate;  
  16. import com.baidu.mapapi.map.MapStatusUpdateFactory;  
  17. import com.baidu.mapapi.map.MapView;  
  18. import com.baidu.mapapi.map.Marker;  
  19. import com.baidu.mapapi.map.MarkerOptions;  
  20. import com.baidu.mapapi.map.OverlayOptions;  
  21. import com.baidu.mapapi.model.LatLng;  
  22. import com.lb.baidumapdemo.R;  
  23. import com.lb.baidumapdemo.base.BaseActivity;  
  24.   
  25. public class MarkerMapActivity extends BaseActivity implements OnMarkerClickListener,OnMapClickListener {  
  26.       private MapView mBaiduMapView; // 地图界面  
  27.       private BaiduMap mBaiduMap; // 地图的管理类  
  28.       private String[] titles = new String[] { "one""two""three""four" };//这是是四个坐标对应的四个信息  
  29.       //要放在地图上的四个坐标  
  30.       private LatLng[] latlngs = new LatLng[] { new LatLng(22.539895,114.058935), new LatLng(22.540729,114.066337),  
  31.                    new LatLng(22.543763,114.06458), new LatLng(22.538614,114.062811) };  
  32.   
  33.       @Override  
  34.       protected void onCreate(Bundle savedInstanceState) {  
  35.              super.onCreate(savedInstanceState);  
  36.             setContentView(R.layout. activity_markermap);  
  37.              mBaiduMapView = (MapView) findViewById(R.id. markermap);  
  38.              mBaiduMap = mBaiduMapView.getMap();  
  39.              //设置地图点击事件  
  40.              mBaiduMap.setOnMapClickListener( this);  
  41.             initMarker();  
  42.       }  
  43.   
  44.       private void initMarker() {  
  45.              mBaiduMap.clear();   
  46.             LatLng latLng = null;  
  47.             OverlayOptions overlayOptions = null;  
  48.              // 设置地图类型 MAP_TYPE_NORMAL 普通图; MAP_TYPE_SATELLITE 卫星图  
  49.              mBaiduMap.setMapType(BaiduMap. MAP_TYPE_NORMAL);  
  50.              // 开启交通图  
  51.              mBaiduMap.setTrafficEnabled( true);  
  52.             MapStatusUpdate statusUpdate = MapStatusUpdateFactory.zoomTo(17);  
  53.              mBaiduMap.setMapStatus(statusUpdate);  
  54.             BitmapDescriptor descriptor = BitmapDescriptorFactory.fromResource(R.drawable. icon_gcoding);  
  55.              //循环添加四个覆盖物到地图上  
  56.              for ( int i = 0; i < titles. length; i++) {  
  57.                   latLng= latlngs[i];  
  58.                   overlayOptions = new MarkerOptions().position(latLng).icon(descriptor);  
  59.                    // 将覆盖物添加到地图上  
  60.                   Marker marker=(Marker) mBaiduMap.addOverlay(overlayOptions);  
  61.                   Bundle bundle = new Bundle();  
  62.                   bundle.putString( "info", titles[i]+ "个");  
  63.                   marker.setExtraInfo(bundle);  
  64.             }  
  65.              // 将最后一个坐标设置为地图中心  
  66.             MapStatusUpdate u = MapStatusUpdateFactory.newLatLng(latLng);  
  67.              mBaiduMap.setMapStatus(u);  
  68.              //设置地图覆盖物的点击事件  
  69.              mBaiduMap.setOnMarkerClickListener(MarkerMapActivity. this);  
  70.               
  71.       }  
  72.   
  73.       /** 
  74.        * @Title: onMarkerClick 
  75.        * @Description: 覆盖物点击事件,每次点击一个覆盖物则会在相应的覆盖物上显示一个InfoWindow 
  76.        * @param marker 
  77.        * @return 
  78.        */  
  79.       @Override  
  80.       public boolean onMarkerClick(Marker marker) {  
  81.              final String msg = marker.getExtraInfo().getString( "info");  
  82.             InfoWindow mInfoWindow;  
  83.              // 生成一个TextView用户在地图中显示InfoWindow  
  84.             TextView location = new TextView(getApplicationContext());  
  85.             location.setBackgroundResource(R.drawable. shape_popup);  
  86.             location.setPadding(30203020);  
  87.             location.setText(msg);  
  88.              //构建弹框所在的经纬度,  
  89.              final LatLng ll = marker.getPosition();  
  90.             Point p = mBaiduMap.getProjection().toScreenLocation(ll);  
  91.             p. y -= 47//让弹框在Y轴偏移47  
  92.             LatLng llInfo = mBaiduMap.getProjection().fromScreenLocation(p);  
  93.              //根据上面配置好的参数信息,构造一个InfoWindow。  
  94.             mInfoWindow = new InfoWindow(location, llInfo, -47);  
  95.              //构建好之后,然后调用show的方法,让弹框显示出来  
  96.              mBaiduMap.showInfoWindow(mInfoWindow);  
  97.              //弹框点击事件-  
  98.             location.setOnClickListener( new OnClickListener() {  
  99.   
  100.                    @Override  
  101.                    public void onClick(View v) {  
  102.                         Toast. makeText(MarkerMapActivity.this, msg, Toast.LENGTH_SHORT).show();  
  103.                   }  
  104.             });  
  105.              return true;  
  106.       }  
  107.         
  108.       /** 
  109.        * @Title: onMapClick 
  110.        * @Description: 地图点击事件,点击地图的时候要让InfoWindow消失 
  111.        * @param arg0 
  112.        */  
  113.       @Override  
  114.       public void onMapClick(LatLng arg0) {  
  115.              mBaiduMap.hideInfoWindow();  
  116.               
  117.       }  
  118.         
  119.       /** 
  120.        * @Title: onMapPoiClick 
  121.        * @Description: 兴趣点点击事件 
  122.        * @param arg0 
  123.        * @return 
  124.        */  
  125.       @Override  
  126.       public boolean onMapPoiClick(MapPoi arg0) {  
  127.              return false;  
  128.       }  
  129.   
  130. }  


3:坐标地址互相换算
     在很多请求当中只会返回经纬度的坐标,并不会返回具体的信息,这个时候需要用到坐标换算成地址。
     坐标反转类:GeoCoder类,我们可以看一下这个类的方法:


 根据上图的方法说明,其实我们需要做的就明白了
  第一步:初始化GeoCoder类(调用newInstance())
  第二步:设置查询结果监听
  第三步:发起请求
 实际核心代码:
         
  1. private GeoCoder geoCoder; // 经纬度地理位置坐标反转类  
  2.     geoCoder = GeoCoder. newInstance();  
  3.      geoCoder.setOnGetGeoCodeResultListener( this); // 设置反地理查询监听器  
  4.           geoCoder.reverseGeoCode(new ReverseGeoCodeOption().location(arg0.getPosition()));  

  这里是根据经纬度来获取地址信息
   然后在下面的方法里面回调:

  1. /** 
  2.  * @Title: onGetGeoCodeResult 
  3.  * @Description: 坐标换算 根据地址得到坐标 
  4.  * @param arg0 
  5.  */  
  6. @Override  
  7. public void onGetGeoCodeResult(GeoCodeResult arg0) {  
  8.   
  9. }  
  10.   
  11. /** 
  12.  * @Title: onGetReverseGeoCodeResult 
  13.  * @Description: 坐标换算,根据坐标得到地质 
  14.  * @param arg0 
  15.  */  
  16. @Override  
  17. public void onGetReverseGeoCodeResult(ReverseGeoCodeResult arg0) {  
  18.      //根据上面的请求之后,回调会进入到这个方法里面来,然后在所有的地址信息在ReverseGeoCodeResult 当中  
  19. }  

4:POI兴趣点检索
    1、初始化PoiSearch类,构造检索的参数
           检索,可以分为四种类型的检索,根据我们自己不同的需求,需要调用不同的方法,并传入不同的参数


   这里我们先看一下范围内检索:  searchInBound ( PoiBoundSearchOption  option)
                                                PoiBoundSearchOption类,他有四个方法,入下图所示,这里的pageNum是从0开始的! 
                                                 在设置pageCapacity的时候,我在测试的过程中最大是50条,超过50默认就返回了10条(这个版本的是50),其他的参数就不多说了。
              其他的三个检索的方法,和这个大同小异,想要详细的了解可以参考:http://wiki.lbsyun.baidu.com/cms/androidsdk/doc/v3_7_0/


     2、设置Search回调接口
    3、发起搜索
             核心代码如下:
  1.        private PoiSearch mSearch ;// 搜索类  
  2.        private int pageNum = 0// 搜索的页数-  
  3.     private void startPointSearch () {  
  4.         mSearch = PoiSearch.newInstance();  
  5.        mSearch.setOnGetPoiSearchResultListener(this); // 检索回调  
  6.       PoiNearbySearchOption option = new PoiNearbySearchOption();  
  7.       option.location( new LatLng( mLocation.getLatitude(), mLocation.getLongitude())); // 设置检索的中心点  
  8.       option.pageCapacity(50); // 设置检索的返回的每页的内容的条数  
  9.       option.pageNum( pageNum);  
  10.       option.radius(30000); // 设置检索的范围,半径。米为单位  
  11.       option.sortType(PoiSortType. distance_from_near_to_far);// 设置排序由近到远  
  12.       option.keyword( "美食");// 搜索关键字  
  13.        mSearch.searchNearby(option); // 开始检索  
  14.        pageNum++;  
  15. }  
  16.   
  17.  @Override  
  18. public void onGetPoiDetailResult(PoiDetailResult arg0) {  
  19.   
  20. }  
  21.   
  22. // Poi检索的回调,所有回调的结果都在这个PoiResult里面,我们可以得到很多参数的信息  
  23. @Override  
  24. public void onGetPoiResult(PoiResult arg0) {  
  25.         
  26.   
  27. }  

上面的代码中,onGetPoiResult(PoiResult arg0)方法中的PoiResult所携带的方法如下:所以可以根据我们自己不同的需求来进行得到信息进行处理。
比如:通过getAllPoi方法,可以得到


5:线路查询(步行,驾车,公交)
    根据4我们可以得到两个POI兴趣点,然后我们就可以查询这两个点的线路
    线路查询的关键类: RoutePlanSearch 


 从上述api中我们可以看到,线路规划分为四条线路(以前没有发起骑行规划线路) ,在上面的四个发起线路的方法中,都需要传入一个参数,这里我就只讲解一下 transitSearch ( TransitRoutePlanOption  option)
这里面需要传入一个TransitRouterPlanOption对象,我们来看一下这个对象所有的方法:


然后我们看到,最重要的就是这个类:PlanNode这个类,这个类不仅在 TransitRouterPlanOption的方法中需要用到,在骑行线路、驾车线路、步行线路的方法中所需的对象中也都是需要设置PlanNode。
PlanNode解释: 路径规划中的出行节点信息,出行节点包括:起点,终点,途经点, 出行节点信息可以通过两种方式确定: 1: 给定出行节点经纬度坐标   2: 给定出行节点地名和城市名
so,我们可以根据自己的具体实际需求来设置这些参数:


看完API的解释之后,调用方法:
1、初始化RouterPlanSearch类,并设置回调接口
2、设置线路参数信息,发起线路查询

下面的代码,是通过地点信息来进行线路查询:

  1. private void startRouterResult( int type, String startAddr, String endAddr) {  
  2.      String cityName = new ShareDB(SearchInfoActivity.this ).getValue(DBConstants. CITY_NAME);  
  3.      PlanNode stNode = PlanNode.withCityNameAndPlaceName(cityName, startAddr);  
  4.      PlanNode enNode = PlanNode.withCityNameAndPlaceName(cityName, endAddr);  
  5.       if (type == 1) {  
  6.             routeSearch .transitSearch(new TransitRoutePlanOption().from(stNode).to(enNode).city(cityName));  
  7.      } else if (type == 2) {  
  8.             routeSearch .drivingSearch(new DrivingRoutePlanOption().from(stNode).to(enNode));  
  9.      } else if (type == 3) {  
  10.             routeSearch .walkingSearch(new WalkingRoutePlanOption().from(stNode).to(enNode));  
  11.      }  

下面的代码是用过经纬度来进行线路查询的:

  1. private void startRouterResult( final int type, LatLng beLat, LatLng endLat) {  
  2.       /*** 
  3.       * 此处应该判断传递过来的经纬度是不是空的,因为有可能不是在listInfo集合里面取出来的数据,如果为空,就要根据控件上的文字,进行坐标反查 
  4.       * ,得到坐标,然后再调用这个方法 ||如果经纬度为空,则用地址信息来进行线路的查询,不过此时查询出来的结果可能为空 
  5.       **/  
  6.       if ( beLat != null && endLat != null) {  
  7.            String cityName = new ShareDB(SearchInfoActivity.this ).getValue(DBConstants. CITY_NAME);  
  8.            PlanNode stNode = PlanNode. withLocation(beLat );  
  9.            PlanNode enNode = PlanNode. withLocation(endLat);  
  10.             if (type == 1) {  
  11.                   routeSearch.transitSearch( new TransitRoutePlanOption().from(stNode).to(enNode).city(cityName));  
  12.            } else if (type == 2) {  
  13.                   routeSearch.drivingSearch( new DrivingRoutePlanOption().from(stNode).to(enNode));  
  14.            } else if (type == 3) {  
  15.                   routeSearch.walkingSearch( new WalkingRoutePlanOption().from(stNode).to(enNode));  
  16.            }  
  17.      }   

OK,下面就是获取结果的代码了:

  1. /******************** 线路查询返回的结果 ***********************/  
  2. // 因DrivingRouteResult、TransitRouteResult、WalkingRouteResult都是继承SearchResult,没有实现序列化,所以无法通过bundle来进行传递到下一个页面。  
  3. // 1、可以通过自定义Model类来对数据进行封装,实现序列化的接口来传递给下个界面  
  4. // 2、可以通过在Application类里定义这三个类的对象,然后再此处赋值,在下一个界面的时候就直接得到(本次就是用的这个方法)  
  5. @Override  
  6. public void onGetDrivingRouteResult(DrivingRouteResult drivingRouteResult) {  
  7.      closeDialog();  
  8.       if (drivingRouteResult. error.toString().equals( "NO_ERROR")) {  
  9.            BaseApplication. drivingRouteResult = drivingRouteResult;  
  10.            startIntent(2);  
  11.      } else {  
  12.            Toast. makeText(SearchInfoActivity. this"未找到路线,请重新选择起点或者终点" , Toast. LENGTH_SHORT).show();  
  13.      }  
  14.   
  15.   
  16. @Override  
  17. public void onGetTransitRouteResult(TransitRouteResult transitRouteResult) {  
  18.      closeDialog();  
  19.       if (transitRouteResult. error.toString().equals( "NO_ERROR")) {  
  20.            BaseApplication. transitRouteResult = transitRouteResult;  
  21.            startIntent(1);  
  22.      } else {  
  23.            Toast. makeText(SearchInfoActivity. this"未找到路线,请重新选择起点或者终点" , Toast. LENGTH_SHORT).show();  
  24.      }  
  25.   
  26.   
  27. @Override  
  28. public void onGetWalkingRouteResult(WalkingRouteResult walkingRouteResult) {  
  29.      closeDialog();  
  30.       if (walkingRouteResult. error.toString().equals( "NO_ERROR")) {  
  31.            BaseApplication. walkingRouteResult = walkingRouteResult;  
  32.            startIntent(3);  
  33.      } else {  
  34.            Toast. makeText(SearchInfoActivity. this"未找到路线,请重新选择起点或者终点" , Toast. LENGTH_SHORT).show();  
  35.      }  
线路规划就到这里结束了,接着就是线路的绘制了。


6:绘制线路(OpenGL和地图SDK绘制)
  步骤:1、得到经纬度集合,从5中线路查询中得到的结果,比如 WalkingRouteResult. getRouteLines() 会返回一个 List<WalkingRouteLine>集合。将这个集合强行转为父类集合List<RouterLine>
              2、得到List<RouterLine> 之后,得到其中一个RouterLine对象(就是其中一条线路),调用RouterLine .getAllStep().get(i). getWayPoints();
                     其中i为线路中的某一段线路,如果需要全部绘制完成,则循环i取出所有的WayPoints()即可

             3、getWayPoint()返回的是 List <LatLng>集合,根据经纬度集合,我们就可以开始绘制线路了
             4、绘制线路
  1. List<LatLng> listLat = (List<LatLng>) getIntent().getSerializableExtra( "latlng" );//得到经纬度集合  
  2.      // 设置地图类型 MAP_TYPE_NORMAL 普通图; MAP_TYPE_SATELLITE 卫星图  
  3.  mBaiduMap.setMapType(BaiduMap. MAP_TYPE_NORMAL);  
  4.  // 开启交通图  
  5.  mBaiduMap.setTrafficEnabled( true);  
  6. MapStatusUpdate statusUpdate = MapStatusUpdateFactory.zoomTo(19);  
  7.  mBaiduMap.setMapStatus(statusUpdate);  
  8. MyLatLng myLatLng = listLat.get(0);  
  9. MapStatusUpdate u = MapStatusUpdateFactory. newLatLng( new LatLng(myLatLng.getLatitude(), myLatLng.getLongitude()));  
  10.  mBaiduMap.setMapStatus(u);  

 绘制线路的两种办法:
1、OpenGL绘制,代码如下:
  1. mBaiduMap .setOnMapDrawFrameCallback(callback );  
  2. *************** 使用OpenGl绘制,是出现Bug,坐标的转换和屏幕上的点的转换,会随着地图大小的拉伸,OpenGl的线不拉伸的情况,建议不要使用此方法 *********************/  
  3.  // 定义地图绘制每一帧时 OpenGL 绘制的回调接口  
  4. OnMapDrawFrameCallback callback = new OnMapDrawFrameCallback() {  
  5.        public void onMapDrawFrame(GL10 gl, MapStatus drawingMapStatus) {  
  6.              if ( mBaiduMap.getProjection() != null) {  
  7.                    // 计算折线的 opengl 坐标  
  8.                   calPolylinePoint(drawingMapStatus);  
  9.                    // 绘制折线  
  10.                   drawPolyline(gl, Color. argb(25525500), vertexBuffer, 103, drawingMapStatus);  
  11.             }  
  12.       }  
  13. };  
  14.   
  15.  // 计算折线 OpenGL 坐标  
  16.  public void calPolylinePoint(MapStatus mspStatus) {  
  17.       PointF[] polyPoints = new PointF[ listLat.size()];  
  18.        vertexs = new float[3 * listLat.size()];  
  19.        int i = 0;  
  20.        for (MyLatLng xy : listLat) {  
  21.              // 将地理坐标转换成 openGL 坐标  
  22.             polyPoints[i] = mBaiduMap.getProjection().toOpenGLLocation( new LatLng(xy.getLatitude(), xy.getLongitude()), mspStatus);  
  23.              vertexs[i * 3] = polyPoints[i]. x;  
  24.              vertexs[i * 3 + 1] = polyPoints[i]. y;  
  25.              vertexs[i * 3 + 2] = 0.0f;  
  26.             i++;  
  27.       }  
  28.        vertexBuffer = makeFloatBuffer( vertexs);  
  29. }  
  30.   
  31.  // 创建OpenGL绘制时的顶点Buffer  
  32.  private FloatBuffer makeFloatBuffer( float[] fs) {  
  33.       ByteBuffer bb = ByteBuffer. allocateDirect(fs. length * 4);  
  34.       bb.order(ByteOrder. nativeOrder());  
  35.       FloatBuffer fb = bb.asFloatBuffer();  
  36.       fb.put(fs);  
  37.       fb.position(0);  
  38.        return fb;  
  39. }  
  40.   
  41.  // 绘制折线  
  42.  private void drawPolyline(GL10 gl, int color, FloatBuffer lineVertexBuffer, float lineWidth, int pointSize, MapStatus drawingMapStatus) {  
  43.   
  44.       gl.glEnable(GL10. GL_BLEND);  
  45.       gl.glEnableClientState(GL10. GL_VERTEX_ARRAY);  
  46.   
  47.       gl.glBlendFunc(GL10. GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA );  
  48.   
  49.        float colorA = Color. alpha(color) / 255f;  
  50.        float colorR = Color. red(color) / 255f;  
  51.        float colorG = Color. green(color) / 255f;  
  52.        float colorB = Color. blue(color) / 255f;  
  53.   
  54.       gl.glVertexPointer(3, GL10. GL_FLOAT, 0, lineVertexBuffer);  
  55.       gl.glColor4f(colorR, colorG, colorB, colorA);  
  56.       gl.glLineWidth(lineWidth);  
  57.       gl.glDrawArrays(GL10. GL_LINE_STRIP, 0, pointSize);  
  58.   
  59.       gl.glDisable(GL10. GL_BLEND);  
  60.       gl.glDisableClientState(GL10. GL_VERTEX_ARRAY);  
  61. }  


2、利用SDK绘制点、线、多边形

  1. /** 
  2.              * 地图SDK提供多种结合图形覆盖物,利用这些图形,可帮助您构建更加丰富多彩的地图应用。目前提供的几何图形有:点(Dot)、折线( 
  3.              * Polyline)、弧线(Arc)、圆(Circle)、多边形(Polygon)。 此处绘制折线 
  4.              */  
  5.             OverlayOptions polygonOption = new PolylineOptions().points(listLat ).color(Color.parseColor( "#FF0000")).width(7);  
  6.              // 在地图上添加多边形Option,用于显示  
  7.              mBaiduMap.addOverlay(polygonOption);  


这个百度地图的集成的时间大概是2015年9月,所以SDK和最新的肯定多多少少有点差异的。
GitHub下载地址(AndroidStudio):http://download.csdn.net/detail/q908555281/9472070
CSDN下载地址(Eclipse):    http://download.csdn.net/detail/q908555281/9472070

本Demo用的百度的Key为私人的,如果要正常运行,得自己去百度地图控制台申请Key,来替换Mainfest中的key
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1.需要在 http://developer.baidu.com/ 注册开发者(个人或公司)账号 2.需要申请Key 打开网址 http://developer.baidu.com/map/index.php 点击 创建应用,跟流程创建应用app 3.点击相关下载->一键下载 4.调用百度地图的APP 需要在 AndroidManifest.xml 添加 <application android:name="baidumapsdk.demo.DemoApplication" android:icon="@drawable/ic_launcher" android:label="@string/app_name" > 这里需要添加key,创建应用后,会有这个key <meta-data android:name="com.baidu.lbsapi.API_KEY" android:value="6t2yuIFylnRG7ECj1xHYuelY" /> ..... package com.obtk.mapdemo; import com.baidu.location.BDLocation; import com.baidu.location.BDLocationListener; import com.baidu.location.LocationClient; import com.baidu.location.LocationClientOption; import com.baidu.mapapi.SDKInitializer; import com.baidu.mapapi.map.BaiduMap; import com.baidu.mapapi.map.BaiduMapOptions; import com.baidu.mapapi.map.MapStatusUpdate; import com.baidu.mapapi.map.MapStatusUpdateFactory; import com.baidu.mapapi.map.MapView; import com.baidu.mapapi.map.MyLocationData; import com.baidu.mapapi.map.MyLocationConfiguration.LocationMode; import com.baidu.mapapi.model.LatLng; import com.baidu.mapapi.search.core.SearchResult; import com.baidu.mapapi.search.geocode.GeoCodeResult; import com.baidu.mapapi.search.geocode.GeoCoder; import com.baidu.mapapi.search.geocode.OnGetGeoCoderResultListener; import com.baidu.mapapi.search.geocode.ReverseGeoCodeOption; import com.baidu.mapapi.search.geocode.ReverseGeoCodeResult; import android.os.Bundle; import android.util.Log; import android.view.Menu; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.RelativeLayout; import android.widget.Toast; import android.app.Activity; import com.obtk.mapdemo.R; public class MapApiDemoActivity extends Activity implements OnGetGeoCoderResultListener { private MapView mMapView = null; private BaiduMap mBaiduMap = null; private GeoCoder mSearch = null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // SDK初始化 SDKInitializer.initialize(getApplicationContext()); //当前视图 setContentView(R.layout.activity_map_api_demo); //创建地图对象 init(); final Button btn_location = (Button) findViewById(R.id.btn_location); btn_location.setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { // TODO Auto-generated method stub getLocation(); btn_location.setEnabled(false); } }); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.activity_map_api_demo, menu); return true; } /** * 初始化方法 */ private void init() { //mMapView = (MapView) findViewById(R.id.bmapview); mMapView = new MapView(this, new BaiduMapOptions()); mBaiduMap = mMapView.getMap(); /**添加一个对象*/ RelativeLayout rlly_map = (RelativeLayout)findViewById(R.id.rlly_map); rlly_map.addView(mMapView); // 开启定位图层 mBaiduMap.setMyLocationEnabled(true); //初始化搜索模块,注册事件监听 mSearch = GeoCoder.newInstance(); mSearch.setOnGetGeoCodeResultListener(this); } @Override protected void onResume() { super.onResume(); mMapView.onResume(); } @Override protected void onPause() { super.onPause(); mMapView.onPause(); } @Override protected void onDestroy() { // 退出时销毁定位 mLocClient.stop(); // 关闭定位图层 mBaiduMap.setMyLocationEnabled(false); mMapView.onDestroy(); mMapView = null; super.onDestroy(); } // 定位相关 LocationClient mLocClient; public MyLocationListenner myListener = new MyLocationListenner(); private LocationMode mCurrentMode; private boolean isFirstLoc = true; /** * 定位SDK监听函数 */ public class MyLocationListenner implements BDLocationListener { @Override public void onReceiveLocation(BDLocation location) { // map view 销毁后不在处理新接收的位置 if (location == null || mMapView == null) return; MyLocationData locData = new MyLocationData.Builder() .accuracy(location.getRadius()) //此处设置开发者获取到的方向信息,顺时针0-360 .direction(100).latitude(location.getLatitude()) .longitude(location.getLongitude()).build(); mBaiduMap.setMyLocationData(locData); if (isFirstLoc) { isFirstLoc = false; LatLng ll = new LatLng(location.getLatitude(), location.getLongitude()); MapStatusUpdate u = MapStatusUpdateFactory.newLatLng(ll); mBaiduMap.animateMapStatus(u); } String addr = location.getAddrStr(); if (addr != null) { Log.i("Test", addr); } else { Log.i("Test","error"); } double longitude = location.getLongitude(); double latitude = location.getLatitude(); if (longitude > 0 && latitude > 0) { Log.i("Test",String.format("纬度:%f 经度:%f", latitude,longitude)); LatLng ptCenter = new LatLng(latitude,longitude); // 反Geo搜索 mSearch.reverseGeoCode(new ReverseGeoCodeOption() .location(ptCenter)); } //停止定位 mLocClient.stop(); } public void onReceivePoi(BDLocation poiLocation) { } } private void getLocation() { // 定位初始化 mLocClient = new LocationClient(this); mLocClient.registerLocationListener(myListener); LocationClientOption option = new LocationClientOption(); option.setOpenGps(true);//打开gps option.setCoorType("bd09ll"); //设置坐标类型 option.setScanSpan(5000); //定位时间间隔 mLocClient.setLocOption(option); mLocClient.start(); } @Override public void onGetGeoCodeResult(GeoCodeResult arg0) { // TODO Auto-generated method stub } @Override public void onGetReverseGeoCodeResult(ReverseGeoCodeResult result) { // TODO Auto-generated method stub if (result == null || result.error != SearchResult.ERRORNO.NO_ERROR) { Toast.makeText(MapApiDemoActivity.this, "抱歉,未能找到结果", Toast.LENGTH_LONG) .show(); return; } mBaiduMap.clear(); // mBaiduMap.addOverlay(new MarkerOptions().position(result.getLocation()) // .icon(BitmapDescriptorFactory // .fromResource(R.drawable.icon_marka))); mBaiduMap.setMapStatus(MapStatusUpdateFactory.newLatLng(result .getLocation())); Toast.makeText(MapApiDemoActivity.this, result.getAddress(), Toast.LENGTH_LONG).show(); String province = result.getAddressDetail().province; String city = result.getAddressDetail().city; if (province != null && city != null) { } } }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值