Flutter模拟定位插件fluttermocklocation的使用

发布于 1周前 作者 vueper 来自 Flutter

fluttermocklocation #

此 Flutter 插件旨在帮助开发者在测试阶段为Android设备设置模拟位置数据。例如,对于地理围栏应用和其他依赖于GPS定位的应用程序来说,这非常有用。

通过启用位置数据的模拟,开发者可以确保他们的应用程序在各种地理环境中表现正常,而无需物理移动设备。这对于彻底测试基于位置的功能至关重要,确保可以在广泛的场景中进行高效和有效的测试。

要使用基于该插件的应用程序,请在您的Android设备上启用开发者选项。

在开发者选项中,选择“选择模拟位置应用”,然后选择您的应用。

示例代码: example/lib/main.dart

import 'package:flutter/material.dart';
import 'dart:async';

import ‘package:flutter/services.dart’; import ‘package:fluttermocklocation/fluttermocklocation.dart’;

void main() { runApp(const MyApp()); }

class MyApp extends StatefulWidget { const MyApp({super.key});

@override State<MyApp> createState() => _MyAppState(); }

class _MyAppState extends State<MyApp> { String _platformVersion = ‘未知’; bool _error = false; String _positionUpdated = ‘’; String _errorString = ‘’; final _fluttermocklocationPlugin = Fluttermocklocation();

final TextEditingController _latController = TextEditingController(); final TextEditingController _lngController = TextEditingController(); final TextEditingController _altitudeController = TextEditingController(); final TextEditingController _delayController = TextEditingController();

@override void initState() { super.initState(); initPlatformState();

// 监听位置更新
_fluttermocklocationPlugin.locationUpdates.listen((locationData) {
  // 获取当前时间戳
  final DateTime now = DateTime.now();
  final String formattedTimestamp =
      "${now.year}-${now.month.toString().padLeft(2, '0')}-${now.day.toString().padLeft(2, '0')} "
      "${now.hour.toString().padLeft(2, '0')}:${now.minute.toString().padLeft(2, '0')}:${now.second.toString().padLeft(2, '0')}";

  // 格式化位置字符串
  final String positionString = '纬度: ${locationData['latitude']}\n'
      '经度: ${locationData['longitude']}\n'
      '海拔: ${locationData['altitude']}\n'
      '时间戳: $formattedTimestamp';

  // 更新位置信息
  setState(() {
    _positionUpdated = positionString;
  });

  print(_positionUpdated);
});

}

@override void dispose() { super.dispose(); }

// 平台消息是异步的,因此我们初始化时使用异步方法。 Future<void> initPlatformState() async { String platformVersion; try { platformVersion = await _fluttermocklocationPlugin.getPlatformVersion() ?? ‘未知平台版本’; } on PlatformException { platformVersion = ‘获取平台版本失败。’; }

if (!mounted) return;

setState(() {
  _platformVersion = platformVersion;
});

}

void _updateLocation() async { try { setState(() { _error = false; _errorString = ‘’; });

  final double latitude = double.parse(_latController.text);
  final double longitude = double.parse(_lngController.text);
  final double altitude = double.parse(_altitudeController.text);
  final int delay =
      int.tryParse(_delayController.text) ?? 5000; // 默认值为5000毫秒

  try {
    await Fluttermocklocation().updateMockLocation(
      latitude,
      longitude,
      altitude: altitude,
      delay: delay,
    );
    print(
        "模拟位置已更新: $latitude, $longitude, $altitude 延迟 $delay 毫秒");
  } catch (e) {
    print("更新位置时发生错误: $e");
    setState(() {
      _errorString =
          '要使用此应用程序,请在您的Android设备上启用开发者选项。\n\n在开发者选项中选择\n\n"选择模拟位置应用"\n\n并选择此应用。';
      _error = true;
    });
  }
} catch (e) {
  setState(() {
    _errorString = '无效的纬度、经度或延迟。';
    _error = true;
  });
}

}

@override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( appBar: AppBar( title: const Text(‘Flutter 模拟位置’), ), body: Padding( padding: const EdgeInsets.all(8.0), child: Column( children: [ Center( child: Text(‘运行在: $_platformVersion\n’), ), TextField( controller: _latController, decoration: const InputDecoration(labelText: ‘纬度’), keyboardType: TextInputType.number, ), TextField( controller: _lngController, decoration: const InputDecoration(labelText: ‘经度’), keyboardType: TextInputType.number, ), TextField( controller: _altitudeController, decoration: const InputDecoration(labelText: ‘海拔’), keyboardType: TextInputType.number, ), TextField( controller: _delayController, decoration: const InputDecoration(labelText: ‘延迟 (毫秒)’), keyboardType: TextInputType.number, ), ElevatedButton( onPressed: _updateLocation, child: const Text(‘设置模拟位置’), ), const SizedBox( height: 20, ), (_positionUpdated != ‘’) ? Card( child: Padding( padding: const EdgeInsets.all(12.0), child: Text( _positionUpdated, ), ), ) : Container(), _error ? Card( child: Padding( padding: const EdgeInsets.all(12.0), child: Text( _errorString, style: const TextStyle(color: Colors.red), ), ), ) : Container(), ], ), ), ), ); } }


更多关于Flutter模拟定位插件fluttermocklocation的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter模拟定位插件fluttermocklocation的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


在Flutter中,flutter_mock_location插件可以用来模拟设备的位置信息,这在开发和测试基于位置的应用时非常有用。以下是如何在Flutter项目中使用flutter_mock_location插件的示例代码。

1. 添加依赖

首先,在你的pubspec.yaml文件中添加flutter_mock_location依赖:

dependencies:
  flutter:
    sdk: flutter
  flutter_mock_location: ^0.x.x  # 请使用最新版本号替换0.x.x

然后运行flutter pub get来安装依赖。

2. 配置Android权限

由于模拟位置涉及到位置权限,你需要在AndroidManifest.xml文件中添加必要的权限:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.yourapp">

    <!-- 其他配置 -->

    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
    <uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION"/>

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity"
            android:launchMode="singleTop"
            android:theme="@style/LaunchTheme"
            android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
            android:hardwareAccelerated="true"
            android:windowSoftInputMode="adjustResize">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <!-- 其他Activity配置 -->
    </application>

    <!-- Mock location provider -->
    <application
        android:testOnly="true"
        ...>
        <!-- This line is crucial for mock location to work -->
    </application>
</manifest>

注意:<application android:testOnly="true" ...>这一行对于模拟位置至关重要,但直接添加到现有的<application>标签中可能会导致编译错误。通常,这是通过在AndroidManifest.xml中定义一个额外的<application>标签(如上所示,但注意不要包含实际的活动或服务定义)来实现的,或者通过编程方式在运行时请求模拟位置权限。然而,由于Flutter的限制,我们通常依赖插件来处理这些细节。

3. 使用Flutter代码模拟位置

在你的Dart代码中,你可以这样使用flutter_mock_location插件:

import 'package:flutter/material.dart';
import 'package:flutter_mock_location/flutter_mock_location.dart';
import 'package:geolocator/geolocator.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  FlutterMockLocation? _mockLocation;

  @override
  void initState() {
    super.initState();
    _initMockLocation();
  }

  Future<void> _initMockLocation() async {
    _mockLocation = FlutterMockLocation();

    // 检查模拟位置是否可用
    bool isMockLocationAvailable = await _mockLocation!.isMockLocationAvailable();
    print('Mock location available: $isMockLocationAvailable');

    if (isMockLocationAvailable) {
      // 设置模拟位置
      Position mockPosition = Position(
        latitude: 37.7749,
        longitude: -122.4194,
        altitude: 16.0,
        accuracy: 5.0,
        heading: 270.0,
        speed: 0.0,
        speedAccuracy: 0.0,
        timestamp: DateTime.now(),
      );
      await _mockLocation!.setMockLocation(mockPosition);
      print('Mock location set');
    } else {
      print('Mock location not available');
    }
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Flutter Mock Location Example'),
        ),
        body: Center(
          child: ElevatedButton(
            onPressed: () async {
              // 获取当前位置(这里将返回我们设置的模拟位置)
              Position? position = await Geolocator.getCurrentPosition(
                desiredAccuracy: LocationAccuracy.high,
              );
              print('Current position: ${position?.latitude}, ${position?.longitude}');
            },
            child: Text('Get Current Position'),
          ),
        ),
      ),
    );
  }
}

注意事项

  1. 权限请求:在实际应用中,你需要请求位置权限。由于flutter_mock_location主要用于测试,通常在生产环境中不会使用它,因此这里的示例代码没有包含权限请求逻辑。
  2. Android模拟器与真实设备:在Android模拟器上,模拟位置通常更容易实现。在真实设备上,你可能需要启用开发者选项中的“允许模拟位置”功能。
  3. iOS支持flutter_mock_location主要支持Android。对于iOS,模拟位置通常需要在Xcode的模拟器中进行配置,或者通过其他方式(如Xcode的Scheme编辑器)来实现。

希望这个示例能帮助你理解如何在Flutter项目中使用flutter_mock_location插件来模拟设备位置。

回到顶部