
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 项目配置
- 在Flutter项目中创建OpenHarmony模块
bash
flutter create -t module your_project_name
- 进入OpenHarmony模块目录
bash
cd your_project_name/ohos
- 配置模块信息(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原生代码的通信:
- Channel名称 :
com.example.yourapp/channel - 通信方向 : 鸿蒙原生 → Flutter(通过
sendMessage方法) - 数据格式: 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 错误处理
组件实现了完整的错误处理机制:
- 使用Promise的catch方法捕获异步定位错误
- 使用try-catch块捕获同步代码异常
- 详细记录错误码和错误信息,便于调试
6. 运行与测试
6.1 构建和运行
bash
# 进入项目根目录
cd your_project_name
# 构建Flutter模块
flutter build flutter_assets
# 在DevEco Studio中打开ohos目录,运行OpenHarmony应用
6.2 预期效果
- 应用启动后显示Flutter界面
- 点击定位按钮,鸿蒙原生代码获取位置信息
- 位置信息通过MethodChannel发送到Flutter端
- Flutter端接收并显示位置信息
- 同时通过fluttertoast弹出位置信息提示
7. 总结
Flutter跨平台开发鸿蒙化定位服务组件成功实现了Flutter与OpenHarmony原生定位服务的深度集成,为开发者提供了便捷的跨平台定位解决方案。该组件具有以下特点:
- 无缝集成: 基于OpenHarmony LocationKit提供原生级定位体验
- 跨平台通信: 通过MethodChannel实现高效的双向通信
- 易于使用: 提供简洁的API接口,降低开发难度
- 稳定可靠: 完善的错误处理机制,确保应用稳定性
- 可扩展性强: 支持自定义定位参数,满足不同场景需求
通过本指南,开发者可以快速上手使用该组件,在Flutter跨平台应用中实现鸿蒙系统的定位功能。
欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net