Как отрендерить локальный HTML-файл с помощью Flutter Dart WebView

Я хочу визуализировать локальный HTML-файл, хранящийся в памяти моего телефона, в веб-просмотре с помощью флаттера и дротика.

вы можете использовать этот stackoverflow.com/a/64875729/7760245

Rasel Khan 21.01.2021 11:45
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
38
1
61 002
11

Ответы 11

Вы можете передать URI данных

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

или вы можете запустить веб-сервер внутри Flutter и передать URL-адрес, указывающий на IP / порт, с которого сервер обслуживает файл.

См. Также обсуждение в 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.getByName ('utf-8') также будет полезна

K.Amanov 07.06.2021 11:34

Я использую плагин webview_flutter от Flutter Team.

Шаги

  1. Добавьте зависимость к pubspec.yaml:

    dependencies:
      webview_flutter: ^0.3.20+2
    
  2. Поместите html-файл в папку assets (см. это). Я назову его help.html.

  3. Получите строку html в коде и добавьте ее в веб-просмотр.

    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 нужно добавить ключ io.flutter.embedded_views_preview как true в файл Info.plist. Проверьте документы на наличие обновлений по этому требованию.

Смотрите также

@Suragch Как мне получить доступ к локальному файлу js из html в веб-просмотре? например: <script type = "text/javascript" src = "froala_editor.pkgd.min.js"></script>

Arnold Parge 03.01.2020 12:31

Я столкнулся с проблемой при загрузке файла .js

Sanjay Kumar 22.08.2020 07:57

@ArnoldParge Я видел, что вы пытаетесь загрузить Froala; Я собираюсь попробовать то же самое. Удалось ли вам заставить это работать?

jdixon04 15.12.2020 00:00

А как насчет PDF? Как бы вы загрузили PDF-файл?

GoodSp33d 19.06.2021 19:09

@ GoodSp33d, Вы, наверное, захотите использовать для этого пакет. Я сам этого не делал.

Suragch 21.06.2021 01:45
<script type = "text/javascript" src = "myjs.js"></script> не работает
Prashant 26.06.2021 20:26

Можем ли мы использовать этот webview_flutter для загрузки локального файла HTML в браузере Windows Chrome?

Abhishek Vishwakarma 21.09.2021 10:08

@Suragch, ваш код не работает в том виде, в котором вы его разместили, в нем говорится, что localUrl был вызван на null. _loadHtmlFromAssets нужно вызвать после назначения контроллера:

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

Тогда нормально работает :)

Спасибо, @Garbor, я считаю, что теперь это исправлено.

Suragch 25.05.2020 01:53

разархивируйте пакет apk, я нашел причину: неверный путь;

Для Android:

"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

AlexeyVMP 29.08.2019 13:39

Просто для Android , Мне пригодится

缘去皆空 03.09.2019 03:55

У меня точно такая же проблема; вот как я это решил.

  1. Добавьте webview_flutter в зависимости вашего проекта:

    webview_flutter: 0.3.14+1

  2. Создайте WebViewController внутри вашего экрана / виджета с отслеживанием состояния

    WebViewController _controller;

  3. Реализуйте WebView и присвойте значение _controller, используя свойство onWebViewCreated. Загрузите файл 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 16.11.2021 04:52

@ 68060 вы декларировали свои активы в pubspec.yaml

ILYAS_Kerbal 16.11.2021 10:29

Вы можете использовать мой плагин flutter_inappwebview, который имеет множество событий, методов и опций по сравнению с другими плагинами!

Чтобы загрузить html-файл из папки с ресурсами, вам необходимо объявить его в файле pubspec.yaml перед его использованием (см. Подробнее здесь).

Пример файла 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

...

После этого вы можете просто использовать параметр initialFile виджета InAppWebView для загрузки 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-5 МБ) строками HTML (через loadData)? Поддерживает ли он внутренние href-ссылки (<a href = "#title-page1"> Title1 </a>) внутри этих страниц?

iBog 18.05.2020 12:29

Вы можете использовать Плагин Flutter InAppWebView. Он создаст локальный сервер внутри приложения и запустит HTML-приложение в WebView. Запустите свой сервер:

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();
  }
}

А затем укажите свой индексный файл localhost html в WebView.

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/

Вы можете увидеть этот учебник для получения дополнительной информации.

Используйте flutter_widget_from_html_core ---->

dependencies:
  flutter_widget_from_html_core: ^0.5.1+4
    

Код вроде этого

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

На мой взгляд, это не ответ, поскольку он упомянул, что хочет отобразить локальный файл. В этом ответе ничего об этом нет.

Iván Yoed 23.09.2021 17:31

Плагин asset_webview специально разработан для этого. Меньше функций, чем у других плагинов, но простой в использовании.

Вы можете получить страницу 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("[email protected]")) {
              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.info(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.info(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.info(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.info(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.info(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.info(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.info(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.info(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.info(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.info(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.info(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.info(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.info(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.info(JSON.stringify({"delete": "delete"}));});
            """);
  }

  _backButton(BuildContext context) {
    return ElevatedButton(
      onPressed: () {
        Navigator.pop(context);
      },
      child: Icon(Icons.arrow_back),
    );
  }
}

Вам следует удалить комментарии и, возможно, разбить код на несколько логических блоков.

Philipos D. 22.12.2021 13:27

Вот гораздо более чистый код приведенного выше кода

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("[email protected]")) {
              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.info(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.info(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.info(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.info(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.info(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.info(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.info(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.info(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.info(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.info(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.info(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.info(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.info(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.info(JSON.stringify({"delete": "delete"}));});
            """);
  }

  _backButton(BuildContext context) {
    return ElevatedButton(
      onPressed: () {
        Navigator.pop(context);
      },
      child: Icon(Icons.arrow_back),
    );
  }
}

В этом коде вы также можете увидеть, как использовать javascript dom-манипуляцию и выбор и взаимодействие с веб-страницей.

Другие вопросы по теме