之前写过一篇 # uni-app实现网络离线定位 的文章,因为之前是在自己的手机进行测试的,使用过程中也仅仅是打开了飞行模式进行测试。

但是代码在迁移到公司的自主研发的终端设备上以后却始终获取不到定位,原因不明。后来询问硬件的同事才知道,这款设备上没有GPS模块, 仅有北斗定位模块

代码交给 Trae 分析后得出结论,可能是因为没有GPS模块导致的离线无法获取到定位,遂考虑采用北斗进行定位。

权限配置

仍然采用 HTML5+ 的定位方法,首先需要打开定位权限:

// manifest.json

/* 模块配置 */
"modules" : {
    "Geolocation" : {}, // 启用定位模块
},
/* 应用发布信息 */
"distribute" : {
    /* android打包配置 */
    "android" : {
        "permissions" : [
            "<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>",
            "<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>",
        ]
    },
    /* SDK配置 */
    "sdkConfigs" : {
        "geolocation" : {
            "system" : {
                "__platform__" : [ "android" ]
            }
        }
    }
},

这里仅设置了安卓代码,IOS系统需要增加额外的配置。

实现

Trae 提醒我这里需要注意,Android 6.0(API 23)及以上版本需要动态申请权限,不能只靠 manifest 声明,否则仍然存在拿不到权限的可能。

// 鉴权
getLocationSafely(onSuccess, onError) {
    let that = this;
    // 1. 先检查系统定位是否开启(Android 特有)
    plus.geolocation.getCurrentPosition(
        () => {
            console.log('定位服务已经开启');
            uni.showToast({
                title: '定位服务已经开启',
                icon: 'none',
                duration: 3000
            });
        }, // 这里只是触发系统检测,不处理成功
        (e) => {
            if (e.code === 4) {
                // code=4 表示“位置服务未开启”
                uni.showModal({
                    title: '定位服务未开启',
                    content: '请前往系统设置开启位置信息,才能获取当前位置',
                    showCancel: true,
                    confirmText: '去设置',
                    success: (res) => {
                        if (res.confirm) {
                            // 跳转到系统定位设置页(仅 Android 有效)
                            plus.runtime.openURL('package:com.android.settings');
                        }
                    }
                });
                onError?.(new Error('系统定位未开启'));
                return;
            }
        }, {
            timeout: 3000
        }
    );
},

// 也可以使用 uni-app 的官方API进行鉴权
uni.authorize({
    scope: 'scope.userLocation',
    success() {
        // 用户同意,可以调用定位
        uni.getLocation({ ... })
    },
    fail() {
        // 用户拒绝,提示去设置开启
        uni.showModal({
        title: '定位权限被禁用',
        content: '请在设置中开启位置权限',
        showCancel: false
        });
    }
});

除却上面的权限原因导致的定位不到,Trae 给出的提示还有需要关注:

  • 定位功能是否已经开启

  • 省电策略是否已经关闭(部分设备省电模式下会限制定位)

  • 一定!一定!一定!要到室外测试

测试的时候可以采用两两对照的方式测试:室外 vs 室内飞行模式 vs 有网GPS 开启 vs 关闭,测试上述九种状态的组合。

// 定位方法
function startBeidouLocation() {
    // TODO 此处可以先检查定位服务是否开启

    plus.geolocation.getCurrentPosition(
        function(position) {
            console.log(' 定位成功');
            console.log('纬度:', position.coords.latitude);
            console.log('经度:', position.coords.longitude);
            console.log('来源:', position.coords.source); // 可能显示 gps/beidou/gnss
            uni.showToast({
                title: `定位成功: ${position.coords.latitude.toFixed(5)}, ${position.coords.longitude.toFixed(5)}`,
                icon: 'none'
            });
        },
        function(error) {
            console.error(' 定位失败', error.code, error.message);
            let msg = '';
            switch (error.code) {
            case 1: msg = '用户拒绝授权'; break;
            case 2: msg = '位置不可用(可能未搜星)'; break;
            case 3: msg = '定位超时'; break;
            default: msg = '未知错误';
            }
            uni.showToast({ title: '定位失败: ' + msg, icon: 'none' });
        },
        {
            enableHighAccuracy: true,   // 此处必须为 true,才能触发 GNSS(含北斗)
            timeout: 60000,             // 给足 60 秒冷启动时间
            maximumAge: 0               // 不使用缓存位置
        }
    );
}

这里的 timeout 甚至可以给的再大点,使用卫星定位冷启动时间其实非常长,不过你如果不是在人迹罕至的区域,60秒基本上就够用了。

本站提供的所有下载资源均来自互联网,仅提供学习交流使用,版权归原作者所有。如需商业使用,请联系原作者获得授权。 如您发现有涉嫌侵权的内容,请联系我们 邮箱:alixiixcom@163.com