uni-app App端需分层检测:先用原生API查系统定位开关(安卓LocationManager、iOS CLLocationManager),再查应用授权状态(plus.android.checkPermission或CLLocationManager.authorizationStatus),二者缺一不可。

uni-app App端怎么检测定位权限是否已授权
不能只靠 uni.getLocation 的 success/fail 回调来判断——它只反映「本次调用是否成功」,不区分是「用户拒绝授权」还是「系统定位服务关闭」。真要准确知道权限状态,得结合平台原生能力做分层检测。
核心逻辑是两步:先查系统级定位开关(GPS 是否启用),再查应用级授权状态(App 是否被授予位置权限)。两者缺一不可。
- 安卓需通过
plus.android调用LocationManager.isProviderEnabled(GPS_PROVIDER)判断系统 GPS 是否开启;再用plus.android.checkPermission或ActivityCompat.checkSelfPermission查应用权限(注意 Android 12+ 需额外处理ACCESS_FINE_LOCATION和ACCESS_COARSE_LOCATION) - iOS 需用
plus.ios调用CLLocationManager.locationServicesEnabled()和CLLocationManager.authorizationStatus(),注意返回值含义:kCLAuthorizationStatusNotDetermined表示未请求过、kCLAuthorizationStatusDenied是明确拒绝、kCLAuthorizationStatusAuthorizedAlways或kCLAuthorizationStatusAuthorizedWhenInUse才算已授权 - H5 和小程序不支持系统级定位开关检测,只能依赖
uni.getSystemInfo的locationEnabled(部分安卓 H5 不可靠)、locationAuthorized(仅微信小程序有效)
为什么 uni.getSystemInfoSync().locationEnabled 在 App 端经常不准
这个字段在 App 端(尤其是 iOS)基本不可信。iOS 上它始终返回 true,哪怕系统定位完全关闭;安卓某些 ROM 也会缓存旧值或直接忽略。它本质是 WebView 层的粗略提示,不是原生系统的真实状态。
真正可靠的依据只有原生 API 返回值:
- 安卓:
mainSvr.isProviderEnabled(locationManager.GPS_PROVIDER)—— 返回false就代表系统定位关了 - iOS:
cllocationManger.locationServicesEnabled()—— 返回false即系统级关闭 - 这两个调用必须放在
plus.ready后执行,否则plus.android/plus.ios对象可能未初始化
如何引导用户跳转到系统设置页开启定位
用户拒绝授权或关闭系统定位后,弹个 modal 提示「请开启定位」只是第一步,关键是要能一键跳转。但不同平台跳转方式差异极大,写错就白忙活。
- 安卓:用
Intent打开Settings.ACTION_LOCATION_SOURCE_SETTINGS(老版本)或Settings.ACTION_SECURITY_SETTINGS(Android 12+ 推荐),注意部分国产 ROM(如华为、小米)会拦截该 Intent,需 fallback 到通用设置页Settings.ACTION_SETTINGS - iOS:用
UIApplication.openURL(NSURL.URLWithString("App-Prefs:root=Privacy&path=LOCATION")),但 iOS 16+ 已废弃该 scheme,必须改用UIApplication.openURL(NSURL.URLWithString("prefs:root=Privacy&path=LOCATION"))或更稳妥的UIApplication.openSettingsURLString(需提前配置LSApplicationQueriesSchemes) - 跳转前务必再次检查状态,避免用户刚点完就跳转失败。例如安卓跳转前再调一次
isProviderEnabled,确认仍是false再执行
通知权限和定位权限是两回事,别混在一起检测
标题里提到「定位通知是否开启」,这本身是个概念错误。uni-app 没有「定位通知」这个权限类型。你实际要处理的是两个独立权限:
-
定位权限:对应
scope.userLocation(小程序)、ACCESS_FINE_LOCATION(安卓)、NSLocationWhenInUseUsageDescription(iOS) -
通知权限:对应
scope.push(小程序)、POST_NOTIFICATIONS(Android 13+)、UNUserNotificationCenter(iOS)
它们的申请时机、触发逻辑、用户设置入口完全不同。检测定位状态时去查通知权限,不仅无效,还会因调用不存在的 API 导致白屏或报错。如果真需要同时处理两者,必须分开判断、分开引导。
最容易被忽略的一点:iOS 上,即使用户给过定位授权,只要之后在系统设置里手动关闭「精确位置」开关,uni.getLocation 仍会返回模糊坐标(误差几百米),但权限检测仍显示「已授权」——这种场景无法自动修复,只能在业务层做容错(比如对比两次获取的坐标距离,异常大则提示「请检查系统定位精度设置」)。











