1. 插件介绍

localtion_demo 是一个专为 Flutter 跨平台开发鸿蒙化应用设计的定位组件,通过 Flutter 与鸿蒙原生代码的交互,实现了设备位置信息的获取功能。该组件提供了简洁的 API,帮助开发者轻松实现跨平台定位功能,特别针对鸿蒙平台的定位服务进行了优化,确保定位数据的准确性和稳定性。

主要功能特点:

  • 支持获取设备当前位置信息
  • 提供完整的位置数据(包括经度、纬度、高度、速度等)
  • 支持定位权限管理
  • 实现了 Flutter 与鸿蒙原生的双向通信

2. 环境要求

在使用本组件前,请确保您的开发环境满足以下要求:

  • Flutter SDK 版本:≥ 2.19.6
  • Dart SDK 版本:≥ 2.19.6
  • 鸿蒙 SDK API 版本:≥ 9
  • DevEco Studio 版本:≥ 3.0
  • 鸿蒙定位服务支持:需要设备支持定位功能

3. 包的引入

由于本组件依赖于自定义修改版本的三方库,需要通过 git 形式引入。在您的 Flutter 项目的 pubspec.yaml 文件中,按照以下方式添加依赖:

dependencies:
  flutter:
    sdk: flutter

  cupertino_icons: ^1.0.2

  # 吐司提示组件
  fluttertoast:
    git:
      url: "https://atomgit.com/openharmony-sig/flutter_fluttertoast.git"
      path: "./"

添加完依赖后,执行以下命令获取依赖包:

flutter pub get

4. 权限配置

在鸿蒙应用中使用定位功能需要配置相应的权限。在 ohos/entry/src/main/module.json5 文件中添加以下权限配置:

"requestPermissions": [
  {
    "name": "ohos.permission.LOCATION",
    "usedScene": {
      "abilities": ["EntryAbility"],
      "when": "inuse"
    }
  },
  {
    "name": "ohos.permission.LOCATION_IN_BACKGROUND",
    "usedScene": {
      "abilities": ["EntryAbility"],
      "when": "always"
    }
  }
]

5. 功能实现与API调用

5.1 Flutter端实现

// ignore_for_file: library_private_types_in_public_api

import 'dart:async';

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:fluttertoast/fluttertoast.dart';

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

class MyApp extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('获取定位信息'),
        ),
        body: const MessageReceiver(),
      ),
    );
  }
}

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

  
  _MessageReceiverState createState() => _MessageReceiverState();
}

class _MessageReceiverState extends State<MessageReceiver> {
  String? message;

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

  Future<void> _setupMethodChannel() async {
    // 创建 MethodChannel 用于与原生通信
    const channel = MethodChannel('com.example.yourapp/channel');

    // 设置方法调用处理器
    channel.setMethodCallHandler((call) async {
      if (call.method == 'sendMessage') {
        // 接收来自原生的定位信息
        final String? msg = call.arguments as String?;
        setState(() {
          message = msg;
        });

        // 显示定位信息吐司
        Fluttertoast.showToast(
          msg: msg.toString(),
          toastLength: Toast.LENGTH_SHORT,
          backgroundColor: Colors.red,
          textColor: Colors.white
        );
      }
    });
  }

  
  Widget build(BuildContext context) {
    return Center(
      child: message == null
          ? Text('未接收到定位信息.')
          : Text('来自Arkts的定位信息: $message'),
    );
  }
}

5.2 鸿蒙原生插件实现

5.2.1 自定义插件类
import MethodChannel, {
  MethodCallHandler,
  MethodResult
} from '@ohos/flutter_ohos/src/main/ets/plugin/common/MethodChannel';
import common from '@ohos.app.ability.common';
import { BinaryMessenger } from '@ohos/flutter_ohos/src/main/ets/plugin/common/BinaryMessenger';
import MethodCall from '@ohos/flutter_ohos/src/main/ets/plugin/common/MethodCall';
import {
  FlutterPlugin,
  FlutterPluginBinding
} from '@ohos/flutter_ohos/src/main/ets/embedding/engine/plugins/FlutterPlugin';

export default class CustomPlugin implements FlutterPlugin, MethodCallHandler {
  private context: common.Context | null = null;
  private channel: MethodChannel | null = null;

  private static instance: CustomPlugin | null = null;
  public static getInstance(): CustomPlugin {
    if (!CustomPlugin.instance) {
      CustomPlugin.instance = new CustomPlugin();
    }
    return CustomPlugin.instance;
  }

  constructor() {
    if (!CustomPlugin.instance) {
      CustomPlugin.instance = this;
    } else {
      return CustomPlugin.instance;
    }
  }

  getUniqueClassName(): string {
    return "CustomPlugin";
  }

  onAttachedToEngine(binding: FlutterPluginBinding): void {
    this.context = binding.getApplicationContext();
    this.channel = new MethodChannel(binding.getBinaryMessenger(), 'com.example.yourapp/channel');
    this.channel.setMethodCallHandler(this);
  }

  onDetachedFromEngine(binding: FlutterPluginBinding): void {
    this.channel?.destroy();
    this.context = null;
  }

  onMethodCall(call: MethodCall, result: MethodResult): void {
    // 可以在此处理来自Flutter的方法调用
  }

  // 向Flutter发送消息的方法
  public sendMessage(res: String): void {
    this.channel?.invokeMethod('sendMessage', res);
  }
}
5.2.2 定位功能实现
import common from '@ohos.app.ability.common';
import { FlutterPage } from '@ohos/flutter_ohos';
import { geoLocationManager } from '@kit.LocationKit';
import { BusinessError } from '@kit.BasicServicesKit';
import CustomPlugin from '../entryability/CustomPlugin';

// 获取当前位置信息
function getCurrentLocationInfo() {
  // 配置定位请求参数
  const requestInfo: geoLocationManager.LocationRequest = {
    'priority': geoLocationManager.LocationRequestPriority.FIRST_FIX,
    'scenario': geoLocationManager.LocationRequestScenario.UNSET,
    'timeInterval': 1,
    'distanceInterval': 0,
    'maxAccuracy': 0
  };

  // 获取自定义插件实例
  const custom = CustomPlugin.getInstance();

  try {
    // 调用鸿蒙定位服务获取当前位置
    geoLocationManager.getCurrentLocation(requestInfo)
      .then((location: geoLocationManager.Location) => {
        // 将位置信息转换为JSON字符串
        let value: ESObject = JSON.stringify(location);
        // 发送位置信息到Flutter端
        custom.sendMessage(value);
      })
      .catch((err: BusinessError) => {
        console.error(`获取位置失败. 错误码: ${err.code}, 错误信息: ${err.message}`);
      });
  } catch (err) {
    console.error(`获取位置失败. 错误码: ${err.code}, 错误信息: ${err.message}`);
  }
}

// 定义位置按钮组件
@Component
struct LocationButton {
  build() {
    Button('获取定位')
      .width(200)
      .height(50)
      .fontSize(18)
  }
}

let storage = LocalStorage.getShared();
const EVENT_BACK_PRESS = 'EVENT_BACK_PRESS';

@Entry(storage)
@Component
struct Index {
  private context = getContext(this) as common.UIAbilityContext;
  @LocalStorageLink('viewId') viewId: string = "";

  build() {
    Column() {
      // 嵌入Flutter页面
      FlutterPage({ viewId: this.viewId });

      // 添加定位按钮
      Button('获取定位')
        .width(200)
        .height(50)
        .fontSize(18)
        .onClick((event: ClickEvent) => {
          console.info("点击了获取定位按钮");
          // 调用获取位置信息函数
          getCurrentLocationInfo();
        })
        .position({ x: '35%', y: '20%' })
    }
  }

  onBackPress(): boolean {
    this.context.eventHub.emit(EVENT_BACK_PRESS);
    return true;
  }
}
5.2.3 注册插件
import { FlutterAbility } from '@ohos/flutter_ohos';
import { GeneratedPluginRegistrant } from '../plugins/GeneratedPluginRegistrant';
import FlutterEngine from '@ohos/flutter_ohos/src/main/ets/embedding/engine/FlutterEngine';
import CustomPlugin from './CustomPlugin';

export default class EntryAbility extends FlutterAbility {
  configureFlutterEngine(flutterEngine: FlutterEngine) {
    super.configureFlutterEngine(flutterEngine);
    GeneratedPluginRegistrant.registerWith(flutterEngine);
    // 注册自定义插件
    this.addPlugin(new CustomPlugin());
  }
}

6. 代码解析

6.1 关键组件说明

  1. MethodChannel:用于 Flutter 与鸿蒙原生代码之间的双向通信
  2. CustomPlugin:自定义插件类,实现了 FlutterPlugin 接口,用于注册和管理 MethodChannel
  3. geoLocationManager:鸿蒙定位服务,用于获取设备当前位置信息
  4. FlutterPage:用于在鸿蒙页面中嵌入 Flutter 组件

6.2 定位流程

  1. 用户点击鸿蒙页面上的"获取定位"按钮
  2. 调用 getCurrentLocationInfo() 函数获取当前位置信息
  3. 使用 geoLocationManager.getCurrentLocation() 方法获取设备位置
  4. 将位置信息转换为 JSON 字符串
  5. 通过 CustomPluginsendMessage() 方法将位置信息发送到 Flutter 端
  6. Flutter 端通过 MethodChannel 接收位置信息并显示

7. 常见问题与解决方案

7.1 定位权限问题

如果无法获取位置信息,请检查是否已正确配置定位权限。在鸿蒙应用中,需要配置 ohos.permission.LOCATIONohos.permission.LOCATION_IN_BACKGROUND 权限。

7.2 MethodChannel 通信失败

确保 Flutter 和鸿蒙原生代码中使用的 MethodChannel 名称一致,本示例中使用的名称是 com.example.yourapp/channel

7.3 依赖包问题

确保已正确添加 fluttertoast 依赖包,并且版本兼容。

8. 总结

localtion_demo 组件为 Flutter 跨平台开发鸿蒙化应用提供了简洁、高效的定位功能解决方案:

  1. 跨平台通信:通过 MethodChannel 实现了 Flutter 与鸿蒙原生代码的无缝通信
  2. 完整的定位功能:支持获取设备当前位置信息,包括经度、纬度、高度、速度等
  3. 权限管理:提供了完整的定位权限配置示例
  4. 易于集成:提供了详细的代码示例和使用说明

该组件的实现充分考虑了鸿蒙平台的特性,确保了定位功能的准确性和稳定性,同时提供了简洁易用的 API,帮助开发者快速集成到自己的应用中。

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

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐