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 项目配置
- 在Flutter项目中创建OpenHarmony模块
flutter create -t module your_project_name
- 进入OpenHarmony模块目录
cd your_project_name/ohos
- 配置模块信息(module.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",
"srcEntrance": "./ets/entryability/EntryAbility.ets",
"description": "",
"icon": "$media:icon",
"label": "$string:app_name",
"type": "page",
"visible": true,
"skills": [
{
"entities": ["entity.system.home"],
"actions": ["action.system.home"]
}
]
}
],
"requestPermissions": [
{
"name": "ohos.permission.LOCATION"
},
{
"name": "ohos.permission.LOCATION_IN_BACKGROUND"
}
]
}
}
3. 包的引入
由于本定位服务组件依赖于自定义修改的fluttertoast包,需要通过AtomGit方式引入。在Flutter项目的pubspec.yaml文件中添加以下配置:
dependencies:
flutter:
sdk: flutter
cupertino_icons: ^1.0.2
fluttertoast:
git:
url: "https://atomgit.com/openharmony-sig/flutter_fluttertoast.git"
path: "fluttertoast"
然后执行flutter pub get命令获取依赖:
flutter pub get
4. API的调用
4.1 MethodChannel通信配置
在Flutter项目的lib/main.dart中配置MethodChannel,用于接收来自OpenHarmony原生代码的定位信息:
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({super.key});
_MessageReceiverState createState() => _MessageReceiverState();
}
class _MessageReceiverState extends State<MessageReceiver> {
String? message;
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
);
}
});
}
Widget build(BuildContext context) {
return Center(
child: message == null
? Text('暂无定位信息')
: Text('来自ArkTS的定位信息: $message'),
);
}
}
4.2 OpenHarmony原生定位服务实现
在OpenHarmony模块中实现定位服务,首先创建自定义插件CustomPlugin.ets:
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 {
}
onMethodCall(call: MethodCall, result: MethodResult): void {
throw new Error('Method not implemented.');
}
public sendMessage(res: String): void {
this.channel?.invokeMethod('sendMessage', res);
}
}
4.3 注册自定义插件
在EntryAbility.ets中注册自定义插件:
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.4 实现定位功能
在OpenHarmony页面中实现定位功能,创建Index.ets:
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: string = JSON.stringify(location);
custom.sendMessage(value);
})
.catch((err: BusinessError) => {
console.error(`Failed to get current location. Code is ${err.code}, message is ${err.message}`);
});
} catch (err) {
console.error(`Failed to get current location. Code is ${err.code}, message is ${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 });
Button('获取定位信息')
.onClick((event)=>{
getCurrentLocationInfo();
})
.position({ x: '35%', y: '20%' })
.backgroundColor('#007AFF')
.fontColor('#FFFFFF')
.padding({ left: 20, right: 20, top: 10, bottom: 10 })
.borderRadius(10)
}
}
onBackPress(): boolean {
this.context.eventHub.emit(EVENT_BACK_PRESS)
return true
}
}
5. 完整示例
5.1 Flutter端完整代码
// lib/main.dart
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({super.key});
_MessageReceiverState createState() => _MessageReceiverState();
}
class _MessageReceiverState extends State<MessageReceiver> {
String? message;
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
);
}
});
}
Widget build(BuildContext context) {
return Center(
child: message == null
? Text('暂无定位信息')
: Text('来自ArkTS的定位信息: $message'),
);
}
}
5.2 OpenHarmony端完整代码
// ets/entryability/CustomPlugin.ets
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 {
}
onMethodCall(call: MethodCall, result: MethodResult): void {
throw new Error('Method not implemented.');
}
public sendMessage(res: String): void {
this.channel?.invokeMethod('sendMessage', res);
}
}
// ets/entryability/EntryAbility.ets
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());
}
}
// ets/pages/Index.ets
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: string = JSON.stringify(location);
custom.sendMessage(value);
})
.catch((err: BusinessError) => {
console.error(`Failed to get current location. Code is ${err.code}, message is ${err.message}`);
});
} catch (err) {
console.error(`Failed to get current location. Code is ${err.code}, message is ${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 });
Button('获取定位信息')
.onClick((event)=>{
getCurrentLocationInfo();
})
.position({ x: '35%', y: '20%' })
.backgroundColor('#007AFF')
.fontColor('#FFFFFF')
.padding({ left: 20, right: 20, top: 10, bottom: 10 })
.borderRadius(10)
}
}
onBackPress(): boolean {
this.context.eventHub.emit(EVENT_BACK_PRESS)
return true
}
}
6. 运行与测试
6.1 运行步骤
- 连接OpenHarmony设备或启动模拟器
- 进入Flutter项目根目录
- 执行以下命令构建并运行项目
flutter run -d ohos
6.2 测试方法
- 首次运行时,应用会请求定位权限,点击"允许"
- 点击页面上的"获取定位信息"按钮
- 应用会调用OpenHarmony的定位服务获取当前位置
- 获取到的位置信息会通过MethodChannel发送到Flutter端
- Flutter端会在页面上显示位置信息,并通过toast弹窗提示
7. 总结
本指南介绍了如何在OpenHarmony系统上使用Flutter跨平台开发鸿蒙化定位服务组件。通过本组件,开发者可以轻松实现Flutter与OpenHarmony原生定位服务的集成,获取设备的位置信息并在Flutter界面中展示。
主要实现了以下功能:
- 使用OpenHarmony LocationKit获取高精度定位信息
- 通过MethodChannel实现Flutter与OpenHarmony的跨平台通信
- 集成fluttertoast实现位置信息的弹窗提示
- 完整的权限配置和错误处理机制
通过本组件的学习,开发者可以掌握Flutter与OpenHarmony原生服务集成的核心技术,为开发更多跨平台应用打下基础。
欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net
更多推荐
所有评论(0)