百度定位FlutterSDK插件封装


import 'dart:io';

import 'package:flutter_baidu_mapapi_base/flutter_baidu_mapapi_base.dart';
import 'package:flutter_baidu_mapapi_map/flutter_baidu_mapapi_map.dart';
import 'package:flutter_bmflocation/flutter_bmflocation.dart';
import 'package:permission_handler/permission_handler.dart';

typedef LocationResultCallback = void Function(BaiduLocation result);

typedef HeadingResultCallback = void Function(BaiduHeading result);

abstract class LocationService {

  LocationFlutterPlugin get locPlugin;

  /// 开始定位
  Future<bool> startLocation(){
    return locPlugin.startLocation();
  }

  /// 开始获取定位朝向
  Future<bool> startUpdatingHeader(){
    return locPlugin.startUpdatingHeading();
  }

  /// 停止定位
  Future<bool> stopLocation(){
    return locPlugin.stopLocation();
  }

  /// 设置定位回调
  void locationCallback(LocationResultCallback callback){
    locPlugin.seriesLocationCallback(callback: callback);
  }

  /// 设置设备朝向回调
  void headerCallback(HeadingResultCallback callback){
    locPlugin.updateHeadingCallback(callback: callback);
  }

  BaiduLocationAndroidOption initAndroidOptions() {
    BaiduLocationAndroidOption options = BaiduLocationAndroidOption(
        coorType: 'bd09ll',
        locationMode: BMFLocationMode.hightAccuracy,
        isNeedAddress: true,
        isNeedAltitude: true,
        isNeedLocationPoiList: true,
        isNeedNewVersionRgc: true,
        isNeedLocationDescribe: true,
        openGps: true,
        locationPurpose: BMFLocationPurpose.sport,
        coordType: BMFLocationCoordType.bd09ll);
    return options;
  }

  BaiduLocationIOSOption initIOSOptions() {
    BaiduLocationIOSOption options = BaiduLocationIOSOption(
        coordType: BMFLocationCoordType.bd09ll,
        BMKLocationCoordinateType: 'yFDD3IlfSk2xTdQ0G41MjRnzd5gUVG1C',
        desiredAccuracy: BMFDesiredAccuracy.best);
    return options;
  }

  /// 初始化定位参数
  void initOptions() async {
    Map iosMap = initIOSOptions().getMap();
    Map androidMap = initAndroidOptions().getMap();
    // Waring 如果不setAgreePrivacy(true) 会导致无法定位
    locPlugin.setAgreePrivacy(true);
    BMFMapSDK.setAgreePrivacy(true);
    await locPlugin.prepareLoc(androidMap, iosMap);
  }

  /// 动态申请定位权限
  void requestPermission() async {
    // 申请权限
    bool hasLocationPermission = await requestLocationPermission();
    if (hasLocationPermission) {
      // 权限申请通过
    } else {}
  }

  /// 授予定位权限返回true, 否则返回false
  Future<bool> requestLocationPermission() async {
    //获取当前的权限
    var status = await Permission.location.status;
    if (status == PermissionStatus.granted) {
      //已经授权
      return true;
    } else {
      //未授权则发起一次申请
      status = await Permission.location.request();
      if (status == PermissionStatus.granted) {
        return true;
      } else {
        return false;
      }
    }
  }

}

/// 单次定位服务
/// @deprecated: 百度Flutter定位目前不支持多实例(LocationFlutterPlugin)
/// 推荐使用 locationServiceImpl 代替

class SingleLocationService extends LocationService {

  final LocationFlutterPlugin _locPlug = LocationFlutterPlugin();

  
  LocationFlutterPlugin get locPlugin => _locPlug;

  SingleLocationService(){
    requestPermission();
    initOptions();
  }

  
  locationCallback(LocationResultCallback callback){
    var call = (loc){
      callback(loc);
      // 停止定位
      stopLocation();
    };
    print("except code : ${call.hashCode}");
    _locPlug.seriesLocationCallback(callback: call);
  }

  /// 获取单次定位
  void location(LocationResultCallback callback) {
    locationCallback(callback);
    _locPlug.startLocation();
    print("single location instance code ${this.hashCode}, locPlugCode ${_locPlug.hashCode}");
  }

  
  BaiduLocationAndroidOption initAndroidOptions(){
    var androidOptions = super.initAndroidOptions();
    androidOptions.setScanspan(0);
    return androidOptions;
  }

}


/// 连续定位服务
/// @deprecated: 百度Flutter定位目前不支持多实例(LocationFlutterPlugin)
/// 推荐使用 locationServiceImpl 代替

class SeriesLocationService extends LocationService{

  final LocationFlutterPlugin _locPlugin =  LocationFlutterPlugin();

  bool locationStatus = false;

  /// 是否正在连续定位中
  bool isStarted() => locationStatus;

  /// 连续定位频率
  int span;

  
  LocationFlutterPlugin get locPlugin => _locPlugin;

  SeriesLocationService({LocationResultCallback? callback, this.span=2000}): super() {
    if (callback != null){
      locationCallback((result){
        callback(result);
      });
    }
    initOptions();
  }

  
  Future<bool> stopLocation(){
    locationStatus = false;
    return locPlugin.stopLocation();
  }

  
  void locationCallback(LocationResultCallback callback){
    _locPlugin.seriesLocationCallback(callback: (loc){
      callback(loc);
    });
  }

  // 参数初始化
  
  BaiduLocationAndroidOption initAndroidOptions() {
    var options = super.initAndroidOptions();
    options.setScanspan(span);
    return options;
  }

  
  Future<bool> startLocation(){
    if(isStarted()){
      return Future(() => false);
    }
    locationStatus=true;
    return locPlugin.startLocation();
  }

  /// 在地图上绘制定位朝向
  void updateUserHeading(BMFMapController mapController, BaiduHeading heading, BMFLocation location, {String title=""}) {
    if (Platform.isAndroid) {
      //android需要通过course设置方向
      location.course = heading.trueHeading;
    }
    BMFUserLocation userLocation = BMFUserLocation(
      //将包含course的BMFLocation对象传值给BMFUserLocation
      location: location,
      //下面均是iOS的参数,iOS通过heading设置方向
      heading: BMFHeading.fromMap(heading.getMap()),
      title: title,
    );
    mapController.updateLocationData(userLocation);
  }

}


class LocationCallBack {

  final bool isSingleLocation;

  final LocationResultCallback locationResultCallback;

  LocationCallBack(this.isSingleLocation, this.locationResultCallback);
}

/// 定位服务(单例方式)
class LocationServiceImpl extends LocationService {

  final LocationFlutterPlugin _locPlugin =  LocationFlutterPlugin();

  static LocationServiceImpl? _instance;

  static get instance {
    _instance ??= LocationServiceImpl._internal();
    return _instance;
  }

  final Set<LocationCallBack> callbackCache = {};

  /// 定位服务状态: true 正在定位, false 停止定位
  bool locationStatus = false;

  LocationServiceImpl._internal() {
    super.initOptions();
    _locPlugin.seriesLocationCallback(callback: (loc){
      List<LocationCallBack> removeItems = [];
      for (var item in callbackCache) {
        item.locationResultCallback(loc);
        if(item.isSingleLocation){
          removeItems.add(item);
        }
      }
      // 移除到期的定位回调服务
      for (var value in removeItems) {
        callbackCache.remove(value);
      }
      stopLocation();
    });
  }

  /// 停止定位 isEnforce 强制停止定位服务, code 停止(移除)某个定位回调服务
  
  Future<bool> stopLocation({int? code, isEnforce=false}) {
    if(isEnforce){
      callbackCache.clear();
      return _locPlugin.stopLocation();
    }
    Future<bool> result = Future(() => false);
    if(code!=null){
      callbackCache.removeWhere((element) => element.hashCode==code);
      result = Future(() => true);
    }
    if (callbackCache.isEmpty) {
      _locPlugin.stopLocation();
    }else{
      print("stop fail there are ${callbackCache.length} callback task");
    }
    return result;
  }

  
  Future<bool> startLocation(){
    if(!locationStatus){
      return _locPlugin.startLocation();
    }
    return Future(() => false);
  }

  
  LocationFlutterPlugin get locPlugin => _locPlugin;

  /// 注册单次定位回调
  void singleLocation(LocationResultCallback callback){
    callbackCache.add(LocationCallBack(true, (loc){
      callback(loc);
      stopLocation();
    }));
    startLocation();
  }

  /// 注册连续位回调
  int seriesLocation(LocationResultCallback callBack){
    var item = LocationCallBack(false, callBack);
    callbackCache.add(item);
    startLocation();
    return item.hashCode;
  }

}


代码说明:

  1. SeriesLocationService 与 SingleLocationService 服务不推荐使用; 因为目前的百度的Flutter 定位插件 只能时单实例的也就是只能创建一个LocationFlutterPlugin对象,当你创建多个LocationFlutterPlugin对象时会出现某个LocationFlutterPlugin实例对象的定位回调无法被调用(定位回调调用错乱-我测试了一下,好像是被覆盖了)
  2. 【推荐】使用LocationServiceImpl ,他支持单次与连续定位,但也有缺点,也就是只能公用一次配置信息(比如:定位回调的周期频率,定位模式等等)。
  3. 代码比较粗糙,大家可以根据自己实际情况进行二次改造。

在这里插入图片描述

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Flutter 是一个很好的跨平台开发框架,可以使开发者在一个代码库中同时构建 iOS 和 Android 应用。Flutter 的强大之处在于其件系统,可以让开发者轻松地使用原生设备功能和第三方服务。以下是几个封装 Flutter 件的步骤: 1. 确定件的功能和 API:定义件的功能和 API,这样就可以在 Flutter 中使用。例如,如果你想封装一个照相机件,你需要决定件支持哪些功能,例如拍照、录像、闪光灯等。 2. 创建 Flutter 件项目:创建一个 Flutter 件项目,可以使用 Flutter CLI 命令行工具创建。Flutter CLI 工具提供了一个简单的命令:flutter create --template=plugin my_plugin。这个命令会创建一个基本的件模板,包括 Dart 和 Kotlin/Swift 代码。 3. 实现件的功能和 API:在 Flutter 件项目中实现件的功能和 API。对于照相机件,需要在原生代码中实现拍照、录像等功能,并在 Dart 代码中暴露这些功能。 4. 测试件:在测试应用程序中测试件的功能和 API。创建一个简单的 Flutter 应用程序,并将件添加到应用程序中。确保件在应用程序中能够正常工作。 5. 发布件:将件发布到公共存储库中,例如 pub.dev。在发布前,需要确保件的文档清晰易懂,同时代码质量和可用性符合标准。 以上是封装 Flutter 件的基本步骤,当然具体实现还需要根据具体的需求进行调整。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值