1. 插件介绍

webview_flutter 是一个功能强大的 Flutter 插件,提供了 WebView 小部件,允许开发者在 Flutter 应用中嵌入网页内容。该插件支持多种平台,包括 iOS、Android、Web 和鸿蒙(API 12+)。

核心功能

  • 在 Flutter 应用中无缝嵌入网页内容
  • 支持网络资源、本地文件和 Flutter 资源加载
  • 提供完整的网页导航控制(前进、后退、刷新)
  • 支持 JavaScript 执行和双向通信
  • 提供网页加载进度监听和导航决策控制
  • 支持自定义用户代理、背景颜色和缩放控制

鸿蒙平台支持

在鸿蒙平台上,webview_flutter 插件基于鸿蒙的 WebView API(API 12+)实现,提供与其他平台一致的功能体验。支持鸿蒙 API 12 及以上版本。

2. 依赖引入

由于这是一个针对鸿蒙平台的自定义修改版本,需要通过 git 形式引入依赖。

配置步骤

  1. 在项目的 pubspec.yaml 文件中,添加以下依赖配置:
dependencies:
  webview_flutter:
    git:
      url: "https://gitcode.com/openharmony-tpc/flutter_packages.git"
      path: "packages/webview_flutter"
  1. 执行以下命令获取依赖:
flutter pub get

3. 鸿蒙平台特殊配置

3.1 权限配置

  1. 添加网络权限:在 entry/src/main/module.json5 文件中添加网络权限声明:
"requestPermissions": [
  {
    "name": "ohos.permission.INTERNET",
    "reason": "$string:network_reason",
    "usedScene": {
      "abilities": ["EntryAbility"],
      "when": "inuse"
    }
  }
]
  1. 添加权限描述:在 entry/src/main/resources/base/element/string.json 文件中添加权限描述:
{
  "string": [
    {
      "name": "network_reason",
      "value": "使用网络访问网页内容"
    }
  ]
}

3.2 应用级别配置

由于 WebView 可能需要系统级权限,需要将应用级别设置为 system_basic,否则在安装 HAP 包时可能会报错。具体配置方法请参考华为官方文档。

4. API 调用与使用示例

4.1 创建 WebViewController

WebViewController 是控制 WebView 行为的核心类,用于加载内容、控制导航和执行 JavaScript 等操作。

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

class WebViewExample extends StatefulWidget {
  const WebViewExample({Key? key}) : super(key: key);

  
  State<WebViewExample> createState() => _WebViewExampleState();
}

class _WebViewExampleState extends State<WebViewExample> {
  late final WebViewController _controller;

  
  void initState() {
    super.initState();
    
    // 创建 WebViewController
    _controller = WebViewController()
      ..setJavaScriptMode(JavaScriptMode.unrestricted) // 启用 JavaScript
      ..setBackgroundColor(const Color(0x00000000)) // 设置透明背景
      ..setNavigationDelegate( // 设置导航委托
        NavigationDelegate(
          onProgress: (int progress) {
            // 更新加载进度
            debugPrint('WebView is loading (progress : $progress%)');
          },
          onPageStarted: (String url) {
            debugPrint('Page started loading: $url');
          },
          onPageFinished: (String url) {
            debugPrint('Page finished loading: $url');
          },
          onWebResourceError: (WebResourceError error) {
            debugPrint('\n\n====\nError: $error\n====\n\n');
          },
          onNavigationRequest: (NavigationRequest request) {
            // 控制导航决策
            if (request.url.startsWith('https://www.youtube.com/')) {
              debugPrint('blocking navigation to ${request.url}');
              return NavigationDecision.prevent;
            }
            debugPrint('allowing navigation to ${request.url}');
            return NavigationDecision.navigate;
          },
        ),
      )
      ..loadRequest(Uri.parse('https://flutter.dev')); // 加载初始 URL
  }

  // ...
}

4.2 创建 WebViewWidget

WebViewWidget 用于在 Flutter 界面中显示 WebView 内容,需要传入之前创建的 WebViewController。


Widget build(BuildContext context) {
  return Scaffold(
    appBar: AppBar(
      title: const Text('Flutter WebView 示例'),
      // 添加导航控制按钮
      actions: [
        NavigationControls(_controller),
      ],
    ),
    body: WebViewWidget(controller: _controller), // 显示 WebView
  );
}

4.3 实现导航控制

class NavigationControls extends StatelessWidget {
  const NavigationControls(this._webViewController, {Key? key}) : super(key: key);

  final WebViewController _webViewController;

  
  Widget build(BuildContext context) {
    return Row(
      children: <Widget>[
        IconButton(
          icon: const Icon(Icons.arrow_back_ios),
          onPressed: () async {
            if (await _webViewController.canGoBack()) {
              await _webViewController.goBack();
            } else {
              if (context.mounted) {
                ScaffoldMessenger.of(context).showSnackBar(
                  const SnackBar(content: Text('No back history item')),
                );
              }
            }
          },
        ),
        IconButton(
          icon: const Icon(Icons.arrow_forward_ios),
          onPressed: () async {
            if (await _webViewController.canGoForward()) {
              await _webViewController.goForward();
            } else {
              if (context.mounted) {
                ScaffoldMessenger.of(context).showSnackBar(
                  const SnackBar(content: Text('No forward history item')),
                );
              }
            }
          },
        ),
        IconButton(
          icon: const Icon(Icons.replay),
          onPressed: () => _webViewController.reload(),
        ),
      ],
    );
  }
}

4.4 执行 JavaScript

// 执行 JavaScript 代码
_controller.runJavaScript('alert("Hello from Flutter!");');

// 执行 JavaScript 代码并获取返回结果
final result = await _controller.runJavaScriptReturningResult(
  'document.body.innerText.length'
);
debugPrint('Body text length: $result');

4.5 监听 JavaScript 消息

// 添加 JavaScript 通道
_controller.addJavaScriptChannel(
  'Toaster',
  onMessageReceived: (JavaScriptMessage message) {
    ScaffoldMessenger.of(context).showSnackBar(
      SnackBar(content: Text(message.message)),
    );
  },
);

// 在网页中发送消息到 Flutter
// window.Toaster.postMessage('Hello from JavaScript!');

4.6 加载不同类型的内容

// 加载网络资源
_controller.loadRequest(Uri.parse('https://flutter.dev'));

// 加载本地文件
_controller.loadFile('/path/to/local/file.html');

// 加载 Flutter 资源
_controller.loadFlutterAsset('assets/html/index.html');

// 加载 HTML 字符串
_controller.loadHtmlString('''
<html>
<body>
  <h1>Hello, World!</h1>
  <p>This is HTML content loaded from a string.</p>
</body>
</html>
''', baseUrl: Uri.parse('https://example.com'));

5. 注意事项

5.1 权限配置

确保正确配置网络权限,否则 WebView 将无法加载网络资源。同时,注意应用级别的设置,避免安装时出现权限错误。

5.2 鸿蒙平台兼容性

  • 支持鸿蒙 API 12 及以上版本
  • 要求 Flutter 版本:3.7.12-ohos-1.1.1 及以上
  • 要求鸿蒙 SDK 版本:5.0.0(12) 及以上

5.3 性能优化

  • 避免在 WebView 中加载过于复杂的网页内容
  • 合理使用 JavaScript 通道,避免频繁的双向通信
  • 在不需要时及时释放 WebView 资源

5.4 安全性考虑

  • 谨慎处理来自网页的 JavaScript 消息
  • 对加载的网页内容进行适当的安全验证
  • 考虑使用内容安全策略 (CSP) 保护应用

6. 总结

webview_flutter 是一个功能强大的 Flutter 插件,为开发者提供了在 Flutter 应用中嵌入网页内容的能力。在鸿蒙平台上,该插件提供了与其他平台一致的功能体验,支持网络资源加载、JavaScript 执行、导航控制等核心功能。

使用该插件的关键步骤包括:

  1. 通过 git 形式引入自定义修改版本的依赖
  2. 配置网络权限和应用级别
  3. 创建 WebViewController 并配置导航委托
  4. 使用 WebViewWidget 在界面中显示 WebView
  5. 实现导航控制和 JavaScript 交互

webview_flutter 插件为鸿蒙平台上的 Flutter 应用提供了强大的网页嵌入能力,使开发者能够轻松构建混合内容应用,结合原生应用的性能优势和网页内容的灵活性。

无论是构建需要嵌入外部网页的应用,还是需要实现复杂网页交互的功能,webview_flutter 都是鸿蒙平台上 Flutter 开发者的理想选择。

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐