android开发调用百度地图api实现加载地图和定位

目录

一.踩的一些坑以及解决方法

1.权限声明不要少

2.地图初始化

3.定位问题

(1)监听器注册

(2)定位监听器类MyLocationListener的实现

(3)定位功能的调用

4.android studio连接真机调试问题 

二.MainActivity的逻辑代码以及运行结果


官方文档地址:

Android地图SDK | 百度地图API SDK (baidu.com)icon-default.png?t=N7T8https://lbsyun.baidu.com/faq/api?title=androidsdk

一.踩的一些坑以及解决方法

1.权限声明不要少


    <!-- 访问网络,进行地图相关业务数据请求,包括地图数据,路线规划,POI检索等 -->
    <uses-permission android:name="android.permission.INTERNET" />
    <!-- 获取网络状态,根据网络状态切换进行数据请求网络转换 -->
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <!-- 用于访问wifi网络信息,wifi信息会用于进行网络定位-->
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
    <!-- 读取外置存储。如果开发者使用了so动态加载功能并且把so文件放在了外置存储区域,则需要申请该权限,否则不需要 -->
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <!-- 写外置存储。如果开发者使用了离线地图,并且数据写在外置存储区域,则需要申请该权限 -->
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <!-- 读取设备的电话状态和身份标识  -->
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    <!-- 这个权限用于进行网络定位 -->
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <!-- 这个权限用于访问GPS定位 -->
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

2.地图初始化

 protected void onCreate(Bundle savedInstanceState) {
        //定位监视器
        super.onCreate(savedInstanceState);
        //隐私保护,必须写,不然会报错
        SDKInitializer.setAgreePrivacy(getApplicationContext(), true);

        SDKInitializer.initialize(getApplicationContext());//一定要先初始化,再加载布局

        SDKInitializer.setCoordType(CoordType.BD09LL);    //经纬坐标,使用中国国测局的。

        setContentView(R.layout.activity_main);  //加载布局

在SDK各功能组件使用之前都需要调用“SDKInitializer.initialize(getApplicationContext())”

这一段官方文档写的不是很清晰,SDKInitializer在MainActivity类的onCreate方法中实现就可以,但是顺序不要错,初始化语句一定要写在引入布局文件的语句之前,且要在初始化之前加上同意隐私协议的语句,其他文件不需要修改。

3.定位问题

首先要完成权限的声明和地图初始化,这在之前已经陈述过。

其中这两条权限用于定位:

  <!-- 这个权限用于进行网络定位 -->
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
  <!-- 这个权限用于访问GPS定位 -->
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

        定位的逻辑需要用到java多线程编程的知识,为了避免阻塞主线程或造成线程间的等待,通常会将耗时的操作放在后台线程执行 。定位通常是一个耗时的操作,涉及到与设备硬件、网络通信等交互。为了避免主线程的阻塞和界面的卡顿,可以将定位操作放在后台线程中进行,使用多线程的技术实现异步定位。这样,应用程序的主线程可以继续响应用户的操作,同时定位操作在后台线程进行。定位操作完成后,需要将定位结果传递给应用程序进行处理。

(1)监听器注册

   public LocationClient mLocationClient= null;   
    //创建一个定位监听器类对象,MyLocationListener 是一个自定义的定位监听器类,用于接收定位结果的回调。
   private MyLocationListener myListener = new MyLocationListener();       
    try {

        //实例化LocationClient 对象并传入应用程序的上下文参数
            mLocationClient = new LocationClient(getApplicationContext());

        } catch (Exception e) {
            e.printStackTrace();
        }
        //将自定义的定位监听器 myListener 注册到 LocationClient 中
        mLocationClient.registerLocationListener(myListener);

这里必须要加上try-catch异常处理机制,不然会报错。

(2)定位监听器类MyLocationListener的实现

//通过继承抽象类BDAbstractListener并重写其onReceieveLocation方法来获取定位数据,并将其传给MapView。
    public class MyLocationListener extends BDAbstractLocationListener {
        @Override
        public void onReceiveLocation(BDLocation location) {
            int locType = location.getLocType();
            Log.d("定位结果错误码", String.valueOf(locType));
            //mapView 销毁后不再处理新接收的位置
            if (location == null || mMapView == null) {             //判断 location 和 mMapView 是否为空来确保在地图视图销毁后不再处理新接收的位置
                return;
            }
            MyLocationData locData = new MyLocationData.Builder()       //通过 Builder 模式,设置位置的精度、方向、纬度和经度等属性。
                    .accuracy(location.getRadius())
                    // 此处设置开发者获取到的方向信息,顺时针0-360
                    .direction(location.getDirection())
                    .latitude(location.getLatitude())
                    .longitude(location.getLongitude())
                    .build();
            baiduMap.setMyLocationData(locData);                //将新的位置信息更新到地图上,以显示当前设备的位置

            if (isFirstLocate) {
                LatLng ll = new LatLng(location.getLatitude(), location.getLongitude());      //根据 BDLocation 对象的经纬度创建一个 LatLng 对象
                System.out.println("纬度"+location.getLatitude());
                System.out.println("经度"+location.getLongitude());
                MapStatusUpdate update = MapStatusUpdateFactory.newLatLng(ll);          //将地图的中心点设置为 ll 所表示的位置
                baiduMap.animateMapStatus(update);                          //动画更新中心点
                update = MapStatusUpdateFactory.zoomTo(16f);        //将地图的缩放级别设置为 16
                baiduMap.animateMapStatus(update);              //动画更新缩放级别
                isFirstLocate = false;
            }

        }
    }

其中          int locType = location.getLocType();
            Log.d("定位结果错误码", String.valueOf(locType));

这两句是打印定位错误码到logcat窗口,去官网对照查表,就可以知道是否定位成功或者发生哪些错误。

Android定位SDK | 百度地图API SDK (baidu.com)icon-default.png?t=N7T8https://lbs.baidu.com/faq/api?title=android-locsdk/guide/addition-func/error-code如果返回的是61,161就是定位成功。

(3)定位功能的调用

mLocationClient.start();  

注意语句的顺序:

监听器的注册要在定位功能的实现之前,然后启动定位(start),然后调用编写定位参数的方法。

注意:不要重复编写监听器注册的代码,可能导致定位偏移,博主在onCreate函数中实例化了一次监听器对象,调试程序时候又在编写定位参数的函数中实例化了一次监听器对象,也就是在start()的调用前后各实例化了一次,定位到了一个离博主所在位置搁一条河的小区里面,当博主整理代码时删掉了start函数后面的实例化监听器代码,再次运行之后就定位到了博主所在位置。

4.android studio连接真机调试问题 

博主所用为华为nova6手机,harmonyos4.0.0系统,连接真机时与其他手机不同。

要下载华为手机助手:

华为手机助手HiSuite官方下载 | 华为官网 (huawei.com)icon-default.png?t=N7T8https://consumer.huawei.com/cn/support/hisuite/用usb连接之后要输入手机上的密码(手机上会自动下载华为手机助手,提供密码)到电脑的华为手机助手。

要开启手机的开发者模式,方法为连续点击设置中的版本号三次,开启usb调试功能,开启ADB,具体操作教程很多,不再赘述。

连接成功后:

在logcat窗口的左上角会显示机型,然后正常run就可以了。

要注意手机的存储空间要充足,否则把软件下载手机上会失败报错 

二.MainActivity的逻辑代码以及运行结果

package com.example.mcssignaltest;

import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;

import android.Manifest;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Bundle;

import android.app.Application;
import android.widget.TextView;
import android.widget.Toast;
import android.util.Log;


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

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


public class MainActivity extends AppCompatActivity {           //AppCompatActivity是 Activity 类的一个子类,提供了对旧版本 Android 平台的兼容性支持
    public LocationClient mLocationClient= null;
    private MyLocationListener myListener = new MyLocationListener();     //创建一个定位监听器类对象
    private MapView mMapView = null;        //百度自定义地图控件
    private BaiduMap baiduMap;              //地图总控制器
    private boolean isFirstLocate = true;     //是否是首次定位
    private TextView positionText;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        //定位监视器
        super.onCreate(savedInstanceState);
        //隐私保护,必须写,不然会报错
        SDKInitializer.setAgreePrivacy(getApplicationContext(), true);
        LocationClient.setAgreePrivacy(true);
        //注册LocationListener监听器
        try {
            mLocationClient = new LocationClient(getApplicationContext());
        } catch (Exception e) {
            e.printStackTrace();
        }

        mLocationClient.registerLocationListener(myListener);



        SDKInitializer.initialize(getApplicationContext());//一定要先初始化,再加载布局

        SDKInitializer.setCoordType(CoordType.BD09LL);    //经纬坐标,使用中国国测局的。

        setContentView(R.layout.activity_main);  //加载布局


        //获取地图控件引用
        mMapView = (MapView) findViewById(R.id.bmapView);
        baiduMap = mMapView.getMap();

        positionText = (TextView) findViewById(R.id.position_text_view);
        List<String> permissionList = new ArrayList<>();//权限列表,记录未允许的权限

        baiduMap.setMyLocationEnabled(true);     //开启地图的定位图层


        //判断单个权限是否已经允许
        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_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
            permissionList.add(Manifest.permission.READ_EXTERNAL_STORAGE);
        }
        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() {
        mLocationClient.start();       //开始定位,回调定位监听器
        initMyLocation();         //调用本地定位方法
    }


    //权限判断
    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        switch (requestCode) {
            case 1:
                if (grantResults.length > 0) {
                    for (int result : grantResults) {
                        if (result != PackageManager.PERMISSION_GRANTED) {
                            Toast.makeText(this, "必须同意所有权限才能使用本程序", Toast.LENGTH_SHORT).show();
                            finish();
                            return;
                        }
                    }
                    requestLocation();
                } else {
                    Toast.makeText(this, "发生未知错误", Toast.LENGTH_SHORT).show();
                    finish();
                }
                break;
            default:
        }
    }

    @Override
    protected void onResume() {
        super.onResume();
        //在activity执行onResume时执行mMapView. onResume (),实现地图生命周期管理
        mMapView.onResume();
    }

    @Override
    protected void onPause() {
        super.onPause();
        //在activity执行onPause时执行mMapView. onPause (),实现地图生命周期管理
        mMapView.onPause();
    }

    //通过继承抽象类BDAbstractListener并重写其onReceieveLocation方法来获取定位数据,并将其传给MapView。
    public class MyLocationListener extends BDAbstractLocationListener {
        @Override
        public void onReceiveLocation(BDLocation location) {
            int locType = location.getLocType();
            Log.d("定位结果错误码", String.valueOf(locType));
            //mapView 销毁后不再处理新接收的位置
            if (location == null || mMapView == null) {             //判断 location 和 mMapView 是否为空来确保在地图视图销毁后不再处理新接收的位置
                return;
            }
            MyLocationData locData = new MyLocationData.Builder()       //通过 Builder 模式,设置位置的精度、方向、纬度和经度等属性。
                    .accuracy(location.getRadius())
                    // 此处设置开发者获取到的方向信息,顺时针0-360
                    .direction(location.getDirection())
                    .latitude(location.getLatitude())
                    .longitude(location.getLongitude())
                    .build();
            baiduMap.setMyLocationData(locData);                //将新的位置信息更新到地图上,以显示当前设备的位置

            if (isFirstLocate) {
                LatLng ll = new LatLng(location.getLatitude(), location.getLongitude());      //根据 BDLocation 对象的经纬度创建一个 LatLng 对象
                System.out.println("纬度"+location.getLatitude());
                System.out.println("经度"+location.getLongitude());
                MapStatusUpdate update = MapStatusUpdateFactory.newLatLng(ll);          //将地图的中心点设置为 ll 所表示的位置
                baiduMap.animateMapStatus(update);                          //动画更新中心点
                update = MapStatusUpdateFactory.zoomTo(16f);        //将地图的缩放级别设置为 16
                baiduMap.animateMapStatus(update);              //动画更新缩放级别
                isFirstLocate = false;
            }

        }
    }

    //通过LocationClient发起定位
    private void initMyLocation() {
        //通过LocationClientOption设置LocationClient相关参数
        LocationClientOption option = new LocationClientOption();
        //强制选择高精度定位,三种模式:Hight_Accuracy(高精度)、Battery_Saving(节电模式)、Device_Sensors(传感器模式)
        option.setLocationMode(LocationClientOption.LocationMode.Device_Sensors);
        option.setOpenGps(true); // 打开gps
        option.setCoorType("bd09ll"); // 设置坐标类型
        option.setScanSpan(1000);           //设置位置更新间隔,1s一更新

        //设置locationClientOption
        mLocationClient.setLocOption(option);

   }

    @Override
    protected void onDestroy() {
        mLocationClient.stop();         //程序销毁时停止定位,防止消耗电量
        baiduMap.setMyLocationEnabled(false);
        mMapView.onDestroy();
        mMapView = null;
        super.onDestroy();
        //在activity执行onDestroy时执行mMapView.onDestroy(),实现地图生命周期管理
    }
}

猜你喜欢

转载自blog.csdn.net/qq_53162179/article/details/135316644