1. 项目背景与核心需求
在移动应用开发中,位置选择功能几乎是LBS类应用的标配需求。最近接手的一个社区服务类APP项目,就要求用户在发布服务时能精准选择位置。作为长期使用uniapp的开发者,我决定基于高德地图安卓SDK实现这个功能模块。
选择高德地图而非百度或腾讯地图,主要基于三点考虑:首先,高德在POI数据更新频率上明显优于竞品(实测新开商铺信息更新周期约3-7天);其次,其安卓端SDK的定位精度可达5米级别;最重要的是,高德为开发者提供的日均10万次免费调用额度完全能满足中小型应用需求。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 开发环境准备
2.1 基础环境配置
在manifest.json中需要声明以下关键配置:
json复制{
"permissions": {
"android": [
"android.permission.ACCESS_COARSE_LOCATION",
"android.permission.ACCESS_FINE_LOCATION",
"android.permission.ACCESS_NETWORK_STATE",
"android.permission.ACCESS_WIFI_STATE"
]
},
"sdkConfigs": {
"maps": {
"amap": {
"appKey_android": "您的高德开发者key",
"appKey_ios": ""
}
}
}
}
特别注意:高德地图SDK要求必须配置Android硬件加速,在manifest的application节点添加
android:hardwareAccelerated="true"
2.2 高德SDK集成
通过HBuilderX的「原生插件配置」添加高德地图依赖:
- 登录高德开放平台 → 创建应用 → 获取Android平台SHA1和PackageName
- 下载最新版Android SDK(当前v8.1.0)
- 将amap-location-x.x.x.jar放入nativeplugins/AMap-Android目录
- 配置build.gradle:
gradle复制dependencies {
implementation 'com.amap.api:location:6.2.0'
implementation 'com.amap.api:search:9.2.0'
implementation 'com.amap.api:maps:9.2.0'
}
3. 核心功能实现
3.1 地图初始化与定位
创建map.vue组件,关键初始化代码:
javascript复制const map = new AMap.Map('mapContainer', {
zoom: 16,
center: [116.397428, 39.90923],
viewMode: '3D'
})
const geolocation = new AMap.Geolocation({
enableHighAccuracy: true,
timeout: 10000
})
geolocation.getCurrentPosition((status, result) => {
if(status === 'complete'){
this.currentPos = [result.position.lng, result.position.lat]
map.setCenter(this.currentPos)
} else {
uni.showToast({ title: '定位失败:'+result.message, icon: 'none' })
}
})
3.2 位置选择交互设计
实现长按选点+搜索复合功能:
- 添加地图长按事件监听:
javascript复制map.on('longpress', (e) => {
this.showMarker(e.lnglat)
this.reverseGeocode(e.lnglat)
})
- 逆地理编码获取地址详情:
javascript复制const geocoder = new AMap.Geocoder()
geocoder.getAddress([lng, lat], (status, result) => {
if (status === 'complete') {
this.address = result.regeocode.formattedAddress
this.poiList = result.regeocode.pois
}
})
- 搜索框联动实现:
javascript复制const placeSearch = new AMap.PlaceSearch({
pageSize: 5,
pageIndex: 1
})
placeSearch.search(keywords, (status, result) => {
this.searchResults = result.poiList.pois
})
4. 性能优化实践
4.1 内存管理要点
在onUnload生命周期必须销毁地图实例:
javascript复制onUnload() {
if(this.map) {
this.map.destroy()
this.map = null
}
}
4.2 离线缓存策略
实现本地POI缓存减少API调用:
javascript复制// 存储
uni.setStorage({
key: `amap_poi_${lng}_${lat}`,
data: JSON.stringify(poiData),
success: () => console.log('缓存成功')
})
// 读取
const cached = uni.getStorageSync(`amap_poi_${lng}_${lat}`)
if(cached) return Promise.resolve(JSON.parse(cached))
4.3 定位频率控制
通过节流函数控制定位请求:
javascript复制let lastLocTime = 0
function throttleLocation() {
const now = Date.now()
if(now - lastLocTime > 5000) {
lastLocTime = now
return getLocation()
}
return Promise.reject('操作过于频繁')
}
5. 典型问题排查
5.1 地图白屏问题
常见原因及解决方案:
- SHA1配置不符:确保打包用的keystore与高德后台登记的SHA1一致
- 网络权限未开启:检查AndroidManifest.xml是否有
<uses-permission android:name="android.permission.INTERNET"/> - GPU渲染冲突:在页面样式添加
#mapContainer { background: transparent }
5.2 定位偏移修正
由于国家安全要求,国内地图需要做GCJ-02加密。若获取的坐标与实际位置有300-500米偏移,需进行坐标转换:
javascript复制// WGS84转GCJ02
function wgs2gcj(wgsLng, wgsLat) {
if (outOfChina(wgsLng, wgsLat)) return [wgsLng, wgsLat]
const d = delta(wgsLng, wgsLat)
return [wgsLng + d[0], wgsLat + d[1]]
}
5.3 标记点闪烁优化
当快速移动地图时,标记点可能出现闪烁。解决方案:
- 使用
marker.setPosition()而非重新创建marker实例 - 对moveend事件添加200ms防抖
- 预加载标记图标:
javascript复制const icon = new AMap.Icon({
image: '/static/marker.png',
size: new AMap.Size(32, 32)
})
6. 上架注意事项
6.1 隐私政策合规
根据高德SDK要求,必须在《隐私政策》中明确说明:
- 收集的个人信息类型(位置信息等)
- 使用的第三方SDK名称及用途
- 数据共享情况
6.2 权限申请策略
建议采用渐进式权限申请:
- 首次进入只申请粗略定位权限
- 当用户触发精准定位功能时再申请ACCESS_FINE_LOCATION
- 拒绝后引导到设置页的代码示例:
javascript复制uni.openSetting({
success(res) {
console.log(res.authSetting)
}
})
在实际项目中,我发现高德地图的POI搜索API在商业区密集区域返回结果较多时(>50条),安卓低端机可能出现1-2秒的卡顿。通过分页加载+前端虚拟滚动优化后,列表滚动流畅度提升明显。另外建议对选择结果做本地历史记录,可显著提升用户重复操作效率。
