目录
一.踩的一些坑以及解决方法
1.权限声明不要少
2.地图初始化
3.定位问题
(1)监听器注册
(2)定位监听器类MyLocationListener的实现
(3)定位功能的调用
4.android studio连接真机调试问题
二.MainActivity的逻辑代码以及运行结果
官方文档地址:
Android地图SDK | 百度地图API SDK (baidu.com)https://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 {@Overridepublic 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); //将地图的缩放级别设置为 16baiduMap.animateMapStatus(update); //动画更新缩放级别isFirstLocate = false;}}}
其中 int locType = location.getLocType();
Log.d("定位结果错误码", String.valueOf(locType));
这两句是打印定位错误码到logcat窗口,去官网对照查表,就可以知道是否定位成功或者发生哪些错误。
Android定位SDK | 百度地图API SDK (baidu.com)https://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)https://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;@Overrideprotected 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(); //调用本地定位方法}//权限判断@Overridepublic 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:}}@Overrideprotected void onResume() {super.onResume();//在activity执行onResume时执行mMapView. onResume (),实现地图生命周期管理mMapView.onResume();}@Overrideprotected void onPause() {super.onPause();//在activity执行onPause时执行mMapView. onPause (),实现地图生命周期管理mMapView.onPause();}//通过继承抽象类BDAbstractListener并重写其onReceieveLocation方法来获取定位数据,并将其传给MapView。public class MyLocationListener extends BDAbstractLocationListener {@Overridepublic 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); //将地图的缩放级别设置为 16baiduMap.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); // 打开gpsoption.setCoorType("bd09ll"); // 设置坐标类型option.setScanSpan(1000); //设置位置更新间隔,1s一更新//设置locationClientOptionmLocationClient.setLocOption(option);}@Overrideprotected void onDestroy() {mLocationClient.stop(); //程序销毁时停止定位,防止消耗电量baiduMap.setMyLocationEnabled(false);mMapView.onDestroy();mMapView = null;super.onDestroy();//在activity执行onDestroy时执行mMapView.onDestroy(),实现地图生命周期管理}
}