鸿蒙Flutter引用tuanjieLib库
·
1.鸿蒙OHOS项目目录下引用tuanjieLib
先把Unity导出的鸿蒙项目中的tuanjieLib整个文件夹考到OHOS项目根目录下,然后在根目录下的build-profile.json5文件添加modules
"modules": [
{
"name": "entry",
"srcPath": "./entry",
"targets": [
{
"name": "default",
"applyToProducts": [
"default"
]
}
]
},
{
"name": "tuanjieLib",
"srcPath": "./tuanjieLib",
"targets": [
{
"name": "default",
"applyToProducts": [
"default"
]
}
]
}
]
2.entry主库添加配置
2.1.oh-package.json5配置
{
"name": "entry",
"version": "1.0.0",
"description": "Please describe the basic information.",
"main": "",
"author": "",
"license": "",
"dependencies": {
"tuanjieLib": "file:../tuanjieLib"
},
}
2.2.src/module.json5配置
unity的权限添加
"requestPermissions": [
{
"name" : "ohos.permission.INTERNET",
"usedScene": {
"abilities": [
"EntryAbility"
],
"when": "always"
},
"reason": "$string:default_reason"
},
{
"name": "ohos.permission.ACCELEROMETER",
"usedScene": {
"abilities": [
"EntryAbility"
],
"when": "always"
},
"reason": "$string:default_reason"
}
]
3.代码添加
3.1.src/main/ets/plugins添加UnityNativeViewPlugin.ets代码
import { FlutterPlugin,FlutterPluginBinding } from '@ohos/flutter_ohos/src/main/ets/embedding/engine/plugins/FlutterPlugin';
import StandardMessageCodec from '@ohos/flutter_ohos/src/main/ets/plugin/common/StandardMessageCodec';
import { CustomUnityFactory } from '../unity/CustomUnityFactory';
import common from '@ohos.app.ability.common';
import EntryAbility from '../entryability/EntryAbility';
export class UnityNativeViewPlugin implements FlutterPlugin {
private myContext: common.Context;
private myAb:EntryAbility;
constructor(context: common.Context,ab:EntryAbility) {
this.myContext = context;
this.myAb = ab;
}
getUniqueClassName(): string {
return 'UnityNativeViewPlugin';
}
onAttachedToEngine(binding: FlutterPluginBinding): void {
binding.getPlatformViewRegistry()?.registerViewFactory(
'com.xxx.xxx.ohos/customUnityView',
new CustomUnityFactory(binding.getBinaryMessenger(), StandardMessageCodec.INSTANCE, this.myAb)
);
}
onDetachedFromEngine(binding: FlutterPluginBinding): void {}
}
3.2src/main/ets/unity添加CustomUnityFactory 和 CustomUnityView
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 {APP_KEY_SAFEAREA_RECT} from 'tuanjieLib';
import { TuanjiePlayerView } from 'tuanjieLib';
import { window } from '@kit.ArkUI';
import { Tuanjie } from 'tuanjieLib/src/main/ets/utils/TuanjieNative';
import { TuanjieLog } from 'tuanjieLib/src/main/ets/common/TuanjieLog';
import { POST_MESSAGE } from 'tuanjieLib/src/main/ets/workers/WorkerProxy';
import { DisplayInfoManager } from 'tuanjieLib/src/main/ets/utils/DisplayInfoManager';
import { VideoPlayerProxy } from 'tuanjieLib/src/main/ets/utils/VideoPlayerProxy';
import { WindowUtils } from 'tuanjieLib/src/main/ets/utils/WindowUtils';
import { GetFromGlobalThis, SetToGlobalThis } from 'tuanjieLib/src/main/ets/common/GlobalThisUtil';
@Entry
@Component
struct CustomUnityComponent {
@State displayIndex0:number = 0;
@StorageProp(APP_KEY_SAFEAREA_RECT) safeAreaRect:window.Rect = {top:0,left:0,width:0,height:0};
build() {
Column() {
TuanjiePlayerView({displayIndex:this.displayIndex0}).width('100%').height('100%');
}
.width('100%')
.height('100%')
}
}
@Builder
function UnityBuilder(params: Params) {
CustomUnityComponent().backgroundColor(Color.White)
}
@Observed
export class CustomUnityView extends PlatformView implements MethodCallHandler{
channel: MethodChannel;
private intervalId: number | undefined;
private static isInitialized = false; // 防止重复初始化
constructor(context: common.Context, viewId: number, args: ESObject, message: BinaryMessenger ,windowStage: window.WindowStage) {
super();
// 注册消息通道
this.channel = new MethodChannel(message, 'com.xxx.xxx.ohos/unity_channel');
this.channel.setMethodCallHandler(this);
this.initializeOnce(context,windowStage);
this.intervalId = setInterval(() => {
//this.sendEventToFlutter('onUnityEvent','bbbb');
}, 2000);
}
onMethodCall(call: MethodCall, result: MethodResult): void {
switch (call.method) {
case 'fromFlutter':
console.log('Received from Flutter: ' + JSON.stringify(call.method));
// 执行原生操作,例如更新 Unity 视图
// 可以回复数据:return 'some result';
break;
case 'onResume':
this.onResume();
break;
case 'onPause':
this.onPause()
break;
case 'onDestroy':
this.onDestroy()
break;
default:
throw new Error('Unknown method ' + call.method);
}
}
/**
* 一次性初始化:原生模块、Worker、显示信息、全局变量
*/
private initializeOnce(context: common.Context,windowStage: window.WindowStage): void {
TuanjieLog.info('%{public}s', 'TuanjiePlayerAbility onCreate, bundleCodeDir:' + context.bundleCodeDir);
Tuanjie.nativeOnCreate();
globalThis.CommandLineArguments = 'undefined';
POST_MESSAGE({
type: 'SetGlobalThisContext', data: context
});
globalThis.AbilityContext = context;
DisplayInfoManager.getInstance().initialize();
AppStorage.setOrCreate("backButtonLeavesApp", false);
CustomUnityView.isInitialized = true;
if(windowStage){
let windowClass = windowStage.getMainWindowSync();
try {
SetToGlobalThis(WindowUtils.getInstance().MainWindowKey, windowClass);
WindowUtils.getInstance().setWindowSizeChangeCallback();
WindowUtils.getInstance().setWindowAvoidAreaChangeCallBack();
windowClass.setWindowLayoutFullScreen(true, (err1, data1) => {
if (err1.code) {
console.error('Failed to enable the full-screen mode. Cause: ' + JSON.stringify(err1));
return;
}
console.info('Succeeded in enabling the full-screen mode. Data: ' + JSON.stringify(data1));
});
} catch (err) {
console.error('Failed to obtain the main window. Cause: ' + JSON.stringify(err));
}
}
this.onResume();
}
public sendEventToFlutter(eventName: string, data: String): void {
this.channel.invokeMethod(eventName, {'data': data});
}
getView(): WrappedBuilder<[Params]> {
return new WrappedBuilder(UnityBuilder);
}
private onResume(): void {
if (VideoPlayerProxy.getInstance().IsPlaying()) {
VideoPlayerProxy.getInstance().OnResume();
}
else {
Tuanjie.nativeOnResume();
}
POST_MESSAGE({
type: 'InternetSubscribe', data: null
});
}
private onPause(): void {
if (VideoPlayerProxy.getInstance().IsPlaying()) {
VideoPlayerProxy.getInstance().OnPause();
}
else {
Tuanjie.nativeOnPause();
}
}
private onDestroy(): void {
TuanjieLog.info('%{public}s', 'TuanjiePlayerAbility onDestroy');
Tuanjie.nativeOnDestroy();
}
dispose(): void {
// 清理资源,可取消窗口监听等
if (this.intervalId !== undefined) {
clearInterval(this.intervalId);
this.intervalId = undefined;
}
}
}
import { BinaryMessenger } from '@ohos/flutter_ohos/src/main/ets/plugin/common/BinaryMessenger';
import MessageCodec from '@ohos/flutter_ohos/src/main/ets/plugin/common/MessageCodec';
import PlatformViewFactory from '@ohos/flutter_ohos/src/main/ets/plugin/platform/PlatformViewFactory';
import common from '@ohos.app.ability.common';
import PlatformView from '@ohos/flutter_ohos/src/main/ets/plugin/platform/PlatformView';
import { CustomUnityView } from './CustomUnityView';
import EntryAbility from '../entryability/EntryAbility';
export class CustomUnityFactory extends PlatformViewFactory {
message: BinaryMessenger;
ability:EntryAbility;
constructor(message: BinaryMessenger, createArgsCodes: MessageCodec<Object>,myAb:EntryAbility) {
super(createArgsCodes);
this.message = message;
this.ability = myAb;
}
public create(context: common.Context, viewId: number, args: Object): PlatformView {
let windowStage = this.ability.getWindowStage();
//let windowStage: window.WindowStage | undefined;
return new CustomUnityView(context, viewId, args, this.message, windowStage!);
}
}
3.3src/main/ets/entryability/EntryAbility代码修改
import { FlutterAbility, FlutterEngine } from '@ohos/flutter_ohos';
import { GeneratedPluginRegistrant } from '../plugins/GeneratedPluginRegistrant';
import { UnityNativeViewPlugin } from '../plugins/UnityNativeViewPlugin';
import { window } from '@kit.ArkUI';
import { AbilityConstant, Want } from '@kit.AbilityKit';
export default class EntryAbility extends FlutterAbility {
private windowStage: window.WindowStage | null = null;
onWindowStageCreate(windowStage: window.WindowStage): void {
super.onWindowStageCreate(windowStage);
this.windowStage = windowStage;
}
// 提供一个获取 WindowStage 的方法
getWindowStage(): window.WindowStage | null {
return this.windowStage;
}
configureFlutterEngine(flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
GeneratedPluginRegistrant.registerWith(flutterEngine)
this.addPlugin(new UnityNativeViewPlugin(this.context,this))
}
}
4.flutter端使用控件
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
class UnityView extends StatefulWidget {
const UnityView({super.key});
@override
State<UnityView> createState() => _UnityViewState();
}
class _UnityViewState extends State<UnityView> with WidgetsBindingObserver{
// 方法通道,用于与原生通信
static const String _channelName = 'com.xxx.xxx.ohos/unity_channel';
MethodChannel? _channel;
@override
void initState() {
super.initState();
// 监听来自原生的事件
_channel = MethodChannel(_channelName);
_channel?.setMethodCallHandler(_handleMethod);
WidgetsBinding.instance.addObserver(this);
}
Future<void> _sendMessageToNative(String name,String message) async {
try {
await _channel?.invokeMethod(name, {'data': message});
} on PlatformException catch (e) {
print('Failed to send message: ${e.message}');
}
}
// 处理从鸿蒙原生发来的消息,无用
Future<dynamic> _handleMethod(MethodCall call) async {
switch (call.method) {
case 'onUnityEvent':
// 例如接收到原生视图的点击事件
print('Received from native: ${call.arguments}');
// 可以回调给业务层
break;
default:
throw UnimplementedError('Unknown method ${call.method}');
}
}
@override
Widget build(BuildContext context) {
// 判断平台,仅在鸿蒙时使用 PlatformView
if (Theme.of(context).platform == TargetPlatform.ohos) {
return Column(
children: [
SizedBox(height: 50,),
SizedBox(width: double.maxFinite,height: 200,
child: BuildOhosView(),
),
ElevatedButton(
child: const Text('Press Me'),
onPressed: () {
_sendMessageToNative('fromFlutter','aaa');
}
)
],
);
}
// 其他平台使用 Flutter 实现的占位控件
return Container(
color: Colors.grey[300],
child: const Center(child: Text('非鸿蒙平台')),
);
}
Widget BuildOhosView(){
return const OhosView(
viewType: 'com.xxx.xxx.ohos/customUnityView', // 必须与鸿蒙端注册的 viewType 一致
creationParams: {'initialText': 'Hello from Flutter'},
creationParamsCodec: StandardMessageCodec(),
);
}
void _onResume(){
_sendMessageToNative('onResume','');
}
void _onPause(){
_sendMessageToNative('onPause','');
}
void _onDestroy(){
_sendMessageToNative('onDestroy','');
}
@override
void dispose() {
WidgetsBinding.instance.removeObserver(this);
_onDestroy();
super.dispose();
}
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
super.didChangeAppLifecycleState(state);
switch (state) {
case AppLifecycleState.resumed:
// 应用从后台返回前台,或应用首次启动时可见 [citation:1][citation:4]
print('应用进入前台');
this._onResume();
break;
case AppLifecycleState.paused:
// 应用进入后台,用户不可见 [citation:4][citation:7]
print('应用进入后台');
this._onPause();
break;
case AppLifecycleState.inactive:
// 应用处于非活跃状态,例如来了电话、或系统弹窗覆盖时 [citation:2][citation:3]
print('应用处于非活跃状态');
break;
case AppLifecycleState.hidden:
// 应用的所有视图都不可见 (Flutter 3.13.0 之后新增) [citation:2]
print('应用被隐藏');
break;
case AppLifecycleState.detached:
// 应用已完全脱离引擎,通常是在销毁前 [citation:2][citation:3]
print('应用已脱离');
break;
}
}
}
更多推荐
所有评论(0)