1. 插件介绍

Flutter Location 是一个用于获取用户地理位置信息的 Flutter 插件,支持在鸿蒙、Android、iOS、Web 等多个平台上使用。该插件提供了简洁的 API 接口,方便开发者快速实现定位功能,包括单次定位获取、持续定位监听、定位权限管理以及后台定位等功能。

核心功能

  • 单次定位获取:获取用户当前的地理位置信息
  • 持续定位监听:实时监听用户位置变化
  • 定位权限管理:检查和请求定位权限
  • 定位服务状态检查:检查定位服务是否启用
  • 定位设置配置:调整定位精度、更新间隔等参数
  • 后台定位支持:在应用后台持续获取定位信息

适用场景

  • 需要获取用户当前位置的应用(如地图、导航类应用)
  • 需要实时追踪用户位置的应用(如运动、物流类应用)
  • 需要在后台获取定位信息的应用
  • 在鸿蒙平台上开发的 Flutter 应用

2. 安装与配置

2.1 依赖配置

由于这是一个针对鸿蒙平台的自定义修改版本,需要通过 Git 形式引入。在项目的 pubspec.yaml 文件中添加以下依赖配置:

dependencies:
  location:
    git:
      url: "https://atomgit.com/openharmony-sig/flutter_location.git"
      path: "./packages/location"

2.2 安装依赖

执行以下命令安装依赖:

flutter pub get

3. 使用方法

3.1 初始化定位对象

首先,导入包并创建 Location 实例:

import 'package:location/location.dart';

Location location = Location();

3.2 检查定位服务和权限

在获取位置信息前,需要检查定位服务是否启用以及应用是否具有定位权限:

// 检查定位服务是否启用
bool _serviceEnabled = await location.serviceEnabled();
if (!_serviceEnabled) {
  // 请求用户启用定位服务
  _serviceEnabled = await location.requestService();
  if (!_serviceEnabled) {
    // 用户未启用定位服务,处理相应逻辑
    return;
  }
}

// 检查定位权限
PermissionStatus _permissionGranted = await location.hasPermission();
if (_permissionGranted == PermissionStatus.denied) {
  // 请求定位权限
  _permissionGranted = await location.requestPermission();
  if (_permissionGranted != PermissionStatus.granted) {
    // 用户拒绝了定位权限,处理相应逻辑
    return;
  }
}

3.3 获取当前位置

使用 getLocation() 方法获取用户当前位置:

try {
  LocationData _locationData = await location.getLocation();

  // 处理获取到的位置信息
  print('纬度: ${_locationData.latitude}');
  print('经度: ${_locationData.longitude}');
  print('精度: ${_locationData.accuracy} 米');
  print('海拔: ${_locationData.altitude} 米');
  print('速度: ${_locationData.speed} 米/秒');
} catch (e) {
  // 处理定位失败的情况
  print('定位失败: $e');
}

3.4 监听位置变化

使用 onLocationChanged 流监听用户位置的实时变化:

// 监听位置变化
location.onLocationChanged.listen((LocationData currentLocation) {
  // 处理位置变化
  print('当前位置: ${currentLocation.latitude}, ${currentLocation.longitude}');

  // 更新UI或执行其他逻辑
});

3.5 配置定位参数

使用 changeSettings() 方法调整定位参数:

// 配置定位参数
bool settingsChanged = await location.changeSettings(
  accuracy: LocationAccuracy.high,  // 定位精度
  interval: 1000,                   // 定位更新间隔(毫秒)
  distanceFilter: 10,               // 距离过滤阈值(米)
  scenario: LocationScenario.navigation,  // 定位场景
);

if (settingsChanged) {
  print('定位参数配置成功');
} else {
  print('定位参数配置失败');
}

3.6 后台定位

启用后台定位模式:

// 检查后台模式是否已启用
bool isBackgroundEnabled = await location.isBackgroundModeEnabled();
print('后台定位模式已启用: $isBackgroundEnabled');

// 启用后台定位模式
bool backgroundModeEnabled = await location.enableBackgroundMode(enable: true);
if (backgroundModeEnabled) {
  print('后台定位模式启用成功');
} else {
  print('后台定位模式启用失败');
}

4. API 参考

4.1 核心 API 方法

方法名 描述 参数 返回值 鸿蒙支持
getLocation() 获取用户当前位置 Future<LocationData>
onLocationChanged 监听位置变化 Stream<LocationData>
hasPermission() 检查定位权限 Future<PermissionStatus>
requestPermission() 请求定位权限 Future<PermissionStatus>
serviceEnabled() 检查定位服务是否启用 Future<bool>
requestService() 请求启用定位服务 Future<bool>
changeSettings() 修改定位请求设置 accuracy: 定位精度
interval: 更新间隔
distanceFilter: 距离过滤
scenario: 定位场景
Future<bool>
enableBackgroundMode() 启用/禁用后台定位 enable: 是否启用 Future<bool>
isBackgroundModeEnabled() 检查后台定位是否启用 Future<bool>

4.2 核心数据结构

LocationData
class LocationData {
  final double latitude;        // 纬度,以度为单位
  final double longitude;       // 经度,以度为单位
  final double accuracy;        // 位置估算精度,以米为单位
  final double verticalAccuracy;// 海拔估算精度,以米为单位
  final double altitude;        // 海拔高度,以米为单位
  final double speed;           // 速度,以米/秒为单位
  final double speedAccuracy;   // 速度估算精度,以米/秒为单位
  final double heading;         // 航向,以度为单位
  final double time;            // 定位时间戳
  final bool isMock;            // 是否为模拟位置
  final int satelliteNumber;    // 用于定位的卫星数量
  final String provider;        // 定位提供者名称
}
PermissionStatus
enum PermissionStatus {
  granted,          // 已授予高精度定位权限
  grantedLimited,   // 已授予低精度定位权限(仅 iOS 14+)
  denied,           // 用户拒绝了定位权限
  deniedForever,    // 用户永久拒绝了定位权限
}
LocationAccuracy
enum LocationAccuracy {
  powerSave,    // 低功耗模式,精度较低
  low,          // 城市级精度
  balanced,     // 街区级精度
  high,         // 高精度
  navigation,   // 导航级精度
  reduced,      // 降低精度(仅 iOS 14+)
  unset,        // 未设置(仅鸿蒙)
}
LocationScenario
enum LocationScenario {
  unset,              // 默认场景
  navigation,         // 导航场景
  trajectoryTracking, // 轨迹跟踪场景
  carHailing,         // 网约车场景
  dailyLifeService,   // 日常生活服务场景
  noPower,            // 无功耗场景
}

5. 完整示例

以下是一个在鸿蒙平台上使用 Flutter Location 插件的完整示例:

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

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

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Location Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const LocationScreen(),
    );
  }
}

class LocationScreen extends StatefulWidget {
  const LocationScreen({Key? key}) : super(key: key);

  
  State<LocationScreen> createState() => _LocationScreenState();
}

class _LocationScreenState extends State<LocationScreen> {
  final Location _location = Location();
  LocationData? _locationData;
  bool _isListening = false;

  
  void initState() {
    super.initState();
    _checkLocationServiceAndPermission();
  }

  Future<void> _checkLocationServiceAndPermission() async {
    // 检查定位服务
    bool serviceEnabled = await _location.serviceEnabled();
    if (!serviceEnabled) {
      serviceEnabled = await _location.requestService();
      if (!serviceEnabled) {
        _showSnackBar('请启用定位服务');
        return;
      }
    }

    // 检查定位权限
    PermissionStatus permissionStatus = await _location.hasPermission();
    if (permissionStatus == PermissionStatus.denied) {
      permissionStatus = await _location.requestPermission();
      if (permissionStatus != PermissionStatus.granted) {
        _showSnackBar('请授予定位权限');
        return;
      }
    }

    _showSnackBar('定位服务和权限已准备就绪');
  }

  Future<void> _getCurrentLocation() async {
    try {
      LocationData locationData = await _location.getLocation();
      setState(() {
        _locationData = locationData;
      });
      _showSnackBar('已获取当前位置');
    } catch (e) {
      _showSnackBar('获取位置失败: $e');
    }
  }

  void _toggleLocationListening() {
    setState(() {
      _isListening = !_isListening;
    });

    if (_isListening) {
      _location.onLocationChanged.listen((LocationData currentLocation) {
        setState(() {
          _locationData = currentLocation;
        });
      });
      _showSnackBar('开始监听位置变化');
    }
  }

  Future<void> _configureLocationSettings() async {
    bool success = await _location.changeSettings(
      accuracy: LocationAccuracy.high,
      interval: 2000,
      distanceFilter: 5,
      scenario: LocationScenario.navigation,
    );
    if (success) {
      _showSnackBar('定位设置已更新');
    } else {
      _showSnackBar('更新定位设置失败');
    }
  }

  void _showSnackBar(String message) {
    ScaffoldMessenger.of(context).showSnackBar(
      SnackBar(content: Text(message)),
    );
  }

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Flutter Location Demo'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(20.0),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            const SizedBox(height: 20),
            ElevatedButton(
              onPressed: _getCurrentLocation,
              child: const Text('获取当前位置'),
            ),
            const SizedBox(height: 10),
            ElevatedButton(
              onPressed: _toggleLocationListening,
              child: Text(_isListening ? '停止监听' : '开始监听位置变化'),
            ),
            const SizedBox(height: 10),
            ElevatedButton(
              onPressed: _configureLocationSettings,
              child: const Text('配置定位参数'),
            ),
            const SizedBox(height: 30),
            const Text(
              '位置信息:',
              style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
            ),
            const SizedBox(height: 10),
            _locationData != null
                ? Column(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: [
                      Text('纬度: ${_locationData!.latitude}'),
                      Text('经度: ${_locationData!.longitude}'),
                      Text('精度: ${_locationData!.accuracy} 米'),
                      if (_locationData!.altitude != null)
                        Text('海拔: ${_locationData!.altitude} 米'),
                      if (_locationData!.speed != null)
                        Text('速度: ${_locationData!.speed} 米/秒'),
                      if (_locationData!.heading != null)
                        Text('航向: ${_locationData!.heading}°'),
                    ],
                  )
                : const Text('暂无位置信息'),
          ],
        ),
      ),
    );
  }
}

6. 约束与限制

  • Flutter 版本:支持 Flutter 3.7.12-ohos-1.0.6 及以上版本
  • 鸿蒙 SDK:支持鸿蒙 SDK 5.0.0(12) 及以上版本
  • IDE:推荐使用 DevEco Studio 5.0.13.200 及以上版本

7. 总结

Flutter Location 是一个功能强大且易于使用的定位插件,为鸿蒙平台上的 Flutter 应用提供了完整的定位解决方案。它支持单次定位获取、持续定位监听、定位权限管理、定位服务状态检查以及后台定位等功能,能够满足各种定位场景的需求。

通过 Git 方式引入的鸿蒙适配版本,确保了在鸿蒙平台上的稳定运行,同时保持了与其他平台一致的 API 接口,方便开发者跨平台使用。

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐