1. 程式人生 > >Android studio3.0對於百度地圖api開發(3)——百度地圖定位當前地點以及地圖覆蓋物簡介

Android studio3.0對於百度地圖api開發(3)——百度地圖定位當前地點以及地圖覆蓋物簡介

   承接上文,上文已經實現了按照緯經度進行地點的定位以及不同地圖型別的切換,https://blog.csdn.net/qq_41562408/article/details/82802082但是就我們普通使用者的需求來說,這遠遠不夠。使用者更希望能夠直接顯示自己的當前位置,而不是通過輸入經緯度來定位。在真實情況中不現實。同時對於開發人員來說,開發百度地圖不光光只是為了簡單的地圖顯示,肯定希望在地圖上進行一定的操作,或新增標記,或導航,或距離查詢等。。。。。。

       這篇文章主要為實現百度地圖開發中的定位當前位置以及在百度地圖上新增覆蓋物進行展開,希望能夠為讀者有所幫助,同時希望讀者有什麼好的建議能夠提出來,幫助我的進步。廢話不多說,開發開始了。

      不知道各位有沒有遇到和我一樣的情況,明明按照百度開發官方文件進行定位操作一步步走過來 ,就是不能定位到當前位置,近乎崩潰,還好csdn裡面大神多,東查查,西找找。還真讓我解決了。具體引用太多了,我也不清楚了。也為了方便讀者我就不就行各種連結了,直接在本次文章中整理。考慮到功能堆疊介面就需要好好規劃了,而且程式碼也會堆疊容易眼花繚亂不利於交流,所以決定將之前的專案分享出去,網址為:https://download.csdn.net/download/qq_41562408/10683082(文章版)、https://download.csdn.net/download/qq_41562408/10683086(改良版)重新開一個專案,只是為了解決一個個單獨的問題,後期筆者會提交一個完整的技術列表專案。歡迎讀者交流。  

改良版
文章版

現就針對本次文章中的問題進行解決:①、實時定位;②地圖覆蓋物;

1、就定位問題對於我來說確實有點麻煩,因為開發文件寫的確實太簡單,好不容易感覺走下來了,定位失敗,確實讓人感覺崩潰。還好四處查資料,算是解決了,解決的具體思路還是通過確定當地緯經度確定當前位置。

工程計較複雜,之間上程式碼,程式碼上有說明,親測有效:

package wang.baidumap.com;

import android.Manifest;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
import android.widget.RadioGroup;
import android.widget.Toast;

import com.baidu.location.BDLocation;
import com.baidu.location.BDLocationListener;
import com.baidu.location.LocationClient;
import com.baidu.location.LocationClientOption;
import com.baidu.mapapi.SDKInitializer;
import com.baidu.mapapi.map.BaiduMap;
import com.baidu.mapapi.map.MapStatusUpdate;
import com.baidu.mapapi.map.MapStatusUpdateFactory;
import com.baidu.mapapi.map.MapView;
import com.baidu.mapapi.map.MyLocationData;
import com.baidu.mapapi.model.LatLng;

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends Activity {
    protected MapView mapView = null;
    public BaiduMap baiduMap;
    private BroadcastReceiver receiver;
    private RadioGroup leixing;
    public LocationClient mLocationClient;
    private boolean isFirstLocate=true;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mLocationClient=new LocationClient(getApplicationContext());
        mLocationClient.registerLocationListener(new MyLocationListener());
        mapView = (MapView) findViewById(R.id.bmapView);
        leixing=(RadioGroup)findViewById(R.id.leixin);
        baiduMap=mapView.getMap();//獲取地圖控制器
        registerSDKCheckReceiver();
        leixing.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(RadioGroup radioGroup, int i) {
                switch (i){
                    case R.id.putong:baiduMap.setMapType(BaiduMap.MAP_TYPE_NORMAL);baiduMap.setTrafficEnabled(false);baiduMap.setBaiduHeatMapEnabled(false);break;
                    case R.id.weixin:baiduMap.setMapType(BaiduMap.MAP_TYPE_SATELLITE);baiduMap.setTrafficEnabled(false);baiduMap.setBaiduHeatMapEnabled(false);break;
                    case R.id.kongbai:baiduMap.setMapType(BaiduMap.MAP_TYPE_NONE);baiduMap.setTrafficEnabled(false);baiduMap.setBaiduHeatMapEnabled(false);break;
                    case R.id.shikuan:baiduMap.setTrafficEnabled(true);baiduMap.setBaiduHeatMapEnabled(false);break;
                    case R.id.reli:baiduMap.setBaiduHeatMapEnabled(true);baiduMap.setTrafficEnabled(false);break;
                }
            }
        });
        baiduMap.setMyLocationEnabled(true);
        //positionText= (TextView) findViewById(R.id.position_text_view);
        List<String> permissionList=new ArrayList<>();
        if(ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.ACCESS_FINE_LOCATION)!= PackageManager.PERMISSION_GRANTED){
            permissionList.add(Manifest.permission.ACCESS_FINE_LOCATION);
        }
        if(ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.READ_PHONE_STATE)!= PackageManager.PERMISSION_GRANTED){
            permissionList.add(Manifest.permission.READ_PHONE_STATE);
        }
        if(ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE)!= PackageManager.PERMISSION_GRANTED){
            permissionList.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
        }
        if(!permissionList.isEmpty()){
            String[]permissions=permissionList.toArray(new String[permissionList.size()]);
            ActivityCompat.requestPermissions(MainActivity.this,permissions,1);
        }else{
            requestLocation();
        }
    }
    private void requestLocation(){
        initLocation();
        mLocationClient.start();
    }
    private void navigateTo(BDLocation location){
        if(isFirstLocate){
            LatLng ll=new LatLng(location.getLatitude(),location.getLongitude());//LatLng類用於存放經緯度
            // 第一個引數是緯度值,第二個引數是精度值。這裡輸入的是本地位置。
            MapStatusUpdate update= MapStatusUpdateFactory.newLatLng(ll);//將LatLng物件傳入
            baiduMap.animateMapStatus(update);
            update=MapStatusUpdateFactory.zoomTo(16f);//百度地圖縮放範圍,限定在3-19之間,可以去小數點位值
            // 值越大,地圖顯示的資訊越精細
            baiduMap.animateMapStatus(update);
            isFirstLocate=false;//防止多次呼叫animateMapStatus()方法,以為將地圖移動到我們當前位置只需在程式
            // 第一次定位的時候呼叫一次就可以了。
        }
        MyLocationData.Builder locationBuilder=new MyLocationData.Builder();
        locationBuilder.latitude(location.getLatitude());
        locationBuilder.longitude(location.getLongitude());
        MyLocationData locationData=locationBuilder.build();
        baiduMap.setMyLocationData(locationData);//獲取我們的當地位置
    }
    private void initLocation() {
        LocationClientOption option=new LocationClientOption();
        option.setScanSpan(5000);//表示每5秒更新一下當前位置
        option.setIsNeedAddress(true);
        option.setLocationMode(LocationClientOption.LocationMode.Device_Sensors);
        // Hight_Accuracy表示高精確度模式,會在GPS訊號正常的情況下優先使用GPS定位,在無法接收GPS訊號的時候使用網路定位。
        // Battery_Saving表示節電模式,只會使用網路進行定位。
        // Device_Sensors表示感測器模式,只會使用GPS進行定位。
        mLocationClient.setLocOption(option);
    }
    @Override
    protected void onDestroy() {
        super.onDestroy();
        mLocationClient.stop();//銷燬之前,用stop()來停止定位
        //在activity執行onDestroy時執行mMapView.onDestroy(),實現地圖生命週期管理
        mapView.onDestroy();
        unregisterReceiver(receiver);
        baiduMap.setMyLocationEnabled(false);
    }
    @Override
    protected void onResume() {
        super.onResume();
        //在activity執行onResume時執行mMapView. onResume (),實現地圖生命週期管理
        mapView.onResume();
    }
    @Override
    protected void onPause() {
        super.onPause();
        //在activity執行onPause時執行mMapView. onPause (),實現地圖生命週期管理
        mapView.onPause();
    }
    private void registerSDKCheckReceiver(){
        receiver=new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                String action=intent.getAction();
                if (SDKInitializer.SDK_BROADCAST_ACTION_STRING_NETWORK_ERROR.equals(action)){
                    Toast.makeText(getApplicationContext(),"網路錯誤",Toast.LENGTH_SHORT).show();
                }else if (SDKInitializer.SDK_BROADTCAST_ACTION_STRING_PERMISSION_CHECK_ERROR.equals(action)){
                    Toast.makeText(getApplicationContext(),"KEY驗證失敗",Toast.LENGTH_SHORT).show();
                }
            }
        };
        IntentFilter filter=new IntentFilter();
        //監聽網路錯誤
        filter.addAction(SDKInitializer.SDK_BROADCAST_ACTION_STRING_NETWORK_ERROR);
        //監聽百度地圖SDK的key是否正確
        filter.addAction(SDKInitializer.SDK_BROADTCAST_ACTION_STRING_PERMISSION_CHECK_ERROR);
        registerReceiver(receiver,filter);
    }
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        switch (requestCode){
            case 1:
                if(grantResults.length>0){
                    for(int result:grantResults){
                        if(result!=PackageManager.PERMISSION_GRANTED){
                            Toast.makeText(this,"必須同意所有許可權才能使用本程式",Toast.LENGTH_LONG).show();
                            finish();
                            return;
                        }
                    }
                    requestLocation();
                }else{
                    Toast.makeText(this,"發生未知錯誤",Toast.LENGTH_LONG).show();
                    finish();
                }
                break;
            default:
        }//onRequestPermissionsResult()方法中,對許可權申請結果進行邏輯判斷。這裡使用一個迴圈對每個許可權進行判斷,
        // 如果有任意一個許可權被拒絕了,那麼就會直接呼叫finish()方法關閉程式,只有當所有的許可權被使用者同意了,才會
        // 呼叫requestPermissions()方法開始地理位置定位。
    }
    public class MyLocationListener implements BDLocationListener {

        @Override
        public void onReceiveLocation(BDLocation location) {
            if(location.getLocType()==BDLocation.TypeGpsLocation||location.getLocType()==BDLocation.TypeNetWorkLocation){
                navigateTo(location);
            }
        }
    }
}

執行結果如下:

就此定位工具以及實現。

2、 就地圖覆蓋物

根據開發文件以及我個人的開發理解,對於地圖覆蓋物,主要是依靠提供的緯經度進行確定位置,並進行屬性的新增便可。較為難度就屬於標註覆蓋物了。為了保持文章的獨立性,“高內聚,低耦合嘛”,先偷個懶,下一篇進行講解。