微信小程序获取用户地理位置失败的原因主要有3种情况:
1. 手机系统设置中地理位置未开启
2. 系统未给微信app授权
3. 用户未给小程序授权地理位置信息
所以需要继续完善下定位失败的处理逻辑。
1. 在获取地理位置信息失败后,首先判断用户手机系统定位服务是否开启 || 微信app是否有定位授权,两种情况任意一种不符合,显示地理位置获取失败状态;
2. 都符合的话调用uni.getLocation,success走成功的操作,fail表示未给小程序授权地理位置信息,显示地理位置获取失败状态;uni.openSetting打开设置,选择允许小程序授权。
涉及到一个关键点是,微信小程序判断手机有没有定位的方法
uni.getSystemInfo文档
//locationEnabled 地理位置的系统开关
//locationAuthorized 允许微信使用定位的开关
uni.getSystemInfo({
success: (res) => {
if (!res.locationEnabled || !res.locationAuthorized) {
uni.showToast({
title: '请确保手机系统定位已开启',
icon: 'none',
duration: 2000,
})
},
})
获取地理位置失败显示效果图
具体代码如下:
封装tool.js
//位置授权
export function getAuthorize () {
return new Promise((resolve, reject) => {
uni.authorize({
scope: 'scope.userLocation',
success: () => {
// 1 用户允许授权
// 2 用户之前已经同意授权,则不会出现弹窗,直接返回成功
// 以上两种情况都会进入到success回调中
resolve() // 允许授权
},
fail: () => {
// 1 用户拒绝授权
// 2 用户之前拒绝了授权,此接口会直接进入失败回调
// 以上两种情况都会进入到fail回调中
reject() // 拒绝授权
},
})
})
}
父组件html
<template>
<view>
<!-- 未开启定位时状态 -->
<notGps v-if="showNoGps" />
<!-- 已开启定位时,正常显示页面 -->
<view v-else class="index_root">
<view>页面内容</view>
</view>
</view>
</template>
父组件js
<script>
import { getAuthorize } from '@/utils/tool.js' //引入位置授权
import notGps from './component/notGps.vue' // 引入未开启定位子组件
data() {
return {
showNoGps: false,
},
onLoad(e) {
uni.showLoading({
title: '加载中',
mask: true,
})
//位置授权
getAuthorize()
//用户允许小程序位置授权
.then(() => {
this.getSystemInfo()
})
//用户拒绝小程序位置授权
.catch(() => {
uni.hideLoading()
this.getSystemInfo()
})
},
onShow() {
if (this.showNoGps === true) {
this.getSystemInfo()
}
}
methods: {
//获取手机系统信息
getSystemInfo() {
uni.getSystemInfo({
success: (res) => {
// 获取地理位置失败原因
// 1.手机系统设置中地理位置未开启
// 2.系统未给微信授权
// 3.用户未给小程序授权地理位置信息
if (!res.locationEnabled || !res.locationAuthorized) {
uni.showToast({
title: '请确保手机系统定位已开启',
icon: 'none',
duration: 2000,
})
this.showNoGps = true
} else {
this.getLocation()
}
},
//先获取经纬度,然后再根据经纬度通过腾讯地图获取地址名称
getLocation() {
const that = this
uni.getLocation({
type: 'gcj02',
success(res) {
// 成功进行的操作
let longitude = res.longitude
let latitude = res.latitude
getAddress(longitude, latitude)
.then((res) => {
let params = {
city: res.result.address_component.city,
name: res.result.address_reference.landmark_l2.title,
lng: longitude,
lat: latitude,
}
that.$store.commit('setLocation', params)
// 获取定位成功,关闭获取地理位置失败显示效果
that.showNoGps = false
uni.showLoading({
title: '加载中',
mask: true,
})
//请求接口获取页面数据
that.getGoodsList()
})
.catch((e) => {
console.log(e, '解释地址失败')
})
},
fail(err) {
// 到这里进入fail就只有情况3,用户未给小程序授权地理位置信息,显示获取地理位置失败显示效果
console.log(err, '获取经纬度失败')
that.showNoGps = true
},
})
},
})
},
}
</script>
notGps组件
<template>
<view class="openGps">
<image src="@/static/image/no_goods.png" class="empty-img"></image>
<view class="empty-txt">
为给您提供最佳服务,小程序需要获取您的当前位置以定位您附近的商户
</view>
<view class="handleBtn" @click="gotoLocation">点击开启定位</view>
</view>
</template>
<script>
export default {
data() {
return {}
},
methods: {
//打开小程序授权地理位置设置,不管用户操作是否授权,返回父组件页面之后,都会触发onShow周期函数里的代码
gotoLocation() {
uni.openSetting({
success(res) {
console.log(res.authSetting)
},
})
},
},
}
</script>
<style lang="scss">
.openGps {
text-align: center;
padding: 400rpx 80rpx 0 80rpx;
}
.empty-img {
width: 380rpx;
height: 284rpx;
}
.empty-txt {
font-size: 28rpx;
color: #999;
}
.handleBtn {
background: linear-gradient(-10deg, #00ca20, #02bb34);
font-size: 20rux;
color: #fff;
font-weight: bold;
width: 300upx;
text-align: center;
height: 70upx;
line-height: 70upx;
border-radius: 35upx;
margin: 30upx auto;
}
</style>