【问题标题】:How to render a local HTML file with flutter dart webview如何使用flutter dart webview渲染本地HTML文件
【发布时间】:2019-05-18 18:28:19
【问题描述】:

我想使用 Flutter 和 dart 在 webview 中渲染存储在我手机内存中的本地 HTML 文件。

【问题讨论】:

标签: webview dart flutter flutter-layout


【解决方案1】:

您可以传递数据 URI

Uri.dataFromString('<html><body>hello world</body></html>', mimeType: 'text/html').toString()

或者你可以在 Flutter 中启动一个 Web 服务器,并传递一个指向服务器提供文件的 IP/端口的 URL。

另见https://github.com/fluttercommunity/flutter_webview_plugin/issues/23中的讨论

请参阅https://flutter.io/docs/development/ui/assets-and-images#loading-text-assets,了解如何从资产中加载字符串。

查看https://flutter.io/docs/cookbook/persistence/reading-writing-files了解如何读取其他文件。

【讨论】:

  • encoding: E​​ncoding.getByName('utf-8') 也很有用
【解决方案2】:

我正在使用 Flutter 团队的 webview_flutter 插件。

步骤

  1. 将依赖添加到pubspec.yaml

    dependencies:
      webview_flutter: ^0.3.20+2
    
  2. 将 html 文件放入 assets 文件夹(请参阅 this)。我就叫它help.html

  3. 获取代码中的html字符串并将其添加到webview中。

    import 'dart:convert';
    
    import 'package:flutter/material.dart';
    import 'package:flutter/services.dart';
    import 'package:webview_flutter/webview_flutter.dart';
    
    
    class HelpScreen extends StatefulWidget {
      @override
      HelpScreenState createState() {
        return HelpScreenState();
      }
    }
    
    class HelpScreenState extends State<HelpScreen> {
      WebViewController _controller;
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(title: Text('Help')),
          body: WebView(
            initialUrl: 'about:blank',
            onWebViewCreated: (WebViewController webViewController) {
              _controller = webViewController;
              _loadHtmlFromAssets();
            },
          ),
        );
      }
    
      _loadHtmlFromAssets() async {
        String fileText = await rootBundle.loadString('assets/help.html');
        _controller.loadUrl( Uri.dataFromString(
            fileText,
            mimeType: 'text/html',
            encoding: Encoding.getByName('utf-8')
        ).toString());
      }
    }
    

注意事项:

  • 我需要将编码设置为 UTF-8,因为我遇到了非 ASCII 字符的崩溃。
  • 在 iOS 中,您需要在 Info.plist 文件中将密钥 io.flutter.embedded_views_preview 添加为 true。查看docs 了解有关此要求的任何更新。

另见

【讨论】:

  • @Suragch 如何在 webview 中从 html 访问本地 js 文件?例如:&lt;script type="text/javascript" src="froala_editor.pkgd.min.js"&gt;&lt;/script&gt;
  • 我在加载 .js 文件时遇到问题
  • @ArnoldParge 我看到您正在尝试加载 Froala;我正要尝试同样的事情。你能让这个工作吗?
  • PDF 怎么样?您将如何加载 PDF?
  • @GoodSp33d,你可能想为此使用一个包。我自己没做过。
【解决方案3】:

@Suragch,您的代码在您发布时不起作用,它说localUrlnull 上被调用。 分配控制器后需要调用_loadHtmlFromAssets

onWebViewCreated: (WebViewController webViewController) {
  _controller = webViewController;
  _loadHtmlFromAssets();
}

然后它工作正常:)

【讨论】:

  • 谢谢@Garbor,我相信它现在已经修复了。
【解决方案4】:

解压apk包,找到原因:路径错误;

对于安卓:

"assets/test.html" == "file:///android_asset/flutter_assets/assets/test.html"

所以,就像这样:

WebView(
    initialUrl: "file:///android_asset/flutter_assets/assets/test.html",
    javascriptMode: JavascriptMode.unrestricted,
  )

你可以加载“assets/test.html”。

【讨论】:

  • 多平台 Flutter 的错误解决方案
  • 安卓专用,对我有用
  • 在 android 上工作正常,但在 ios 上?
【解决方案5】:

我也有同样的问题;我就是这样解决的。

  1. 将 webview_flutter 添加到您的项目依赖项中:

    webview_flutter: 0.3.14+1

  2. 在您的屏幕/有状态小部件中创建一个 WebViewController

    WebViewController _controller;

  3. 实现 WebView 并使用 onWebViewCreated 属性为 _controller 分配一个值。加载 HTML 文件。

    WebView(
        initialUrl: '',
        onWebViewCreated: (WebViewController webViewController) async {
          _controller = webViewController;
          await loadHtmlFromAssets('legal/privacy_policy.html', _controller);
        },
      )
  1. 实现从资产文件夹加载文件的功能
    Future<void> loadHtmlFromAssets(String filename, controller) async {
        String fileText = await rootBundle.loadString(filename);
        controller.loadUrl(Uri.dataFromString(fileText, mimeType: 'text/html', encoding: Encoding.getByName('utf-8')).toString());
    }

【讨论】:

  • 谢谢,但它似乎停在这一行 String fileText = await rootBundle.loadString(filename);
  • @68060 你在 pubspec.yaml 中声明了你的资产
【解决方案6】:

你可以使用我的插件flutter_inappwebview,与其他插件相比,它有很多事件、方法和选项!

要从资产文件夹加载 html 文件,您需要在使用前在 pubspec.yaml 文件中声明它(查看更多 here)。

pubspec.yaml 文件示例:

...

# The following section is specific to Flutter.
flutter:

  # The following line ensures that the Material Icons font is
  # included with your application, so that you can use the icons in
  # the material Icons class.
  uses-material-design: true

  assets:
    - assets/index.html

...

之后,您可以简单地使用InAppWebView 小部件的initialFile 参数将index.html 加载到WebView 中:

import 'dart:async';

import 'package:flutter/material.dart';

import 'package:flutter_inappwebview/flutter_inappwebview.dart';

Future main() async {
  runApp(new MyApp());
}

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => new _MyAppState();
}

class _MyAppState extends State<MyApp> {

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

  @override
  void dispose() {
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        home: InAppWebViewPage()
    );
  }
}

class InAppWebViewPage extends StatefulWidget {
  @override
  _InAppWebViewPageState createState() => new _InAppWebViewPageState();
}

class _InAppWebViewPageState extends State<InAppWebViewPage> {
  InAppWebViewController webView;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
            title: Text("InAppWebView")
        ),
        body: Container(
            child: Column(children: <Widget>[
              Expanded(
                child: Container(
                  child: InAppWebView(
                    initialFile: "assets/index.html",
                    initialHeaders: {},
                    initialOptions: InAppWebViewWidgetOptions(
                      inAppWebViewOptions: InAppWebViewOptions(
                        debuggingEnabled: true,
                      ),
                    ),
                    onWebViewCreated: (InAppWebViewController controller) {
                      webView = controller;
                    },
                    onLoadStart: (InAppWebViewController controller, String url) {

                    },
                    onLoadStop: (InAppWebViewController controller, String url) {

                    },
                  ),
                ),
              ),
            ]))
    );
  }
}

【讨论】:

  • 它是否适用于大 (3-5Mb) html 字符串(通过 loadData)?它是否支持这些页面内的内部href链接(Title1)?
【解决方案7】:

您可以使用Flutter InAppWebView Plugin。它将在应用程序内创建一个本地服务器,并在 WebView 中运行 HTML 应用程序。启动你的服务器:

InAppLocalhostServer localhostServer = new InAppLocalhostServer();

Future main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await localhostServer.start();
  runApp(new MyApp());
}

//... ...

class _MyHomePageState extends State < MyHomePage > {

//... ...

  @override
  void dispose() {
    localhostServer.close();
    super.dispose();
  }
}

然后在 WebView 中指向你的 localhost html 索引文件。

InAppWebView(
  initialUrlRequest: URLRequest(
          url: Uri.parse('http://localhost:8080/assets/index.html')),
),

在许多情况下,它对许多人不起作用,因为他们忘记将所有文件夹添加为 pubspec.yaml 文件中的资产。例如,您需要指定所有文件夹和索引文件,如下所示:

  assets:
    - assets/index.html
    - assets/css/
    - assets/images/
    - assets/js/
    - assets/others/

您可以查看this tutorial了解更多详情。

【讨论】:

    【解决方案8】:

    使用flutter_widget_from_html_core---->

    dependencies:
      flutter_widget_from_html_core: ^0.5.1+4
        
    

    这样的代码

    HtmlWidget(
         """
                   <html lang="en">
                    <body>hello world</body>
                   </html>
              """,
        ),
    

    【讨论】:

    • 在我看来这没有答案,因为他提到他想渲染一个本地文件。这个答案中没有任何内容。
    【解决方案9】:

    asset_webview 插件是专门为此设计的。功能比其他插件少,但使用简单。

    【讨论】:

      【解决方案10】:

      您可以获取页面 html 并使用它来加载页面,下面的代码是一个示例

          import 'dart:convert';
      
      import 'package:aws_bot/Utils/Const.dart';
      import 'package:aws_bot/Utils/User.dart';
      import 'package:flutter/material.dart';
      import 'package:flutter_inappwebview/flutter_inappwebview.dart';
      import 'package:flutter_webview_plugin/flutter_webview_plugin.dart';
      import 'package:html/parser.dart';
      
      class signIn extends StatefulWidget {
        const signIn({Key? key}) : super(key: key);
      
        @override
        _signInState createState() => _signInState();
      }
      
      class _signInState extends State<signIn> {
        String userEmail = "";
        String userPassword = "";
        final flutterWebviewPlugin = new FlutterWebviewPlugin();
        bool evalJsOnce = false;
        String _currentUrl = "";
      
        User _user = User();
        bool _loading = true;
        double progress = 0.0;
      
        @override
        void initState() {
          super.initState();
          // Future.delayed(Duration(microseconds: 3), () async {
          //   Map info = await _user.getEmailPassword();
          //   _user.userEmail = info['email'];
          //   _user.userPassword = info['password'];
          //   setState(() {});
          // });
        }
      
        @override
        Widget build(BuildContext context) {
          flutterWebviewPlugin.onProgressChanged.listen((double progress) {
            print("progress changed = $progress");
            if (progress == 1.0) {
              //https://portal.aws.amazon.com/billing/signup
              flutterWebviewPlugin.onUrlChanged.listen((String url) {
                _currentUrl = url;
                print("url changed = $url");
                if (url.contains('https://portal.aws.amazon.com/billing/signup')) {
                  print("signup");
                  flutterWebviewPlugin.evalJavascript(''
                      'document.querySelector("#CredentialCollection").addEventListener("submit", function(e) {window.Mchannel.postMessage(JSON.stringify({"email": document.querySelector("#awsui-input-0").value, "password": document.querySelector("#awsui-input-1").value, "confirmPass": document.querySelector("#awsui-input-2").value, "accountName": document.querySelector("#awsui-input-3").value}));});');
                } else {
                  flutterWebviewPlugin.evalJavascript(''
                      'let pageHtml = document.documentElement.innerHTML;'
                      'window.Emailchannel.postMessage(pageHtml);'
                      'if (pageHtml.includes("Root user email address")) {'
                      'document.querySelector("#next_button").addEventListener("click", function(e) {window.Emailchannel.postMessage(JSON.stringify({"email": document.querySelector("#resolving_input").value}));});}'
                      '');
                }
                // } else if (url.contains(
                //     'https://signin.aws.amazon.com/signin?redirect_uri=https%3A%2F%2Fconsole.aws.amazon.com%2Fconsole%2Fhome%3Ffromtb%3Dtrue%26hashArgs%3D%2523%26isauthcode%3Dtrue%26state%3DhashArgsFromTB_us-east-1_2b2a9061808657b8&client_id=arn%3Aaws%3Asignin%3A%3A%3Aconsole%2Fcanvas&forceMobileApp=0&code_challenge=-HEkj8kWzXDv2qBLcBQX2GYULvcP2gsHr0p0X_fJJcU&code_challenge_method=SHA-256')) {
                //   flutterWebviewPlugin.evalJavascript(''
                //       'document.querySelector("#next_button").addEventListener("click", function(e) {e.preventDefault(); window.Emailchannel.postMessage(JSON.stringify({"email": document.querySelector("#resolving_input").value}));});;');
                // } else if (url.contains(
                //     "https://signin.aws.amazon.com/signin?redirect_uri=https%3A%2F%2Fconsole.aws.amazon.com%2Fconsole%2Fhome%3Ffromtb%3Dtrue%26hashArgs%3D%2523%26isauthcode%3Dtrue%26state%3DhashArgsFromTB_us-east-1_c885b81ed0514ab4&client_id=arn%3Aaws%3Asignin%3A%3A%3Aconsole%2Fcanvas&forceMobileApp=0&code_challenge=_Tqr3pEXTDAqOYjWp0ehE6ToYYSN7OLeyJWBx5HTPVM&code_challenge_method=SHA-256")) {
                //   print("enter pass");
                //   // flutterWebviewPlugin.evalJavascript(''
                //   //     'document.querySelector("#signin_button").addEventListener("click", function(e) {e.preventDefault(); window.Passwordchannel.postMessage(JSON.stringify({"password": document.querySelector("#password").value}));});;');
                // } else if (url.contains("https://console.aws.amazon.com/")) {
                //   // flutterWebviewPlugin.launch(_consts.successDirectUrl +
                //   //     "email=${_user.userEmail}&password=${_user.userPassword}");
                // }
              });
            }
          });
      
          flutterWebviewPlugin.onStateChanged.listen((WebViewStateChanged state) {
            print("state changed = $state");
          });
      
          return Scaffold(
            appBar: AppBar(
              title: Text(
                'AWS Sign In',
                style: TextStyle(color: Colors.black),
              ),
              backgroundColor: Colors.yellow[600],
            ),
            floatingActionButton: _backButton(context),
            body: Column(
              children: [
                (progress != 1.0)
                    ? LinearProgressIndicator(
                        // minHeight: 10.0,
                        value: progress,
                        backgroundColor: Colors.redAccent,
                        valueColor: AlwaysStoppedAnimation<Color>(Colors.black))
                    : Container(),
                Container(
                    color: Colors.yellow[600],
                    width: double.infinity,
                    padding: EdgeInsets.all(8.0),
                    child: Column(
                      mainAxisAlignment: MainAxisAlignment.start,
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: [
                        Text(
                          "Email Address of you AWS : ${consts.user.userEmail}",
                          style: TextStyle(
                            fontWeight: FontWeight.w600,
                          ),
                        ),
                        SizedBox(
                          height: 4.0,
                        ),
                        Text(
                          "IAM user name : ${consts.user.accountName}",
                          style: TextStyle(
                            fontWeight: FontWeight.w600,
                          ),
                        ),
                        SizedBox(
                          height: 4.0,
                        ),
                        Text(
                          "Password : ${consts.user.userPassword != "null" && consts.user.userPassword != "" ? consts.user.userPassword.replaceAll(consts.user.userPassword, "******") : ""}",
                          style: TextStyle(
                            fontWeight: FontWeight.w600,
                          ),
                        ),
                      ],
                    )),
                Expanded(child: _buildSignInPage()),
              ],
            ),
          );
        }
      
        _buildSignInPage() {
          String _url = "https://console.aws.amazon.com/iam/home#/users";
          return InAppWebView(
            initialUrlRequest: URLRequest(url: Uri.parse(_url)),
            // javascriptChannels: Set.from([
            //   JavascriptChannel(
            //       name: 'Emailchannel',
            //       onMessageReceived: (JavascriptMessage message) {
            //         //This is where you receive message from
            //         //javascript code and handle in Flutter/Dart
            //         //like here, the message is just being printed
            //         //in Run/LogCat window of android studio
            //         print("console message = ${message.message}");
            //         setState(() {
            //           _user.userEmail =
            //               jsonDecode(message.message)['email'].toString();
            //         });
            //       }),
            //   JavascriptChannel(
            //       name: 'Passwordchannel',
            //       onMessageReceived: (JavascriptMessage message) {
            //         //This is where you receive message from
            //         //javascript code and handle in Flutter/Dart
            //         //like here, the message is just being printed
            //         //in Run/LogCat window of android studio
            //         print("console message = ${jsonDecode(message.message)}");
            //         setState(() {
            //           _user.userEmail =
            //               jsonDecode(message.message)['password'].toString();
            //         });
            //       })
            // ]),
            // withJavascript: true,
            onConsoleMessage: (controller, consoleMessage) async {
              print("console message = ${consoleMessage.message}");
              print(consoleMessage.messageLevel.toString());
              // LOG ERROR => message levels
              if (consoleMessage.messageLevel.toString() != "ERROR" &&
                  consoleMessage.messageLevel.toString() != "WARNING") {
                Map message = jsonDecode(consoleMessage.message);
                if (message.containsKey("email")) {
                  consts.user.userEmail = message['email'].toString();
                  await consts.user.storeSignUpInfo(email: consts.user.userEmail);
                } else if (message.containsKey("password")) {
                  consts.user.userPassword = message['password'].toString();
                  await consts.user
                      .storeSignUpInfo(password: consts.user.userPassword);
                } else if (message.containsKey("delete")) {
                  Future.delayed(Duration.zero, () async {
                    await consts.user.clearStorage();
                    consts.user.userEmail = "";
                    consts.user.userPassword = "";
                  });
                } else if (message.containsKey("sEmail")) {
                  consts.user.userEmail = message['sEmail'].toString();
                  await consts.user.storeSignUpInfo(email: consts.user.userEmail);
                } else if (message.containsKey("sPassword")) {
                  consts.user.userPassword = message["sPassword"].toString();
                  await consts.user
                      .storeSignUpInfo(password: consts.user.userPassword);
                } else if (message.containsKey("sAccountName")) {
                  consts.user.accountName = message["sAccountName"].toString();
                  await consts.user
                      .storeSignUpInfo(accountName: consts.user.accountName);
                } else if (message.containsKey("sFullName")) {
                  consts.user.fullName = message["sFullName"].toString();
                  await consts.user.storeSignUpInfo(fullName: consts.user.fullName);
                } else if (message.containsKey("sPhone")) {
                  consts.user.phoneNumber = message["sPhone"].toString();
                  await consts.user
                      .storeSignUpInfo(phoneNumber: consts.user.phoneNumber);
                } else if (message.containsKey("sRegion")) {
                  consts.user.region = message["sRegion"].toString();
                  await consts.user.storeSignUpInfo(region: consts.user.region);
                } else if (message.containsKey("sAddress")) {
                  consts.user.address = message["sAddress"].toString();
                  await consts.user.storeSignUpInfo(address: consts.user.address);
                } else if (message.containsKey("sCity")) {
                  consts.user.city = message["sCity"].toString();
                  await consts.user.storeSignUpInfo(city: consts.user.city);
                } else if (message.containsKey("sState")) {
                  consts.user.state = message["sState"].toString();
                  await consts.user.storeSignUpInfo(state: consts.user.state);
                } else if (message.containsKey("sPostal")) {
                  consts.user.postalCode = message["sPostal"].toString();
                  await consts.user
                      .storeSignUpInfo(postalCode: consts.user.postalCode);
                } else if (message.containsKey("sOrganize")) {
                  consts.user.oraganization = message["sOrganize"].toString();
                  await consts.user
                      .storeSignUpInfo(organization: consts.user.oraganization);
                }
      
                setState(() {
                  if (consts.user.userPassword != "" &&
                      !message.containsKey("delete")) {
                    /*Future.delayed(Duration.zero, () async {
                      await consts.user.storeEmailAndPassword(
                          consts.user.userEmail, consts.user.userPassword);
                      // controller.loadUrl(
                      //     urlRequest: URLRequest(
                      //         url: Uri.parse(_consts.successDirectUrl +
                      //             "email=${_user.userEmail}&password=${_user.userPassword}")));
                    });*/
                  }
                });
              }
            },
            onWindowFocus: (controller) async {
              var currentUrl = await controller.getUrl();
              final html = await controller.getHtml();
              var document = parse(html);
              if (currentUrl != _currentUrl) {
                Future.delayed(Duration.zero, () async {
                  var htmlCode = await controller.getHtml();
                  var document = parse(htmlCode);
                  var currentUrl = await controller.getUrl();
                  print("currentUrl = ${currentUrl}");
                  if (document.body!.innerHtml.contains("username@example.com")) {
                    print("get email");
                    await consts.user.clearStorage();
      
                    // get entered email address
                    getUserEmail(controller, document.body!.innerHtml);
                  } else if (document.body!.innerHtml.contains("Root user sign in")) {
                    print("get pass");
                    // get entered password
                    getUserPassword(controller, document.body!.innerHtml);
                  } else if (currentUrl
                      .toString()
                      .contains("https://portal.aws.amazon.com/billing/signup")) {
                    if (document.body!.innerHtml.contains("AWS account name")) {
                      print("sign up");
                      // get signUp email
                      getSignUpEmail(controller);
                      // get signUp password
                      getSignUpPassword(controller);
                      // get signUp account name
                      getSignUpAccountName(controller);
                    } else if (document.body!.innerHtml
                        .contains("Contact Information")) {
                      // get full name
                      getSignUpFullname(controller);
                      // get phone number
                      getSignUpPhoneNumber(controller);
                      // get region
                      getSignUpRegion(controller);
                      // get address
                      getSignUpAddress(controller);
                      // get city
                      getSignUpCity(controller);
                      // get state
                      getSignUpState(controller);
                      // get postal code
                      getSignUpPostalCode(controller);
                      // get organization
                      getSignUpOrganization(controller);
                    }
                  }
                });
              }
              _currentUrl = currentUrl.toString();
              //controller.goBack();
            },
            onProgressChanged:
                (InAppWebViewController controller, int progress) async {
              setState(() {
                this.progress = progress / 100;
                print("progress = ${this.progress}");
              });
              if (progress == 100) {
                var currentUrl = await controller.getUrl();
      
                Future.delayed(Duration(microseconds: 3), () async {
                  var htmlCode = await controller.getHtml();
                  var document = parse(htmlCode);
      
                  print("currentUrl progress = ${currentUrl.toString()}");
                  //print("html = ${document.body!.innerHtml}");
                  if (document.body!.innerHtml
                      .contains("Email address of your AWS account")) {
                    print("get email");
                    await consts.user.clearStorage();
                    consts.user.userEmail = "";
                    consts.user.userPassword = "";
                    controller.evaluateJavascript(source: """
                         document.querySelector("#new_account_container").style.display = "none";
                  """);
                    setState(() {});
      
                    // get entered email address
                    getUserEmail(controller, document.body!.innerHtml);
                  } else if (document.body!.innerHtml.contains("Root user sign in")) {
                    print("get pass");
                    // get entered password
                    getUserPassword(controller, document.body!.innerHtml);
                  } else if (currentUrl
                      .toString()
                      .contains("https://portal.aws.amazon.com/billing/signup#/")) {
                    if (document.body!.innerHtml.contains("AWS account name")) {
                      print("sign up progress");
                      // get signUp email
                      getSignUpEmail(controller);
                      // get signUp password
                      getSignUpPassword(controller);
                      // get signUp account name
                      getSignUpAccountName(controller);
                    } else if (document.body!.innerHtml
                        .contains("Contact Information")) {
                      // get full name
                      getSignUpFullname(controller);
                      // get phone number
                      getSignUpPhoneNumber(controller);
                      // get region
                      getSignUpRegion(controller);
                      // get address
                      getSignUpAddress(controller);
                      // get city
                      getSignUpCity(controller);
                      // get state
                      getSignUpState(controller);
                      // get postal code
                      getSignUpPostalCode(controller);
                      // get organization
                      getSignUpOrganization(controller);
                    }
                  }
                  if (currentUrl.toString() ==
                          "https://console.aws.amazon.com/iam/home#/users" ||
                      currentUrl.toString() ==
                          "https://console.aws.amazon.com/iam/home?#/users") {
                    print("delete credentials");
                    // delete user data if loged out
                    deleteCredentials(controller);
                  }
                });
              }
            },
          );
        }
      
        // get user amil
        getUserEmail(InAppWebViewController controller, String html) {
          controller.addJavaScriptHandler(
              handlerName: 'EmailGetter',
              callback: (args) {
                // print arguments coming from the JavaScript side!
                print("email args = $args");
                // return data to the JavaScript side!
                return args;
              });
          controller.evaluateJavascript(source: """
                  document.querySelector("#next_button").addEventListener("click", function(ee) {
                  window.console.log(JSON.stringify({"email": document.querySelector("#resolving_input").value}));});
                  """);
        }
      
        // getting password
        getUserPassword(InAppWebViewController controller, String html) {
          controller.evaluateJavascript(source: """
                  document.querySelector("#signin_button").addEventListener("click", function(ee) {
                  window.console.log(JSON.stringify({"password": document.querySelector("#password").value}));});
                  """);
        }
      
        // getting SignUp Email address
        getSignUpEmail(InAppWebViewController controller) {
          controller.evaluateJavascript(source: """
                  document.querySelector("#CredentialCollection").addEventListener("submit", function(ee) {
                  window.console.log(JSON.stringify({"sEmail": document.querySelector("input[name='email']").value}));});
                  """);
        }
      
        // getting SignUp password
        getSignUpPassword(InAppWebViewController controller) {
          controller.evaluateJavascript(source: """
                  document.querySelector("#CredentialCollection").addEventListener("submit", function(ee) {
                  window.console.log(JSON.stringify({"sPassword": document.querySelector("input[name='password']").value}));});
                  """);
        }
      
        // getting SignUp account name
        getSignUpAccountName(InAppWebViewController controller) {
          controller.evaluateJavascript(source: """
                  document.querySelector("#CredentialCollection").addEventListener("submit", function(ee) {
                  window.console.log(JSON.stringify({"sAccountName": document.querySelector("input[name='accountName']").value}));});
                  """);
        }
      
        // getting SignUp fullName
        getSignUpFullname(InAppWebViewController controller) {
          controller.evaluateJavascript(source: """
                  document.querySelector("#ContactInformation").addEventListener("submit", function(ee) {
                  window.console.log(JSON.stringify({"sFullName": document.querySelector("input[name='address.fullName']").value}));});
                  """);
        }
      
        // getting SignUp phone number
        getSignUpPhoneNumber(InAppWebViewController controller) {
          controller.evaluateJavascript(source: """
                  document.querySelector("#ContactInformation").addEventListener("submit", function(ee) {
                  window.console.log(JSON.stringify({"sPhone": document.querySelector("input[name='address.phoneNumber']").value}));});
                  """);
        }
      
        // getting SignUp region
        getSignUpRegion(InAppWebViewController controller) {
          controller.evaluateJavascript(source: """
                  document.querySelector("#ContactInformation").addEventListener("submit", function(ee) {
                  window.console.log(JSON.stringify({"sRegion": document.querySelectorAll(".awsui-select-trigger-label")[1].innerText}));});
                  """);
        }
      
        // getting SignUp address
        getSignUpAddress(InAppWebViewController controller) {
          controller.evaluateJavascript(source: """
                  document.querySelector("#ContactInformation").addEventListener("submit", function(ee) {
                  window.console.log(JSON.stringify({"sAddress": document.querySelectorAll("input[name='address.addressLine1']").value}));});
                  """);
        }
      
        // getting SignUp city
        getSignUpCity(InAppWebViewController controller) {
          controller.evaluateJavascript(source: """
                  document.querySelector("#ContactInformation").addEventListener("submit", function(ee) {
                  window.console.log(JSON.stringify({"sCity": document.querySelectorAll("input[name='address.city']").value}));});
                  """);
        }
      
        // getting SignUp state
        getSignUpState(InAppWebViewController controller) {
          controller.evaluateJavascript(source: """
                  document.querySelector("#ContactInformation").addEventListener("submit", function(ee) {
                  window.console.log(JSON.stringify({"sState": document.querySelectorAll("input[name='address.state']").value}));});
                  """);
        }
      
        // getting SignUp postal code
        getSignUpPostalCode(controller) {
          controller.evaluateJavascript(source: """
                  document.querySelector("#ContactInformation").addEventListener("submit", function(ee) {
                  window.console.log(JSON.stringify({"sPostal": document.querySelectorAll("input[name='address.postalCode']").value}));});
                  """);
        }
      
        // getting SignUp organization
        getSignUpOrganization(InAppWebViewController controller) {
          controller.evaluateJavascript(source: """
                  document.querySelector("#ContactInformation").addEventListener("submit", function(ee) {
                  window.console.log(JSON.stringify({"sOrganize": document.querySelectorAll("input[name='address.company']").value}));});
                  """);
        }
      
        // deleting user credentials
        deleteCredentials(InAppWebViewController controller) {
          controller.evaluateJavascript(source: """
                  document.querySelector("#aws-console-logout").addEventListener("click", function(ee) {
                  window.console.log(JSON.stringify({"delete": "delete"}));});
                  """);
        }
      
        _backButton(BuildContext context) {
          return ElevatedButton(
            onPressed: () {
              Navigator.pop(context);
            },
            child: Icon(Icons.arrow_back),
          );
        }
      }
      

      【讨论】:

      • 您应该删除 cmets 并可能将您的代码拆分为更多逻辑块
      【解决方案11】:

      这是上面代码的更简洁的代码

      import 'dart:convert';
      
      import 'package:aws_bot/Utils/Const.dart';
      import 'package:aws_bot/Utils/User.dart';
      import 'package:flutter/material.dart';
      import 'package:flutter_inappwebview/flutter_inappwebview.dart';
      import 'package:flutter_webview_plugin/flutter_webview_plugin.dart';
      import 'package:html/parser.dart';
      
      class signIn extends StatefulWidget {
        const signIn({Key? key}) : super(key: key);
      
        @override
        _signInState createState() => _signInState();
      }
      
      class _signInState extends State<signIn> {
        String userEmail = "";
        String userPassword = "";
        final flutterWebviewPlugin = new FlutterWebviewPlugin();
        bool evalJsOnce = false;
        String _currentUrl = "";
      
        User _user = User();
        bool _loading = true;
        double progress = 0.0;
      
        @override
        void initState() {
          super.initState();
          
        }
      
        @override
        Widget build(BuildContext context) {
          flutterWebviewPlugin.onProgressChanged.listen((double progress) {
            print("progress changed = $progress");
            if (progress == 1.0) {
              //https://portal.aws.amazon.com/billing/signup
              flutterWebviewPlugin.onUrlChanged.listen((String url) {
                _currentUrl = url;
                print("url changed = $url");
                if (url.contains('https://portal.aws.amazon.com/billing/signup')) {
                  print("signup");
                  flutterWebviewPlugin.evalJavascript(''
                      'document.querySelector("#CredentialCollection").addEventListener("submit", function(e) {window.Mchannel.postMessage(JSON.stringify({"email": document.querySelector("#awsui-input-0").value, "password": document.querySelector("#awsui-input-1").value, "confirmPass": document.querySelector("#awsui-input-2").value, "accountName": document.querySelector("#awsui-input-3").value}));});');
                } else {
                  flutterWebviewPlugin.evalJavascript(''
                      'let pageHtml = document.documentElement.innerHTML;'
                      'window.Emailchannel.postMessage(pageHtml);'
                      'if (pageHtml.includes("Root user email address")) {'
                      'document.querySelector("#next_button").addEventListener("click", function(e) {window.Emailchannel.postMessage(JSON.stringify({"email": document.querySelector("#resolving_input").value}));});}'
                      '');
                }
                redirect_uri=https%3A%2F%2Fconsole.aws.amazon.com%2Fconsole%2Fhome%3Ffromtb%3Dtrue%26hashArgs%3D%2523%26isauthcode%3Dtrue%26state%3DhashArgsFromTB_us-east-1_2b2a9061808657b8&client_id=arn%3Aaws%3Asignin%3A%3A%3Aconsole%2Fcanvas&forceMobileApp=0&code_challenge=-HEkj8kWzXDv2qBLcBQX2GYULvcP2gsHr0p0X_fJJcU&code_challenge_method=SHA-256')) {  'document.querySelector("#next_button").addEventListener("click", function(e) {e.preventDefault(); window.Emailchannel.postMessage(JSON.stringify({"email": document.querySelector("#resolving_input").value}));});;');redirect_uri=https%3A%2F%2Fconsole.aws.amazon.com%2Fconsole%2Fhome%3Ffromtb%3Dtrue%26hashArgs%3D%2523%26isauthcode%3Dtrue%26state%3DhashArgsFromTB_us-east-1_c885b81ed0514ab4&client_id=arn%3Aaws%3Asignin%3A%3A%3Aconsole%2Fcanvas&forceMobileApp=0&code_challenge=_Tqr3pEXTDAqOYjWp0ehE6ToYYSN7OLeyJWBx5HTPVM&code_challenge_method=SHA-256")) {   'document.querySelector("#signin_button").addEventListener("click", function(e) {e.preventDefault(); window.Passwordchannel.postMessage(JSON.stringify({"password": document.querySelector("#password").value}));});;');
              });
            }
          });
      
          flutterWebviewPlugin.onStateChanged.listen((WebViewStateChanged state) {
            print("state changed = $state");
          });
      
          return Scaffold(
            appBar: AppBar(
              title: Text(
                'AWS Sign In',
                style: TextStyle(color: Colors.black),
              ),
              backgroundColor: Colors.yellow[600],
            ),
            floatingActionButton: _backButton(context),
            body: Column(
              children: [
                (progress != 1.0)
                    ? LinearProgressIndicator(
                        // minHeight: 10.0,
                        value: progress,
                        backgroundColor: Colors.redAccent,
                        valueColor: AlwaysStoppedAnimation<Color>(Colors.black))
                    : Container(),
                Container(
                    color: Colors.yellow[600],
                    width: double.infinity,
                    padding: EdgeInsets.all(8.0),
                    child: Column(
                      mainAxisAlignment: MainAxisAlignment.start,
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: [
                        Text(
                          "Email Address of you AWS : ${consts.user.userEmail}",
                          style: TextStyle(
                            fontWeight: FontWeight.w600,
                          ),
                        ),
                        SizedBox(
                          height: 4.0,
                        ),
                        Text(
                          "IAM user name : ${consts.user.accountName}",
                          style: TextStyle(
                            fontWeight: FontWeight.w600,
                          ),
                        ),
                        SizedBox(
                          height: 4.0,
                        ),
                        Text(
                          "Password : ${consts.user.userPassword != "null" && consts.user.userPassword != "" ? consts.user.userPassword.replaceAll(consts.user.userPassword, "******") : ""}",
                          style: TextStyle(
                            fontWeight: FontWeight.w600,
                          ),
                        ),
                      ],
                    )),
                Expanded(child: _buildSignInPage()),
              ],
            ),
          );
        }
      
        _buildSignInPage() {
          String _url = "https://console.aws.amazon.com/iam/home#/users";
          return InAppWebView(
            initialUrlRequest: URLRequest(url: Uri.parse(_url)),
            onConsoleMessage: (controller, consoleMessage) async {
              print("console message = ${consoleMessage.message}");
              print(consoleMessage.messageLevel.toString());
              // LOG ERROR => message levels
              if (consoleMessage.messageLevel.toString() != "ERROR" &&
                  consoleMessage.messageLevel.toString() != "WARNING") {
                Map message = jsonDecode(consoleMessage.message);
                if (message.containsKey("email")) {
                  consts.user.userEmail = message['email'].toString();
                  await consts.user.storeSignUpInfo(email: consts.user.userEmail);
                } else if (message.containsKey("password")) {
                  consts.user.userPassword = message['password'].toString();
                  await consts.user
                      .storeSignUpInfo(password: consts.user.userPassword);
                } else if (message.containsKey("delete")) {
                  Future.delayed(Duration.zero, () async {
                    await consts.user.clearStorage();
                    consts.user.userEmail = "";
                    consts.user.userPassword = "";
                  });
                } else if (message.containsKey("sEmail")) {
                  consts.user.userEmail = message['sEmail'].toString();
                  await consts.user.storeSignUpInfo(email: consts.user.userEmail);
                } else if (message.containsKey("sPassword")) {
                  consts.user.userPassword = message["sPassword"].toString();
                  await consts.user
                      .storeSignUpInfo(password: consts.user.userPassword);
                } else if (message.containsKey("sAccountName")) {
                  consts.user.accountName = message["sAccountName"].toString();
                  await consts.user
                      .storeSignUpInfo(accountName: consts.user.accountName);
                } else if (message.containsKey("sFullName")) {
                  consts.user.fullName = message["sFullName"].toString();
                  await consts.user.storeSignUpInfo(fullName: consts.user.fullName);
                } else if (message.containsKey("sPhone")) {
                  consts.user.phoneNumber = message["sPhone"].toString();
                  await consts.user
                      .storeSignUpInfo(phoneNumber: consts.user.phoneNumber);
                } else if (message.containsKey("sRegion")) {
                  consts.user.region = message["sRegion"].toString();
                  await consts.user.storeSignUpInfo(region: consts.user.region);
                } else if (message.containsKey("sAddress")) {
                  consts.user.address = message["sAddress"].toString();
                  await consts.user.storeSignUpInfo(address: consts.user.address);
                } else if (message.containsKey("sCity")) {
                  consts.user.city = message["sCity"].toString();
                  await consts.user.storeSignUpInfo(city: consts.user.city);
                } else if (message.containsKey("sState")) {
                  consts.user.state = message["sState"].toString();
                  await consts.user.storeSignUpInfo(state: consts.user.state);
                } else if (message.containsKey("sPostal")) {
                  consts.user.postalCode = message["sPostal"].toString();
                  await consts.user
                      .storeSignUpInfo(postalCode: consts.user.postalCode);
                } else if (message.containsKey("sOrganize")) {
                  consts.user.oraganization = message["sOrganize"].toString();
                  await consts.user
                      .storeSignUpInfo(organization: consts.user.oraganization);
                }
      
                setState(() {
                  if (consts.user.userPassword != "" &&
                      !message.containsKey("delete")) {
                  }
                });
              }
            },
            onWindowFocus: (controller) async {
              var currentUrl = await controller.getUrl();
              final html = await controller.getHtml();
              var document = parse(html);
              if (currentUrl != _currentUrl) {
                Future.delayed(Duration.zero, () async {
                  var htmlCode = await controller.getHtml();
                  var document = parse(htmlCode);
                  var currentUrl = await controller.getUrl();
                  print("currentUrl = ${currentUrl}");
                  if (document.body!.innerHtml.contains("username@example.com")) {
                    print("get email");
                    await consts.user.clearStorage();
      
                    // get entered email address
                    getUserEmail(controller, document.body!.innerHtml);
                  } else if (document.body!.innerHtml.contains("Root user sign in")) {
                    print("get pass");
                    // get entered password
                    getUserPassword(controller, document.body!.innerHtml);
                  } else if (currentUrl
                      .toString()
                      .contains("https://portal.aws.amazon.com/billing/signup")) {
                    if (document.body!.innerHtml.contains("AWS account name")) {
                      print("sign up");
                      // get signUp email
                      getSignUpEmail(controller);
                      // get signUp password
                      getSignUpPassword(controller);
                      // get signUp account name
                      getSignUpAccountName(controller);
                    } else if (document.body!.innerHtml
                        .contains("Contact Information")) {
                      // get full name
                      getSignUpFullname(controller);
                      // get phone number
                      getSignUpPhoneNumber(controller);
                      // get region
                      getSignUpRegion(controller);
                      // get address
                      getSignUpAddress(controller);
                      // get city
                      getSignUpCity(controller);
                      // get state
                      getSignUpState(controller);
                      // get postal code
                      getSignUpPostalCode(controller);
                      // get organization
                      getSignUpOrganization(controller);
                    }
                  }
                });
              }
              _currentUrl = currentUrl.toString();
              //controller.goBack();
            },
            onProgressChanged:
                (InAppWebViewController controller, int progress) async {
              setState(() {
                this.progress = progress / 100;
                print("progress = ${this.progress}");
              });
              if (progress == 100) {
                var currentUrl = await controller.getUrl();
      
                Future.delayed(Duration(microseconds: 3), () async {
                  var htmlCode = await controller.getHtml();
                  var document = parse(htmlCode);
      
                  print("currentUrl progress = ${currentUrl.toString()}");
                  //print("html = ${document.body!.innerHtml}");
                  if (document.body!.innerHtml
                      .contains("Email address of your AWS account")) {
                    print("get email");
                    await consts.user.clearStorage();
                    consts.user.userEmail = "";
                    consts.user.userPassword = "";
                    controller.evaluateJavascript(source: """
                         document.querySelector("#new_account_container").style.display = "none";
                  """);
                    setState(() {});
      
                    // get entered email address
                    getUserEmail(controller, document.body!.innerHtml);
                  } else if (document.body!.innerHtml.contains("Root user sign in")) {
                    print("get pass");
                    // get entered password
                    getUserPassword(controller, document.body!.innerHtml);
                  } else if (currentUrl
                      .toString()
                      .contains("https://portal.aws.amazon.com/billing/signup#/")) {
                    if (document.body!.innerHtml.contains("AWS account name")) {
                      print("sign up progress");
                      // get signUp email
                      getSignUpEmail(controller);
                      // get signUp password
                      getSignUpPassword(controller);
                      // get signUp account name
                      getSignUpAccountName(controller);
                    } else if (document.body!.innerHtml
                        .contains("Contact Information")) {
                      // get full name
                      getSignUpFullname(controller);
                      // get phone number
                      getSignUpPhoneNumber(controller);
                      // get region
                      getSignUpRegion(controller);
                      // get address
                      getSignUpAddress(controller);
                      // get city
                      getSignUpCity(controller);
                      // get state
                      getSignUpState(controller);
                      // get postal code
                      getSignUpPostalCode(controller);
                      // get organization
                      getSignUpOrganization(controller);
                    }
                  }
                  if (currentUrl.toString() ==
                          "https://console.aws.amazon.com/iam/home#/users" ||
                      currentUrl.toString() ==
                          "https://console.aws.amazon.com/iam/home?#/users") {
                    print("delete credentials");
                    // delete user data if loged out
                    deleteCredentials(controller);
                  }
                });
              }
            },
          );
        }
      
        // get user amil
        getUserEmail(InAppWebViewController controller, String html) {
          controller.addJavaScriptHandler(
              handlerName: 'EmailGetter',
              callback: (args) {
                // print arguments coming from the JavaScript side!
                print("email args = $args");
                // return data to the JavaScript side!
                return args;
              });
          controller.evaluateJavascript(source: """
                  document.querySelector("#next_button").addEventListener("click", function(ee) {
                  window.console.log(JSON.stringify({"email": document.querySelector("#resolving_input").value}));});
                  """);
        }
      
        // getting password
        getUserPassword(InAppWebViewController controller, String html) {
          controller.evaluateJavascript(source: """
                  document.querySelector("#signin_button").addEventListener("click", function(ee) {
                  window.console.log(JSON.stringify({"password": document.querySelector("#password").value}));});
                  """);
        }
      
        // getting SignUp Email address
        getSignUpEmail(InAppWebViewController controller) {
          controller.evaluateJavascript(source: """
                  document.querySelector("#CredentialCollection").addEventListener("submit", function(ee) {
                  window.console.log(JSON.stringify({"sEmail": document.querySelector("input[name='email']").value}));});
                  """);
        }
      
        // getting SignUp password
        getSignUpPassword(InAppWebViewController controller) {
          controller.evaluateJavascript(source: """
                  document.querySelector("#CredentialCollection").addEventListener("submit", function(ee) {
                  window.console.log(JSON.stringify({"sPassword": document.querySelector("input[name='password']").value}));});
                  """);
        }
      
        // getting SignUp account name
        getSignUpAccountName(InAppWebViewController controller) {
          controller.evaluateJavascript(source: """
                  document.querySelector("#CredentialCollection").addEventListener("submit", function(ee) {
                  window.console.log(JSON.stringify({"sAccountName": document.querySelector("input[name='accountName']").value}));});
                  """);
        }
      
        // getting SignUp fullName
        getSignUpFullname(InAppWebViewController controller) {
          controller.evaluateJavascript(source: """
                  document.querySelector("#ContactInformation").addEventListener("submit", function(ee) {
                  window.console.log(JSON.stringify({"sFullName": document.querySelector("input[name='address.fullName']").value}));});
                  """);
        }
      
        // getting SignUp phone number
        getSignUpPhoneNumber(InAppWebViewController controller) {
          controller.evaluateJavascript(source: """
                  document.querySelector("#ContactInformation").addEventListener("submit", function(ee) {
                  window.console.log(JSON.stringify({"sPhone": document.querySelector("input[name='address.phoneNumber']").value}));});
                  """);
        }
      
        // getting SignUp region
        getSignUpRegion(InAppWebViewController controller) {
          controller.evaluateJavascript(source: """
                  document.querySelector("#ContactInformation").addEventListener("submit", function(ee) {
                  window.console.log(JSON.stringify({"sRegion": document.querySelectorAll(".awsui-select-trigger-label")[1].innerText}));});
                  """);
        }
      
        // getting SignUp address
        getSignUpAddress(InAppWebViewController controller) {
          controller.evaluateJavascript(source: """
                  document.querySelector("#ContactInformation").addEventListener("submit", function(ee) {
                  window.console.log(JSON.stringify({"sAddress": document.querySelectorAll("input[name='address.addressLine1']").value}));});
                  """);
        }
      
        // getting SignUp city
        getSignUpCity(InAppWebViewController controller) {
          controller.evaluateJavascript(source: """
                  document.querySelector("#ContactInformation").addEventListener("submit", function(ee) {
                  window.console.log(JSON.stringify({"sCity": document.querySelectorAll("input[name='address.city']").value}));});
                  """);
        }
      
        // getting SignUp state
        getSignUpState(InAppWebViewController controller) {
          controller.evaluateJavascript(source: """
                  document.querySelector("#ContactInformation").addEventListener("submit", function(ee) {
                  window.console.log(JSON.stringify({"sState": document.querySelectorAll("input[name='address.state']").value}));});
                  """);
        }
      
        // getting SignUp postal code
        getSignUpPostalCode(controller) {
          controller.evaluateJavascript(source: """
                  document.querySelector("#ContactInformation").addEventListener("submit", function(ee) {
                  window.console.log(JSON.stringify({"sPostal": document.querySelectorAll("input[name='address.postalCode']").value}));});
                  """);
        }
      
        // getting SignUp organization
        getSignUpOrganization(InAppWebViewController controller) {
          controller.evaluateJavascript(source: """
                  document.querySelector("#ContactInformation").addEventListener("submit", function(ee) {
                  window.console.log(JSON.stringify({"sOrganize": document.querySelectorAll("input[name='address.company']").value}));});
                  """);
        }
      
        // deleting user credentials
        deleteCredentials(InAppWebViewController controller) {
          controller.evaluateJavascript(source: """
                  document.querySelector("#aws-console-logout").addEventListener("click", function(ee) {
                  window.console.log(JSON.stringify({"delete": "delete"}));});
                  """);
        }
      
        _backButton(BuildContext context) {
          return ElevatedButton(
            onPressed: () {
              Navigator.pop(context);
            },
            child: Icon(Icons.arrow_back),
          );
        }
      }
      

      在此代码中,您还可以看到如何使用 javascript dom 操作和选择以及与网页的交互。

      【讨论】:

        猜你喜欢
        • 2019-10-04
        • 2020-12-10
        • 1970-01-01
        • 2020-10-14
        • 2019-05-11
        • 2019-04-08
        • 2020-01-23
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多