Android 高德地图API(新版)
新版高德地图
- 前言
- 正文
- 一、创建应用
- ① 获取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-dataandroid: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 {@Overridepublic 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就是拒绝了权限,下面我们需要判断一下是否有权限,没有则请求权限,有则进入下一步。
@Overrideprotected 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()
方法中的代码,如下所示:
/*** 定位回调结果*/@Overridepublic 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.MapViewandroid: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()
,这三个方法当前没有所以我们需要增加,代码如下所示:
@Overrideprotected void onPause() {super.onPause();// 绑定生命周期 onPausebinding.mapView.onPause();}@Overrideprotected void onSaveInstanceState(@NonNull Bundle outState) {super.onSaveInstanceState(outState);// 绑定生命周期 onSaveInstanceStatebinding.mapView.onSaveInstanceState(outState);}@Overrideprotected void onDestroy() {super.onDestroy();// 绑定生命周期 onDestroybinding.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*/@Overridepublic void activate(OnLocationChangedListener onLocationChangedListener) {if (mListener == null) {mListener = onLocationChangedListener;}startLocation();}/*** 禁用*/@Overridepublic 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.FloatingActionButtonandroid: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);// 设置每页最多返回多少条poiItemquery.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*/@Overridepublic 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*/@Overridepublic void onPoiItemSearched(PoiItem poiItem, int i) {}
添加位置如下图所示:
最后在onCreate()
方法中调用initView()
。
下面运行一下,然后点击页面右下角的浮动按钮,查看控制台,你会看到有打印,如下图所示:
相关文章:

Android 高德地图API(新版)
新版高德地图 前言正文一、创建应用① 获取PackageName② 获取调试版安全码SHA1③ 获取发布版安全码SHA1 二、配置项目① 导入SDK② 配置AndroidManifest.xml 三、获取当前定位信息① ViewBinding使用和导包② 隐私合规设置③ 权限请求④ 初始化定位⑤ 获取定位信息 四、显示地…...

LeetCode---二叉树
144/94/145. 二叉树的前、中、后序的递归遍历 以中序遍历为例,其余类似: 给定一个二叉树的根节点 root ,返回 它的 中序 遍历 。 代码示例: /*** Definition for a binary tree node.* struct TreeNode {* int val;* Tr…...
从0开发一个Chrome插件:核心功能开发——弹出页面
前言 这是《从0开发一个Chrome插件》系列的第十一篇文章,本系列教你如何从0去开发一个Chrome插件,每篇文章都会好好打磨,写清楚我在开发过程遇到的问题,还有开发经验和技巧。 专栏: 从0开发一个Chrome插件:什么是Chrome插件?从0开发一个Chrome插件:开发Chrome插件的必…...
AIGC笔记--Stable Diffusion源码剖析之UNetModel
1--前言 以论文《High-Resolution Image Synthesis with Latent Diffusion Models》 开源的项目为例,剖析Stable Diffusion经典组成部分,巩固学习加深印象。 2--UNetModel 一个可以debug的小demo:SD_UNet 以文生图为例&#…...

Linux文件系统与日志分析
目录 inode block 链接 文件修复 实验步骤 针对ext文件系统恢复删除文件 针对xfs文件系统恢复删除文件 日志 日志级别 rsyslogd服务 日志目录 messages日志文件(系统日志) 集中管理日志 - 实验 1.环境配置 1.1 1.2 1.3 1.4 1.5 2.远…...

【SkyWalking】使用PostgreSQL做存储K8s部署
拉取镜像 docker pull apache/skywalking-ui:10.0.1 docker tag apache/skywalking-ui:10.0.1 xxx/xxx/skywalking-ui:10.0.1 docker push xxx/xxx/skywalking-ui:10.0.1docker pull apache/skywalking-oap-server:10.0.1 docker tag apache/skywalking-oap-server:10.0.1 xxx…...

详解大模型微调数据集构建方法(持续更新)
大家好,我是herosunly。985院校硕士毕业,现担任算法t研究员一职,热衷于机器学习算法研究与应用。曾获得阿里云天池比赛第一名,CCF比赛第二名,科大讯飞比赛第三名。拥有多项发明专利。对机器学习和深度学习拥有自己独到的见解。曾经辅导过若干个非计算机专业的学生进入到算…...

自制植物大战僵尸:HTML5与JavaScript实现的简单游戏
引言 在本文中,我们将一起探索如何使用HTML5和JavaScript来创建一个简单的植物大战僵尸游戏。这不仅是一项有趣的编程挑战,也是学习游戏开发基础的绝佳机会。 什么是植物大战僵尸? 植物大战僵尸是一款流行的策略塔防游戏,玩家需…...

Istio_1.17.8安装
项目背景 按照istio官网的命令一路安装下来,安装好的istio版本为目前的最新版本,1.22.0。而我的k8s集群的版本并不支持istio_1.22的版本,导致ingress-gate网关安装不上,再仔细查看istio的发布文档,如果用istio_1.22版本…...

[数据集][目标检测]室内积水检测数据集VOC+YOLO格式761张1类别
数据集格式:Pascal VOC格式YOLO格式(不包含分割路径的txt文件,仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数):761 标注数量(xml文件个数):761 标注数量(txt文件个数):761 标注类别…...

17_Vue高级监听器生命周期Vue组件组件通信
文章目录 1. 数据监听器watch2. Vue生命周期3. Vue组件4. Vue组件通信Appendix 1. 数据监听器watch 首先watch需要单独引 import {watch} from vuewatch函数监听ref响应式数据 watch(监听的内容,监听行为)监听行为默认为(newValue,oldValue) let firstname ref…...

【ROS使用记录】—— ros使用过程中的rosbag录制播放和ros话题信息相关的指令与操作记录
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、rosbag的介绍二、rosbag的在线和离线录制三、rosbag的播放相关的指令四、其他rosbag和ros话题相关的指令总结 前言 rosbag是ROS(机器人操作系统…...
Laravel 富文本内容
Laravel 获取富文本的纯文本内容-CSDN博客 Laravel 富文本内容里面的图片添加前缀URL-CSDN博客 Laravel 富文本图片的style样式删除-CSDN博客. Laravel 获取富文本中的所有图片-CSDN博客 富文本字体font-famly删除 $data preg_replace(/(<[^>])style["\][^"…...
Spark Python环境搭建与优化:深入剖析四个方面、五个方面、六个方面及七个关键要点
Spark Python环境搭建与优化:深入剖析四个方面、五个方面、六个方面及七个关键要点 在大数据处理领域,Apache Spark凭借其出色的性能和灵活性备受瞩目。而要在Python中利用Spark的强大功能,首先需要搭建一个稳定且高效的Spark Python环境。本…...

【微信小程序开发】小程序中的上滑加载更多,下拉刷新是如何实现的?
✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,…...

从 Android 恢复已删除的备份录
本文介绍了几种在 Android 上恢复丢失和删除的短信的方法。这些方法都不能保证一定成功,但您可能能够恢复一些短信或其中存储的文件。 首先要尝试什么 首先,尝试保留数据。如果你刚刚删除了信息,请立即将手机置于飞行模式,方法是…...
如何使用Python中的random模块生成随机数
在Python中,random模块提供了多种用于生成随机数的函数。以下是一些基本示例: 生成随机整数: 使用random.randint(a, b)函数生成一个介于a和b之间的随机整数(包括a和b)。 python复制代码 import random random_int …...

AI大数据处理与分析实战--体育问卷分析
AI大数据处理与分析实战–体育问卷分析 前言:前一段时间接了一个需求,使用AI进行数据分析与处理,遂整理了一下大致过程和大致简要结果(更详细就不方便放了)。 文章目录 AI大数据处理与分析实战--体育问卷分析一、数据…...

C++第二十五弹---从零开始模拟STL中的list(下)
✨个人主页: 熬夜学编程的小林 💗系列专栏: 【C语言详解】 【数据结构详解】【C详解】 目录 1、函数补充 2、迭代器完善 3、const迭代器 总结 1、函数补充 拷贝构造 思路: 先构造一个头结点,然后将 lt 类中的元…...
STM32/keil把多个c文件编译为静态库lib
把常用的、不经常修改的代码库编译成lib以后,可以加快整个工程的编译速度。 一个常见的应用场景就是,把ST的标准库或HAL库等编译成lib,这样以后再编译整个工程时,就无需再次编译他们了,可以节省编译时间。当然&#x…...

工业安全零事故的智能守护者:一体化AI智能安防平台
前言: 通过AI视觉技术,为船厂提供全面的安全监控解决方案,涵盖交通违规检测、起重机轨道安全、非法入侵检测、盗窃防范、安全规范执行监控等多个方面,能够实现对应负责人反馈机制,并最终实现数据的统计报表。提升船厂…...
线程与协程
1. 线程与协程 1.1. “函数调用级别”的切换、上下文切换 1. 函数调用级别的切换 “函数调用级别的切换”是指:像函数调用/返回一样轻量地完成任务切换。 举例说明: 当你在程序中写一个函数调用: funcA() 然后 funcA 执行完后返回&…...

c#开发AI模型对话
AI模型 前面已经介绍了一般AI模型本地部署,直接调用现成的模型数据。这里主要讲述讲接口集成到我们自己的程序中使用方式。 微软提供了ML.NET来开发和使用AI模型,但是目前国内可能使用不多,至少实践例子很少看见。开发训练模型就不介绍了&am…...

如何在网页里填写 PDF 表格?
有时候,你可能希望用户能在你的网站上填写 PDF 表单。然而,这件事并不简单,因为 PDF 并不是一种原生的网页格式。虽然浏览器可以显示 PDF 文件,但原生并不支持编辑或填写它们。更糟的是,如果你想收集表单数据ÿ…...
根目录0xa0属性对应的Ntfs!_SCB中的FileObject是什么时候被建立的----NTFS源代码分析--重要
根目录0xa0属性对应的Ntfs!_SCB中的FileObject是什么时候被建立的 第一部分: 0: kd> g Breakpoint 9 hit Ntfs!ReadIndexBuffer: f7173886 55 push ebp 0: kd> kc # 00 Ntfs!ReadIndexBuffer 01 Ntfs!FindFirstIndexEntry 02 Ntfs!NtfsUpda…...
CppCon 2015 学习:Time Programming Fundamentals
Civil Time 公历时间 特点: 共 6 个字段: Year(年)Month(月)Day(日)Hour(小时)Minute(分钟)Second(秒) 表示…...

Java后端检查空条件查询
通过抛出运行异常:throw new RuntimeException("请输入查询条件!");BranchWarehouseServiceImpl.java // 查询试剂交易(入库/出库)记录Overridepublic List<BranchWarehouseTransactions> queryForReagent(Branch…...

[拓扑优化] 1.概述
常见的拓扑优化方法有:均匀化法、变密度法、渐进结构优化法、水平集法、移动可变形组件法等。 常见的数值计算方法有:有限元法、有限差分法、边界元法、离散元法、无网格法、扩展有限元法、等几何分析等。 将上述数值计算方法与拓扑优化方法结合&#…...

医疗AI模型可解释性编程研究:基于SHAP、LIME与Anchor
1 医疗树模型与可解释人工智能基础 医疗领域的人工智能应用正迅速从理论研究转向临床实践,在这一过程中,模型可解释性已成为确保AI系统被医疗专业人员接受和信任的关键因素。基于树模型的集成算法(如RandomForest、XGBoost、LightGBM)因其卓越的预测性能和相对良好的解释性…...

qt+vs Generated File下的moc_和ui_文件丢失导致 error LNK2001
qt 5.9.7 vs2013 qt add-in 2.3.2 起因是添加一个新的控件类,直接把源文件拖进VS的项目里,然后VS卡住十秒,然后编译就报一堆 error LNK2001 一看项目的Generated Files下的moc_和ui_文件丢失了一部分,导致编译的时候找不到了。因…...