更新记录

1.0.0(2026-08-28)

  • 发布插件

平台兼容性

uni-app(5.07)

Vue2 Vue3 Chrome Safari app-vue app-nvue Android iOS 鸿蒙
- - - - - - 5.0 - -
微信小程序 支付宝小程序 抖音小程序 百度小程序 快手小程序 京东小程序 鸿蒙元服务 QQ小程序 飞书小程序 小红书小程序 快应用-华为 快应用-联盟
- - - - - - - - - - - -

uni-app x(5.07)

Chrome Safari Android iOS 鸿蒙 微信小程序
- - 5.0 - - -

概述

  • 安卓虚拟修改定位插件

使用前准备

  1. 打开手机「设置 - 关于手机」
  2. 连续点击「版本号」3 次,开启「开发者选项」
  3. 进入「设置 - 系统 - 开发者选项」
  4. 找到「选择模拟位置信息应用」,选择本应用

温馨提示 如何调用插件

import {
  startMockLocation,
  stopMockLocation
} from "@/uni_modules/yuange-xlocation"

启动模拟定位

// latitude  纬度,例如 39.9042
// longitude 经度,例如 116.4074
startMockLocation(39.9042, 116.4074, {
  success(res) {
    console.log(JSON.stringify(res));
  },
  fail(err) {
    console.log(JSON.stringify(err));
  }
})

停止模拟定位

stopMockLocation({
  success(res) {
    console.log(JSON.stringify(res));
  },
  fail(err) {
    console.log(JSON.stringify(err));
  }
})

回调结果数据格式

  • 成功
{
  "code": 200,
  "msg": "模拟定位已启动"
}
  • 失败
{
  "code": 500,
  "msg": "请先在开发者选项中将本应用设为模拟位置应用"
}

完整Demo示例

<template>
    <view class="container">
        <view class="section">
            <text class="section-title">坐标设置</text>
            <view class="input-row">
                <text class="input-label">纬度</text>
                <input class="input" type="digit" v-model="latitude" placeholder="例如 39.9042" />
            </view>
            <view class="input-row">
                <text class="input-label">经度</text>
                <input class="input" type="digit" v-model="longitude" placeholder="例如 116.4074" />
            </view>
        </view>

        <view class="section">
            <text class="section-title">常用城市预设</text>
            <view class="preset-grid">
                <button class="button preset" v-for="item in presets" :key="item.name" @click="onPreset(item)">{{item.name}}</button>
            </view>
        </view>

        <view class="section">
            <text class="section-title">模拟定位控制</text>
            <button @click="onStart" class="button primary">启动模拟定位</button>
            <button @click="onStop" class="button danger">停止模拟定位</button>
        </view>

        <view class="section">
            <text class="section-title">验证当前定位</text>
            <button @click="onGetLocation" class="button">获取当前定位</button>
            <view class="location-info" v-if="currentLocation">
                <text class="location-text">纬度: {{currentLocation.latitude}}</text>
                <text class="location-text">经度: {{currentLocation.longitude}}</text>
                <text class="location-text">精度: {{currentLocation.accuracy}}米</text>
            </view>
        </view>

        <view class="section">
            <text class="section-title">使用说明</text>
            <text class="tip">1. 先在「开发者选项 - 选择模拟位置信息应用」中选中本应用</text>
            <text class="tip">2. 设置目标坐标(可输入或选择预设城市)</text>
            <text class="tip">3. 点击「启动模拟定位」</text>
            <text class="tip">4. 点击「获取当前定位」验证是否生效</text>
            <text class="tip">5. 测试完毕点击「停止模拟定位」</text>
        </view>

        <view class="section">
            <text class="section-title">日志</text>
            <scroll-view scroll-y class="log-scroll">
                <text class="log-text">{{logText}}</text>
            </scroll-view>
            <button @click="onClearLog" class="button small">清空日志</button>
        </view>
    </view>
</template>

<script>
    import {
        startMockLocation,
        stopMockLocation
    } from "@/uni_modules/yuange-xlocation"

    export default {
        data() {
            return {
                latitude: "39.9042",
                longitude: "116.4074",
                currentLocation: null,
                logText: "",
                presets: [
                    { name: "北京", latitude: "39.9042", longitude: "116.4074" },
                    { name: "上海", latitude: "31.2304", longitude: "121.4737" },
                    { name: "广州", latitude: "23.1291", longitude: "113.2644" },
                    { name: "深圳", latitude: "22.5431", longitude: "114.0579" },
                    { name: "杭州", latitude: "30.2741", longitude: "120.1551" },
                    { name: "成都", latitude: "30.5728", longitude: "104.0668" }
                ]
            }
        },
        onLoad() {
            this.log("页面加载完成");
            this.log("请确保已在开发者选项中将本应用设为模拟位置应用");
        },
        methods: {
            onPreset(item) {
                this.latitude = item.latitude;
                this.longitude = item.longitude;
                this.log("选择预设: " + item.name + " (" + item.latitude + ", " + item.longitude + ")");
            },

            onStart() {
                let lat = parseFloat(this.latitude);
                let lng = parseFloat(this.longitude);
                if (isNaN(lat) || isNaN(lng)) {
                    this.log("坐标无效,请输入数字");
                    return;
                }
                if (lat < -90 || lat > 90) {
                    this.log("纬度范围为[-90, 90]");
                    return;
                }
                if (lng < -180 || lng > 180) {
                    this.log("经度范围为[-180, 180]");
                    return;
                }
                this.log(">>> startMockLocation(" + lat + ", " + lng + ")");
                startMockLocation(lat, lng, {
                    success: (res) => {
                        this.log("startMockLocation success: " + JSON.stringify(res));
                    },
                    fail: (err) => {
                        this.log("startMockLocation fail: " + JSON.stringify(err));
                    }
                });
            },

            onStop() {
                this.log(">>> stopMockLocation");
                stopMockLocation({
                    success: (res) => {
                        this.log("stopMockLocation success: " + JSON.stringify(res));
                    },
                    fail: (err) => {
                        this.log("stopMockLocation fail: " + JSON.stringify(err));
                    }
                });
            },

            onGetLocation() {
                this.log(">>> uni.getLocation");
                uni.getLocation({
                    type: "wgs84",
                    success: (res) => {
                        this.currentLocation = {
                            latitude: res.latitude,
                            longitude: res.longitude,
                            accuracy: res.accuracy
                        };
                        this.log("getLocation success: " + JSON.stringify(res));
                    },
                    fail: (err) => {
                        this.log("getLocation fail: " + JSON.stringify(err));
                    }
                });
            },

            log(msg) {
                let now = new Date();
                let timeStr = String(now.getHours()).padStart(2, '0') + ":" +
                    String(now.getMinutes()).padStart(2, '0') + ":" +
                    String(now.getSeconds()).padStart(2, '0');
                this.logText = "[" + timeStr + "] " + msg + "\n" + this.logText;
        console.log(this.logText)
            },

            onClearLog() {
                this.logText = "";
            }
        }
    }
</script>

<style>
    .container {
        padding: 20rpx;
    }

    .section {
        margin-bottom: 30rpx;
    }

    .section-title {
        font-size: 28rpx;
        font-weight: bold;
        color: #333;
        margin-bottom: 15rpx;
        display: block;
    }

    .input-row {
        display: flex;
        flex-direction: row;
        align-items: center;
        margin-bottom: 15rpx;
    }

    .input-label {
        width: 100rpx;
        font-size: 28rpx;
        color: #333;
    }

    .input {
        flex: 1;
        border: 1px solid #ddd;
        border-radius: 8rpx;
        padding: 15rpx;
        font-size: 28rpx;
    }

    .preset-grid {
        display: flex;
        flex-direction: row;
        flex-wrap: wrap;
    }

    .button {
        margin-bottom: 15rpx;
        background-color: #f0f0f0;
        color: #333;
        font-size: 28rpx;
    }

    .button.preset {
        width: 30%;
        margin-right: 15rpx;
        font-size: 26rpx;
    }

    .button.primary {
        background-color: dodgerblue;
        color: white;
    }

    .button.danger {
        background-color: #e74c3c;
        color: white;
    }

    .button.small {
        font-size: 24rpx;
        padding: 10rpx;
    }

    .location-info {
        background-color: #f8f8f8;
        padding: 20rpx;
        border-radius: 10rpx;
        margin-top: 15rpx;
    }

    .location-text {
        font-size: 28rpx;
        color: #333;
        font-family: monospace;
        display: block;
        margin-bottom: 8rpx;
    }

    .tip {
        font-size: 24rpx;
        color: #999;
        display: block;
        margin-bottom: 8rpx;
        line-height: 1.6;
    }

    .log-scroll {
        height: 400rpx;
        background-color: #1e1e1e;
        border-radius: 10rpx;
        padding: 15rpx;
    }

    .log-text {
        font-size: 22rpx;
        color: #4caf50;
        font-family: monospace;
        white-space: pre-line;
    }
</style>

隐私、权限声明

1. 本插件需要申请的系统权限列表:

android.permission.ACCESS_FINE_LOCATION android.permission.ACCESS_COARSE_LOCATION android.permission.ACCESS_MOCK_LOCATION

2. 本插件采集的数据、发送的服务器地址、以及数据用途说明:

插件不采集任何数据

3. 本插件是否包含广告,如包含需详细说明广告表达方式、展示频率:

暂无用户评论。