定位
xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<com.baidu.mapapi.map.MapView
android:id="@+id/bmapView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clickable="true" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:id="@+id/location"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="定位"/>
</LinearLayout>
</FrameLayout>
Activity
1、开启地图的定位图层
在Activity的onCreate()方法中
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private MapView mMapView;
private Button location;
private BaiduMap mBaiduMap;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initPermission();
initView();
mBaiduMap = mMapView.getMap();
}
private void initView() {
mMapView = (MapView) findViewById(R.id.bmapView);
location = (Button) findViewById(R.id.location);
location.setOnClickListener(this);
}
2、构造地图数据
在Activity中创建MyLocationListener 类(内部类)继承自BDAbstractLocationListener 类
public class MyLocationListener extends BDAbstractLocationListener {
@Override
public void onReceiveLocation(BDLocation location) {
//mapView 销毁后不在处理新接收的位置
if (location == null || mMapView == null) {
return;
}
MyLocationData locData = new MyLocationData.Builder()
.accuracy(location.getRadius())
// 此处设置开发者获取到的方向信息,顺时针0-360
.direction(location.getDirection()).latitude(location.getLatitude())
.longitude(location.getLongitude()).build();
// mUser_latlng 用户在地图上的位置,抽成成员变量即可
// location.getLatitude() 获取纬度信息 location.getLongitude() 获取经度信息
mUser_latlng = new LatLng(location.getLatitude(), location.getLongitude());
mBaiduMap.setMyLocationData(locData);
}
}
3、通过LocationClient发起定位
在Activity的onCreate()方法中创建location()方法
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initPermission();
initView();
mBaiduMap = mMapView.getMap();
location();
}
location()方法代码如下
mBaiduMap.setMyLocationEnabled(true);
//定位初始化
mLocationClient = new LocationClient(this);
//通过LocationClientOption设置LocationClient相关参数
LocationClientOption option = new LocationClientOption();
option.setOpenGps(true); // 打开gps
option.setCoorType("bd09ll"); // 设置坐标类型
option.setScanSpan(1000);
//设置locationClientOption
mLocationClient.setLocOption(option);
//注册LocationListener监听器
MyLocationListener myLocationListener = new MyLocationListener();
mLocationClient.registerLocationListener(myLocationListener);
//开启地图定位图层
mLocationClient.start();
这时只是得到了用户的位置,并没有使地图移到客户的位置,然后点击定位按钮,使地图显示用户当前的位置
在定位按钮的监听方法里调用locationUser()方法,代码如下:
private void locationUser() {
MapStatusUpdate status2 = MapStatusUpdateFactory.newLatLng(mUser_latlng);
mBaiduMap.setMapStatus(status2);
}
生命周期的onDestroy()中
@Override
protected void onDestroy() {
mLocationClient.stop();
mBaiduMap.setMyLocationEnabled(false);
mMapView.onDestroy();
mMapView = null;
super.onDestroy();
}
完成以上工作,即可在您的地图应用中显示当前位置的蓝点,如下图:
MapLocation.png
导航
1、点击地图的任意位置并添加一个Marker图标,添加Marker图标的代码如下:
private void addMarker(LatLng latLng) {
mBaiduMap.clear();
//构建Marker图标
BitmapDescriptor bitmap = BitmapDescriptorFactory
.fromResource(R.drawable.icon_marka);
Bundle bundle = new Bundle();
bundle.putString("id", "id_01");
//构建MarkerOption,用于在地图上添加Marker
OverlayOptions option = new MarkerOptions()
.position(latLng)
.animateType(MarkerOptions.MarkerAnimateType.jump)
.draggable(true)
.title("你好,百度")
.extraInfo(bundle)
.icon(bitmap);
//在地图上添加Marker,并显示
mBaiduMap.addOverlay(option);
}
2、点击Marker图标跳到导航页面
先给地图和Marker图标设置监听事件并在Activity的onCreate()方法中调用initListener() 方法
private void initListener() {
mBaiduMap.setOnMarkerClickListener(new BaiduMap.OnMarkerClickListener() {
//marker被点击时回调的方法
//若响应点击事件,返回true,否则返回false
//默认返回false
@Override
public boolean onMarkerClick(Marker marker) {
Bundle extraInfo = marker.getExtraInfo();
String id = extraInfo.getString("id");
if ("id_01".equals(id)) {
showToast(marker.getTitle());
}
walkNavi(marker.getPosition());
return false;
}
});
mBaiduMap.setOnMapClickListener(new BaiduMap.OnMapClickListener() {
@Override
public void onMapClick(LatLng latLng) {
addMarker(latLng);
}
@Override
public boolean onMapPoiClick(MapPoi mapPoi) {
return false;
}
});
}
private void walkNavi(final LatLng end) {
// 获取导航控制类
// 引擎初始化
WalkNavigateHelper.getInstance().initNaviEngine(this, new IWEngineInitListener() {
@Override
public void engineInitSuccess() {
//引擎初始化成功的回调
routeWalkPlanWithParam(end);
}
@Override
public void engineInitFail() {
//引擎初始化失败的回调
}
});
}
private void routeWalkPlanWithParam(LatLng end) {
//发起算路
//构造WalkNaviLaunchParam
//起终点位置
//构造WalkNaviLaunchParam
WalkNaviLaunchParam mParam = new WalkNaviLaunchParam().stPt(mUser_latlng).endPt(end);
//发起算路
WalkNavigateHelper.getInstance().routePlanWithParams(mParam, new IWRoutePlanListener() {
@Override
public void onRoutePlanStart() {
//开始算路的回调
}
@Override
public void onRoutePlanSuccess() {
//算路成功
//跳转至诱导页面
Intent intent = new Intent(MainActivity.this,
WNaviGuideActivity.class);
startActivity(intent);
}
@Override
public void onRoutePlanFail(WalkRoutePlanError walkRoutePlanError) {
//算路失败的回调
}
});
}
public void showToast(String msg) {
Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
}
在MainActivity的onDestroy()方法中
@Override
protected void onDestroy() {
if (mLocationClient != null) {
mLocationClient.stop();
}
mBaiduMap.setMyLocationEnabled(false);
mMapView.onDestroy();
mMapView = null;
super.onDestroy();
}
导航Activity
注意,导航Activity一定要继承Activity,不能继承AppCompatActivity
//步行导航的时候不能够继承AppCompatActivity
public class WNaviGuideActivity extends Activity {
private WalkNavigateHelper mNaviHelper;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//获取WalkNavigateHelper实例
mNaviHelper = WalkNavigateHelper.getInstance();
//获取诱导页面地图展示View
View view = mNaviHelper.onCreate(WNaviGuideActivity.this);
if (view != null) {
setContentView(view);
}
mNaviHelper.startWalkNavi(WNaviGuideActivity.this);
mNaviHelper.setWalkNaviStatusListener(new IWNaviStatusListener() {
/**
* 普通步行导航模式和步行AR导航模式的切换
* @param mode 导航模式
* @param walkNaviModeSwitchListener 步行导航模式切换的监听器
*/
@Override
public void onWalkNaviModeChange(int mode, WalkNaviModeSwitchListener walkNaviModeSwitchListener) {
mNaviHelper.switchWalkNaviMode(WNaviGuideActivity.this, mode, walkNaviModeSwitchListener);
}
@Override
public void onNaviExit() {
}
});
mNaviHelper.setRouteGuidanceListener(this, new IWRouteGuidanceListener() {
//诱导图标更新
@Override
public void onRouteGuideIconUpdate(Drawable drawable) {
}
//诱导类型枚举
@Override
public void onRouteGuideKind(RouteGuideKind routeGuideKind) {
}
/**
* 诱导信息
*
* @param charSequence 第一行显示的信息,如“沿当前道路”
* @param charSequence1 第二行显示的信息,比如“向东出发”,第二行信息也可能为空
*/
@Override
public void onRoadGuideTextUpdate(CharSequence charSequence, CharSequence charSequence1) {
}
//总的剩余距离
@Override
public void onRemainDistanceUpdate(CharSequence charSequence) {
}
//总的剩余时间
@Override
public void onRemainTimeUpdate(CharSequence charSequence) {
}
//GPS状态发生变化,来自诱导引擎的消息
@Override
public void onGpsStatusChange(CharSequence charSequence, Drawable drawable) {
}
//已经开始偏航
@Override
public void onRouteFarAway(CharSequence charSequence, Drawable drawable) {
}
//偏航规划中
@Override
public void onRoutePlanYawing(CharSequence charSequence, Drawable drawable) {
}
//重新算路成功
@Override
public void onReRouteComplete() {
}
//抵达目的地
@Override
public void onArriveDest() {
}
//震动
@Override
public void onVibrate() {
}
});
}
@Override
protected void onResume() {
super.onResume();
mNaviHelper.resume();
}
@Override
protected void onPause() {
super.onPause();
mNaviHelper.pause();
}
@Override
protected void onDestroy() {
super.onDestroy();
mNaviHelper.quit();
}
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == ArCameraView.WALK_AR_PERMISSION) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
mNaviHelper.startCameraAndSetMapView(WNaviGuideActivity.this);
} else if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_DENIED) {
Toast.makeText(this, "需要开启相机使用权限", Toast.LENGTH_SHORT).show();
}
}
}
}
导航.gif
获取周边POI
1、创建POI检索实例、设置检索监听器
在Activity的onCreate()方法中
// 创建POI检索实例
mPoiSearch = PoiSearch.newInstance();
// 设置检索监听器
mPoiSearch.setOnGetPoiSearchResultListener(listener);
2、POI检索按钮的监听里调用以下方法
private void poi() {
/**
* 以用户为中心,搜索半径5000米以内的餐厅
*/
mPoiSearch.searchNearby(new PoiNearbySearchOption()
.location(new LatLng(mUser_latlng.latitude, mUser_latlng.longitude))
//.city("北京")
.radius(5000)
.keyword("餐厅")
.pageNum(10));
}
OnGetPoiSearchResultListener listener = new OnGetPoiSearchResultListener() {
@Override
public void onGetPoiResult(PoiResult poiResult) {
if (poiResult.error == SearchResult.ERRORNO.NO_ERROR) {
mBaiduMap.clear();
//创建PoiOverlay对象
PoiOverlay poiOverlay = new PoiOverlay(mBaiduMap);
//设置Poi检索数据
poiOverlay.setData(poiResult);
//将poiOverlay添加至地图并缩放至合适级别
poiOverlay.addToMap();
poiOverlay.zoomToSpan();
}
}
@Override
public void onGetPoiDetailResult(PoiDetailSearchResult poiDetailSearchResult) {
}
@Override
public void onGetPoiIndoorResult(PoiIndoorResult poiIndoorResult) {
}
//废弃
@Override
public void onGetPoiDetailResult(PoiDetailResult poiDetailResult) {
}
};
3、PoiOverlay
import android.os.Bundle;
import com.baidu.mapapi.map.BaiduMap;
import com.baidu.mapapi.map.BitmapDescriptorFactory;
import com.baidu.mapapi.map.Marker;
import com.baidu.mapapi.map.MarkerOptions;
import com.baidu.mapapi.map.OverlayOptions;
import com.baidu.mapapi.map.Polyline;
import com.baidu.mapapi.search.poi.PoiResult;
import java.util.ArrayList;
import java.util.List;
/**
* 用于显示poi的overly
*/
public class PoiOverlay extends OverlayManager {
private static final int MAX_POI_SIZE = 10;
private PoiResult mPoiResult = null;
/**
* 构造函数
*
* @param baiduMap 该 PoiOverlay 引用的 BaiduMap 对象
*/
public PoiOverlay(BaiduMap baiduMap) {
super(baiduMap);
}
/**
* 设置POI数据
*
* @param poiResult 设置POI数据
*/
public void setData(PoiResult poiResult) {
this.mPoiResult = poiResult;
}
@Override
public final List<OverlayOptions> getOverlayOptions() {
if (mPoiResult == null || mPoiResult.getAllPoi() == null) {
return null;
}
List<OverlayOptions> markerList = new ArrayList<>();
int markerSize = 0;
for (int i = 0; i < mPoiResult.getAllPoi().size() && markerSize < MAX_POI_SIZE; i++) {
if (mPoiResult.getAllPoi().get(i).location == null) {
continue;
}
markerSize++;
Bundle bundle = new Bundle();
bundle.putInt("index", i);
markerList.add(new MarkerOptions()
.icon(BitmapDescriptorFactory.fromAssetWithDpi("Icon_mark" + markerSize + ".png"))
.extraInfo(bundle)
.position(mPoiResult.getAllPoi().get(i).location));
}
return markerList;
}
/**
* 获取该PoiOverlay的poi数据
*
* @return POI数据
*/
public PoiResult getPoiResult() {
return mPoiResult;
}
/**
* 覆写此方法以改变默认点击行为
*
* @param i 被点击的poi在
* {@link PoiResult#getAllPoi()} 中的索引
* @return true--事件已经处理,false--事件未处理
*/
public boolean onPoiClick(int i) {
// if (mPoiResult.getAllPoi() != null
// && mPoiResult.getAllPoi().get(i) != null) {
// Toast.makeText(BMapManager.getInstance().getContext(),
// mPoiResult.getAllPoi().get(i).name, Toast.LENGTH_LONG)
// .show();
// }
return false;
}
@Override
public final boolean onMarkerClick(Marker marker) {
if (!mOverlayList.contains(marker)) {
return false;
}
if (marker.getExtraInfo() != null) {
return onPoiClick(marker.getExtraInfo().getInt("index"));
}
return false;
}
@Override
public boolean onPolylineClick(Polyline polyline) {
return false;
}
}
4、在onDestroy()方法里加如下代码:
if (mPoiSearch != null) {
mPoiSearch.destroy();
}
记录一个问题:
通过百度地图逆地理编码检索实例时因百度地图服务器宕机造成 APP 崩溃
private void initView() {
......
// 逆地理编码检索实例
geoCoder = GeoCoder.newInstance();
geoCoder.setOnGetGeoCodeResultListener(geoListener);
reverseGeoCodeOption = new ReverseGeoCodeOption();
......
}
OnGetGeoCoderResultListener geoListener = new OnGetGeoCoderResultListener() {
@Override
public void onGetGeoCodeResult(GeoCodeResult geoCodeResult) {
}
@Override
public void onGetReverseGeoCodeResult(ReverseGeoCodeResult reverseGeoCodeResult) {
if (reverseGeoCodeResult == null
|| reverseGeoCodeResult.error != SearchResult.ERRORNO.NO_ERROR) {
// 没有找到检索结果
HLog.d("reverseGeoCodeResult == null");
BaiduMapViewModel.getInstance().nowPosition.setValue("");
} else {
// 解决因百度地图服务器宕机造成获取 AddressDetail 为 null 从而使 APP 崩溃的问题
if (reverseGeoCodeResult.getAddressDetail() != null) {
String street = reverseGeoCodeResult.getAddressDetail().street;
if (!lastStreet.equals(street)) {
HLog.d("reverseGeoCodeResult = " + reverseGeoCodeResult.toString());
lastStreet = street;
// 通过 LiveData 回调给 Activity
BaiduMapViewModel.getInstance().nowPosition.setValue(street);
}
}
}
}
};
网友评论