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

[InAppWebview]: window.flutter_inappwebview.callHandler is not a function #218

Closed
OPY-bbt opened this issue Dec 11, 2019 · 37 comments
Closed

Comments

@OPY-bbt
Copy link

OPY-bbt commented Dec 11, 2019

Environment

Flutter version: 1.10.15
Plugin version: ^2.1.0+1
Android version: 9
iOS version:
Xcode version:
Device information:

Description

I use demo to load url, but get javascript error when click div.
I/flutter (27593): Uncaught TypeError: window.flutter_inappwebview.callHandler is not a function

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
        div {
            font-size: 30px;
        }
    </style>
</head>
<body>
    <div>click</div>
    <script>
        window.addEventListener("flutterInAppWebViewPlatformReady", function(event) {
            console.log("ready");

            var div = document.body.querySelector('div');
            div.addEventListener('click', function() {
                window.flutter_inappwebview.callHandler('handleData', 1, true, ['bar', 5], {foo: 'baz'});
            });
        });
    </script>
</body>
</html>
onLoadStop:
    (InAppWebViewController controller, String url) async {
  setState(() {
    this.url = url;
  });

  webView.addJavaScriptHandler(
      handlerName: 'handleData',
      callback: (args) {
        print(args);
      });
},
@OPY-bbt OPY-bbt changed the title [inAppWebview]: window.flutter_inappwebview.callHandler is not a function [InAppWebview]: window.flutter_inappwebview.callHandler is not a function Dec 11, 2019
@OPY-bbt
Copy link
Author

OPY-bbt commented Dec 12, 2019

image

@ositano
Copy link

ositano commented Dec 13, 2019

I get this error TypeError: undefined is not an object (evaluating 'window.flutter_inappbrowser.callHandler') on running the below example

  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> {
      InAppWebViewController webView;
    String url = "";
   double progress = 0;

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

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

    @override
    Widget build(BuildContext context) {
         return MaterialApp(
             home: Scaffold(
             appBar: AppBar(
             title: const Text('InAppWebView Example'),
            ),
           body: Container(
               child: Column(children: <Widget>[
              Container(
              padding: EdgeInsets.all(20.0),
               child: Text(
                   "CURRENT URL\n${(url.length > 50) ? url.substring(0, 50) + "..." : url}"),
               ),
              Container(
                   padding: EdgeInsets.all(10.0),
                   child: progress < 1.0
                     ? LinearProgressIndicator(value: progress)
                     : Container()),
      Expanded(
        child: Container(
          margin: const EdgeInsets.all(10.0),
          decoration:
              BoxDecoration(border: Border.all(color: Colors.blueAccent)),
          child: InAppWebView(
            initialUrl: "https://flutter.dev/",
            initialHeaders: {},
            initialOptions: InAppWebViewWidgetOptions(
                inAppWebViewOptions: InAppWebViewOptions(
              debuggingEnabled: true,
              javaScriptEnabled: true,
              useShouldOverrideUrlLoading: true,
              useOnLoadResource: true,
              cacheEnabled: true,
            )),
            onWebViewCreated: (InAppWebViewController controller) {
              webView = controller;
              webView.addJavaScriptHandler(
                  handlerName: "test",
                  callback: (arguments) async {
                    print('hello from test');
                    print(arguments.length);
                    print(arguments);
                  });
            },
            onLoadStart: (InAppWebViewController controller, String url) {
              setState(() {
                this.url = url;
              });
            },
            onLoadStop:
                (InAppWebViewController controller, String url) async {
              setState(() {
                this.url = url;
              });

              String js2 = "window.flutter_inappwebview.callHandler('test', 'Text from Javascript').then(function(result) {console.log(result);})";
              await controller.evaluateJavascript(source: js2);
            },
            onProgressChanged:
                (InAppWebViewController controller, int progress) {
              setState(() {
                this.progress = progress / 100;
              });
            },
            onConsoleMessage: (InAppWebViewController controller,
                ConsoleMessage consoleMessage) {
              print("""
                          console output:

                            message: ${consoleMessage.message}
                            messageLevel: ${consoleMessage.messageLevel}
                          """);
            }, //fires when browser receives console message
          ),
        ),
      ),
      ButtonBar(
        alignment: MainAxisAlignment.center,
        children: <Widget>[
          RaisedButton(
            child: Icon(Icons.arrow_back),
            onPressed: () {
              if (webView != null) {
                webView.goBack();
              }
            },
          ),
          RaisedButton(
            child: Icon(Icons.arrow_forward),
            onPressed: () {
              if (webView != null) {
                webView.goForward();
              }
            },
          ),
          RaisedButton(
            child: Icon(Icons.refresh),
            onPressed: () {
              if (webView != null) {
                webView.reload();
              }
            },
          ),
        ],
      ),
    ])),
  ),
);
  }
 }

@pichillilorenzo
Copy link
Owner

@ositano that's because it is not window.flutter_inappbrowser, but it needs to be window.flutter_inappwebview

@OPY-bbt
Copy link
Author

OPY-bbt commented Dec 13, 2019

#204

@ositano
Copy link

ositano commented Dec 13, 2019

@ositano that's because it is not window.flutter_inappbrowser, but it needs to be window.flutter_inappwebview

@pichillilorenzo thank you, I have changed it as you pointed, but now it crashes the app. I am running on iOS simulator. When i tried running using _callHandler as mentioned on the issue @OPY-bbt referenced I get TypeError: window.flutter_inappwebview._callHandler is not a function

@pichillilorenzo
Copy link
Owner

_callHandler should not be used because it is a "private API" that I use to manage javascript handlers. callHandler is the public one that you need to use. I need to debug it more.

@pichillilorenzo
Copy link
Owner

@ositano please post the error log you get! For iOS, open launch your app with Xcode and take the logs from it

@ositano
Copy link

ositano commented Dec 13, 2019

Screenshot 2019-12-13 at 9 01 03 AM

@pichillilorenzo i was unable to run from xcode

@pichillilorenzo
Copy link
Owner

@ositano thats because you are using an Xcode version below 11. This plugin, as written in the Requirements section of the README.md file and in the official documantation, requires Xcode >= 11. Just update Xcode and it should work.

@ositano
Copy link

ositano commented Dec 13, 2019

@pichillilorenzo see this
Screenshot 2019-12-13 at 11 55 58 AM

@OPY-bbt
Copy link
Author

OPY-bbt commented Dec 14, 2019

@ositano Please create a new issue. Don't ask questions that are irrelevant to the title

@koteezy
Copy link

koteezy commented Dec 17, 2019

flutterInAppWebViewPlatformReady - is never called, my js:

console.log("JS injected");

window.addEventListener("flutterInAppWebViewPlatformReady", function(event) {
    console.log("flutterInAppWebViewPlatformReady is ready!");

    const tracks = [1,2,3,4];

    window.flutter_inappwebview.callHandler('tracks', JSON.stringify({ tracks: tracks }));
  });

Browser console

@shaiful-hisham
Copy link

I also have the same issue in Android, but in iOS it working fine. Do we have any workaround yet?

@eryanwcp
Copy link

it's not working in Android 9-,but in Android 10 and iOS it working fine.

@koteezy
Copy link

koteezy commented Jan 12, 2020

Any news?

@fuiyu
Copy link

fuiyu commented Feb 10, 2020

Looking for help for this problem, Android 8 is not working

@a4081675
Copy link

求解决。。。官方不支持选择文件,这个还有不少bug。心好累。。。。

@a4081675
Copy link

String js = InAppWebView.consoleLogJS.replaceAll("[\r\n]+", "");
js += JavaScriptBridgeInterface.flutterInAppBroserJSClass.replaceAll("[\r\n]+", "");
if (webView.options.useShouldInterceptAjaxRequest) {
js += InAppWebView.interceptAjaxRequestsJS.replaceAll("[\r\n]+", "");
}
if (webView.options.useShouldInterceptFetchRequest) {
js += InAppWebView.interceptFetchRequestsJS.replaceAll("[\r\n]+", "");
}
if (webView.options.useOnLoadResource) {
js += InAppWebView.resourceObserverJS.replaceAll("[\r\n]+", "");
}
js += InAppWebView.printJS.replaceAll("[\r\n]+", "");

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
  webView.evaluateJavascript(js, (ValueCallback<String>) null);
} else {
  webView.loadUrl("javascript:" + js);
}

换到onPageFinished里面就好使了

@hisaichi5518
Copy link

my workaround:

const message = "value";
if (window.flutter_inappwebview.callHandler) {
  window.flutter_inappwebview.callHandler('handlerName', message);
} else {
   window.flutter_inappwebview._callHandler('handlerName', setTimeout(function(){}), JSON.stringify([message]));
}

@asjqkkkk
Copy link

asjqkkkk commented Mar 4, 2020

I have the same issue.
and console logs:

[ERROR:interface_registry.cc(104)] Failed to locate a binder for interface: autofill::mojom::PasswordManagerDriver

Maybe this is the problem

@hisaichi5518
Copy link

The cause of this issue is that only onPageStarted callback sets callHandler JS.
If you set the callHandler JS in onPageFinished, no problem will occur.

diff --git a/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/InAppWebView/InAppWebViewClient.java b/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/InAppWebView/InAppWebViewClient.java
index 84ad883..3276175 100644
--- a/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/InAppWebView/InAppWebViewClient.java
+++ b/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/InAppWebView/InAppWebViewClient.java
@@ -223,7 +223,8 @@ public class InAppWebViewClient extends WebViewClient {
     view.clearFocus();
     view.requestFocus();

-    String js = InAppWebView.platformReadyJS.replaceAll("[\r\n]+", "");
+    String js = JavaScriptBridgeInterface.flutterInAppBroserJSClass.replaceAll("[\r\n]+", "");
+    js += InAppWebView.platformReadyJS.replaceAll("[\r\n]+", "");

     if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
       webView.evaluateJavascript(js, (ValueCallback<String>) null);

This was referenced Jul 6, 2020
@mrcrixx
Copy link

mrcrixx commented Jul 14, 2020

I have tried everything but I'm still stucked on the original problem: callHandler is not a function...

on Dart side I use this that should inject the handler

onWebViewCreated: (InAppWebViewController controller) {
webView = controller;
webView.addJavaScriptHandler(
handlerName: "mySum",
callback: (args) {
// Here you receive all the arguments from the JavaScript side
// that is a List
print("From the JavaScript side:");
print(args);
return args.reduce((curr, next) => curr + next);
});

            },

on HTML side I use this and I get the error:

    <script>
       // In order to call window.flutter_inappwebview.callHandler(handlerName <String>, ...args) 
       // properly, you need to wait and listen the JavaScript event flutterInAppWebViewPlatformReady. 
       // This event will be dispatched as soon as the platform (Android or iOS) is ready to handle the callHandler method. 
        window.addEventListener("flutterInAppWebViewPlatformReady", function(event) {
       console.log('Here I am, I get this message');
      
				             // call flutter handler with name 'mySum' and pass one or more arguments
				             window.flutter_inappwebview.callHandler('mySum', 12, 2, 50).then(function(result) {
				               // get result from Flutter side. It will be the number 64.
				               console.log(result);
				             });
       	
       });
    </script>

Just an example

Any idea?

@letyletylety
Copy link

anyone solved this?

@WangPe1n
Copy link

WangPe1n commented Aug 10, 2020

I solved this issue by adding these code:

...
String _js = '''
  if (!window.flutter_inappwebview.callHandler) {
      window.flutter_inappwebview.callHandler = function () {
          var _callHandlerID = setTimeout(function () { });
          window.flutter_inappwebview._callHandler(arguments[0], _callHandlerID, JSON.stringify(Array.prototype.slice.call(arguments, 1)));
          return new Promise(function (resolve, reject) {
              window.flutter_inappwebview[_callHandlerID] = resolve;
          });
      };
  }
  ''';
...

InAppWebView(
...
  onWebViewCreated: (controller) {
    controller.addJavaScriptHandler(
      ...
    );
  },
  onLoadStop: (controller, url) {
    controller.evaluateJavascript(source: _js);
  },
...
);

hope this help. 😁

@WangPe1n
Copy link

WangPe1n commented Aug 10, 2020

anyone solved this?

here

@JanusKun
Copy link

how can i solve it? head big

@Clean-Cole
Copy link

Confirmed @WangPe1n 's fix did the trick.

@checkblue
Copy link

@WangPe1n Your code is valid!!!

@rajashah33
Copy link

@WangPe1n workaround not working. I'm still getting the same error

@DRL9
Copy link

DRL9 commented Dec 11, 2020

@WangPe1n workaround not working. I'm still getting the same error

@rajashah33 Copy that js fragment to js file can resolve it.

@cijianzy
Copy link

cijianzy commented Mar 7, 2021

@WangPe1n you save me!!!

@pichillilorenzo
Copy link
Owner

@cijianzy it should already work with the latest version without any workaround

@kiwiidb
Copy link

kiwiidb commented Apr 28, 2021

I am using

  • version ^5.3.2
  • classpath 'com.android.tools.build:gradle:3.5.4'
    compileSdkVersion 30

    sourceSets {
        main.java.srcDirs += 'src/main/kotlin'
    }

    lintOptions {
        disable 'InvalidPackage'
    }

    defaultConfig {
        minSdkVersion 17
        targetSdkVersion 30
        versionCode flutterVersionCode.toInteger()
        versionName flutterVersionName
    }

and I only got the callback it to work when using @WangPe1n 's workaround. Worked on ios but did not work on android except with this workaround.

@pichillilorenzo
Copy link
Owner

pichillilorenzo commented Apr 28, 2021

@kiwiidb if you have problems, please post a new issue with a code example to be able to reproduce that behavior. It should already work with version 5+.
Using that workaround could not work on future versions. It is something "private" and it could change at any time. So, open a new issue and post your problem there with all the info.
Also, be sure to read how JavaScript Communication works and check if you are following the right steps.

@maxmitz
Copy link
Contributor

maxmitz commented May 26, 2023

This bug still occurs for me. I'm going to post a new issue in the next few days.

@codemobiles
Copy link

You can use this code to prevent the crash error in the javascript level. I add try-catch to prevent the crash and allow flutter handle the exception itself.

`String _js = '''
(function() {
try {
return $fullMethodSignature;
} catch (e) {
return "failed";
}
})();
''';

result = await webController.evaluateJavascript(source: _js) ?? "failed";
`

Copy link

github-actions bot commented Oct 3, 2024

This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug and a minimal reproduction of the issue.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Oct 3, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests