二、android百度地圖定位顯示當前位置(android百度地圖SDK系列)

上一篇文章,我們知道了如何集成百度地圖并且顯示出來,那么這一篇文章我們就來看看如何對百度地圖進行需要的設(shè)置以及定位并且顯示當前的位置。

一、android集成百度地圖(android百度地圖SDK系列)
二、android百度地圖定位顯示當前位置(android百度地圖SDK系列)
三、android百度地圖覆蓋物(android百度地圖SDK系列)

一、百度地圖基本的配置

我們知道,一個最基本的地圖是肯定滿足不了我們的需求的,所以就要進行一些設(shè)置,來改變地圖。
首先我們看最基本的:

    //地圖控件
    private MapView mapView;
    //百度地圖
    private BaiduMap baiduMap;

    /**
     * 初始化控件
     */
    public void initView(){
        mapView = (MapView)findViewById(R.id.mapView);
    }

    /**
     * 初始化地圖
     */
    public void initMap(){
        //得到地圖實例
        baiduMap = mapView.getMap();
        /*
        設(shè)置地圖類型
         */
        //普通地圖
        baiduMap.setMapType(BaiduMap.MAP_TYPE_NORMAL);
        //衛(wèi)星地圖
        //baiduMap.setMapType(BaiduMap.MAP_TYPE_SATELLITE);
        //空白地圖, 基礎(chǔ)地圖瓦片將不會被渲染。在地圖類型中設(shè)置為NONE,將不會使用流量下載基礎(chǔ)地圖瓦片圖層。使用場景:與瓦片圖層一起使用,節(jié)省流量,提升自定義瓦片圖下載速度。
        //baiduMap.setMapType(BaiduMap.MAP_TYPE_NONE);
        //開啟交通圖
        baiduMap.setTrafficEnabled(true);
        //關(guān)閉縮放按鈕
        mapView.showZoomControls(false);
    }

以上代碼就是最基本的設(shè)置了,很簡單的樣子,所以不過多停留在此。

二、定位與顯示中心點

說到定位,不得不提起android6.0的動態(tài)權(quán)限,如果版本小于6.0則不會有問題,一旦大于等于6.0直接定位就不行了,必須要申請動態(tài)權(quán)限,所以在這里我就直接將動態(tài)權(quán)限簡單的說一下。不過大家都知道因為國內(nèi)很多廠商對android系統(tǒng)進行所謂的包殼,所以我們永遠也摸不清這些殼的尿性,因此在這里是選擇了PermissionsDispatcher第三方權(quán)限框架來做。
下面我們就來看看它的用法:
首先在build.gradle里加入依賴

compile 'com.github.hotchemi:permissionsdispatcher:2.2.0'
annotationProcessor 'com.github.hotchemi:permissionsdispatcher-processor:2.2.0'

依賴成功后我們先要看看它的幾個注解和方法:
@NeedsPermission:申請權(quán)限成功時
@OnShowRationale:申請權(quán)限告訴用戶原因時
@OnPermissionDenied:申請權(quán)限被拒絕時
@OnNeverAskAgain:申請權(quán)限被拒絕并勾選不再提醒時
@RuntimePermissions:注釋此Activity或Fragment,在Make project生成類時會用到
onRequestPermissionsResult:回調(diào)方法

首先我們對需要定位權(quán)限的當前Activity類加上@RuntimePermissions注解:

@RuntimePermissions
public class MainActivity extends AppCompatActivity {}

下面我們使用上面剩下的注解和方法來完成對權(quán)限的動態(tài)申請:

@Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        // NOTE: delegate the permission handling to generated method
        MainActivityPermissionsDispatcher.onRequestPermissionsResult(this, requestCode, grantResults);
    }

    /**
     * 申請權(quán)限成功時
     */
    @NeedsPermission(Manifest.permission.ACCESS_COARSE_LOCATION)
    void ApplySuccess() {
    }

    /**
     * 申請權(quán)限告訴用戶原因時
     * @param request
     */
    @OnShowRationale(Manifest.permission.ACCESS_COARSE_LOCATION)
    void showRationaleForMap(PermissionRequest request) {
        showRationaleDialog("使用此功能需要打開定位的權(quán)限", request);
    }

    /**
     * 申請權(quán)限被拒絕時
     *
     */
    @OnPermissionDenied(Manifest.permission.ACCESS_COARSE_LOCATION)
    void onMapDenied() {
        Toast.makeText(this,"你拒絕了權(quán)限,該功能不可用",Toast.LENGTH_LONG).show();
    }

    /**
     * 申請權(quán)限被拒絕并勾選不再提醒時
     */
    @OnNeverAskAgain(Manifest.permission.ACCESS_COARSE_LOCATION)
    void onMapNeverAskAgain() {
        AskForPermission();
    }

    /**
     * 告知用戶具體需要權(quán)限的原因
     * @param messageResId
     * @param request
     */
    private void showRationaleDialog(String messageResId, final PermissionRequest request) {
        new AlertDialog.Builder(this)
                .setPositiveButton("確定", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(@NonNull DialogInterface dialog, int which) {
                        request.proceed();//請求權(quán)限
                    }
                })
                .setNegativeButton("取消", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(@NonNull DialogInterface dialog, int which) {
                        request.cancel();
                    }
                })
                .setCancelable(false)
                .setMessage(messageResId)
                .show();
    }

    /**
     * 被拒絕并且不再提醒,提示用戶去設(shè)置界面重新打開權(quán)限
     */
    private void AskForPermission() {
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setTitle("當前應(yīng)用缺少定位權(quán)限,請去設(shè)置界面打開\n打開之后按兩次返回鍵可回到該應(yīng)用哦");
        builder.setNegativeButton("取消", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                return;
            }
        });
        builder.setPositiveButton("設(shè)置", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
                intent.setData(Uri.parse("package:" + MainActivity.this.getPackageName())); // 根據(jù)包名打開對應(yīng)的設(shè)置界面
                startActivity(intent);
            }
        });
        builder.create().show();
    }

我們可以看到其中四個注解后面跟得有參數(shù),這個參數(shù)就是我們需要申請的權(quán)限。然后在onRequestPermissionsResult里出現(xiàn)了以下一句代碼:

MainActivityPermissionsDispatcher.onRequestPermissionsResult(this, requestCode, grantResults);

這句代碼里的類和方法是沒有的,它是通過對Activity或者Fragment@RuntimePermissions注解后并且進行Make project后才出現(xiàn)的。
至此,定位權(quán)限的動態(tài)申請就搞定了,上面只是該框架的簡單用法。更加全面的文檔:PermissionsDispatcher

既然權(quán)限搞定了,那么我們就可以一鼓作氣的完成的定位并顯示了。
1.我們在之前的InitMap方法里加上以下代碼:

    // 開啟定位圖層
    baiduMap.setMyLocationEnabled(true);
    //聲明LocationClient類
    mLocationClient = new LocationClient(this);
    //注冊監(jiān)聽函數(shù)
    mLocationClient.registerLocationListener(myListener);
    initLocation();
    //開始定位
    mLocationClient.start();

2.聲明一些需要的變量,配置定位參數(shù),實現(xiàn)定位監(jiān)聽方法,設(shè)置中心點和marker

    //防止每次定位都重新設(shè)置中心點和marker
    private boolean isFirstLocation = true;
    //初始化LocationClient定位類
    private LocationClient mLocationClient = null;
    //BDAbstractLocationListener為7.2版本新增的Abstract類型的監(jiān)聽接口,原有BDLocationListener接口
    private BDLocationListener myListener = new MyLocationListener();
    //經(jīng)緯度
    private double lat;
    private double lon;

    /**
     * 配置定位參數(shù)
     */
    private void initLocation() {
        LocationClientOption option = new LocationClientOption();
        //可選,默認高精度,設(shè)置定位模式,高精度,低功耗,僅設(shè)備
        option.setLocationMode(LocationClientOption.LocationMode.Hight_Accuracy);
        //可選,默認gcj02,設(shè)置返回的定位結(jié)果坐標系
        option.setCoorType("bd09ll");
        //可選,默認0,即僅定位一次,設(shè)置發(fā)起定位請求的間隔需要大于等于1000ms才是有效的
        int span = 5000;
        option.setScanSpan(span);
        //可選,設(shè)置是否需要地址信息,默認不需要
        option.setIsNeedAddress(true);
        //可選,默認false,設(shè)置是否使用gps
        option.setOpenGps(true);
        //可選,默認false,設(shè)置是否當GPS有效時按照1S/1次頻率輸出GPS結(jié)果
        option.setLocationNotify(true);
        //可選,默認false,設(shè)置是否需要位置語義化結(jié)果,可以在BDLocation.getLocationDescribe里得到,結(jié)果類似于“在北京天安門附近”
        option.setIsNeedLocationDescribe(true);
        //可選,默認false,設(shè)置是否需要POI結(jié)果,可以在BDLocation.getPoiList里得到
        option.setIsNeedLocationPoiList(true);
        //可選,默認true,定位SDK內(nèi)部是一個SERVICE,并放到了獨立進程,設(shè)置是否在stop的時候殺死這個進程,默認不殺死
        option.setIgnoreKillProcess(false);
        //可選,默認false,設(shè)置是否收集CRASH信息,默認收集
        option.SetIgnoreCacheException(false);
        //可選,默認false,設(shè)置是否需要過濾GPS仿真結(jié)果,默認需要
        option.setEnableSimulateGps(false);
        mLocationClient.setLocOption(option);
    }

    /**
     * 實現(xiàn)定位監(jiān)聽 位置一旦有所改變就會調(diào)用這個方法
     * 可以在這個方法里面獲取到定位之后獲取到的一系列數(shù)據(jù)
     */
    public class MyLocationListener implements BDLocationListener {

        @Override
        public void onReceiveLocation(BDLocation location) {
            //獲取定位結(jié)果
            location.getTime();    //獲取定位時間
            location.getLocationID();    //獲取定位唯一ID,v7.2版本新增,用于排查定位問題
            location.getLocType();    //獲取定位類型
            location.getLatitude();    //獲取緯度信息
            location.getLongitude();    //獲取經(jīng)度信息
            location.getRadius();    //獲取定位精準度
            location.getAddrStr();    //獲取地址信息
            location.getCountry();    //獲取國家信息
            location.getCountryCode();    //獲取國家碼
            location.getCity();    //獲取城市信息
            location.getCityCode();    //獲取城市碼
            location.getDistrict();    //獲取區(qū)縣信息
            location.getStreet();    //獲取街道信息
            location.getStreetNumber();    //獲取街道碼
            location.getLocationDescribe();    //獲取當前位置描述信息
            location.getPoiList();    //獲取當前位置周邊POI信息

            location.getBuildingID();    //室內(nèi)精準定位下,獲取樓宇I(lǐng)D
            location.getBuildingName();    //室內(nèi)精準定位下,獲取樓宇名稱
            location.getFloor();    //室內(nèi)精準定位下,獲取當前位置所處的樓層信息
            //經(jīng)緯度
            lat = location.getLatitude();
            lon = location.getLongitude();
            
            //這個判斷是為了防止每次定位都重新設(shè)置中心點和marker
            if (isFirstLocation) {
                isFirstLocation = false;
                //設(shè)置并顯示中心點
                setPosition2Center(baiduMap, location, true);
            }
        }
    }

    /**
     * 設(shè)置中心點和添加marker
     *
     * @param map
     * @param bdLocation
     * @param isShowLoc
     */
    public void setPosition2Center(BaiduMap map, BDLocation bdLocation, Boolean isShowLoc) {
        MyLocationData locData = new MyLocationData.Builder()
                .accuracy(bdLocation.getRadius())
                .direction(bdLocation.getRadius()).latitude(bdLocation.getLatitude())
                .longitude(bdLocation.getLongitude()).build();
        map.setMyLocationData(locData);

        if (isShowLoc) {
            LatLng ll = new LatLng(bdLocation.getLatitude(), bdLocation.getLongitude());
            MapStatus.Builder builder = new MapStatus.Builder();
            builder.target(ll).zoom(18.0f);
            map.animateMapStatus(MapStatusUpdateFactory.newMapStatus(builder.build()));
        }
    }

3.最后我們在onCreate方法里進行android版本的判斷,根據(jù)android版本來決定直接定位顯示還是需要動態(tài)權(quán)限以及需要在權(quán)限申請成功的方法里調(diào)用initMap方法和生命周期的管理,代碼如下:

    //當android系統(tǒng)小于5.0的時候直接定位顯示,不用動態(tài)申請權(quán)限
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
        initMap();
    } else {
        MainActivityPermissionsDispatcher.ApplySuccessWithCheck(this);
    }

    /**
    * 申請權(quán)限成功時
    */
    @NeedsPermission(Manifest.permission.ACCESS_COARSE_LOCATION)
    void ApplySuccess() {
        initMap();
    }

    @Override
    public void onResume() {
        super.onResume();
        //在activity執(zhí)行onResume時執(zhí)行mMapView. onResume (),實現(xiàn)地圖生命周期管理
        mapView.onResume();
    }

    @Override
    public void onPause() {
        super.onPause();
        //在activity執(zhí)行onPause時執(zhí)行mMapView. onPause (),實現(xiàn)地圖生命周期管理
        mapView.onPause();
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        //在activity執(zhí)行onDestroy時執(zhí)行mMapView.onDestroy(),實現(xiàn)地圖生命周期管理
        // 退出時銷毀定位
        mLocationClient.unRegisterLocationListener(myListener);
        mLocationClient.stop();
        // 關(guān)閉定位圖層
        baiduMap.setMyLocationEnabled(false);
        mapView.onDestroy();
        mapView = null;
    }

最后我們來看看運行效果

動態(tài)申請權(quán)限.png
定位顯示當前位置.png

到此為止,android集成百度地圖的定位與顯示當前位置就結(jié)束了,從第一篇文章到第二篇所有的地方我都注釋的比較細,以便新手學習和參考。最后因為我公司的項目中還涉及到了動態(tài)添加點和幾何圖形覆蓋物,所以還有有一篇結(jié)尾的文章,大家耐心等待~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容