1. 程式人生 > >Android整合百度地圖-----顯示地圖、定位、長按顯示地址資訊

Android整合百度地圖-----顯示地圖、定位、長按顯示地址資訊

一、基礎部分

轉載請註明出處:https://blog.csdn.net/Hunter2916/article/details/82867205

1、下載百度地圖的SDK

下載地址:http://lbsyun.baidu.com/index.php?title=android-locsdk/geosdk-android-download

2、申請key值

註冊百度賬號——>登入百度地圖官網——>控制檯—–>建立應用

具體方法地址:http://lbsyun.baidu.com/apiconsole/key 

3、解壓後的jar包放到app下的libs中,並右鍵add到build.gradle中

build.gradle中新增ndk

ndk {
            //選擇要新增的對應 cpu 型別的.so 庫。
            abiFilters 'armeabi', 'armeabi-v7a', 'armeabi64-v8a', 'x86', 'x86_64'
            // 還可以新增 'x86', 'x86_64', 'mips', 'mips64'
        }


dependencies{
//百度定位架包
    compile files('libs/BaiduLBS_Android.jar')
}

4、在manifest.xml中新增key和service

 <meta-data
            android:name="com.baidu.lbsapi.API_KEY"
            android:value="你自己申請的key" />
        <!-- 宣告service元件 -->
        <service
            android:name="com.baidu.location.f"
            android:enabled="true"
            android:process=":remote" />

5、新增許可權

<!-- 這個許可權用於進行網路定位-->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"></uses-permission>
<!-- 這個許可權用於訪問GPS定位-->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"></uses-permission>
<!-- 用於訪問wifi網路資訊,wifi資訊會用於進行網路定位-->
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"></uses-permission>
<!-- 獲取運營商資訊,用於支援提供運營商資訊相關的介面-->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"></uses-permission>
<!-- 這個許可權用於獲取wifi的獲取許可權,wifi資訊會用來進行網路定位-->
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"></uses-permission>
<!-- 用於讀取手機當前的狀態-->
<uses-permission android:name="android.permission.READ_PHONE_STATE"></uses-permission>
<!-- 寫入擴充套件儲存,向擴充套件卡寫入資料,用於寫入離線定位資料-->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
<!-- 訪問網路,網路定位需要上網-->
<uses-permission android:name="android.permission.INTERNET" />
<!-- SD卡讀取許可權,使用者寫入離線定位資料-->
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"></uses-permission>



//切記有些許可權在Android5.0以後還需要在程式碼中動態獲取
//例如:

private void requestRunPermissions() {
        List<PermissionItem> permisson = new ArrayList<>();
        permisson.add(new PermissionItem(Manifest.permission.READ_PHONE_STATE, "電話狀態", R.drawable.permission_ic_phone));
        permisson.add(new PermissionItem(Manifest.permission.ACCESS_COARSE_LOCATION, "地理位置", R.drawable.permission_ic_location));
        permisson.add(new PermissionItem(Manifest.permission.ACCESS_FINE_LOCATION, "地理位置", R.drawable.permission_ic_location));
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
            permisson.add(new PermissionItem(Manifest.permission.READ_EXTERNAL_STORAGE, "讀取許可權", R.drawable.permission_ic_storage));
            permisson.add(new PermissionItem(Manifest.permission.WRITE_EXTERNAL_STORAGE, "寫入許可權", R.drawable.permission_ic_storage));
        }
        HiPermission.create(this)
                .title("開啟地圖許可權")
                .permissions(permisson)
                .filterColor(ResourcesCompat.getColor(getResources(), R.color.colorAccent, getTheme()))
                .style(R.style.PermissionBlueStyle)
                .msg("我們需要獲得以下許可權才能為您提供服務")
                .checkMutiPermission(new PermissionCallback() {
                    @Override
                    public void onClose() {

                    }

                    @Override
                    public void onFinish() {
//                        showToastShort("所有許可權申請完成");
                    }

                    @Override
                    public void onDeny(String permission, int position) {

                    }

                    @Override
                    public void onGuarantee(String permission, int position) {

                    }
                });
    }


//新增許可權第三方框架
compile 'me.weyye.hipermission:library:1.0.7'

6、主介面佈局

 <com.baidu.mapapi.map.MapView
            android:id="@+id/bmapView"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:clickable="true" />

7、Activity中的程式碼

private BaiduMap mBaiduMap;



 @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
        mBaiduMap = binding.bmapView.getMap();
        //initView();
        //在定位之前進行一次動態的獲取許可權
        requestRunPermissions();
    }

在不設定任何屬性的情況下,定位在北京比例為5公里

7.1、設定縮放比例並使用靜態定位

private void initView() {
        //更新地圖
        //設定初始化比例  500米左右   zoom越大則地圖越詳細
       LatLng latLng = new LatLng(30.272858,120.15941);
        MapStatus mMapStatus = new MapStatus.Builder()
                .target(latLng)
                .zoom(16)
                .build();
        MapStatusUpdate mMapStatusUpdate = MapStatusUpdateFactory.newMapStatus(mMapStatus);        //改變地圖狀態
        mBaiduMap.setMapStatus(mMapStatusUpdate);

    }

二、定位以及長按地圖獲取地理資訊

1、Activity中程式碼

public class MainActivity extends BaseActivity {
    ActivityMainBinding binding;
    private Context context;
    private BaiduMap mBaiduMap;

    //定位相關
    private LocationClient mLocationClient;
    private MyLocationListener mLocationListener = new MyLocationListener();
    private Boolean isFirstIn = true;
    private double latitude;
    private double longtitude;
    //定點陣圖標
    private BitmapDescriptor mIconLocation;
    private MyOrientationListener myOrientationListener;
    private float mCurrentX;
    private LatLng mDestLocationData;
    private LatLng mLastLocationData;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
//        mLocationListener = new MyLocationListener();
        context = this;

        binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
        geoCoder = GeoCoder.newInstance();
        mBaiduMap = binding.bmapView.getMap();
        initView();
        //在定位之前進行一次動態的獲取許可權
//        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
//        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
        requestRunPermissions();
//        }
        initLocation();
    }



    private void initListener() {
        binding.typeNone.setOnClickListener(this);
        binding.typeNoraml.setOnClickListener(this);
//        binding.typeSatellite.setOnClickListener(this);
        binding.typeTraffic.setOnClickListener(this);
        binding.location.setOnClickListener(this);
        binding.overlay.setOnClickListener(this);
      
    }


    private void requestRunPermissions() {
        List<PermissionItem> permisson = new ArrayList<>();
        permisson.add(new PermissionItem(Manifest.permission.READ_PHONE_STATE, "電話狀態", R.drawable.permission_ic_phone));
        permisson.add(new PermissionItem(Manifest.permission.ACCESS_COARSE_LOCATION, "地理位置", R.drawable.permission_ic_location));
        permisson.add(new PermissionItem(Manifest.permission.ACCESS_FINE_LOCATION, "地理位置", R.drawable.permission_ic_location));
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
            permisson.add(new PermissionItem(Manifest.permission.READ_EXTERNAL_STORAGE, "讀取許可權", R.drawable.permission_ic_storage));
            permisson.add(new PermissionItem(Manifest.permission.WRITE_EXTERNAL_STORAGE, "寫入許可權", R.drawable.permission_ic_storage));
        }
        HiPermission.create(this)
                .title("開啟地圖許可權")
                .permissions(permisson)
                .filterColor(ResourcesCompat.getColor(getResources(), R.color.colorAccent, getTheme()))
                .style(R.style.PermissionBlueStyle)
                .msg("我們需要獲得以下許可權才能為您提供服務")
                .checkMutiPermission(new PermissionCallback() {
                    @Override
                    public void onClose() {

                    }

                    @Override
                    public void onFinish() {
//                        showToastShort("所有許可權申請完成");
                    }

                    @Override
                    public void onDeny(String permission, int position) {

                    }

                    @Override
                    public void onGuarantee(String permission, int position) {

                    }
                });
    }

    /**
     * 定位的方法
     */
    private void initLocation() {
//        binding.LocationResult.setMovementMethod(ScrollingMovementMethod.getInstance());
        myOrientationListener = new MyOrientationListener(this);
        mLocationClient = new LocationClient(this);
        mLocationClient.registerLocationListener(mLocationListener);
        LocationClientOption option = new LocationClientOption();
        option.setLocationMode(LocationClientOption.LocationMode.Hight_Accuracy);//精確定位
        option.setCoorType("bd09ll");//可選,設定返回的定位結果座標系
        option.setIsNeedAddress(true);//獲取詳細地址
        option.setOpenGps(true);//設定是否使用GPS
//        option.setScanSpan(1000);//可選,預設0,即僅定位一次,設定發起定位請求的間隔需要大於等於1000ms才是有效的
        option.setIsNeedLocationDescribe(true);//可選,預設false,設定是否需要位置語義化結果,可以在BDLocation
        option.setIsNeedLocationPoiList(true);//可選,預設false,設定是否需要POI結果,可以在BDLocation.getPoiList裡得到
        option.SetIgnoreCacheException(false);//可選,預設false,設定是否收集CRASH資訊,預設收集
        option.setEnableSimulateGps(false);//可選,預設false,設定是否需要過濾GPS模擬結果,預設需要
        mLocationClient.setLocOption(option);
        //定位後的圖示 初始化圖示
        mIconLocation = BitmapDescriptorFactory.fromResource(R.mipmap.navi_map_gps_locked);
//設定自定以圖示
            MyLocationConfiguration configuration = new
                    MyLocationConfiguration(MyLocationConfiguration.LocationMode.NORMAL, true, mIconLocation);
            mBaiduMap.setMyLocationConfiguration(configuration);
    }

    private void initView() {
        //更新地圖
        //設定初始化比例  500米左右   zoom越大則地圖越詳細

 MapStatusUpdate msu = MapStatusUpdateFactory.zoomTo(15.0f);
        mBaiduMap.setMapStatus(msu);

    }


    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.type_noraml://普通地圖
                mBaiduMap.setMapType(BaiduMap.MAP_TYPE_NORMAL);
                break;
//            case R.id.type_satellite://衛星模式
//                mBaiduMap.setMapType(BaiduMap.MAP_TYPE_SATELLITE);
//                break;
            case R.id.type_none:
                mBaiduMap.setMapType(BaiduMap.MAP_TYPE_NONE);
                break;
            case R.id.type_traffic:
                if (mBaiduMap.isTrafficEnabled()) {
                    mBaiduMap.setTrafficEnabled(false);
                    binding.typeTraffic.setText("實時路況(開)");
                } else {
                    mBaiduMap.setTrafficEnabled(true);
                    binding.typeTraffic.setText("實時路況(關)");
                }
                break;

        }
    }

   
    /***
     * Stop location service
     */
    @Override
    protected void onStop() {
        super.onStop();
        //停止定位
        mBaiduMap.setMyLocationEnabled(false);
        mLocationClient.stop();
    }

    @Override
    protected void onStart() {
        super.onStart();
        //開啟定位
        mBaiduMap.setMyLocationEnabled(true);
        //判斷的時候注意
        if (!mLocationClient.isStarted()) {
            mLocationClient.start();
        }
    }

    @Override
    protected void onResume() {
        super.onResume();
        binding.bmapView.onResume();
    }

    @Override
    protected void onPause() {
        super.onPause();
        binding.bmapView.onPause();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        binding.bmapView.onDestroy();
        
    }

   
    /**
     * 定位結果回撥,重寫onReceiveLocation方法,定位的回撥  latitude 緯度
     */
    private class MyLocationListener extends BDAbstractLocationListener {
        if (location == null || binding.bmapView == null) {
                return;
            }
            MyLocationData data = new MyLocationData.Builder()
                    .accuracy(location.getRadius())
                    .latitude(location.getLatitude())
                    .longitude(location.getLongitude())
                    .build();
            mBaiduMap.setMyLocationData(data);

        @Override
        public void onReceiveLocation(BDLocation location) {
            
            if (isFirstIn) {
                LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude());
                MapStatusUpdate msu = MapStatusUpdateFactory.newLatLng(latLng);
                mBaiduMap.animateMapStatus(msu);
                isFirstIn = false;
                Toast.makeText(context, "我的位置資訊為::" + location.getDistrict(),
                        Toast.LENGTH_SHORT).show();
            }

           
        }
    }


}

2、點選按鈕回到定位的地方

private double latitude;//緯度
private double longtitude;//經度


 /**
     * 獲取當前的定位方法
     */
    private void getMyLocation() {
        LatLng latLng = new LatLng(latitude, longtitude);
        MapStatusUpdate msu = MapStatusUpdateFactory.newLatLng(latLng);
        mBaiduMap.animateMapStatus(msu);
    }




/**
     * 定位結果回撥,重寫onReceiveLocation方法,定位的回撥  latitude 緯度
     */
    private class MyLocationListener extends BDAbstractLocationListener {

        @Override
        public void onReceiveLocation(BDLocation location) {
            if (location == null || binding.bmapView == null) {
                return;
            }
            MyLocationData data = new MyLocationData.Builder()
                    .accuracy(location.getRadius())
                    .direction(mCurrentX)//方向感測器
                    .latitude(location.getLatitude())
                    .longitude(location.getLongitude())
                    .build();
            mBaiduMap.setMyLocationData(data);

            latitude = location.getLatitude();
            longtitude = location.getLongitude();
            if (isFirstIn) {
                LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude());
                MapStatusUpdate msu = MapStatusUpdateFactory.newLatLng(latLng);
                mBaiduMap.animateMapStatus(msu);
                isFirstIn = false;
//                Toast.makeText(context, "我的位置資訊為::" + poiList.get(0).getName(),
//                        Toast.LENGTH_SHORT).show();
                Toast.makeText(context, "我的位置資訊為::" + location.getDistrict(),
                        Toast.LENGTH_SHORT).show();
            }


        }
    }

3、長按定位顯示資訊

 /**
         * 長按定點陣圖標
         */
        mBaiduMap.setOnMapLongClickListener(new BaiduMap.OnMapLongClickListener() {
            @Override
            public void onMapLongClick(LatLng latLng) {
//                MapStatus maps = new MapStatus.Builder().target(latLng).zoom(15).build();
//                MapStatusUpdate m = MapStatusUpdateFactory.newMapStatus(maps);
                //改變地圖狀態
//                mBaiduMap.setMapStatus(m);


//                showToastShort("設定目的地成功");
//                showToastShort("設定目的地成功"+latLng.toString());
//                mDestLocationData = latLng;
                latlngToAddress(latLng);
                addDestInfoOverLay(latLng);
            }
        });



 /**
     * 經緯度或地址相互轉換
     *
     * @param latlng
     */
    private void latlngToAddress(LatLng latlng) {

        // 設定反地理經緯度座標,請求位置時,需要一個經緯度
//        geoCoder.reverseGeoCode(new ReverseGeoCodeOption().location(latlng));

        //設定地址或經緯度反編譯後的監聽,這裡有兩個回撥方法,
        geoCoder.setOnGetGeoCodeResultListener(new OnGetGeoCoderResultListener() {
            //經緯度轉換成地址
            @Override
            public void onGetReverseGeoCodeResult(ReverseGeoCodeResult result) {
                if (result == null || result.error != SearchResult.ERRORNO.NO_ERROR) {
                    Toast.makeText(MainActivity.this, "找不到該地址!", Toast.LENGTH_SHORT).show();
                }
//                tv_address.setText("地址:" + result.getAddress());
                assert result != null;
                showToastShort("地址:" + result.getAddress());
            }

            //把地址轉換成經緯度
            @Override
            public void onGetGeoCodeResult(GeoCodeResult result) {
                // 詳細地址轉換在經緯度
                String address = result.getAddress();
            }
        });

        // 設定反地理經緯度座標,請求位置時,需要一個經緯度
        //切記一定要放在下面不然第一次長按定位不走該方法
        geoCoder.reverseGeoCode(new ReverseGeoCodeOption().location(latlng));
    }



 /**
     * 長按新增覆蓋物
     *
     * @param latLng
     */
    private void addDestInfoOverLay(LatLng latLng) {
        //清除所有的覆蓋物
        mBaiduMap.clear();
        OverlayOptions options = new MarkerOptions().position(latLng)
                .icon(BitmapDescriptorFactory.fromResource(R.mipmap.ic_myloc))
                .zIndex(5);//層數
        mBaiduMap.addOverlay(options);

    }