Flutter地理位置获取插件geolocator_cn的使用

Flutter地理位置获取插件geolocator_cn的使用

特性

  • 多位置服务助手类:可以同时使用多种位置服务。
    • 系统 ✅
    • 百度 ✅
    • 高德 ✅
    • IP位置 ✅
  • 自动处理权限请求
  • 自动将CRS转换为GCJ02(在中国大陆)。你也可以手动设置CRS。

开始使用

在你的pubspec.yaml文件中添加以下依赖:

dependencies:
  geolocator_cn: ^1.1.0

配置

1. 配置项目工作空间

Android

AndroidX

  1. gradle.properties文件中添加以下内容:
    android.useAndroidX=true
    android.enableJetifier=true
    
  2. android/app/build.gradle文件中将compileSdkVersion设置为30:
    android {
      compileSdkVersion 30
    
      ...
    }
    
  3. 将所有android.依赖替换为其AndroidX对应版本(完整列表可在此处找到:Migrating to AndroidX)。

权限 在Android上,你需要在Android Manifest中添加ACCESS_COARSE_LOCATIONACCESS_FINE_LOCATION权限。打开AndroidManifest.xml文件(位于android/app/src/main目录下),并添加以下两行之一作为<manifest>标签的直接子元素(当你配置两个权限时,ACCESS_FINE_LOCATION将被geolocator插件使用):

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

从Android 10开始,如果你希望即使应用程序在后台运行时也能继续接收更新,则需要添加ACCESS_BACKGROUND_LOCATION权限(注意geolocator插件不支持在后台运行时接收和处理位置更新):

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

注意: 指定ACCESS_COARSE_LOCATION权限会导致位置更新精度大约相当于一个城市街区。可能需要几分钟才能获得第一个位置更新,因为ACCESS_COARSE_LOCATION仅使用网络服务来计算设备的位置。更多信息可在此处找到:here

iOS

在iOS上,为了访问设备的位置,你需要在Info.plist文件(位于ios/Runner目录下)中添加以下条目。只需打开你的Info.plist文件并添加以下内容(确保你更新描述以便与你的应用程序上下文相关):

<key>NSLocationWhenInUseUsageDescription</key>
<string>此应用在打开时需要访问您的位置。</string>
<key>NSLocationAlwaysUsageDescription</key>
<string>此应用在后台运行时需要访问您的位置。</string>

如果你想在应用程序在后台运行时接收更新,还需要向你的XCode项目中添加Background Modes功能(Project > Signing and Capabilities > "+ Capability"按钮)并选择Location Updates。请注意,你需要详细解释给Apple为什么你的应用程序需要这个功能,否则你的应用程序可能会被拒绝。

当你使用requestTemporaryFullAccuracy({purposeKey: "YourPurposeKey"})方法时,需要在Info.plist文件中添加一个字典。

<key>NSLocationTemporaryUsageDescriptionDictionary</key>
<dict>
  <key>YourPurposeKey</key>
  <string>示例应用需要临时访问设备的精确位置。</string>
</dict>

第二个键(在这个例子中称为YourPurposeKey)应该匹配requestTemporaryFullAccuracy()方法中传递的目的键。你可以为应用程序的不同功能定义多个键。更多信息可以在Apple的文档中找到:documentation

注意: 第一次请求临时完全准确的访问时,可能需要几秒钟的时间弹出窗口才会出现。这是由于iOS正在确定用户的精确位置,这可能需要几秒钟。不幸的是,这不是我们能控制的。

2. 配置百度LBS SDK API密钥

编辑android/app/src/Manifest.xml,并在<Application>节点中添加以下代码:

<meta-data
    android:name="com.baidu.lbsapi.API_KEY"
    android:value="YOUR API KEY" />

3. 配置高德Android依赖

编辑android/app/build.gradle,在dependencies中添加以下内容:

dependencies
{
    implementation 'com.amap.api:location:5.6.0'
}

使用

import 'package:geolocator_cn/geolocator_cn.dart';

GeolocatorCNProviders.config = {
      'baidu': {'ios': 'YOUR API KEY'},
      'amap': {'ios': 'YOUR API KEY', 'android': 'YOUR API KEY'},
    };

GeolocatorCN().getLocation().then((location) {
      print(location);
    });

或者

import 'package:geolocator_cn/geolocator_cn.dart';

GeolocatorCNProviders.config = {
      'baidu': {'ios': 'YOUR API KEY'},
      'amap': {'ios': 'YOUR API KEY', 'android': 'YOUR API KEY'},
    };

LocationData location = await GeolocatorCN().getLocation();
print(location);

示例代码

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

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

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

  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key, required this.title}) : super(key: key);

  final String title;

  [@override](/user/override)
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  LocationData locationData = LocationData();

  [@override](/user/override)
  void initState() {
    GeolocatorCNProviders.config = {
      'baidu': {'ios': 'YOUR API KEY'},
      'amap': {'ios': 'YOUR API KEY', 'android': 'YOUR API KEY'},
    };
    super.initState();
  }

  void _getLocation() async {
    GeolocatorCN().getLocation().then((location) {
      setState(() {
        locationData = location;
      });
    });
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            locationData.latitude == 0
                ? Text('按按钮获取位置')
                : Text('$locationData'),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _getLocation,
        tooltip: '获取位置',
        child: const Icon(Icons.location_searching),
      ),
    );
  }
}

更多关于Flutter地理位置获取插件geolocator_cn的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter地理位置获取插件geolocator_cn的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


geolocator_cn 是一个适用于 Flutter 的插件,用于获取设备的地理位置信息。该插件是基于 geolocator 插件的一个中国地区优化版本,特别适用于在中国大陆地区使用。

安装插件

首先,你需要在 pubspec.yaml 文件中添加 geolocator_cn 插件的依赖:

dependencies:
  flutter:
    sdk: flutter
  geolocator_cn: ^0.2.0

然后运行 flutter pub get 来安装插件。

配置权限

在获取地理位置之前,你需要在 Android 和 iOS 项目中配置相应的权限。

Android

android/app/src/main/AndroidManifest.xml 文件中添加以下权限:

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

iOS

ios/Runner/Info.plist 文件中添加以下权限:

<key>NSLocationWhenInUseUsageDescription</key>
<string>我们需要您的位置信息来提供更好的服务</string>
<key>NSLocationAlwaysUsageDescription</key>
<string>我们需要您的位置信息来提供更好的服务</string>

使用插件

1. 导入插件

在你的 Dart 文件中导入 geolocator_cn 插件:

import 'package:geolocator_cn/geolocator_cn.dart';

2. 检查权限

在获取地理位置之前,首先检查是否有权限:

bool serviceEnabled = await GeolocatorCn.isLocationServiceEnabled();
if (!serviceEnabled) {
  // 位置服务未启用,提示用户启用
  return;
}

LocationPermission permission = await GeolocatorCn.checkPermission();
if (permission == LocationPermission.denied) {
  permission = await GeolocatorCn.requestPermission();
  if (permission == LocationPermission.denied) {
    // 用户拒绝了权限
    return;
  }
}

if (permission == LocationPermission.deniedForever) {
  // 用户永久拒绝了权限,提示用户手动开启
  return;
}

3. 获取当前位置

你可以使用以下代码获取设备的当前位置:

Position position = await GeolocatorCn.getCurrentPosition(
    desiredAccuracy: LocationAccuracy.high);

print('Latitude: ${position.latitude}, Longitude: ${position.longitude}');

4. 监听位置变化

你也可以监听位置的变化:

StreamSubscription<Position> positionStream = GeolocatorCn.getPositionStream(
    desiredAccuracy: LocationAccuracy.high,
    distanceFilter: 10, // 位置变化超过10米时触发
).listen((Position position) {
    print('Latitude: ${position.latitude}, Longitude: ${position.longitude}');
});

注意事项

  1. 中国地区优化geolocator_cn 插件针对中国地区进行了优化,确保在中国大陆地区能够正常获取地理位置信息。
  2. 权限管理:在使用地理位置功能时,务必处理好权限请求,确保用户体验。
  3. 精度选择:根据应用需求选择合适的精度(LocationAccuracy),高精度可能会消耗更多电量。

示例代码

以下是一个完整的示例代码,展示了如何使用 geolocator_cn 获取设备的当前位置:

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

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

class MyApp extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      home: LocationScreen(),
    );
  }
}

class LocationScreen extends StatefulWidget {
  [@override](/user/override)
  _LocationScreenState createState() => _LocationScreenState();
}

class _LocationScreenState extends State<LocationScreen> {
  Position? _currentPosition;

  Future<void> _getCurrentLocation() async {
    bool serviceEnabled = await GeolocatorCn.isLocationServiceEnabled();
    if (!serviceEnabled) {
      // 位置服务未启用,提示用户启用
      return;
    }

    LocationPermission permission = await GeolocatorCn.checkPermission();
    if (permission == LocationPermission.denied) {
      permission = await GeolocatorCn.requestPermission();
      if (permission == LocationPermission.denied) {
        // 用户拒绝了权限
        return;
      }
    }

    if (permission == LocationPermission.deniedForever) {
      // 用户永久拒绝了权限,提示用户手动开启
      return;
    }

    Position position = await GeolocatorCn.getCurrentPosition(
        desiredAccuracy: LocationAccuracy.high);

    setState(() {
      _currentPosition = position;
    });
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('获取地理位置'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            _currentPosition != null
                ? Text(
                    '纬度: ${_currentPosition!.latitude}, 经度: ${_currentPosition!.longitude}')
                : Text('未获取到位置信息'),
            SizedBox(height: 20),
            ElevatedButton(
              onPressed: _getCurrentLocation,
              child: Text('获取当前位置'),
            ),
          ],
        ),
      ),
    );
  }
}
回到顶部