Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

The web project did not receive the onLoadStop callback, as well as the addJavaScriptHandler and evaluateJavascript methods #2217

Open
MichaelSSY opened this issue Jul 9, 2024 · 28 comments
Labels
bug Something isn't working

Comments

@MichaelSSY
Copy link

The web project did not receive the onLoadStop callback, as well as the addJavaScriptHandler and evaluateJavascript methods

@MichaelSSY MichaelSSY added the bug Something isn't working label Jul 9, 2024
Copy link

github-actions bot commented Jul 9, 2024

👋 @MichaelSSY

NOTE: This comment is auto-generated.

Are you sure you have already searched for the same problem?

Some people open new issues but they didn't search for something similar or for the same issue. Please, search for it using the GitHub issue search box or on the official inappwebview.dev website, or, also, using Google, StackOverflow, etc. before posting a new one. You may already find an answer to your problem!

If this is really a new issue, then thank you for raising it. I will investigate it and get back to you as soon as possible. Please, make sure you have given me as much context as possible! Also, if you didn't already, post a code example that can replicate this issue.

In the meantime, you can already search for some possible solutions online! Because this plugin uses native WebView, you can search online for the same issue adding android WebView [MY ERROR HERE] or ios WKWebView [MY ERROR HERE] keywords.

Following these steps can save you, me, and other people a lot of time, thanks!

@fawdlstty
Copy link

You can try the combination of the following versions, which works fine with me.
Flutter: 3.16.9, Dart:3.2.6,DevTools:2.28.5,flutter_inappwebview:^6.0.0-beta.31

@MichaelSSY
Copy link
Author

You can try the combination of the following versions, which works fine with me. Flutter: 3.16.9, Dart:3.2.6,DevTools:2.28.5,flutter_inappwebview:^6.0.0-beta.31

Thank you, I am currently using Flutter_ inappwebview: 6.0.0 beta.28. If I use Flutter_ inappwebview: 6.0.0 beta.31, the following error will occur. Have you encountered it?
image

@fawdlstty
Copy link

Thank you, I am currently using Flutter_ inappwebview: 6.0.0 beta.28. If I use Flutter_ inappwebview: 6.0.0 beta.31, the following error will occur. Have you encountered it?

Is this encountered in a new project or after modifying the version number of an old project?

@fawdlstty
Copy link

@MichaelSSY The reason for the issue you encountered is that the Flutter version is too high and needs to be lowered. Have you also modified the Flutter version?

@MichaelSSY
Copy link
Author

@MichaelSSY The reason for the issue you encountered is that the Flutter version is too high and needs to be lowered. Have you also modified the Flutter version?

It shouldn't be an issue with the Flutter version, as our Flutter version is already very low. Below is the version information:

Flutter 3.10.6 • channel stable • https://github.com/flutter/flutter.git
Framework • revision f468f3366c (12 months ago) • 2023-07-12 15:19:05 -0700
Engine • revision cdbeda788a
Tools • Dart 3.0.6 • DevTools 2.23.1

@fawdlstty
Copy link

@MichaelSSY Try creating a new project according to the version I provided?

@skalex4
Copy link

skalex4 commented Jul 12, 2024

You can try the combination of the following versions, which works fine with me. Flutter: 3.16.9, Dart:3.2.6,DevTools:2.28.5,flutter_inappwebview:^6.0.0-beta.31

Thank you, I am currently using Flutter_ inappwebview: 6.0.0 beta.28. If I use Flutter_ inappwebview: 6.0.0 beta.31, the following error will occur. Have you encountered it? image

You might need to lower the version of the dependencies too, for it to work.

Check dependent packages for interface & web.

@skalex4
Copy link

skalex4 commented Jul 12, 2024

Solved @ #2058

@MichaelSSY
Copy link
Author

已解决 @ #2058

May I ask what is your version of Flutter? I am currently using 3.10.6, but I cannot upgrade it now as it will affect other functions. Has version 3.10.6 been resolved?

@fawdlstty
Copy link

did you try to add this code in your /repo_path/web/index.html?

<script type="application/javascript" src="assets/packages/flutter_inappwebview_web/assets/web/web_support.js" defer></script>

@skalex4
Copy link

skalex4 commented Jul 13, 2024

已解决 @ #2058

May I ask what is your version of Flutter? I am currently using 3.10.6, but I cannot upgrade it now as it will affect other functions. Has version 3.10.6 been resolved?

I tried it on 3.22.2 & 3.19.6

@sriramkondeti
Copy link

You can try the combination of the following versions, which works fine with me. Flutter: 3.16.9, Dart:3.2.6,DevTools:2.28.5,flutter_inappwebview:^6.0.0-beta.31

@fawdlstty I have used exactly the same versions as you told me, below screenshots for reference.

Screenshot 2024-07-15 at 11 04 15 PM Screenshot 2024-07-15 at 11 05 53 PM

However, I am still getting below error though, upon calling controller.addJavaScriptHandler. Can you please let me know what I am missing ?
Screenshot 2024-07-15 at 11 08 31 PM
Screenshot 2024-07-15 at 11 08 22 PM

@sriramkondeti
Copy link

@skalex4 @MichaelSSY @yashharkhani did any of you find a solution for Flutter web to receive a event or a message from JSlayer to Flutter Layer? if yes, can you please let me know how any of you did resolve this ?

@fawdlstty
Copy link

@sriramkondeti Can you confirm that this project was created in the current version of Flutter environment, and that you have added the following content under web/index.html:

<script type="application/javascript" src="assets/packages/flutter_inappwebview_web/assets/web/web_support.js"
    defer></script>

@fawdlstty
Copy link

If so, then you may need to show your code for calling flutter_inappwebview

@sriramkondeti
Copy link

Here you go @fawdlstty

  final GlobalKey webViewKey = GlobalKey();

  InAppWebViewController? webViewController;

  @override
  Widget build(BuildContext context) {
    return Consumer<ReportViewModel>(builder: (context, viewModel, child) {
      if (viewModel.needsRefresh) {
        _log.finest('Report ${viewModel.report.id} needs to be refreshed');
        if (viewModel.isActive) {
          _log.finest(
              'Report ${viewModel.report.id} is being viewed so can refresh');

          WidgetsBinding.instance.addPostFrameCallback((timeStamp) async {
            viewModel.isRefreshing = true;
            await refreshPage(viewModel);
            viewModel.needsRefresh = false;
          });
        } else {
          _log.finest(
              'Report ${viewModel.report.id} is not being viewed so wait');
        }
      }
      return Column(
        children: [
          Expanded(
            child: Builder(builder: (context) {
              var showLiveView = viewModel.pageLoaded && viewModel.connected;
              _log.finest(
                  'Show live view for report ${viewModel.report.id} is $showLiveView');
              return Stack(
                children: [
                  const Positioned(
                    left: 0,
                    right: 0,
                    bottom: 0,
                    top: 0,
                    child: ColoredBox(color: Colors.white),
                  ),
                  Positioned(
                    left: 0,
                    right: 0,
                    bottom: 0,
                    top: 0,
                    child: Offstage(
                      offstage: !showLiveView,
                      child: InAppWebView(
                        key: webViewKey,
                        initialSettings: InAppWebViewSettings(
                            sharedCookiesEnabled: true,
                            useShouldOverrideUrlLoading: true,
                            isInspectable: true,
                            javaScriptEnabled: true,
                            thirdPartyCookiesEnabled: true),
                        initialData: (viewModel.isTableau || viewModel.isPdf)
                            ? null
                            : InAppWebViewInitialData(
                                data: getHtmlString(
                                    widget.report.report.reportUri),
                                mimeType: 'text/html',
                                encoding: 'utf8',
                              ),
                        initialUrlRequest: (viewModel.isTableau ||
                                viewModel.isPdf ||
                                viewModel.isURL)
                            ? URLRequest(
                                url: WebUri(widget.report.report.reportUri))
                            : null,
                        onWebContentProcessDidTerminate: (controller) {
                          _log.finest(
                              'Report ${viewModel.report.id} is stopped, marking as need to be refreshed');
                          viewModel.needsRefresh = true;
                        },
                        onWebViewCreated: (controller) async {
                          webViewController = controller;
                          if (!kIsWeb) await viewModel.setCookies();
                          widget.reportController.registerReport(
                            widget.report.report,
                            ReportControls(
                              refresh: () async => refreshPage(viewModel),
                            ),
                          );
                          if (!(viewModel.isTableau ||
                              viewModel.isPdf ||
                              viewModel.isURL)) {
                            controller.addJavaScriptHandler(
                                handlerName: 'tokenExpired',
                                callback: (args) async {
                                  if (args.isNotEmpty &&
                                      args[0]['errorCode'] != null &&
                                      args[0]['errorCode'] == '403') {
                                    _log.finest(
                                        'Token expired for report ${viewModel.report.id}');
                                    await context
                                        .read<AuthenticationViewModel>()
                                        .refreshAuth(silentRefresh: true);
                                    await refreshPage(viewModel);
                                  }
                                });
                          }
                        },
                        onLoadStart: (controller, uri) {
                          _log.finest(
                              'onLoadStart(${viewModel.report.id}): $uri');
                        },
                        onReceivedError: (controller, uri, error) {
                          viewModel.connected = false;
                          _log.finest(
                              'onLoadError(${viewModel.report.id}): $uri \n${error.description}');
                          viewModel.isRefreshing = false;
                        },
                        onReceivedHttpError: (controller, uri, error) {
                          _log.finest(
                              'onLoadHttpError(${viewModel.report.id}): $uri');
                          viewModel.isRefreshing = false;
                        },
                        shouldOverrideUrlLoading:
                            (controller, navigationAction) async {
                          _log.finest(
                              'shouldOverrideUrlLoading(${viewModel.report.id}): ${navigationAction.request.url}');
                          if (navigationAction.request.url
                              .toString()
                              .startsWith(
                                  'https://login.microsoftonline.com/')) {
                            viewModel.needsRefresh = true;
                          }
                          return NavigationActionPolicy.ALLOW;
                        },
                        onLoadStop: (controller, uri) async {
                          _log.finest(
                              'onLoadStopped(${viewModel.report.id}): $uri');
                          viewModel.isRefreshing = false;
                          viewModel.pageLoaded = true;
                          widget.reportController.registerReport(
                            widget.report.report,
                            ReportControls(
                              refresh: () => refreshPage(viewModel),
                              captureScreenshot: () async {
                                return (viewModel.pageLoaded &&
                                        viewModel.connected)
                                    ? null
                                    : null;
                              },
                            ),
                          );
                        },
                      ),
                    ),
                  ),
                ],
              );
            }),
          ),
        ],
      );
    });
  }```

@sriramkondeti
Copy link

@sriramkondeti Can you confirm that this project was created in the current version of Flutter environment, and that you have added the following content under web/index.html:

<script type="application/javascript" src="assets/packages/flutter_inappwebview_web/assets/web/web_support.js"
    defer></script>

Yes Sir, this is in place.

Screenshot 2024-07-15 at 11 54 32 PM

@sriramkondeti
Copy link

sriramkondeti commented Jul 16, 2024

Here you go @fawdlstty

  final GlobalKey webViewKey = GlobalKey();

  InAppWebViewController? webViewController;

  @override
  Widget build(BuildContext context) {
    return Consumer<ReportViewModel>(builder: (context, viewModel, child) {
      if (viewModel.needsRefresh) {
        _log.finest('Report ${viewModel.report.id} needs to be refreshed');
        if (viewModel.isActive) {
          _log.finest(
              'Report ${viewModel.report.id} is being viewed so can refresh');

          WidgetsBinding.instance.addPostFrameCallback((timeStamp) async {
            viewModel.isRefreshing = true;
            await refreshPage(viewModel);
            viewModel.needsRefresh = false;
          });
        } else {
          _log.finest(
              'Report ${viewModel.report.id} is not being viewed so wait');
        }
      }
      return Column(
        children: [
          Expanded(
            child: Builder(builder: (context) {
              var showLiveView = viewModel.pageLoaded && viewModel.connected;
              _log.finest(
                  'Show live view for report ${viewModel.report.id} is $showLiveView');
              return Stack(
                children: [
                  const Positioned(
                    left: 0,
                    right: 0,
                    bottom: 0,
                    top: 0,
                    child: ColoredBox(color: Colors.white),
                  ),
                  Positioned(
                    left: 0,
                    right: 0,
                    bottom: 0,
                    top: 0,
                    child: Offstage(
                      offstage: !showLiveView,
                      child: InAppWebView(
                        key: webViewKey,
                        initialSettings: InAppWebViewSettings(
                            sharedCookiesEnabled: true,
                            useShouldOverrideUrlLoading: true,
                            isInspectable: true,
                            javaScriptEnabled: true,
                            thirdPartyCookiesEnabled: true),
                        initialData: (viewModel.isTableau || viewModel.isPdf)
                            ? null
                            : InAppWebViewInitialData(
                                data: getHtmlString(
                                    widget.report.report.reportUri),
                                mimeType: 'text/html',
                                encoding: 'utf8',
                              ),
                        initialUrlRequest: (viewModel.isTableau ||
                                viewModel.isPdf ||
                                viewModel.isURL)
                            ? URLRequest(
                                url: WebUri(widget.report.report.reportUri))
                            : null,
                        onWebContentProcessDidTerminate: (controller) {
                          _log.finest(
                              'Report ${viewModel.report.id} is stopped, marking as need to be refreshed');
                          viewModel.needsRefresh = true;
                        },
                        onWebViewCreated: (controller) async {
                          webViewController = controller;
                          if (!kIsWeb) await viewModel.setCookies();
                          widget.reportController.registerReport(
                            widget.report.report,
                            ReportControls(
                              refresh: () async => refreshPage(viewModel),
                            ),
                          );
                          if (!(viewModel.isTableau ||
                              viewModel.isPdf ||
                              viewModel.isURL)) {
                            controller.addJavaScriptHandler(
                                handlerName: 'tokenExpired',
                                callback: (args) async {
                                  if (args.isNotEmpty &&
                                      args[0]['errorCode'] != null &&
                                      args[0]['errorCode'] == '403') {
                                    _log.finest(
                                        'Token expired for report ${viewModel.report.id}');
                                    await context
                                        .read<AuthenticationViewModel>()
                                        .refreshAuth(silentRefresh: true);
                                    await refreshPage(viewModel);
                                  }
                                });
                          }
                        },
                        onLoadStart: (controller, uri) {
                          _log.finest(
                              'onLoadStart(${viewModel.report.id}): $uri');
                        }
              );
            }),
          ),
        ],
      );
    });
  }```

To make things easier, I am just instantiating a Webview to load HTML Data, if token of that HTML data expires, I want to get a new token and refresh the Webview

@skalex4
Copy link

skalex4 commented Jul 16, 2024

@sriramkondeti, please use below for web package.

As well as match the domain of webview url and flutter app.

  flutter_inappwebview_web:
    git:
      url: git@github.com:p-mazhnik/flutter_inappwebview.git
      path: flutter_inappwebview_web
      ref: 295ff82

Note: It won't work on localhost while in debug mode, you'll have to deploy the app and check. more info

Credit goes to @p-mazhnik for this.

@sriramkondeti
Copy link

@sriramkondeti, please use below for web package.

As well as match the domain of webview url and flutter app.

  flutter_inappwebview_web:
    git:
      url: git@github.com:p-mazhnik/flutter_inappwebview.git
      path: flutter_inappwebview_web
      ref: 295ff82

Note: It won't work on localhost while in debug mode, you'll have to deploy the app and check. more info

Absolutely will deploy and test this, Thanks a ton @skalex4, this resolved controller.addJavaScriptHandler

Last question, does window.flutter_inappwebview.callHandler will not work in this case? Please confirm

Screenshot 2024-07-16 at 12 05 02 AM

@MichaelSSY
Copy link
Author

@sriramkondeti, please use below for web package.
As well as match the domain of webview url and flutter app.

  flutter_inappwebview_web:
    git:
      url: git@github.com:p-mazhnik/flutter_inappwebview.git
      path: flutter_inappwebview_web
      ref: 295ff82

Note: It won't work on localhost while in debug mode, you'll have to deploy the app and check. more info

Absolutely will deploy and test this, Thanks a ton @skalex4, this resolved controller.addJavaScriptHandler

Last question, does window.flutter_inappwebview.callHandler will not work in this case? Please confirm

Screenshot 2024-07-16 at 12 05 02 AM

Hello, I am using Flutter3.19.6 and still get the following error, which is very strange!!! @sriramkondeti @skalex4

Flutter 3.19.6 • channel stable • https://github.com/flutter/flutter.git
Framework • revision 54e66469a9 (3 months ago) • 2024-04-17 13:08:03 -0700
Engine • revision c4cd48e186
Tools • Dart 3.3.4 • DevTools 2.31.1

image image image

@skalex4
Copy link

skalex4 commented Jul 16, 2024

Hi @MichaelSSY,

Could you please try 6.0.0 once and check once

flutter_inappwebview: ^6.0.0

@MichaelSSY
Copy link
Author

Hi @MichaelSSY,

Could you please try 6.0.0 once and check once

flutter_inappwebview: ^6.0.0

When I run the web version using flutter-inappwebview: ^ 6.0.0 or flutter-inappwebview: 6.0.0-rc.3, the JS event will report an error:

image

@A-Elbadawy
Copy link

I have same problem.
unfortunately it's not supported in web platform
i don't know if any solution in comments works, anyone tried any solution with same package and worked

image

@skalex4
Copy link

skalex4 commented Oct 22, 2024

Hi @MichaelSSY @sriramkondeti,

I've create custom class to handle the events from webview using js_interops

/// This code is used to handle events triggered by JavaScript and communicate with the Flutter app package.

import 'dart:convert';
import 'dart:js_interop';
import 'dart:js_interop_unsafe';

import 'package:flutter/material.dart';

@JS('callDartFunction')
external void executeDartHandler();

class DartEventHandler {
  DartEventHandler() {
    globalContext['executeDartHandler'] = handleEvent.toJS;
  }

  void handleEvent(String eventType, String payload) {
    try {
      // Event payload will be stringified from JS and then transmitted to dart.
      Map<String, dynamic> eventData = {};
      if (payload.isNotEmpty) {
        eventData = json.decode(payload);
      }

      switch (eventType) {
        case 'printMessage':
          printMessage(payload);
          break;
        //....add custom events handlers here
        default:
          break;
      }
    } catch (e, st) {  }
  }

  void printMessage(String message) {
    debugPrint('Message from Webview: $message');
  }
}

Invoke this class from main.dart

void main() {
DartEventHandler(); // JS communication handler

runApp(...);
}

Trigger from JS:

window.parent.executeDartHandler(
  eventType,
  JSON.stringify(payload)
);

Hope this helps!!

CC: @pichillilorenzo

@mminhlequang
Copy link

Hello, I'm looking for evaluateJavascript fix

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

7 participants