美文网首页
百度地图(二)

百度地图(二)

作者: 沈溺_16e5 | 来源:发表于2019-04-24 17:01 被阅读0次

    定位

    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);
                    }
                }
            }
        }
    };
    

    相关文章

      网友评论

          本文标题:百度地图(二)

          本文链接:https://www.haomeiwen.com/subject/kavggqtx.html