新版高德地图
- 前言
- 正文
- 一、创建应用
- ① 获取PackageName
- ② 获取调试版安全码SHA1
- ③ 获取发布版安全码SHA1
- 二、配置项目
- ① 导入SDK
- ② 配置AndroidManifest.xml
- 三、获取当前定位信息
- ① ViewBinding使用和导包
- ② 隐私合规设置
- ③ 权限请求
- ④ 初始化定位
- ⑤ 获取定位信息
- 四、显示地图
- 五、显示当前定位地图
- 六、地图设置
- ① 修改定位图标样式
- ② 设置缩放等级
- ③ 开启室内地图
- ④ 地图控件设置
- 七、获取POI数据
前言
2020年的时候我写了关于高德地图的使用,在当时你按照文章是没有问题,然而现在到了2024年了,这几年高德的SDK发生了变化,Android Studio发生了变化,不变的是什么呢?就是学校的老师还是让一个没接触过Android的学生去完成相关的功能,定位地图之类的,然后不会怎么办呢?就搜索到我的文章了,一操作发现不对,几百个人问同样的问题,我是真的回答累了,因此我打算重新写一遍,根据最新的内容来写,从内容上和之前的文章大概相同,下面进入正文。
正文
在此之前呢,默认都没有账号,因此需要先注册一个账号才行,点击高德开放平台进入主页面。
完成账号的注册,注册的类型如果没有公司就选择个人开发者,注册完成之后登录,登录之后就创建应用。
一、创建应用
点击 控制台
→ 应用管理
→ 我的应用
然后点击右上角 创建新应用
按钮,会出现弹窗,输入内容。
点击创建
按钮。完成之后我们需要添加Key。
点击 添加Key
,出现弹窗,弹窗中需要我们配置Android工程中的内容,弹窗如下图所示:
你可以和我写的一样,这里选择Android平台
,还有3个输入框需要我们填写值,其中有红色 * 号的是必填项,也就是说,这个调试版安全码SHA1我们可以不填,但是我还是会说明该怎么获取。这个网页先保留好,先别关了。
- ① 发布版安全码SHA1就是你的应用发布正式版本时的安全码,常规是使用jks秘钥来生成release包。
- ② 调试版安全码SHA1就是你的应用通过usb直接运行在手机或者虚拟机时的安全码,同一个项目在不同的电脑上运行,这个安全码各不相同。
- ③ PackageName 就是你的应用包名。
① 获取PackageName
要获取PackageName 就需要创建一个Android 项目,而这个项目创建也有很多细节可以说明,先看看我的Android Studio版本:
这个版本是属于比较新的,如果你还使用的老版本,那么参考老版本的文章,下面我们创建工程,这里要选择Empty Views Activity
,别选错了。
点击Next
,然后我们需要注意的地方就来了,首先是Package name
也就是我们需要填到网页里的内容,也是项目的包名,然后项目的编程语言我们选择了Java
,因为相比于不会Java的来说,不会Kotlin的更多,最后一点,就是配置文件所使用的语言,这里我使用了Groovy,默认是Kotlin。目前很多的SDK配置还是基于Groovy的,如果你使用了Kotlin,那么可能就会出现一些问题,这些问题我同样回答的烦了。
请对照我上面的配置去设置你的项目,包名你可以自行更改为自己习惯的,改好之后点击Finish
,完成项目创建,与此同时我们将包名复制进行,如下图所示:
现在我们还差两个值需要填写,等项目创建完成之后我们就来获取。创建成功之后我们运行在真机上,什么是真机,就是Android手机,不要使用AS的虚拟机或者其他第三方虚拟机,为什么呢?因为你在使用SDK的时候会出现问题。没有真机的自己想办法,不要再问我虚拟机出现问题怎么办了。
OK ,真机上运行成功,我使用的是荣耀V40,Android 12的系统版本。下面我们来获取调试版安全码SHA1
。
② 获取调试版安全码SHA1
Windows电脑,使用快捷键Win + R
,输入cmd
,进入命令窗口。
输入cd .android
cd .android
先切换到.android目录下,然后输入如下指令:
keytool -list -v -keystore debug.keystore
然后回车,如下图所示:
这里提示了keytool不是内部或外部命令,这说明我们没有配置JDK,下面我们配置一下,参考:JDK 安装与环境变量配置,配置之后我们重新走一下这个流程,如下图所示:
这里的密钥库口令是:android
输入的时候看不到内容,输入完成之后回车就可以了,如果你发现不是这样的话,就先运行一下项目,运行成功之后再尝试这一步。这里我们就拿到了调试版安全码SHA1
,这里需要注意一点,调试版安全码SHA1
会跟随电脑环境改变而改变,同一个项目在不同电脑上编译之后调试版安全码SHA1
也会有变化,现在我们复制到那个网页里。
现在就只有一个发布版安全码SHA1
需要获取了。
③ 获取发布版安全码SHA1
这个稍微有一些麻烦,因此需要先创建一个jks文件才行,首先我们点击这个菜单按钮。
然后点击Build
选择点击Generate Signed Bundle / APK…
这时候会出现一个弹窗,我们选择APK
,Android App Bundle
打包的是aab格式,这种格式的包用于上传Google应用商店,国内都是apk格式。
点击Next
。
在生成apk时需要一个jks文件,这里我们选择Create new...
,创建一个新的jks
文件。
首先指明生成的jks文件的路径,点击这个文件夹图标。
这里我选择将jks就生成在项目的根目录下,点击OK,然后我们输入一些其他的信息,实际上你只要输入商量密码和别名密码就可以了,但是还是都填好比较好。Confirm就是再输入一次密码,这里建议你把商店密码和别名密码设置成一样的。
点击OK,然后选择Remember passwords
。
然后点击Next
,然后选择release
。
点击Create
,当你看到右下角出现如下弹窗。
则说明这个Apk生成成功了,下面我们就可以来获取发布版安全码SHA1
,还是之前那个窗口,我们输入:
keytool -list -v -keystore D:\Android\NewGaodeMapDemo\map.jks
这里需要注意地址是我项目的地址,你需要按照自己实际的地址填。
密钥口令,就是你刚才设置的jks密码,然后我们复制这个SHA1到那个网页里面。
现在需要的内容都有了,点击提交。
这里的Key我们需要到Android工程的AndroidManifest.xml中去配置,你需要使用自己的。到了这一步我们初期的应用创建就完成了,为自己点个赞吧,虽然这挺容易的。
二、配置项目
这里我们需要用到高德的SDK
,点击 文档与支持
→ Android 地图SDK
。
点击相关下载
,然后向下滑动。
这里我们选择 3D地图合包
,可以看到里面包含了,3D地图SDK、搜索SDK和定位SDK,点击下载。
下载之后解压,看到有一个Jar包和两个架构文件夹,里面都是so库。
① 导入SDK
下面我们需要将她复制到Android项目的libs目录下,下面我们创建这个目录。这里默认是Android工程模式,我们先切换成Project工程模式,然后鼠标右键点击app
→ New
→ Directory
。
出现弹窗输入libs
,然后回车。
然后将解压包里的4个文件都复制进来,如下图所示:
只不过现在这个包现在还没有用起来,我们需要配置一下,在app模块下的build.gradle中添加如下代码:
ndk {
//设置支持的SO库架构(开发者可以根据需要,选择一个或多个平台的so)
abiFilters "armeabi", "armeabi-v7a", "arm64-v8a", "x86","x86_64"
}
sourceSets {
main {
jniLibs.srcDirs = ['libs']
}
debug.setRoot('build-types/debug')
release.setRoot('build-types/release')
}
buildFeatures {
viewBinding true
}
implementation fileTree(dir: 'libs', include: ['*.jar'])
添加位置如下图所示:
这里我除了添加配置代码,还配置了打开ViewBinding,记得点击Sync Now
进行同步,同步完成之后就会发现Jar包前面就一个箭头,我们可以打开这个包,如下图所示:
这说明我们导入的SDK可以使用了。
② 配置AndroidManifest.xml
打开AndroidManifest.xml,首先在application标签下添加定位服务,添加代码如下:
<!--高德定位服务-->
<service android:name="com.amap.api.location.APSService" />
<!--高德的Key value里面的值请使用自己的Key-->
<meta-data
android:name="com.amap.api.v2.apikey"
android:value="key" />
添加位置如下图所示:
这里的value里面的值你就填写自己高德平台所创建的Key,我在前面提到过,这里不能错,请注意,下面我们添加权限。代码如下:
<!--用于进行网络定位-->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<!--用于访问GPS定位-->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<!--用于获取运营商信息,用于支持提供运营商信息相关的接口-->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<!--用于访问wifi网络信息,wifi信息会用于进行网络定位-->
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<!--用于获取wifi的获取权限,wifi信息会用来进行网络定位-->
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
<!--用于访问网络,网络定位需要上网-->
<uses-permission android:name="android.permission.INTERNET"/>
<!--用于写入缓存数据到扩展存储卡-->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<!--用于申请调用A-GPS模块-->
<uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS"/>
<!--如果设置了target >= 28 如果需要启动后台定位则必须声明这个权限-->
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<!--如果您的应用需要后台定位权限,且有可能运行在Android Q设备上,并且设置了target>28,必须增加这个权限声明-->
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION"/>
<!--允许写设备缓存,用于问题排查-->
<uses-permission android:name="android.permission.WRITE_SETTINGS"
tools:ignore="ProtectedPermissions" />
添加位置如下图所示:
三、获取当前定位信息
获取定位信息之前我们需要先动态请求位置权限。
① ViewBinding使用和导包
在此之前我们先了解一下ViewBinding的使用和导包,为什么我要说这个,因为确实别问我为什么报错的时候,我一看没有导包,那时候我的内心是相当复杂的,如果你是从事这个行业的你就会懂我的心情。
可以看到ActivityMainBinding是爆红的,这是因为使用了ViewBinding才有这个文件的生成,如果你想了解ViewBinding可以单独去了解。注意上面的一个小弹窗,有一个快捷键,Alt + Enter,使用之后就导了文件的包进来,就可以使用这个类了。
现在看到就不爆红了,后面你遇到这个情况的时候就知道怎么做了,为什么呢?因为很多人代码都不是一行行敲的,都是复制粘贴的,所以并不会自动导包,使用的方式如下图所示:
参考来就行了,汲取之前那篇文章的经验,我尽量每一行代码写在什么地方都截图,避免你不知道代码应该添加在哪里,又来问我怎么报错了。
② 隐私合规设置
随着工信部推行加强个人信息隐私的保护政策,各大SDK都需要相应增加一个API接口,确保用户是在知道会采集信息的情况下使用某一个功能,所以我们在使用高德的定位、地图、搜索功能时,需要先同意隐私政策,不通过则无法使用,一般是通过App启动之后出现一个弹窗,弹窗中你告知用户那些信息被采集,用到了那些SDK,作用是什么。并且要有隐私政策的链接地址,很麻烦。这里我们就简单一些,鼠标右键com.llw.newmapdemo
包,然后选择New
→ Java Class
。
在出现的弹窗中输入App,然后回车。
里面的代码如下所示:
public class App extends Application {
@Override
public void onCreate() {
super.onCreate();
Context mContext = this;
// 定位隐私政策同意
AMapLocationClient.updatePrivacyShow(mContext,true,true);
AMapLocationClient.updatePrivacyAgree(mContext,true);
// 地图隐私政策同意
MapsInitializer.updatePrivacyShow(mContext,true,true);
MapsInitializer.updatePrivacyAgree(mContext,true);
// 搜索隐私政策同意
ServiceSettings.updatePrivacyShow(mContext,true,true);
ServiceSettings.updatePrivacyAgree(mContext,true);
}
}
记得导包,后面我就不重复提醒,不要又来问我为什么没有这个AMapLocationClient
和ServiceSettings
,这里我们还需要将App
配置到AndroidManifest.xml
中的application
标签里,如下图所示:
③ 权限请求
这里我们使用Android 原生的方式来请求动态权限,首先在MainActivity
中添加如下代码:
private static final String TAG = "MainActivity";
// 请求权限意图
private ActivityResultLauncher<String> requestPermission;
然后再onCreate()方法中添加如下代码:
requestPermission = registerForActivityResult(new ActivityResultContracts.RequestPermission(), result -> {
// 权限申请结果
Log.d(TAG, "权限申请结果: " + result);
});
两处代码添加位置如下图所示:
在权限申请结果处,我们打印了值,True就是授予了权限,False就是拒绝了权限,下面我们需要判断一下是否有权限,没有则请求权限,有则进入下一步。
@Override
protected void onResume() {
super.onResume();
// 检查是否已经获取到定位权限
if (checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
// 获取到权限
Log.d(TAG, "onResume: 已获取到权限");
} else {
// 请求定位权限
requestPermission.launch(Manifest.permission.ACCESS_FINE_LOCATION);
}
}
这里添加了一个onResume()
方法,它属于Activity的生命周期之一,通过注释你应该明白这个代码是什么意思。添加位置如下图所示:
下面我们运行一下看看。
在运行之后就会请求权限,点击仅使用期间允许
,然后就可以看到权限通过了,如果你希望更明显一些,可以使用Toast,在MainActivity中添加一个方法。
private void showMsg(CharSequence llw) {
Toast.makeText(this, llw, Toast.LENGTH_SHORT).show();
}
再看看使用的地方,如下图所示:
这里就是换成更明显的Toast。
④ 初始化定位
在获取到权限之后我们就需要进行定位了,在定位之前我们首先要初始化定位,首先声明一个变量,代码如下:
//声明AMapLocationClient类对象
public AMapLocationClient mLocationClient = null;
然后写一个方法去进行初始化,代码如下所示:
/**
* 初始化定位
*/
private void initLocation() {
try {
//初始化定位
mLocationClient = new AMapLocationClient(getApplicationContext());
//设置定位回调监听
mLocationClient.setLocationListener(this);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
最后我们需要在onCreate()
方法中进行调用,以上代码及调用的地方如下图所示:
在initLocation()
方法中设置了回调监听,这里用的是this,这表示在当前类,而下面有红线,说明我们没有实现里面的方法,鼠标点击这个this,然后使用快捷键Alt + Enter
,会出现一个提示弹窗。
这里选择我标注的这一项进行回车,会再出现一个弹窗。
这里什么都不用改,点击OK即可,然后我们看看当前的MainActivity有什么变化。
我们实现了AMapLocationListener
接口,重写了里面onLocationChanged()
方法,同时this也没有红线了,此时代码是正常的。但是我们的定位配置还没有完成,再声明一个变量:
//声明AMapLocationClientOption对象
public AMapLocationClientOption mLocationOption = null;
然后在initLocation()
方法中进行配置,代码如下所示:
//初始化AMapLocationClientOption对象
mLocationOption = new AMapLocationClientOption();
//设置定位模式为AMapLocationMode.Hight_Accuracy,高精度模式。
mLocationOption.setLocationMode(AMapLocationClientOption.AMapLocationMode.Hight_Accuracy);
//获取最近3s内精度最高的一次定位结果
mLocationOption.setOnceLocationLatest(true);
//设置是否返回地址信息(默认返回地址信息)
mLocationOption.setNeedAddress(true);
//设置定位超时时间,单位是毫秒
mLocationOption.setHttpTimeOut(6000);
//给定位客户端对象设置定位参数
mLocationClient.setLocationOption(mLocationOption);
添加位置如下图所示:
下一步我们写开始和停止定位的方法,在MainActivity
中增加如下代码:
/**
* 开始定位
*/
private void startLocation() {
if (mLocationClient != null) mLocationClient.startLocation();
}
/**
* 停止定位
*/
private void stopLocation() {
if (mLocationClient != null) mLocationClient.stopLocation();
}
添加位置如下所示:
⑤ 获取定位信息
然后就是这两个方法的调用位置了,首先看开始定位,首先我们在获取权限之后就要开始定位,增加代码如下图所示:
至于停止定位的使用,我们需要在拿到定位结果之后,同时我们需要将定位结果显示在页面,那么我们先修改一下activity_main.xml
中的代码,为TextView
控件增加一个为tv_address
的id
,代码如下所示:
然后我们再回到MainActivity中,修改onLocationChanged()
方法中的代码,如下所示:
/**
* 定位回调结果
*/
@Override
public void onLocationChanged(AMapLocation aMapLocation) {
if (aMapLocation == null) {
showMsg("定位失败,aMapLocation 为空");
return;
}
// 获取定位结果
if (aMapLocation.getErrorCode() == 0) {
// 定位成功
showMsg("定位成功");
// aMapLocation.getLocationType();//获取当前定位结果来源,如网络定位结果,详见定位类型表
// aMapLocation.getLatitude();//获取纬度
// aMapLocation.getLongitude();//获取经度
// aMapLocation.getAccuracy();//获取精度信息
// aMapLocation.getAddress();//详细地址,如果option中设置isNeedAddress为false,则没有此结果,网络定位结果中会有地址信息,GPS定位不返回地址信息。
// aMapLocation.getCountry();//国家信息
// aMapLocation.getProvince();//省信息
// aMapLocation.getCity();//城市信息
String result = aMapLocation.getDistrict();//城区信息
// aMapLocation.getStreet();//街道信息
// aMapLocation.getStreetNum();//街道门牌号信息
// aMapLocation.getCityCode();//城市编码
// aMapLocation.getAdCode();//地区编码
// aMapLocation.getAoiName();//获取当前定位点的AOI信息
// aMapLocation.getBuildingId();//获取当前室内定位的建筑物Id
// aMapLocation.getFloor();//获取当前室内定位的楼层
// aMapLocation.getGpsAccuracyStatus();//获取GPS的当前状态
binding.tvAddress.setText(result);
// 停止定位
stopLocation();
} else {
// 定位失败
showMsg("定位失败,错误:" + aMapLocation.getErrorInfo());
Log.e(TAG,"location Error, ErrCode:"
+ aMapLocation.getErrorCode() + ", errInfo:"
+ aMapLocation.getErrorInfo());
}
}
这里我只在页面上显示了所在的城区信息,其他的信息我先注释了,你可以根据自己的需求拿相应的数据进行显示,下面我们就可以开始运行了。
无论你是第一次进来时获取权限还是后面已经拿到权限再进来都是会获取定位信息,需要注意的是使用真机,同时需要联网。
四、显示地图
现在我们开始显示地图,首先我们需要修改一下activity_main.xml
中的代码:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<com.amap.api.maps.MapView
android:id="@+id/map_view"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
这里主要的改动就是去掉TextView,然后使用了MapView,因为根布局使用的约束布局,如果不了解的话尽量代码跟我一样,避免不必要的错误出现。
好了,下面我们回到MainActivity
中,首先我们删除掉onLocationChanged()
方法中之前显示定位结果在TextView上的一行代码,删除后如下图所示:
然后我们需要去配置MapView,将MapView和Activity的声明周期绑定起来,首先是onCreate()
,如下图所示:
然后是onResume()
之后是onPause()、onSaveInstanceState()和onDestroy()
,这三个方法当前没有所以我们需要增加,代码如下所示:
@Override
protected void onPause() {
super.onPause();
// 绑定生命周期 onPause
binding.mapView.onPause();
}
@Override
protected void onSaveInstanceState(@NonNull Bundle outState) {
super.onSaveInstanceState(outState);
// 绑定生命周期 onSaveInstanceState
binding.mapView.onSaveInstanceState(outState);
}
@Override
protected void onDestroy() {
super.onDestroy();
// 绑定生命周期 onDestroy
binding.mapView.onDestroy();
}
添加位置如下图所示:
好了,下面我们运行一下看看:
地图是显示出来了,但是很明显,不是我当前的位置,那么如果我想显示当前的位置呢?比如我在广东省深圳市南山区,我要定位到我这里。
五、显示当前定位地图
要显示当前定位地图,首先我们需要将位置在地图上进行设置,从而使地图中心点移动到我们所在的位置,首先我们声明两个变量。
// 声明地图控制器
private AMap aMap = null;
// 声明地图定位监听
private LocationSource.OnLocationChangedListener mListener = null;
添加位置如下图所示:
然后我们新增一个方法,代码如下所示:
/**
* 初始化地图
*/
private void initMap() {
if (aMap == null) {
aMap = binding.mapView.getMap();
// 设置定位监听
aMap.setLocationSource(this);
// 设置为true表示启动显示定位蓝点,false表示隐藏定位蓝点并不进行定位,默认是false。
aMap.setMyLocationEnabled(true);
}
}
这里的this同样会有红线,我们依然使用之前的方式去实现接口,会有两个方法,如下图所示:
实现那两个方法之后,我们修改里面的代码如下所示:
/**
* 激活定位
* @param onLocationChangedListener
*/
@Override
public void activate(OnLocationChangedListener onLocationChangedListener) {
if (mListener == null) {
mListener = onLocationChangedListener;
}
startLocation();
}
/**
* 禁用
*/
@Override
public void deactivate() {
mListener = null;
if (mLocationClient != null) {
mLocationClient.stopLocation();
mLocationClient.onDestroy();
}
mLocationClient = null;
}
两个方法,激活和禁止,在地图上激活定位后,我们开始定位,在定位的回调中,我们需要显示地图定位结果onLocationChanged()
方法中增加如下代码:
// 显示地图定位结果
if (mListener != null) {
mListener.onLocationChanged(aMapLocation);
}
两个方法的位置如下图所示:
最后我们要做的就是在onCreate()
方法中调用initMap()
方法,使我们的配置生效,如下图所示:
下面我们运行一下看看效果:
六、地图设置
① 修改定位图标样式
我们可以直接在initMap()
方法中完成,增加如下代码:
// 创建定位蓝点的样式
MyLocationStyle myLocationStyle = new MyLocationStyle();
// 自定义定位蓝点图标
myLocationStyle.myLocationIcon(BitmapDescriptorFactory.fromResource(R.drawable.gps_point));
// 自定义精度范围的圆形边框颜色 都为0则透明
myLocationStyle.strokeColor(Color.argb(0, 0, 0, 0));
// 自定义精度范围的圆形边框宽度 0 无宽度
myLocationStyle.strokeWidth(0);
// 设置圆形的填充颜色 都为0则透明
myLocationStyle.radiusFillColor(Color.argb(0, 0, 0, 0));
// 设置定位蓝点的样式
aMap.setMyLocationStyle(myLocationStyle);
这里如果你没有这个图标,不修改自定义图标,或者去我的代码中获取这个R.drawable.gps_point
图标。
② 设置缩放等级
//设置最小缩放等级为12 ,缩放级别范围为[3, 20]
aMap.setMinZoomLevel(12);
最终设置如下图所示:
下面运行一下:
③ 开启室内地图
// 开启室内地图
aMap.showIndoorMap(true);
这里你就在initMap()中添加即可,然后加载地图出来后,不断放大,直到你看到3D的建筑,添加位置如下图所示:
④ 地图控件设置
// 地图控件设置
UiSettings uiSettings = aMap.getUiSettings();
// 隐藏缩放按钮
uiSettings.setZoomControlsEnabled(false);
// 显示比例尺,默认不显示
uiSettings.setScaleControlsEnabled(true);
添加位置如下图所示:
运行一下看看:
七、获取POI数据
POI (Point of Interest,兴趣点)
。在地图表达中,一个 POI 可代表一栋大厦、一家商铺、一处景点等等。通过POI搜索,完成找餐馆、找景点、找厕所等等的功能,首先我们修改一下activity_main.xml
中的代码:
<!--浮动按钮-->
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/fab_poi"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="20dp"
android:clickable="true"
android:focusable="true"
android:src="@drawable/ic_favorite_red"
app:hoveredFocusedTranslationZ="18dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:pressedTranslationZ="18dp" />
添加位置如下图所示:
然后回到MainActivity
中,我们声明变量,代码如下所示:
//POI查询对象
private PoiSearch.Query query;
//POI搜索对象
private PoiSearch poiSearch;
//城市码
private String cityCode = null;
添加位置如下图所示:
然后在onLocationChanged()
方法中显示这个浮动按钮,添加代码如下:
// 显示浮动按钮
binding.fabPoi.show();
// 城市编码赋值
cityCode = aMapLocation.getCityCode();
添加位置如下图所示:
下面我们添加一个initView()
方法,处理点击浮动按钮事件,代码如下所示:
/**
* 初始化控件
*/
private void initView() {
// Poi搜索按钮点击事件
binding.fabPoi.setOnClickListener(v -> {
//构造query对象
query = new PoiSearch.Query("购物", "", cityCode);
// 设置每页最多返回多少条poiItem
query.setPageSize(10);
//设置查询页码
query.setPageNum(1);
//构造 PoiSearch 对象
try {
poiSearch = new PoiSearch(this, query);
//设置搜索回调监听
poiSearch.setOnPoiSearchListener(this);
//发起搜索附近POI异步请求
poiSearch.searchPOIAsyn();
} catch (AMapException e) {
throw new RuntimeException(e);
}
});
}
这里同样this
会报错,实现接口,出现弹窗如下所示:
现在代码如下所示:
/**
* POI搜索返回
*
* @param poiResult POI所有数据
* @param i
*/
@Override
public void onPoiSearched(PoiResult poiResult, int i) {
//解析result获取POI信息
//获取POI组数列表
ArrayList<PoiItem> poiItems = poiResult.getPois();
for (PoiItem poiItem : poiItems) {
Log.d("MainActivity", " Title:" + poiItem.getTitle() + " Snippet:" + poiItem.getSnippet());
}
}
/**
* POI中的项目搜索返回
*
* @param poiItem 获取POI item
* @param i
*/
@Override
public void onPoiItemSearched(PoiItem poiItem, int i) {
}
添加位置如下图所示:
最后在onCreate()
方法中调用initView()
。
下面运行一下,然后点击页面右下角的浮动按钮,查看控制台,你会看到有打印,如下图所示: