1. 程式人生 > >Android:百度地圖的簡單定位開發

Android:百度地圖的簡單定位開發

在網上學習使用百度定位,看了很多文章和部落格始終覺得很亂,而且是看的越多,邏輯越迷糊。直到看了《Android定位技術 LBS視訊教程》https://www.douban.com/group/topic/80331061/才感覺總算把邏輯理清楚了。我就在這裡把我的邏輯總結出來,希望能幫到需要的人,同時也方便我今後回顧。

本篇文章不再講述如何搭建百度地圖環境了,網上大把,我就不浪費時間了,本篇著重講實現的邏輯。

實現邏輯分為四步:

1.初始化地圖。2.動態新增許可權。3.請求位置。4.更新地圖。

邏輯最重要的部分就是第三,第四步。也是看其他文章最容易被攪暈的步驟。

下面為各個部分貼出程式碼:

成員變數:

private static final int 
REQUEST_PERMISSION = 1;//許可權請求碼 private static final String TAG = "MainActivity"; private ArrayList<String> permissionList = new ArrayList<>();//許可權集合 private BaiduMap baiduMap;//百度地圖例項 private MapView mapView;//地圖控制元件 private LocationClient locationClient;//位置客戶端 private boolean ToastFlag = true;

該專案的整體思想:

整個專案就執行這四個大的邏輯。其中,第四步更新地圖是放在第三步請求位置中執行的,因為第三步需要實時的更新位置資訊,所以第四步也要隨第三步實時的更新地圖。

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
//初始化SDK。SDK隨App銷燬而銷燬
SDKInitializer.initialize(getApplicationContext());
setContentView(R.layout.activity_main);
mapView = (MapView) findViewById(R.id.mapView);//管理地圖週期 //初始化地圖 initialMap(); //動態新增許可權 initialPermission(); //請求位置 requestLocation(); //更新地圖 }

PS:1.使用百度SDK,務必要在設定佈局之前初始化!

        2.要對地圖控制元件mapView的生命週期進行管理,確保資源的及時釋放,如下所示:

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

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

@Override
protected void onDestroy() {
    super.onDestroy();
mapView.onDestroy();
    if (locationClient != null){
        locationClient.stop();
}
    baiduMap.setMyLocationEnabled(false);
}

一、初始化地圖

//--------------初始化地圖
private void initialMap() {
    //拿到地圖例項
baiduMap = mapView.getMap();
baiduMap.setMyLocationEnabled(true);//在地圖上顯示當前位置(小圓點)
MapStatusUpdate updateZoom = MapStatusUpdateFactory.zoomTo(18f);//顯示初始地圖縮放大小
baiduMap.animateMapStatus(updateZoom);//更新地圖狀態
}

二、動態新增許可權

//--------------動態新增許可權
private void initialPermission() {
    if (ContextCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED){
        //加入到集合中,在集合中一起請求許可權
permissionList.add(Manifest.permission.ACCESS_COARSE_LOCATION);
}
    if (ContextCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED){
        permissionList.add(Manifest.permission.ACCESS_FINE_LOCATION);
}
    if (ContextCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED){
        permissionList.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
}
    if (ContextCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED){
        permissionList.add(Manifest.permission.READ_PHONE_STATE);
}
    if (!permissionList.isEmpty()){
        //集合轉陣列
String[] permissions = permissionList.toArray(new String[permissionList.size()]);
//請求許可權
ActivityCompat.requestPermissions(MainActivity.this,permissions,REQUEST_PERMISSION);
}
}

上面四個許可權都是危險許可權,6.0以上的手機需要動態新增許可權。這裡也是把沒有授權的許可權全部加入到集合中統一授權。

//---------回撥許可權請求結果
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    if (requestCode == REQUEST_PERMISSION){

        if (grantResults.length>0){
            //遍歷陣列結果
for (int result:grantResults){
                if (result != PackageManager.PERMISSION_GRANTED){
                    finish();
                    return;
}
            }
        }

    }
}

三、請求位置(請求位置→返回資料→更新地圖)

private void requestLocation() {
    locationClient = new LocationClient(this);
locationClient.registerLocationListener(new MyLocationListener());//註冊監聽事件
    //設定位置引數
LocationClientOption option = new LocationClientOption();
option.setCoorType("bd09ll");//設定地圖型別
option.setScanSpan(5000);//設定定位重新整理時間
option.setIsNeedAddress(true);//是否使用地址(可選)
option.setOpenGps(true);//開啟GPS;預設不開啟
locationClient.setLocOption(option);
locationClient.start();
}

一定要記得註冊監聽事件,這樣當你呼叫start方法就會自動執行監聽器內部類的onReceive方法。

位置引數只提一點,一定要記得setOpenGps開啟GPS,否則即便你開啟手機上的GPS也無法使用GPS定位!新手不懂這裡,很容易被坑死,而且室內通常接受不到GPS訊號。。。。

接下來我們就拿到了我們的位置資料,它們都封裝在onReceriveLocation方法的引數bdLocation中,如下圖所示,我們需要操作這些資料。在操作資料之前,我們需要明確一點,我們最終目的是要更新地圖,更新地圖我們需要的兩個核心方法是:1.把資料和地圖繫結起來:baiduMap.setMyLocationData(data); 2.動態更新地圖:baiduMap.animateMapStatus(update);

因此,我們需要準備引數MyLocationData和引數MapStatusUpdate。

//-------------監聽器內部類
private class MyLocationListener extends BDAbstractLocationListener {
    @Override
public void onReceiveLocation(BDLocation bdLocation) {
        Log.d(TAG, "緯度: " + bdLocation.getLatitude());
Log.d(TAG, "經度: " + bdLocation.getLongitude());
//封裝資料
MyLocationData.Builder builder = new MyLocationData.Builder();
MyLocationData data = builder.direction(100)
                .latitude(bdLocation.getLatitude())
                .longitude(bdLocation.getLongitude())
                .build();
//更新地圖
updateMap(data);
//第一次開啟地圖,彈出Toast提示當前地址
if (ToastFlag){
            ToastFlag = false;
Toast.makeText(MainActivity.this,bdLocation.getAddrStr(), Toast.LENGTH_LONG).show();
}
    }
}

首先我們位置資訊全部封裝到了MyLocationData類中,然後執行我們的第四步更新地圖操作。

四、更新地圖

//-------------------更新地圖
private void updateMap(MyLocationData data) {
    //地圖繫結資料
baiduMap.setMyLocationData(data);
LatLng latLng = new LatLng(data.latitude, data.longitude);//經緯度例項
MapStatusUpdate updateLatLng = MapStatusUpdateFactory.newLatLng(latLng);//地圖狀態更新的例項
baiduMap.animateMapStatus(updateLatLng);//動態更新地圖
}

繫結資料就用我們傳過來的data即可。

動態更新地圖,我們主要就是更新經緯度,缺什麼我們就給它什麼。需要一個地圖狀態更新的例項,好,我們就通過靜態工廠類建立一個例項,建立地圖狀態更新例項時需要用到經緯度的例項,我們也給它準備一個經緯度的例項。

五、總結

至此我們的定位就大功告成了,最後我貼出整個程式的縮略碼,方便大家回顧整個程式的邏輯結構:

public class MainActivity extends AppCompatActivity {

    private static final int REQUEST_PERMISSION = 1;//許可權請求碼
private static final String TAG = "MainActivity";
    private ArrayList<String> permissionList = new ArrayList<>();//許可權集合
private BaiduMap baiduMap;//百度地圖例項
private MapView mapView;//地圖控制元件
private LocationClient locationClient;//位置客戶端
private boolean ToastFlag = true;
@Override
protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
//初始化SDK。SDK隨App銷燬而銷燬
SDKInitializer.initialize(getApplicationContext());
setContentView(R.layout.activity_main);
mapView = (MapView) findViewById(R.id.mapView);//管理地圖週期
        //初始化地圖
initialMap();
//動態新增許可權
initialPermission();
//請求位置
requestLocation();
//更新地圖
}

    //--------------初始化地圖
private void initialMap() {
        //拿到地圖例項
baiduMap = mapView.getMap();
baiduMap.setMyLocationEnabled(true);//在地圖上顯示當前位置(小圓點)
MapStatusUpdate updateZoom = MapStatusUpdateFactory.zoomTo(18f);
baiduMap.animateMapStatus(updateZoom);
}

    //-------------------更新地圖
private void updateMap(MyLocationData data) {
        //地圖繫結資料
baiduMap.setMyLocationData(data);
LatLng latLng = new LatLng(data.latitude, data.longitude);//經緯度例項
MapStatusUpdate updateLatLng = MapStatusUpdateFactory.newLatLng(latLng);//地圖狀態更新的例項
baiduMap.animateMapStatus(updateLatLng);//動態更新地圖
}

    //----------------請求位置
private void requestLocation() {
        locationClient = new LocationClient(this);
locationClient.registerLocationListener(new MyLocationListener());//註冊監聽事件
        //設定位置引數
LocationClientOption option = new LocationClientOption();
option.setCoorType("bd09ll");//設定地圖型別
option.setScanSpan(5000);//設定定位重新整理時間
option.setIsNeedAddress(true);//是否使用地址(可選)
option.setOpenGps(true);//開啟GPS;預設不開啟
locationClient.setLocOption(option);
locationClient.start();
}

    //--------------動態新增許可權
private void initialPermission() {
        if (ContextCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED){
            //加入到集合中,在集合中一起請求許可權
permissionList.add(Manifest.permission.ACCESS_COARSE_LOCATION);
}
        if (ContextCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED){
            permissionList.add(Manifest.permission.ACCESS_FINE_LOCATION);
}
        if (ContextCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED){
            permissionList.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
}
        if (ContextCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED){
            permissionList.add(Manifest.permission.READ_PHONE_STATE);
}
        if (!permissionList.isEmpty()){
            //集合轉陣列
String[] permissions = permissionList.toArray(new String[permissionList.size()]);
//請求許可權
ActivityCompat.requestPermissions(MainActivity.this,permissions,REQUEST_PERMISSION);
}
    }


    //---------回撥許可權請求結果
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == REQUEST_PERMISSION){

            if (grantResults.length>0){
                //遍歷陣列結果
for (int result:grantResults){
                    if (result != PackageManager.PERMISSION_GRANTED){
                        finish();
                        return;
}
                }
            }

        }
    }

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

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

    @Override
protected void onDestroy() {
        super.onDestroy();
mapView.onDestroy();
        if (locationClient != null){
            locationClient.stop();
}
        baiduMap.setMyLocationEnabled(false);
}

    //-------------監聽器內部類
private class MyLocationListener extends BDAbstractLocationListener {
        @Override
public void onReceiveLocation(BDLocation bdLocation) {
            Log.d(TAG, "緯度: " + bdLocation.getLatitude());
Log.d(TAG, "經度: " + bdLocation.getLongitude());
//封裝資料
MyLocationData.Builder builder = new MyLocationData.Builder();
MyLocationData data = builder.direction(100)
                    .latitude(bdLocation.getLatitude())
                    .longitude(bdLocation.getLongitude())
                    .build();
//更新地圖
updateMap(data);
//第一次開啟地圖,彈出Toast提示當前地址
if (ToastFlag){
                ToastFlag = false;
Toast.makeText(MainActivity.this,bdLocation.getAddrStr(), Toast.LENGTH_LONG).show();
}
        }
    }
}