Flutter地理位置定位插件uclocation的使用

Flutter地理位置定位插件uclocation的使用

插件用于在后台跟踪位置。

开始使用

请参阅示例以获取更多详细信息。

iOS

  1. 在AppDelegate.swift文件中添加以下代码:
func registerPlugins(registry: FlutterPluginRegistry) {
    GeneratedPluginRegistrant.register(with: registry)
}

UCLocationPlugin.setPluginRegistrantCallback(registerPlugins)
  1. 在Capabilities中添加以下更改:

1

2

3

完整示例代码

以下是使用uclocation插件的完整示例代码:

import 'dart:async';
import 'dart:ffi';
import 'dart:isolate';
import 'dart:ui';
import 'package:uclocation/uclocation.dart';
import 'package:uclocation/location_dto.dart';
import 'package:uclocation/settings/android_settings.dart';
import 'package:uclocation/settings/ios_settings.dart';
import 'package:uclocation/settings/locator_settings.dart';
import 'package:flutter/material.dart';
import 'package:permission_handler/permission_handler.dart';

import 'file_manager.dart';
import 'location_callback_handler.dart';
import 'location_service_repository.dart';

void main() {
  /// 在初始化位置插件之前
  WidgetsFlutterBinding.ensureInitialized();
  runApp(MyApp());
}

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

class _MyAppState extends State<MyApp> {
  ReceivePort port = ReceivePort();

  String? logStr = '';
  bool isRunning = false;
  LocationDto? lastLocation;

  [@override](/user/override)
  void initState() {
    super.initState();

    if (IsolateNameServer.lookupPortByName(
            LocationServiceRepository.isolateName) !=
        null) {
      IsolateNameServer.removePortNameMapping(
          LocationServiceRepository.isolateName);
    }

    IsolateNameServer.registerPortWithName(
        port.sendPort, LocationServiceRepository.isolateName);

    port.listen(
      (dynamic data) async {
        if (data != null && data != 'Null') {
          await updateUI(data);
        }
      },
    );
    initPlatformState();
  }

  [@override](/user/override)
  void dispose() {
    super.dispose();
  }

  Future<void> updateUI(LocationDto data) async {
    final log = await FileManager.readLogFile();

    await _updateNotificationText(data);

    setState(() {
      if (data != null) {
        lastLocation = data;
      }
      logStr = log;
    });
  }

  Future<void> _updateNotificationText(LocationDto data) async {
    if (data == null) {
      return;
    }

    await UClocation.updateNotificationText(
        title: "新位置已接收",
        msg: "${DateTime.now()}",
        bigMsg: "${data.latitude}, ${data.longitude}");
  }

  Future<void> initPlatformState() async {
    print('初始化...');
    await UClocation.initialize();
    logStr = await FileManager.readLogFile();
    print('初始化完成');
    final _isRunning = await UClocation.isServiceRunning();
    setState(() {
      isRunning = _isRunning;
    });
    print('运行状态 ${isRunning.toString()}');
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    final start = SizedBox(
      width: double.maxFinite,
      child: ElevatedButton(
        child: Text('开始'),
        onPressed: () {
          _onStart();
        },
      ),
    );
    final stop = SizedBox(
      width: double.maxFinite,
      child: ElevatedButton(
        child: Text('停止'),
        onPressed: () {
          onStop();
        },
      ),
    );
    final clear = SizedBox(
      width: double.maxFinite,
      child: ElevatedButton(
        child: Text('清除日志'),
        onPressed: () {
          FileManager.clearLogFile();
          setState(() {
            logStr = '';
          });
        },
      ),
    );
    String msgStatus = "-";
    if (isRunning != null) {
      if (isRunning) {
        msgStatus = '正在运行';
      } else {
        msgStatus = '未运行';
      }
    }
    final status = Text("状态: $msgStatus");

    final log = Text(
      logStr!,
    );

    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Flutter后台定位器'),
        ),
        body: Container(
          width: double.maxFinite,
          padding: const EdgeInsets.all(22),
          child: SingleChildScrollView(
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.center,
              children: <Widget>[start, stop, clear, status, log],
            ),
          ),
        ),
      ),
    );
  }

  void onStop() async {
    await UClocation.unRegisterLocationUpdate();
    final _isRunning = await UClocation.isServiceRunning();
    setState(() {
      isRunning = _isRunning;
    });
  }

  void _onStart() async {
    if (await _checkLocationPermission()) {
      await _startLocator();
      final _isRunning = await UClocation.isServiceRunning();

      setState(() {
        isRunning = _isRunning;
        lastLocation = null;
      });
    } else {
      // 显示错误
    }
  }

  Future<bool> _checkLocationPermission() async {
    var permission = await Permission.location.status;
    if (permission.isDenied) {
      permission = await Permission.location.request();
    }
    if (permission.isGranted) {
      return true;
    } else {
      return false;
    }
  }

  Future<void> _startLocator() async {
    Map<String, dynamic> data = {'countInit': 1};
    return await UClocation.registerLocationUpdate(
      LocationCallbackHandler.callback,
      initCallback: LocationCallbackHandler.initCallback,
      initDataCallback: data,
      disposeCallback: LocationCallbackHandler.disposeCallback,
      iosSettings: const IOSSettings(
          accuracy: LocationAccuracy.NAVIGATION, distanceFilter: 0),
      autoStop: false,
      androidSettings: const AndroidSettings(
          accuracy: LocationAccuracy.NAVIGATION,
          interval: 5,
          distanceFilter: 0,
          client: LocationClient.google,
          androidNotificationSettings: AndroidNotificationSettings(
              notificationChannelName: '位置追踪',
              notificationTitle: '开始位置追踪',
              notificationMsg: '在后台追踪位置',
              notificationBigMsg:
                  '为了在应用不运行时保持应用更新,背景位置已开启。这是主要功能正常工作所必需的。',
              notificationIconColor: Colors.grey,
              notificationTapCallback:
                  LocationCallbackHandler.notificationCallback));
  }
}

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

1 回复

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


uclocation 是一个 Flutter 插件,用于在 Android 和 iOS 设备上获取地理位置信息。它基于 Google Play Services Location API(Android)和 CoreLocation(iOS),提供了一种简单的方式来获取设备的当前位置。

安装 uclocation 插件

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

dependencies:
  flutter:
    sdk: flutter
  uclocation: ^0.0.1  # 请使用最新版本

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

使用 uclocation 插件

  1. 导入插件

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

    import 'package:uclocation/uclocation.dart';
    
  2. 获取地理位置

    使用 UCLocation 类来获取设备的地理位置。你可以使用 getLocation() 方法来获取当前位置:

    void getCurrentLocation() async {
      try {
        LocationData locationData = await UCLocation.getLocation();
        print("Latitude: ${locationData.latitude}");
        print("Longitude: ${locationData.longitude}");
        print("Accuracy: ${locationData.accuracy}");
        print("Altitude: ${locationData.altitude}");
        print("Speed: ${locationData.speed}");
        print("Speed Accuracy: ${locationData.speedAccuracy}");
        print("Heading: ${locationData.heading}");
        print("Time: ${locationData.time}");
      } catch (e) {
        print("Error getting location: $e");
      }
    }
    
  3. 监听位置变化

    如果你需要持续监听位置变化,可以使用 onLocationChanged 流:

    void listenToLocationChanges() {
      UCLocation.onLocationChanged.listen((LocationData locationData) {
        print("Updated Latitude: ${locationData.latitude}");
        print("Updated Longitude: ${locationData.longitude}");
      });
    }
    
  4. 权限处理

    在 Android 和 iOS 上,获取地理位置需要用户授予相应的权限。你需要在 AndroidManifest.xmlInfo.plist 文件中添加相应的权限声明。

    • Android: 在 AndroidManifest.xml 中添加以下权限:

      <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
      <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
      
    • iOS: 在 Info.plist 中添加以下键值对:

      <key>NSLocationWhenInUseUsageDescription</key>
      <string>We need access to your location to provide location-based services.</string>
      <key>NSLocationAlwaysUsageDescription</key>
      <string>We need access to your location to provide location-based services.</string>
      
  5. 请求权限

    在运行时,你还需要请求用户授予定位权限。你可以使用 permission_handler 插件来处理权限请求:

    import 'package:permission_handler/permission_handler.dart';
    
    void requestLocationPermission() async {
      var status = await Permission.location.status;
      if (!status.isGranted) {
        await Permission.location.request();
      }
    }
    

完整示例

以下是一个完整的示例,展示了如何使用 uclocation 插件获取和监听设备的地理位置:

import 'package:flutter/material.dart';
import 'package:uclocation/uclocation.dart';
import 'package:permission_handler/permission_handler.dart';

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

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

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

class _HomeScreenState extends State<HomeScreen> {
  String _locationInfo = "No location data";

  [@override](/user/override)
  void initState() {
    super.initState();
    requestLocationPermission();
    listenToLocationChanges();
  }

  void requestLocationPermission() async {
    var status = await Permission.location.status;
    if (!status.isGranted) {
      await Permission.location.request();
    }
  }

  void listenToLocationChanges() {
    UCLocation.onLocationChanged.listen((LocationData locationData) {
      setState(() {
        _locationInfo = "Latitude: ${locationData.latitude}, Longitude: ${locationData.longitude}";
      });
    });
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Location Example"),
      ),
      body: Center(
        child: Text(_locationInfo),
      ),
    );
  }
}
回到顶部