鸿蒙 Flutter 开发中集成 Webview
主要有两种方案
使用第三方库
如 使用flutter_inappwebview插件,在 pubspec.lock 文件中配置:
1 flutter_inappwebview: 2 git: 3 url: https://gitee.com/openharmony-sig/flutter_inappwebview.git 4 path: "flutter_inappwebview"
或者使用 webview_flutter 插件
1 webview_flutter: 2 git: 3 url: https://gitee.com/openharmony-sig/flutter_packages.git 4 path: "packages/webview_flutter/webview_flutter"
编写原生 ArkTS 代码实现 PlatformView
创建 entryablitiy
在 src/main/module.json5中配置ablitiy
1 "abilities": [ 2 { 3 "name": "EntryAbility", 4 "srcEntry": "./ets/entryability/EntryAbility.ets", 5 "description": "$string:EntryAbility_desc", 6 "icon": "$media:icon", 7 "label": "$string:EntryAbility_label", 8 "startWindowIcon": "$media:icon", 9 "startWindowBackground": "$color:start_window_background", 10 "exported": true, 11 "skills": [ 12 { 13 "entities": [ 14 "entity.system.home" 15 ], 16 "actions": [ 17 "action.system.home" 18 ] 19 } 20 ], 21 "orientation": "landscape" 22 } 23 ],
cat src/main/entryablity/CustomFactory.ets
1import { BinaryMessenger } from '@ohos/flutter_ohos/src/main/ets/plugin/common/BinaryMessenger'; 2import MessageCodec from '@ohos/flutter_ohos/src/main/ets/plugin/common/MessageCodec'; 3import PlatformViewFactory from '@ohos/flutter_ohos/src/main/ets/plugin/platform/PlatformViewFactory'; 4import { CustomView } from './CustomView'; 5import common from '@ohos.app.ability.common'; 6import PlatformView from '@ohos/flutter_ohos/src/main/ets/plugin/platform/PlatformView'; 7 8export class CustomFactory extends PlatformViewFactory { 9 message: BinaryMessenger; 10 11 constructor(message: BinaryMessenger, createArgsCodes: MessageCodec<Object>) { 12 super(createArgsCodes); 13 this.message = message; 14 } 15 16 public create(context: common.Context, viewId: number, args: Object): PlatformView { 17 return new CustomView(context, viewId, args, this.message); 18 } 19}
cat src/main/entryablity/CustomPlugin.ets
1import { FlutterPlugin, 2 FlutterPluginBinding } from '@ohos/flutter_ohos/src/main/ets/embedding/engine/plugins/FlutterPlugin'; 3import StandardMessageCodec from '@ohos/flutter_ohos/src/main/ets/plugin/common/StandardMessageCodec'; 4import { CustomFactory } from './CustomFactory'; 5 6export class CustomPlugin implements FlutterPlugin { 7 getUniqueClassName(): string { 8 return 'CustomPlugin'; 9 } 10 11 onAttachedToEngine(binding: FlutterPluginBinding): void { 12 binding.getPlatformViewRegistry()?. 13 registerViewFactory('com.rex.custom.ohos/customView', new CustomFactory(binding.getBinaryMessenger(), StandardMessageCodec.INSTANCE)); 14 } 15 16 onDetachedFromEngine(binding: FlutterPluginBinding): void {} 17}
cat src/main/entryablity/CustomView.ets
1import MethodChannel, { 2 MethodCallHandler, 3 MethodResult 4} from '@ohos/flutter_ohos/src/main/ets/plugin/common/MethodChannel'; 5import PlatformView, { Params } from '@ohos/flutter_ohos/src/main/ets/plugin/platform/PlatformView'; 6import common from '@ohos.app.ability.common'; 7import { BinaryMessenger } from '@ohos/flutter_ohos/src/main/ets/plugin/common/BinaryMessenger'; 8import StandardMethodCodec from '@ohos/flutter_ohos/src/main/ets/plugin/common/StandardMethodCodec'; 9import MethodCall from '@ohos/flutter_ohos/src/main/ets/plugin/common/MethodCall'; 10import { webview } from '@kit.ArkWeb'; 11 12@Component 13struct ButtonComponent { 14 @Prop params: Params 15 customView: CustomView = this.params.platformView as CustomView 16 @StorageLink('numValue') storageLink: string = "first" 17 @State bkColor: Color = Color.Red 18 19 private webviewController: WebviewController = new webview.WebviewController() 20 21 build() { 22 Web({src: 'https://baidu.com', controller: this.webviewController}) 23 .domStorageAccess(true) 24 .fileAccess(true) 25 .mixedMode(MixedMode.All) 26 .databaseAccess(true) 27 .userAgent("Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71 Safari/537.36") 28 } 29} 30 31@Builder 32function ButtonBuilder(params: Params) { 33 ButtonComponent({ params: params }) 34 .backgroundColor(Color.Transparent) 35} 36 37AppStorage.setOrCreate('numValue', 'test') 38 39@Observed 40export class CustomView extends PlatformView implements MethodCallHandler { 41 numValue: string = "test"; 42 43 methodChannel: MethodChannel; 44 index: number = 1; 45 46 constructor(context: common.Context, viewId: number, args: ESObject, message: BinaryMessenger) { 47 super(); 48 // 注册消息通道 49 this.methodChannel = new MethodChannel(message, `com.rex.custom.ohos/customView${viewId}`, StandardMethodCodec.INSTANCE); 50 this.methodChannel.setMethodCallHandler(this); 51 } 52 53 onMethodCall(call: MethodCall, result: MethodResult): void { 54 // 接受Dart侧发来的消息 55 let method: string = call.method; 56 let link1: SubscribedAbstractProperty<number> = AppStorage.link('numValue'); 57 switch (method) { 58 case 'getMessageFromFlutterView': 59 let value: ESObject = call.args; 60 this.numValue = value; 61 link1.set(value) 62 console.log("nodeController receive message from dart: " + this.numValue); 63 result.success(true); 64 break; 65 } 66 } 67 68 public sendMessage = () => { 69 console.log("nodeController sendMessage") 70 //向Dart侧发送消息 71 this.methodChannel.invokeMethod('getMessageFromOhosView', 'natvie - ' + this.index++); 72 } 73 74 getView(): WrappedBuilder<[Params]> { 75 return new WrappedBuilder(ButtonBuilder); 76 } 77 78 dispose(): void { 79 } 80}
cat src/main/entryablity/EntryAbility.ets
1import { FlutterAbility, FlutterEngine } from '@ohos/flutter_ohos'; 2import { GeneratedPluginRegistrant } from '../plugins/GeneratedPluginRegistrant'; 3import { CustomPlugin } from './CustomPlugin'; 4 5export default class EntryAbility extends FlutterAbility { 6 configureFlutterEngine(flutterEngine: FlutterEngine) { 7 super.configureFlutterEngine(flutterEngine) 8 GeneratedPluginRegistrant.registerWith(flutterEngine) 9 this.addPlugin(new CustomPlugin()) 10 } 11} 12
创建 pages
cat src/main/ets/pages/index.ets
1import common from '@ohos.app.ability.common'; 2import { FlutterPage } from '@ohos/flutter_ohos' 3 4let storage = LocalStorage.getShared() 5const EVENT_BACK_PRESS = 'EVENT_BACK_PRESS' 6 7@Entry(storage) 8@Component 9struct Index { 10 private context = getContext(this) as common.UIAbilityContext 11 @LocalStorageLink('viewId') viewId: string = ""; 12 13 build() { 14 Column() { 15 FlutterPage({ viewId: this.viewId }) 16 } 17 } 18 19 onBackPress(): boolean { 20 this.context.eventHub.emit(EVENT_BACK_PRESS) 21 return true 22 } 23}
在src/main/resources/base/profile/main_page.json中配置路由
1{ 2 "src": [ 3 "pages/Index" 4 ] 5}
在 Dart 侧调用该 PlatformView
1Scaffold( 2 appBar: AppBar(title: Text('code')), 3 body: OhosView( 4 viewType: 'com.rex.custom.ohos/customView', 5 // onPlatformViewCreated: _onPlatformViewCreated, 6 creationParams: const <String, dynamic>{'initParams': 'hello world'}, 7 creationParamsCodec: const StandardMessageCodec(), 8)
