Flutter跨平台开发鸿蒙化定位服务组件使用指南

1. 插件介绍

Flutter跨平台开发鸿蒙化定位服务组件是一个专为OpenHarmony系统设计的Flutter插件,它实现了Flutter与OpenHarmony原生定位服务的无缝集成。该组件基于OpenHarmony的LocationKit提供高精度定位功能,通过MethodChannel实现Flutter与原生鸿蒙代码的双向通信,支持实时获取设备位置信息并在Flutter界面中展示。

主要功能特性:

  • 基于OpenHarmony LocationKit实现高精度定位
  • 通过MethodChannel实现跨平台通信
  • 支持自定义定位请求参数(优先级、时间间隔、距离间隔等)
  • 集成fluttertoast实现位置信息的弹窗提示
  • 完整的错误处理机制

2. 环境设置

2.1 系统要求

  • Flutter SDK: ≥ 2.19.6
  • Dart SDK: ≥ 2.19.6 < 3.0.0
  • OpenHarmony SDK: API 9及以上
  • DevEco Studio: 4.0及以上

2.2 项目配置

  1. 在Flutter项目中创建OpenHarmony模块
bash 复制代码
flutter create -t module your_project_name
  1. 进入OpenHarmony模块目录
bash 复制代码
cd your_project_name/ohos
  1. 配置模块信息(module.json5),添加定位权限
json5 复制代码
{
  "module": {
    "name": "entry",
    "type": "entry",
    "description": "Flutter OpenHarmony Location Demo",
    "mainElement": "EntryAbility",
    "deviceTypes": ["phone", "tablet"],
    "distro": {
      "deliveryWithInstall": true,
      "moduleName": "entry",
      "moduleType": "entry"
    },
    "abilities": [
      {
        "name": "EntryAbility",
        "srcEntry": "./ets/entryability/EntryAbility.ts",
        "description": "Main Ability",
        "icon": "$media:icon",
        "label": "Flutter Location Demo",
        "startWindowIcon": "$media:icon",
        "startWindowBackground": "$color:start_window_background",
        "formsEnabled": false,
        "permissions": [
          "ohos.permission.LOCATION",
          "ohos.permission.LOCATION_IN_BACKGROUND"
        ]
      }
    ]
  }
}

3. 包的引入

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

yaml 复制代码
dependencies:
  flutter:
    sdk: flutter
  cupertino_icons: ^1.0.2
  fluttertoast:
    git:
      url: "https://atomgit.com/openharmony-sig/flutter_fluttertoast.git"
      path: "fluttertoast"

然后执行依赖获取命令:

bash 复制代码
flutter pub get

4. API调用与使用示例

4.1 Flutter端实现

在Flutter项目的lib/main.dart中实现位置信息接收和展示:

dart 复制代码
// 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 {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('获取定位信息'),
        ),
        body: const MessageReceiver(),
      ),
    );
  }
}

class MessageReceiver extends StatefulWidget {
  const MessageReceiver({super.key});

  @override
  _MessageReceiverState createState() => _MessageReceiverState();
}

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

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

  Future<void> _setupMethodChannel() async {
    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
        );
      }
    });
  }

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

4.2 鸿蒙端实现

4.2.1 自定义插件实现(CustomPlugin.ets)
typescript 复制代码
import MethodChannel, {
  MethodCallHandler,
  MethodResult
} from '@ohos/flutter_ohos/src/main/ets/plugin/common/MethodChannel';
import PlatformView, { Params } from '@ohos/flutter_ohos/src/main/ets/plugin/platform/PlatformView';
import common from '@ohos.app.ability.common';
import { BinaryMessenger } from '@ohos/flutter_ohos/src/main/ets/plugin/common/BinaryMessenger';
import StandardMethodCodec from '@ohos/flutter_ohos/src/main/ets/plugin/common/StandardMethodCodec';
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 {
  }

  onMethodCall(call: MethodCall, result: MethodResult): void {
    throw new Error('Method not implemented.');
  }

  public sendMessage(res: String): void {
    this.channel?.invokeMethod('sendMessage', res);
  }
}
4.2.2 注册插件(EntryAbility.ets)
typescript 复制代码
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());
  }
}
4.2.3 定位逻辑实现(Index.ets)
typescript 复制代码
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) => {
        let value: ESObject = JSON.stringify(location);
        custom.sendMessage(value);
      })
      .catch((err: BusinessError) => {
        console.error(`获取位置失败,错误码: ${err.code}, 错误信息: ${err.message}`);
      });
  } catch (err) {
    console.error(`获取位置异常,错误码: ${err.code}, 错误信息: ${err.message}`);
  }
}

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() {
      FlutterPage({ viewId: this.viewId });
      LocationButton()
        .onClick((event: ClickEvent, result: LocationButtonOnClickResult)=>{
          console.info("定位按钮点击结果: " + result)
          getCurrentLocationInfo();
        }).position({ x: '35%', y: '20%' })
    }
  }

  onBackPress(): boolean {
    this.context.eventHub.emit(EVENT_BACK_PRESS)
    return true
  }
}

5. 代码解析与关键点说明

5.1 跨平台通信机制

该组件采用MethodChannel实现Flutter与OpenHarmony原生代码的通信:

  1. Channel名称 : com.example.yourapp/channel
  2. 通信方向 : 鸿蒙原生 → Flutter(通过sendMessage方法)
  3. 数据格式: JSON字符串

5.2 定位请求参数配置

getCurrentLocationInfo函数中,我们可以配置以下定位参数:

  • priority: 定位优先级(如FIRST_FIX表示尽快获取首次定位结果)
  • scenario: 定位场景(如导航、运动等,本例中设为UNSET
  • timeInterval: 定位时间间隔(单位:秒)
  • distanceInterval: 定位距离间隔(单位:米)
  • maxAccuracy: 最大精度要求

5.3 权限配置

module.json5中需要添加以下定位权限:

  • ohos.permission.LOCATION: 获取设备位置的基本权限
  • ohos.permission.LOCATION_IN_BACKGROUND: 后台获取位置的权限

5.4 错误处理

组件实现了完整的错误处理机制:

  1. 使用Promise的catch方法捕获异步定位错误
  2. 使用try-catch块捕获同步代码异常
  3. 详细记录错误码和错误信息,便于调试

6. 运行与测试

6.1 构建和运行

bash 复制代码
# 进入项目根目录
cd your_project_name

# 构建Flutter模块
flutter build flutter_assets

# 在DevEco Studio中打开ohos目录,运行OpenHarmony应用

6.2 预期效果

  1. 应用启动后显示Flutter界面
  2. 点击定位按钮,鸿蒙原生代码获取位置信息
  3. 位置信息通过MethodChannel发送到Flutter端
  4. Flutter端接收并显示位置信息
  5. 同时通过fluttertoast弹出位置信息提示

7. 总结

Flutter跨平台开发鸿蒙化定位服务组件成功实现了Flutter与OpenHarmony原生定位服务的深度集成,为开发者提供了便捷的跨平台定位解决方案。该组件具有以下特点:

  1. 无缝集成: 基于OpenHarmony LocationKit提供原生级定位体验
  2. 跨平台通信: 通过MethodChannel实现高效的双向通信
  3. 易于使用: 提供简洁的API接口,降低开发难度
  4. 稳定可靠: 完善的错误处理机制,确保应用稳定性
  5. 可扩展性强: 支持自定义定位参数,满足不同场景需求

通过本指南,开发者可以快速上手使用该组件,在Flutter跨平台应用中实现鸿蒙系统的定位功能。

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

相关推荐
特立独行的猫a2 小时前
移植开源软件Notepad--(NDD)到鸿蒙PC:环境搭建与配置
notepad++·开源软件·harmonyos·鸿蒙pc·notpad--
我是人机不吃鸭梨2 小时前
Flutter 桌面端开发终极指南(2025版):构建跨平台企业级应用的完整解决方案
开发语言·javascript·人工智能·flutter·架构
乾坤一气杀3 小时前
Retrofit 内部工作原理时序图
架构·开源
Rysxt_3 小时前
Flutter框架:重塑跨平台开发的新纪元
flutter
鸿蒙开发工程师—阿辉3 小时前
HarmonyOS 上下文的使用: 脱离 UI 怎么用 Context?
ui·华为·harmonyos
云和恩墨3 小时前
数智聚力,开源破局!openGauss Summit 2025见证数据库产业革新,云和恩墨深耕生态载誉而归
数据库·开源
名字被你们想完了4 小时前
Flutter 实现一个容器内部元素可平移、缩放和旋转等功能(九)
前端·flutter
FrameNotWork4 小时前
HarmonyOS 教学实战(八):后台任务、Worker 与任务调度
华为·harmonyos
说私域5 小时前
基于AI大模型与AI智能名片S2B2C商城小程序的抖音内容力构建与品牌增长研究
大数据·人工智能·小程序·开源