美文网首页Android
Flutter 在Windows上使用内嵌WebView

Flutter 在Windows上使用内嵌WebView

作者: 咸鱼本鱼丶 | 来源:发表于2022-08-06 17:58 被阅读0次

    一、问题背景

    对于Flutter的App开发来说,在一些场景下,我们需要用到内嵌的WebView来加载一些H5网页资源等。

    在移动平台Android和IOS中,官方已经有插件来实现相关功能,webview_flutter,支持移动平台的内嵌WebView功能,使用简单,也可以通过源码导入的方式实现自定义功能。

    在Flutter 3.0后,开始全面支持桌面平台,MacOS,Windows等。

    我们的摸鱼kik App,作为资讯订阅类应用,在PC上也有很强的用户需求,所有需要开发桌面平台版本。

    Window版本的摸鱼kik,当然也需要有相应的WebView插件来实现资讯内容的浏览功能。

    下面主要来介绍一下在Windows平台上的内嵌WebView如何使用。
    本文章暂时只介绍一个基本的插件使用和打包方式,之后会再通过源码层面介绍插件的具体情况,以及如何使用微软的fixed version版本,将网页内嵌到自己的源码中。

    二、了解WebView2 Runtime

    要使用WebView,我们需要先了解一下Windows平台上的WebView环境。

    Microsoft Edge WebView2 是Windows平台的WebView内核。

    控件允许在本机应用中嵌入 web 技术(HTML、CSS 以及 JavaScript)。 WebView2 控件使用 Microsoft Edge 作为绘制引擎,以在本机应用中显示 web 内容。
    使用 WebView2 可以在本机应用的不同部分嵌入 Web 代码,或在单个 WebView2 实例中生成所有本机应用。

    三、插件接入

    对于移动平台Android和IOS来说,WebView插件包括两个部分,即Android和IOS原生部分代码实现,以及Dart语言实现的Flutter调用层。

    对于Windows平台,原理也是一样的,即Windows API与C++实现的原生部分,以及Dart语言实现的Flutter调用层。

    想要深度自定义的开发者,可以参考WebView2Samples,这是微软在Github上提供的Webview2库的相关代码与演示Demo。之后再自己实现Flutter层的MethodChannel调用即可。

    仅想要使用WebView功能,不需要深度自定义,可以使用开发好的Flutter插件,webview_windows

    四、 Webview_windows介绍

    使用webview_windows进行开发,需要

    • Visual Studio 2019+版本
    • Window10 SDK
    • nuget.exe

    运行包含WebView2的软件,需要电脑上安装以下环境

    • WebView2 Runtime

    运行时环境后面会说明,如何保障没有安装WebView2 Runtime的电脑运行软件时可以正常使用。

    其中前两项是需要安装在开发设备上的环境,nuget.exe需要我们放到工程根目录下。nuget下载路径,下载最左侧的exe文件即可。

    环境配置好后,在项目配置中增加

    dependencies:
      webview_windows: ^0.2.0
    

    之后执行flutter pub get即可。

    基本使用示例:

    late WebviewController _controller;
    
      @override
      void initState() {
        super.initState();
        _controller = WebviewController();
        initPlatformState();
      }
    
      @override
      Widget build(BuildContext context) {
        return Webview(_controller);
      }
    
      Future<void> initPlatformState() async {
        // Optionally initialize the webview environment using
        // a custom user data directory
        // and/or a custom browser executable directory
        // and/or custom chromium command line flags
        //await WebviewController.initializeEnvironment(
        //    additionalArguments: '--show-fps-counter');
    
        try {
          await _controller.initialize();
          await _controller.setBackgroundColor(Colors.white);
          await _controller.setPopupWindowPolicy(WebviewPopupWindowPolicy.deny);
          await _controller.loadUrl(url);
    
          if (!mounted) return;
          setState(() {});
        } catch(e) {
    
        }
      }
    

    至此,WebView已经可以在Windows上正常使用了。

    这里以我目前开发的阅读App摸鱼Kik举例,目前支持Android与IOS,PC端过段时间即将上线,也欢迎下载体验

    加载一个微博页面的效果大致如下,效果和电脑中的浏览器体验基本一致:

    Windows上网页展示

    五、WebView2 Runtime环境预安装

    由于我们使用了WebView2,它只能在安装了WebView2 Runtime的电脑上运行,所以我们在对Windows软件进行打包时候,需要配置好安装环境。让用户在安装过程中无感知地装入WebView2 Runtime。

    这里还是以摸鱼Kik举例,介绍一下Flutter的Windows平台项目如何进行打包和预安装环境的配置。

    Visual Studio配置

    1.找到SLN文件

    SLN:解决方案文件。解决方案是用于在 Visual Studio 中组织项目的结构。

    1.png

    2.安装插件 installer project

    在扩展-管理扩展中安装Microsoft Visual Studio Installer Project

    插件本身体积不大,但可能涉及网络环境问题(墙)

    2.png

    3.为工程创建setup project

    3.png

    在弹出菜单中搜索Setup Project

    4.png

    在Setup Project创建完成后,会自动打开其配置窗口

    5.png

    这里面包含3个项目

    • Application Folder
    • User's Desktop
    • User's Programs Menu

    Application Folder配置

    Application Folder中存放项目所需要的所有文件

    其中包括

    • 资源文件
    • 动态链接库
    • 项目执行文件

    Visual Studio在打包时候将这些文件一并放到安装包中,在安装时候解压出来

    首先为Application Folder添加项目输出

    6.png

    先将自己项目作为主输出,添加到Application Folder中

    7.png

    在添加成功后,可以在右侧看到我们的项目输出。其中包括Visual Studio自动添加的一些环境依赖的动态链接库

    如MSVCP140.dll等等,是启动所需要的环境。(这里建议直接去系统C盘/Windows/System32下,将不带D的DLL文件拖进来。比如VCRUNTIME140_1.dll,VCRUNTIME140.dll。图中带D后缀的为Debug版本)

    8.png

    然后我们添加资源文件

    Flutter的资源文件位置为:\工程目录\build\windows\runner\Debug(Release)

    将其整体导入到Application Folder中,并保持层级不变

    导入成功后结构如图所示:

    9.png

    之后再为项目添加额外的依赖,如Flutter插件所需要的动态链接库,这些文件要根据插件的需求进行添加

    比如Flutter的数据库需要依赖sqlite3.dll

    如果项目中有插件依赖一些额外的动态链接库,就需要手动添加进来。

    在添加完成所有需要的资源后,初步完成Application Folder的配置

    预安装环境配置

    由于项目可能依赖一些额外的启动环境,如.net framework,WebView2Runtime等,我们需要将这些安装文件导入到我们的项目中,并在安装软件时候,通过引导程序为用户安装这些环境。

    引导程序会先检测系统是否有所需要的运行环境,如果没有,则先安装环境,再安装软件。

    整个过程对于用户来说是没有明显感知的,只需要一直进行下一步即可。

    打开我们所创建的 Setup Project的属性,在此处打开Prerequisites配置。

    10.png

    Prerequisites包含所支持的环境,这里面有3个选项

    11.png
    • 从组件供应商的网站上下载系统必备组件
    • 从与我的应用程序相同的位置下载系统必备组件
    • 从下列位置下载系统必备组件

    其中第一和第三个选项都是从网络上下载,区别在于是从官方网站还是自己所配置的服务器上下载。

    第二个选项是我们来提供安装包,一同打包到安装包中,在安装开始时候,引导程序如果发现环境不满足运行,先来安装我们提供的这些文件,再去安装软件。

    如何配置预安装包

    Visual Studio会从以下位置查找环境安装包

    C:\Program Files (x86)\Microsoft SDKs\ClickOnce Bootstrapper\Packages

    其中每个环境对于的子文件夹路径不一样,如.net framework对应DoNetFX,后面的数字表示版本号,如472代表4.7.2

    12.png

    打开任意需要的环境路径,这里以DotNetFX472举例。初始状态如下

    13.png

    每个文件夹对应一种语言。

    这个语言是引导程序在安装时候为用户展示的界面

    其中zh-Hans是简体中文

    我们需要为打包提供2个安装包,程序安装包和语言包

    每个语言路径下有Eula和Package两个文件

    Eula:微软软件补充程序许可条款

    Package:是对引导程序的翻译,并指明了我们需要在哪里下载语言包

    搜索fwlink即可找到:

    http://go.microsoft.com/fwlink/?LinkId=863262&clcid=0x804

    <?xml version="1.0" encoding="UTF-8"?>
    
    -<Package LicenseAgreement="eula.rtf" Culture="Culture" Name="DisplayName" xmlns="http://schemas.microsoft.com/developer/2004/01/bootstrapper">
    
    <!-- Defines list of files to be copied on build -->
    
    -<PackageFiles CopyAllPackageFiles="false">
    
    <PackageFile Name="eula.rtf"/>
    
    <PackageFile Name="NDP472-KB4054530-x86-x64-AllOS-CHS.exe" PublicKey="3082010a0282010100b6bb19591000a3a9f1e4b85ca80b07cbdb9a1f23d0d958ab78c048f7241438f063edd54b03bfcdf809ca1450f327b3fe82b4fa1a4384e1cbf91b38e83fcc9027ac97a2310a917b62ec75bfcd488da05d75fd95a775ff23d40ce5e8e063703e35ead49662f87655f756d4afa663cde3e3d60f9b7a9b2a77f1c2d5749c8f47d3dda0312d1ca4252cc4c4406653d792cae3b052eabe0ab8ae750b5618c74953ae74bff2a6cdf338e98ea5a3f3029e7a6fcf7cc42fb3cc754770aa3fe7621186dd45482f15fbb4074c6f3ecb37ee96388a53d40e35af06a83959effbc51af781f0863666bb54bbdf2795ed1659371a2111e8098bd618b2c5daed465452408203e2a70203010001" HomeSite="DotNetFX472FullLanguagePackBootstrapper"/>
    
    </PackageFiles>
    
    -<InstallChecks>
    
    <RegistryCheck Value="Release" Key="HKLM\Software\Microsoft\NET Framework Setup\NDP\v4\Full\2052" Property="DotNetFullLangPack_Release"/>
    
    <RegistryCheck Value="LCID" Key="HKLM\SYSTEM\CurrentControlSet\Control\MUI\UILanguages\zh-CN" Property="DotNetFullLangPack_OS_LCID"/>
    
    <RegistryCheck Value="v4" Key="HKLM\SOFTWARE\Microsoft\NET Framework Setup\OS Integration" Property="DotNetFullLangPack_OSIntegrated"/>
    
    </InstallChecks>
    
    <!-- Defines how to invoke the setup for .NET Framework redist -->
    
    -<Commands>
    
    -<Command EstimatedInstallSeconds="90" EstimatedTempBytes="77473415" EstimatedInstalledBytes="130718421" Arguments=" /q /norestart /skipenucheck /ChainingPackage FullX64ClickOnce" PackageFile="NDP472-KB4054530-x86-x64-AllOS-CHS.exe">
    
    <!-- These checks determine whether the package is to be installed in the cases where .NET is not integrated into the OS (MSI install)-->
    
    -<InstallConditions>
    
    <!-- This indicates .NET Framework is already installed -->
    
    <BypassIf Value="461808" Property="DotNetFullLangPack_Release" Compare="ValueGreaterThanOrEqualTo"/>
    
    <!-- If netfx is part of the OS, then bypass this command. -->
    
    <BypassIf Value="1" Property="DotNetFullLangPack_OSIntegrated" Compare="ValueEqualTo"/>
    
    <!-- Block install if user does not have admin privileges -->
    
    <FailIf Value="false" Property="AdminUser" Compare="ValueEqualTo" String="AdminRequired"/>
    
    <!-- Block install on less than Windows 7 RTM -->
    
    <FailIf Value="6.1.0" Property="VersionNT" Compare="VersionLessThan" String="InvalidPlatformWinNT"/>
    
    <!-- Block install if the platform is IA-64 -->
    
    <FailIf Value="IA64" Property="ProcessorArchitecture" Compare="ValueEqualTo" String="InvalidPlatformArchitecture"/>
    
    </InstallConditions>
    
    -<ExitCodes>
    
    <ExitCode Value="0" Result="Success"/>
    
    <ExitCode Value="3010" Result="SuccessReboot"/>
    
    <DefaultExitCode String="GeneralFailure" Result="Success" FormatMessageFromSystem="false"/>
    
    </ExitCodes>
    
    </Command>
    
    -<Command EstimatedInstallSeconds="90" EstimatedTempBytes="77473415" EstimatedInstalledBytes="130718421" Arguments=" /q /norestart /skipenucheck /ChainingPackage FullX64ClickOnce" PackageFile="NDP472-KB4054530-x86-x64-AllOS-CHS.exe">
    
    <!-- These checks determine whether the package is to be installed in the cases where .NET is integrated into the OS -->
    
    -<InstallConditions>
    
    <!-- This indicates .NET Framework is already installed -->
    
    <BypassIf Value="461808" Property="DotNetFullLangPack_Release" Compare="ValueGreaterThanOrEqualTo"/>
    
    <!-- If netfx is not part of the OS, then bypass this command. -->
    
    <BypassIf Value="1" Property="DotNetFullLangPack_OSIntegrated" Compare="ValueNotEqualTo"/>
    
    <BypassIf Value="1" Property="DotNetFullLangPack_OSIntegrated" Compare="ValueNotExists"/>
    
    <!-- Do not attempt to install on OS where NetFx is integrated in OS and MUI LCID doesn't match with this package. -->
    
    <BypassIf Value="2052" Property="DotNetFullLangPack_OS_LCID" Compare="ValueNotEqualTo"/>
    
    <!-- Block install if user does not have admin privileges -->
    
    <FailIf Value="false" Property="AdminUser" Compare="ValueEqualTo" String="AdminRequired"/>
    
    <!-- Block install on OS less than Windows 8.0 -->
    
    <FailIf Value="6.2.0" Property="VersionNT" Compare="VersionLessThan" String="InvalidPlatformWinNT"/>
    
    <!-- Block install if the platform is IA-64 -->
    
    <FailIf Value="IA64" Property="ProcessorArchitecture" Compare="ValueEqualTo" String="InvalidPlatformArchitecture"/>
    
    </InstallConditions>
    
    -<ExitCodes>
    
    <ExitCode Value="0" Result="Success"/>
    
    <ExitCode Value="3010" Result="SuccessReboot"/>
    
    <DefaultExitCode String="GeneralFailure" Result="Success" FormatMessageFromSystem="false"/>
    
    </ExitCodes>
    
    </Command>
    
    </Commands>
    
    <!-- Defines a localizable string table for error messages-->
    
    -<Strings>
    
    <String Name="DisplayName">Microsoft .NET Framework 4.7.2 (x86 和 x64)</String>
    
    <String Name="Culture">zh-Hans</String>
    
    <String Name="AdminRequired">安装 Microsoft .NET Framework 4.7.2 需要管理员权限。请与管理员联系。</String>
    
    <String Name="InvalidPlatformWinNT">在此操作系统上不支持安装 Microsoft .NET Framework 4.7.2。请与应用程序供应商联系。</String>
    
    <String Name="InvalidPlatformArchitecture">在 IA-64 操作系统上不支持该版本的 Microsoft .NET Framework 4.7.2。请与应用供应商联系。</String>
    
    <String Name="DotNetFX472FullWebBootstrapper">http://go.microsoft.com/fwlink/?LinkId=863262&clcid=0x804</String>
    
    <String Name="DotNetFX472FullLanguagePackBootstrapper">http://go.microsoft.com/fwlink/?LinkId=863258&clcid=0x804</String>
    
    <String Name="GeneralFailure">尝试安装 Microsoft .NET Framework 4.7.2 时出现故障。</String>
    
    </Strings>
    
    </Package>
    
    

    配置Edge WebView Runtime环境

    对于Flutter Windows上的Webview,使用了微软的WebView2 Runtime环境

    在我们打包时候,需要添加这个环境的依赖,并且和其他环境一样提供安装程序。

    目前这个环境需要我们手动添加配置:

    1.在C:\Program Files (x86)\Microsoft SDKs\ClickOnce Bootstrapper\Package*路径下创建WebViewRuntime*

    路径如下:

    C:\Program Files (x86)\Microsoft SDKs\ClickOnce Bootstrapper\Packages\WebViewRuntime

    2.将Webview2的安装包放在此路径下面

    安装包下载:WebView2 - Microsoft Edge Developer

    • Evergreen Bootstrapper,这是一个下载+安装的包,打开后会自动下载最小的runtime包安装
    • Evergreen Standalone Installer,这是完整的离线安装包
    • Fixed Version,这是一个固定版本的,可以内嵌到软件内部的压缩包。你可以在软件里嵌入Webview2,这样可以独立于系统中的Webview2存在,软件会使用你自己的Webview2 Runtime,但是会增加安装包的体积。

    建议使用Evergreen Bootstrapper

    3.配置Product、Package、Eula

    仅有安装包并不能直接使用,需要使用配套的引导文件

    Product文件:

    <?xml version="1.0" encoding="utf-8" ?>
    <!--
    ***********************************************************************
    
      Copyright (C) Microsoft Corporation.  All rights reserved.
    
     THIS CODE AND INFORMATION ARE PROVIDED AS IS WITHOUT WARRANTY OF ANY
     KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
     IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
     PARTICULAR PURPOSE.
    ***********************************************************************
    -->
    
    <Product 
      xmlns="http://schemas.microsoft.com/developer/2004/01/bootstrapper" 
      ProductCode="Microsoft.EdgeRuntime">
    
      <!-- Defines the list of files to be copied on build. -->
      <PackageFiles CopyAllPackageFiles="false">
        <PackageFile Name="MicrosoftEdgeWebview2Setup.exe" HomeSite="WebViewRuntime" PublicKey="0"/>
      </PackageFiles>
    
      <InstallChecks>
        <RegistryCheck Property="EdgeRuntimeVersionInstalled" Key="HKLM\SOFTWARE\Microsoft\EdgeUpdate\Clients\{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}" Value="pv"/>
      </InstallChecks>
    
      <!-- Defines how to run the Setup package. -->
      <Commands Reboot="Defer">
        <Command 
          PackageFile="MicrosoftEdgeWebview2Setup.exe" 
          Arguments=" /silent /installelevated /install" 
          EstimatedInstalledBytes="2600000" 
          EstimatedTempBytes="4500000"
          EstimatedInstallSeconds="60">
          <InstallConditions>
            <BypassIf Property="EdgeRuntimeVersionInstalled" Compare="VersionGreaterThanOrEqualTo" Value="86.0.622.15"/>
          </InstallConditions>
          <ExitCodes>
            <ExitCode Value="0" Result="Success"/>
            <DefaultExitCode Result="Fail" FormatMessageFromSystem="true" String="GeneralFailure" />
          </ExitCodes>
        </Command>
      </Commands>
    </Product>
    
    

    Package文件:

    <?xml version="1.0" encoding="utf-8" ?>
    <!--
    ***********************************************************************
    
      Copyright (C) Microsoft Corporation.  All rights reserved.
    
     THIS CODE AND INFORMATION ARE PROVIDED AS IS WITHOUT WARRANTY OF ANY
     KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
     IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
     PARTICULAR PURPOSE.
    ***********************************************************************
    -->
    
    <Package 
      xmlns="http://schemas.microsoft.com/developer/2004/01/bootstrapper"
      Name="DisplayName"
      Culture="Culture"
      LicenseAgreement="placeholdereula.txt">
      <PackageFiles>
        <PackageFile Name="placeholdereula.txt"/>
      </PackageFiles>
    
      <!-- Defines a localizable string table for messages. -->
      <Strings>
        <String Name="DisplayName">Edge WebView runtime bootstrapper</String>
        <String Name="Culture">en</String>
        <String Name="AdminRequired">Administrator permissions are required to install the Microsoft Edge WebView runtime. Contact your administrator.</String>
        <String Name="GeneralFailure">A failure occurred attempting to install the Microsoft Edge WebView runtime.</String>
        <String Name="WebViewRuntime">http://go.microsoft.com/fwlink/p/?LinkId=2124703</String>
      </Strings>
    </Package>
    

    Eula文件:

    Eula文件是一个纯文本文件,里面包含协议的内容等。由Package文件引用。

    配置完成后即可重新生成 Setup Project。成功后即可生成安装文件。


    打包完成效果

    相关文章

      网友评论

        本文标题:Flutter 在Windows上使用内嵌WebView

        本文链接:https://www.haomeiwen.com/subject/pqrvwrtx.html