Flutter for OpenHarmony 中 webview_flutter 适配实战指南

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net
摘要
本文基于真实项目实践,完整介绍了在 Flutter for OpenHarmony(以下简称 FOH)工程中,如何集成 webview_flutter 实现网页加载、JS 交互、Cookie 同步等核心能力,并针对鸿蒙平台的权限、兼容性问题给出了适配方案,附完整代码与验证截图,帮助开发者快速实现跨平台 WebView 功能落地。
一、背景与目标
在跨平台应用开发中,WebView 是实现混合开发、H5 页面嵌入、第三方服务对接的核心组件。但在 OpenHarmony 生态中,第三方 WebView 库的适配程度、权限配置、JS 通信机制都存在特殊的兼容性问题。本文以 webview_flutter 为核心,结合 OpenHarmony 平台特性,完成了以下目标:
实现网页加载、前进 / 后退 / 刷新等基础浏览器能力
支持 JS 注入与双向通信,适配鸿蒙 ArkWeb 内核交互机制
完成 Cookie 同步处理,保障登录态与数据一致性
兼容 OpenHarmony 权限配置,解决网络访问阻断问题
提供可直接运行的代码模板与验证流程
二、依赖配置与工程准备
2.1 pubspec.yaml 依赖添加
首先在 pubspec.yaml 中声明所需依赖,确保版本与当前 Flutter/OpenHarmony SDK 适配:

dependencies:
  flutter:
    sdk: flutter
  webview_flutter: ^4.13.0          # 核心WebView库,需确认鸿蒙插件适配版本
  webview_cookie_manager: ^2.0.6    # Cookie同步管理工具

执行依赖拉取命令,验证依赖兼容性:

flutter pub get

说明:webview_flutter 的鸿蒙适配依赖于 OpenHarmony TPC 社区的插件分支,若拉取失败需检查当前 SDK 版本与插件分支的匹配关系。
2.2 OpenHarmony 权限配置
在 ohos/entry/src/main/module.json5 中添加网络权限,否则会出现网页加载失败问题:

{
  "module": {
    "requestPermissions": [
      {
        "name": "ohos.permission.INTERNET",
        "reason": "$string:permission_internet_reason",
        "usedScene": {
          "abilities": ["./EntryAbility"],
          "when": "inuse"
        }
      }
    ]
  }
}

关键提醒:OpenHarmony 权限为运行时动态权限,需在代码中同步申请网络权限,避免高版本系统的权限拦截。
三、核心功能实现与鸿蒙适配
3.1 WebView 基础页面搭建
在 lib/main.dart 中创建 WebView 容器页面,封装基础控制逻辑:

import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
import 'package:webview_cookie_manager/webview_cookie_manager.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'FOH WebView Demo',
      theme: ThemeData(primarySwatch: Colors.blue),
      home: const WebViewPage(),
    );
  }
}

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

  @override
  State<WebViewPage> createState() => _WebViewPageState();
}

class _WebViewPageState extends State<WebViewPage> {
  late final WebViewController _controller;
  final WebviewCookieManager _cookieManager = WebviewCookieManager();
  String? _pageTitle;
  String? _currentUrl;

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

  Future<void> _initWebView() async {
    _controller = WebViewController()
      ..setJavaScriptMode(JavaScriptMode.unrestricted)
      ..setBackgroundColor(const Color(0x00000000))
      ..setNavigationDelegate(
        NavigationDelegate(
          onPageStarted: (String url) {
            setState(() => _currentUrl = url);
          },
          onPageFinished: (String url) async {
            // 读取页面标题
            final title = await _controller.getTitle();
            setState(() => _pageTitle = title);
            // 同步Cookie到鸿蒙侧
            await _syncCookiesToNative(url);
          },
          onWebResourceError: (WebResourceError error) {
            debugPrint('WebView加载错误: ${error.description}');
          },
        ),
      )
      ..loadRequest(Uri.parse('https://openharmonycrossplatform.csdn.net'));
  }

  // Cookie同步处理
  Future<void> _syncCookiesToNative(String url) async {
    final cookies = await _cookieManager.getCookies(url);
    // 鸿蒙侧Cookie存储需适配ArkWeb的CookieManager API
    debugPrint('同步Cookie数量: ${cookies.length}');
  }

  // JS注入示例:调用H5方法并接收回传结果
  Future<void> _injectJavaScript() async {
    const jsCode = """
      (function() {
        return document.title;
      })();
    """;
    final result = await _controller.runJavaScriptReturningResult(jsCode);
    debugPrint('JS执行结果: $result');
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(_pageTitle ?? '加载中...'),
        actions: [
          IconButton(
            icon: const Icon(Icons.arrow_back),
            onPressed: () async {
              if (await _controller.canGoBack()) {
                await _controller.goBack();
              }
            },
          ),
          IconButton(
            icon: const Icon(Icons.arrow_forward),
            onPressed: () async {
              if (await _controller.canGoForward()) {
                await _controller.goForward();
              }
            },
          ),
          IconButton(
            icon: const Icon(Icons.refresh),
            onPressed: () => _controller.reload(),
          ),
        ],
      ),
      body: WebViewWidget(controller: _controller),
    );
  }
}

3.2.2 Cookie 同步问题
鸿蒙 ArkWeb 的 Cookie 存储机制与 Android/iOS 存在差异,需通过 webview_cookie_manager 封装统一接口,避免直接调用平台原生 API,减少平台差异带来的适配成本。
3.2.3 网络权限动态申请
高版本 OpenHarmony 系统中,仅声明权限不足以访问网络,需在代码中动态申请:

// 需引入ohos相关权限申请库,此处为简化示例
Future<void> _requestNetworkPermission() async {
  // 调用鸿蒙权限申请API,确认ohos.permission.INTERNET已授权
}

四、构建验证与运行结果
4.1 构建验证
执行 OpenHarmony HAP 构建命令,验证代码无阻断性错误:

hvigor assembleHap

构建结果:仅存在 SDK 兼容性警告,无错误日志,构建成功。
4.2 设备运行验证
在 OpenHarmony 设备上安装 HAP 包,验证以下核心能力:
网页加载正常,无白屏 / 加载失败问题
前进、后退、刷新功能响应正常
JS 注入可正确获取页面标题,回传结果无异常
Cookie 同步日志正常,H5 登录态可正常保持
页面标题与 URL 实时更新,与预期一致
五、扩展与替代方案
若当前 webview_flutter 鸿蒙适配存在兼容性问题,可采用以下备选方案:
平台切换实现:通过 defaultTargetPlatform 区分平台,鸿蒙侧使用 flutter_inappwebview 或自定义 ArkWeb 插件
混合开发模式:使用 Flutter Web 页面嵌套在鸿蒙原生 WebView 中,快速实现基础页面展示
原生插件封装:直接封装 ArkWeb 原生 API,通过 Platform Channel 与 Flutter 侧通信,完全适配鸿蒙平台特性
在这里插入图片描述

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐