4、配置AndroidMainfest.xml文件:
< uses-permission android:name ="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name ="android.permission.INTERNET" /> <uses-permission android:name= "com.android.launcher.permission.READ_SETTINGS" /> <uses-permission android:name ="android.permission.WAKE_LOCK" /> <uses-permission android:name ="android.permission.CHANGE_WIFI_STATE" /> <uses-permission android:name ="android.permission.ACCESS_WIFI_STATE" /> <uses-permission android:name ="android.permission.GET_TASKS" /> <uses-permission android:name= "android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name ="android.permission.WRITE_SETTINGS" /> <!-- 这个权限用于进行网络定位 --> <uses-permission android:name= "android.permission.ACCESS_COARSE_LOCATION" /> <!-- 这个权限用于访问GPS定位 --> <uses-permission android:name= "android.permission.ACCESS_FINE_LOCATION" /> <!-- 用于读取手机当前的状态 --> <uses-permission android:name ="android.permission.READ_PHONE_STATE" /> <!-- SD卡读取权限,用户写入离线定位数据 --> <uses-permission android:name= "android.permission.MOUNT_UNMOUNT_FILESYSTEMS" /> <uses-permission android:name= "android.permission.BAIDU_LOCATION_SERVICE" /> <uses-permission android:name= "android.permission.ACCES_MOCK_LOCATION" /> <uses-permission android:name ="android.permission.ACCESS_GPS" /> <uses-permission android:name ="android.permission.BROADCAST_STICKY" /> <!-- 来电消音 --> <uses-permission android:name= "android.permission.PROCESS_OUTGOING_CALLS" /> <uses-permission android:name= "android.permission.MODIFY_AUDIO_SETTINGS" /> <uses-permission android:name ="android.permission.RECORD_AUDIO" /> <!-- 摄影机 --> <uses-permission android:name ="android.permission.CAMERA" />
< meta-data android:name= "com.baidu.lbsapi.API_KEY" android:value= "API控制台申请到的AK" /> < service android:name= "com.baidu.location.f" android:enabled= "true" android:process= ":remote" > </service >
import com.baidu.location.BDLocation; import com.baidu.location.BDLocationListener; import com.baidu.location.LocationClient; import com.baidu.location.LocationClientOption; import com.baidu.location.LocationClientOption.LocationMode; import com.lb.baidumapdemo.db.DBConstants; import com.lb.baidumapdemo.db.ShareDB; import com.lb.baidumapdemo.face.LocationFace; import android.content.Context; /** * @ClassName: LocationFaceUtil * @Description: 定位帮助类,这个类只用来做定位用 * @author libiao * @date 2015 -8 -20 下午2:48:07 * */ public class LocationFaceUtil implements BDLocationListener { private LocationFace locationFace; // 这个为自己写的一个接口,用来回调给外部处理 public LocationClient mLocationClient = null; private Context context; public LocationFaceUtil(Context context, LocationFace locationFace) { super(); this. locationFace = locationFace; this. context = context; mLocationClient = new LocationClient(context); mLocationClient.registerLocationListener(LocationFaceUtil. this); startLocation(); } private void startLocation() { LocationClientOption option = new LocationClientOption(); option.setLocationMode(LocationMode. Hight_Accuracy); // 可选,默认高精度,设置定位模式,高精度,低功耗,仅设备 option.setCoorType( "bd09ll"); // 可选,默认gcj02,设置返回的定位结果坐标系 option.setScanSpan(0); // 可选,默认0,即仅定位一次,设置发起定位请求的间隔需要大于等于1000ms才是有效的 option.setIsNeedAddress( true); // 可选,设置是否需要地址信息,默认不需要 option.setOpenGps( true); // 可选,默认false,设置是否使用 gps option.setLocationNotify( true); // 可选,默认false,设置是否当 gps有效时按照1S1次频率输出GPS结果 option.setIsNeedLocationDescribe( true); // 可选,默认false,设置是否需要位置语义化结果,可以在BDLocation.getLocationDescribe里得到,结果类似于“在北京天安门附近” option.setIsNeedLocationPoiList( true); // 可选,默认false,设置是否需要POI结果,可以在BDLocation.getPoiList里得到 option.setIgnoreKillProcess( false); // 可选,默认false,定位SDK内部是一个SERVICE,并放到了独立进程,设置是否在stop的时候杀死这个进程,默认杀死 option.SetIgnoreCacheException( false); // 可选,默认false,设置是否收集CRASH信息,默认收集 option.setEnableSimulateGps( false); // 可选,默认false,设置是否需要过滤 gps仿真结果,默认需要 mLocationClient.setLocOption(option); mLocationClient.start(); } @Override public void onReceiveLocation(BDLocation arg0) { //注意这里,一定要判断BdLocation的返回值,只有在getLocType()==61或者161的情况下才表示定位成功,具体返回的错误码可参考http://lbsyun.baidu.com/index.php?title=android-locsdk/guide/ermsg if (arg0.getLocType() == 61 || arg0.getLocType() == 161 && arg0.getLatitude() != 0.0) { //将城市的名字存到SharedPreferences里面 new ShareDB( context).save(DBConstants. CITY_NAME, arg0.getCity()); //将定位结果回调给locationFace的locationResult()方法 locationFace.locationResult(arg0); } } }
new LocationFaceUtil(getApplicationContext(), new LocationFace() { @Override public void locationResult(BDLocation location) { bdLocation = location; addMarker(); } });
private void addMarker() { // 设置地图类型 MAP_TYPE_NORMAL 普通图; MAP_TYPE_SATELLITE 卫星图 mBaiduMap.setMapType(BaiduMap. MAP_TYPE_NORMAL); // 开启交通图 mBaiduMap.setTrafficEnabled( true); // 设置地图当前级别 MapStatusUpdate statusUpdate = MapStatusUpdateFactory.zoomTo(19); mBaiduMap.setMapStatus(statusUpdate); // 构建覆盖物的经纬度 LatLng latLng = new LatLng( bdLocation.getLatitude(), bdLocation.getLongitude()); //覆盖物显示的图标 BitmapDescriptor descriptor = BitmapDescriptorFactory.fromResource(R.drawable. icon_gcoding); OverlayOptions option = new MarkerOptions().position(latLng).icon(descriptor).draggable(true); // 清除地图上所有的覆盖物 mBaiduMap.clear(); // 将覆盖物添加到地图上 mBaiduMap.addOverlay(option); // 将覆盖物设置为地图中心 MapStatusUpdate u = MapStatusUpdateFactory.newLatLng(latLng); // 以动画方式更新地图状态,动画耗时 300 ms mBaiduMap.animateMapStatus(u); mBaiduMap.setOnMarkerClickListener(BaseMapActivity. this); mBaiduMap.setOnMarkerDragListener(BaseMapActivity. this); }
import android.graphics.Point; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.widget.TextView; import android.widget.Toast; import com.baidu.mapapi.map.BaiduMap; import com.baidu.mapapi.map.BaiduMap.OnMapClickListener; import com.baidu.mapapi.map.BaiduMap.OnMarkerClickListener; import com.baidu.mapapi.map.BitmapDescriptor; import com.baidu.mapapi.map.BitmapDescriptorFactory; import com.baidu.mapapi.map.InfoWindow; import com.baidu.mapapi.map.MapPoi; import com.baidu.mapapi.map.MapStatusUpdate; import com.baidu.mapapi.map.MapStatusUpdateFactory; import com.baidu.mapapi.map.MapView; import com.baidu.mapapi.map.Marker; import com.baidu.mapapi.map.MarkerOptions; import com.baidu.mapapi.map.OverlayOptions; import com.baidu.mapapi.model.LatLng; import com.lb.baidumapdemo.R; import com.lb.baidumapdemo.base.BaseActivity; public class MarkerMapActivity extends BaseActivity implements OnMarkerClickListener,OnMapClickListener { private MapView mBaiduMapView; // 地图界面 private BaiduMap mBaiduMap; // 地图的管理类 private String[] titles = new String[] { "one", "two", "three", "four" };//这是是四个坐标对应的四个信息 //要放在地图上的四个坐标 private LatLng[] latlngs = new LatLng[] { new LatLng(22.539895,114.058935), new LatLng(22.540729,114.066337), new LatLng(22.543763,114.06458), new LatLng(22.538614,114.062811) }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout. activity_markermap); mBaiduMapView = (MapView) findViewById(R.id. markermap); mBaiduMap = mBaiduMapView.getMap(); //设置地图点击事件 mBaiduMap.setOnMapClickListener( this); initMarker(); } private void initMarker() { mBaiduMap.clear(); LatLng latLng = null; OverlayOptions overlayOptions = null; // 设置地图类型 MAP_TYPE_NORMAL 普通图; MAP_TYPE_SATELLITE 卫星图 mBaiduMap.setMapType(BaiduMap. MAP_TYPE_NORMAL); // 开启交通图 mBaiduMap.setTrafficEnabled( true); MapStatusUpdate statusUpdate = MapStatusUpdateFactory.zoomTo(17); mBaiduMap.setMapStatus(statusUpdate); BitmapDescriptor descriptor = BitmapDescriptorFactory.fromResource(R.drawable. icon_gcoding); //循环添加四个覆盖物到地图上 for ( int i = 0; i < titles. length; i++) { latLng= latlngs[i]; overlayOptions = new MarkerOptions().position(latLng).icon(descriptor); // 将覆盖物添加到地图上 Marker marker=(Marker) mBaiduMap.addOverlay(overlayOptions); Bundle bundle = new Bundle(); bundle.putString( "info", titles[i]+ "个"); marker.setExtraInfo(bundle); } // 将最后一个坐标设置为地图中心 MapStatusUpdate u = MapStatusUpdateFactory.newLatLng(latLng); mBaiduMap.setMapStatus(u); //设置地图覆盖物的点击事件 mBaiduMap.setOnMarkerClickListener(MarkerMapActivity. this); } /** * @Title: onMarkerClick * @Description: 覆盖物点击事件,每次点击一个覆盖物则会在相应的覆盖物上显示一个InfoWindow * @param marker * @return */ @Override public boolean onMarkerClick(Marker marker) { final String msg = marker.getExtraInfo().getString( "info"); InfoWindow mInfoWindow; // 生成一个TextView用户在地图中显示InfoWindow TextView location = new TextView(getApplicationContext()); location.setBackgroundResource(R.drawable. shape_popup); location.setPadding(30, 20, 30, 20); location.setText(msg); //构建弹框所在的经纬度, final LatLng ll = marker.getPosition(); Point p = mBaiduMap.getProjection().toScreenLocation(ll); p. y -= 47; //让弹框在Y轴偏移47 LatLng llInfo = mBaiduMap.getProjection().fromScreenLocation(p); //根据上面配置好的参数信息,构造一个InfoWindow。 mInfoWindow = new InfoWindow(location, llInfo, -47); //构建好之后,然后调用show的方法,让弹框显示出来 mBaiduMap.showInfoWindow(mInfoWindow); //弹框点击事件- location.setOnClickListener( new OnClickListener() { @Override public void onClick(View v) { Toast. makeText(MarkerMapActivity.this, msg, Toast.LENGTH_SHORT).show(); } }); return true; } /** * @Title: onMapClick * @Description: 地图点击事件,点击地图的时候要让InfoWindow消失 * @param arg0 */ @Override public void onMapClick(LatLng arg0) { mBaiduMap.hideInfoWindow(); } /** * @Title: onMapPoiClick * @Description: 兴趣点点击事件 * @param arg0 * @return */ @Override public boolean onMapPoiClick(MapPoi arg0) { return false; } }
private GeoCoder geoCoder; // 经纬度地理位置坐标反转类 geoCoder = GeoCoder. newInstance(); geoCoder.setOnGetGeoCodeResultListener( this); // 设置反地理查询监听器 geoCoder.reverseGeoCode(new ReverseGeoCodeOption().location(arg0.getPosition()));
/** * @Title: onGetGeoCodeResult * @Description: 坐标换算 根据地址得到坐标 * @param arg0 */ @Override public void onGetGeoCodeResult(GeoCodeResult arg0) { } /** * @Title: onGetReverseGeoCodeResult * @Description: 坐标换算,根据坐标得到地质 * @param arg0 */ @Override public void onGetReverseGeoCodeResult(ReverseGeoCodeResult arg0) { //根据上面的请求之后,回调会进入到这个方法里面来,然后在所有的地址信息在ReverseGeoCodeResult 当中 }
private PoiSearch mSearch ;// 搜索类 private int pageNum = 0; // 搜索的页数- private void startPointSearch () { mSearch = PoiSearch.newInstance(); mSearch.setOnGetPoiSearchResultListener(this); // 检索回调 PoiNearbySearchOption option = new PoiNearbySearchOption(); option.location( new LatLng( mLocation.getLatitude(), mLocation.getLongitude())); // 设置检索的中心点 option.pageCapacity(50); // 设置检索的返回的每页的内容的条数 option.pageNum( pageNum); option.radius(30000); // 设置检索的范围,半径。米为单位 option.sortType(PoiSortType. distance_from_near_to_far);// 设置排序由近到远 option.keyword( "美食");// 搜索关键字 mSearch.searchNearby(option); // 开始检索 pageNum++; } @Override public void onGetPoiDetailResult(PoiDetailResult arg0) { } // Poi检索的回调,所有回调的结果都在这个PoiResult里面,我们可以得到很多参数的信息 @Override public void onGetPoiResult(PoiResult arg0) { }
private void startRouterResult( int type, String startAddr, String endAddr) { String cityName = new ShareDB(SearchInfoActivity.this ).getValue(DBConstants. CITY_NAME); PlanNode stNode = PlanNode.withCityNameAndPlaceName(cityName, startAddr); PlanNode enNode = PlanNode.withCityNameAndPlaceName(cityName, endAddr); if (type == 1) { routeSearch .transitSearch(new TransitRoutePlanOption().from(stNode).to(enNode).city(cityName)); } else if (type == 2) { routeSearch .drivingSearch(new DrivingRoutePlanOption().from(stNode).to(enNode)); } else if (type == 3) { routeSearch .walkingSearch(new WalkingRoutePlanOption().from(stNode).to(enNode)); } }
private void startRouterResult( final int type, LatLng beLat, LatLng endLat) { /*** * 此处应该判断传递过来的经纬度是不是空的,因为有可能不是在listInfo集合里面取出来的数据,如果为空,就要根据控件上的文字,进行坐标反查 * ,得到坐标,然后再调用这个方法 ||如果经纬度为空,则用地址信息来进行线路的查询,不过此时查询出来的结果可能为空 **/ if ( beLat != null && endLat != null) { String cityName = new ShareDB(SearchInfoActivity.this ).getValue(DBConstants. CITY_NAME); PlanNode stNode = PlanNode. withLocation(beLat ); PlanNode enNode = PlanNode. withLocation(endLat); if (type == 1) { routeSearch.transitSearch( new TransitRoutePlanOption().from(stNode).to(enNode).city(cityName)); } else if (type == 2) { routeSearch.drivingSearch( new DrivingRoutePlanOption().from(stNode).to(enNode)); } else if (type == 3) { routeSearch.walkingSearch( new WalkingRoutePlanOption().from(stNode).to(enNode)); } } }
/******************** 线路查询返回的结果 ***********************/ // 因DrivingRouteResult、TransitRouteResult、WalkingRouteResult都是继承SearchResult,没有实现序列化,所以无法通过bundle来进行传递到下一个页面。 // 1、可以通过自定义Model类来对数据进行封装,实现序列化的接口来传递给下个界面 // 2、可以通过在Application类里定义这三个类的对象,然后再此处赋值,在下一个界面的时候就直接得到(本次就是用的这个方法) @Override public void onGetDrivingRouteResult(DrivingRouteResult drivingRouteResult) { closeDialog(); if (drivingRouteResult. error.toString().equals( "NO_ERROR")) { BaseApplication. drivingRouteResult = drivingRouteResult; startIntent(2); } else { Toast. makeText(SearchInfoActivity. this, "未找到路线,请重新选择起点或者终点" , Toast. LENGTH_SHORT).show(); } } @Override public void onGetTransitRouteResult(TransitRouteResult transitRouteResult) { closeDialog(); if (transitRouteResult. error.toString().equals( "NO_ERROR")) { BaseApplication. transitRouteResult = transitRouteResult; startIntent(1); } else { Toast. makeText(SearchInfoActivity. this, "未找到路线,请重新选择起点或者终点" , Toast. LENGTH_SHORT).show(); } } @Override public void onGetWalkingRouteResult(WalkingRouteResult walkingRouteResult) { closeDialog(); if (walkingRouteResult. error.toString().equals( "NO_ERROR")) { BaseApplication. walkingRouteResult = walkingRouteResult; startIntent(3); } else { Toast. makeText(SearchInfoActivity. this, "未找到路线,请重新选择起点或者终点" , Toast. LENGTH_SHORT).show(); } }线路规划就到这里结束了,接着就是线路的绘制了。
List<LatLng> listLat = (List<LatLng>) getIntent().getSerializableExtra( "latlng" );//得到经纬度集合 // 设置地图类型 MAP_TYPE_NORMAL 普通图; MAP_TYPE_SATELLITE 卫星图 mBaiduMap.setMapType(BaiduMap. MAP_TYPE_NORMAL); // 开启交通图 mBaiduMap.setTrafficEnabled( true); MapStatusUpdate statusUpdate = MapStatusUpdateFactory.zoomTo(19); mBaiduMap.setMapStatus(statusUpdate); MyLatLng myLatLng = listLat.get(0); MapStatusUpdate u = MapStatusUpdateFactory. newLatLng( new LatLng(myLatLng.getLatitude(), myLatLng.getLongitude())); mBaiduMap.setMapStatus(u);
mBaiduMap .setOnMapDrawFrameCallback(callback ); /******************** 使用OpenGl绘制,是出现Bug,坐标的转换和屏幕上的点的转换,会随着地图大小的拉伸,OpenGl的线不拉伸的情况,建议不要使用此方法 *********************/ // 定义地图绘制每一帧时 OpenGL 绘制的回调接口 OnMapDrawFrameCallback callback = new OnMapDrawFrameCallback() { public void onMapDrawFrame(GL10 gl, MapStatus drawingMapStatus) { if ( mBaiduMap.getProjection() != null) { // 计算折线的 opengl 坐标 calPolylinePoint(drawingMapStatus); // 绘制折线 drawPolyline(gl, Color. argb(255, 255, 0, 0), vertexBuffer, 10, 3, drawingMapStatus); } } }; // 计算折线 OpenGL 坐标 public void calPolylinePoint(MapStatus mspStatus) { PointF[] polyPoints = new PointF[ listLat.size()]; vertexs = new float[3 * listLat.size()]; int i = 0; for (MyLatLng xy : listLat) { // 将地理坐标转换成 openGL 坐标 polyPoints[i] = mBaiduMap.getProjection().toOpenGLLocation( new LatLng(xy.getLatitude(), xy.getLongitude()), mspStatus); vertexs[i * 3] = polyPoints[i]. x; vertexs[i * 3 + 1] = polyPoints[i]. y; vertexs[i * 3 + 2] = 0.0f; i++; } vertexBuffer = makeFloatBuffer( vertexs); } // 创建OpenGL绘制时的顶点Buffer private FloatBuffer makeFloatBuffer( float[] fs) { ByteBuffer bb = ByteBuffer. allocateDirect(fs. length * 4); bb.order(ByteOrder. nativeOrder()); FloatBuffer fb = bb.asFloatBuffer(); fb.put(fs); fb.position(0); return fb; } // 绘制折线 private void drawPolyline(GL10 gl, int color, FloatBuffer lineVertexBuffer, float lineWidth, int pointSize, MapStatus drawingMapStatus) { gl.glEnable(GL10. GL_BLEND); gl.glEnableClientState(GL10. GL_VERTEX_ARRAY); gl.glBlendFunc(GL10. GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA ); float colorA = Color. alpha(color) / 255f; float colorR = Color. red(color) / 255f; float colorG = Color. green(color) / 255f; float colorB = Color. blue(color) / 255f; gl.glVertexPointer(3, GL10. GL_FLOAT, 0, lineVertexBuffer); gl.glColor4f(colorR, colorG, colorB, colorA); gl.glLineWidth(lineWidth); gl.glDrawArrays(GL10. GL_LINE_STRIP, 0, pointSize); gl.glDisable(GL10. GL_BLEND); gl.glDisableClientState(GL10. GL_VERTEX_ARRAY); }
/** * 地图SDK提供多种结合图形覆盖物,利用这些图形,可帮助您构建更加丰富多彩的地图应用。目前提供的几何图形有:点(Dot)、折线( * Polyline)、弧线(Arc)、圆(Circle)、多边形(Polygon)。 此处绘制折线 */ OverlayOptions polygonOption = new PolylineOptions().points(listLat ).color(Color.parseColor( "#FF0000")).width(7); // 在地图上添加多边形Option,用于显示 mBaiduMap.addOverlay(polygonOption);