Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/341.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何从Android调用javascript?_Java_Javascript_Android_Return - Fatal编程技术网

如何从Android调用javascript?

如何从Android调用javascript?,java,javascript,android,return,Java,Javascript,Android,Return,我们如何从Android调用javascript?我有一个我想使用的javascript库,我想调用javascript函数并将结果值传递给android java代码。从现在起我还没有找到答案。我设法从javascript调用android代码,但我想换一种方式。有一个黑客: 绑定一些Java对象,以便可以使用WebView从Javascript调用它: addJavascriptInterface(javaObjectCallback, "JavaCallback") 通过强制在现有页面

我们如何从Android调用javascript?我有一个我想使用的javascript库,我想调用javascript函数并将结果值传递给android java代码。从现在起我还没有找到答案。我设法从javascript调用android代码,但我想换一种方式。

有一个黑客:

  • 绑定一些Java对象,以便可以使用WebView从Javascript调用它:

    addJavascriptInterface(javaObjectCallback, "JavaCallback")
    
  • 通过强制在现有页面内执行javascript

    WebView.loadUrl("javascript: var result = window.YourJSLibrary.callSomeFunction();
        window.JavaCallback.returnResult(result)");
    
  • (在这种情况下,java类
    JavaObjectCallback
    应该有一个方法
    returnResult(..)


    注意:这是一个安全风险-此网页中的任何JS代码都可以访问/调用绑定的Java对象。最好将一些一次性cookie传递给loadUrl(),并将它们传回您的Java对象,以检查调用的是您的代码。

    为了匹配iOS WebviewJavascriptBridge()的方法调用,我为
    register\u handle
    call\u handle
    的调用制作了一些代理。请注意,我不是Javascript大师,因此可能有更好的解决方案

         javascriptBridge = (function() {
            var handlers = {};
            return {
                init: function () {
                },
                getHandlers : function() {
                    return handlers;
                },
                callHandler : function(name, param) {
                    if(param !== null && param !== undefined) {
                        JSInterface[name](param);
                    } else {
                        JSInterface[name]();
                    }
                },
                registerHandler : function(name, method) {
                    if(handlers === undefined) {
                        handlers = {};
                    }
                    if(handlers[name] === undefined) {
                        handlers[name] = method;
                    }
                }
            };
        }());
    
    通过这种方式,您可以从Javascript向Java发送具有字符串参数的调用

    javascriptBridge.callHandler("login", JSON.stringify(jsonObj));
    
    号召

    @JavascriptInterface
    public void login(String credentialsJSON)
    {
        Log.d(getClass().getName(), "Login: " + credentialsJSON);
        new Thread(new Runnable() {
             public void run() {              
                 Gson gson = new Gson();
                 LoginObject credentials = gson.fromJson(credentialsJSON, LoginObject.class);
                 SingletonBus.INSTANCE.getBus().post(new Events.Login.LoginEvent(credentials));
             }
        }).start();
    }
    
    您可以使用

    javascriptBridge.registerHandler('successfullAuthentication', function () {
        alert('hello');
    })
    

    如果需要传递参数,请序列化为JSON字符串,然后调用
    StringEscapeUtils.escapeEcmaScript(JSON)
    ,否则会得到
    意外标识符:source(1)
    错误

    有点俗气,但它能用。您只需删除以下内容

    connectWebViewJavascriptBridge(function(bridge) {
    }
    
    编辑:

    为了将全局变量更改为实际属性,我将上述代码更改为:

    (function(root) {
        root.bridge = (function() {
            var handlers = {};
            return {
                init: function () {
                },
                getHandlers : function() {
                    return handlers;
                },
                callHandler : function(name, param) {
                    if(param !== null && param !== undefined) {
                        Android[name](param);
                    } else {
                        Android[name]();
                    }
                },
                registerHandler : function(name, method) {
                    if(handlers === undefined) {
                        handlers = {};
                    }
                    if(handlers[name] === undefined) {
                        handlers[name] = method;
                    }
                }
            };
        }());
    })(this);
    

    我的想法来自。

    您可以使用
    Rhino
    库在没有WebView的情况下执行JavaScript

    首先,解压缩它,将js.jar文件放在libs文件夹下。它非常小,所以您不必担心apk文件会因为这个外部jar而大得离谱

    下面是一些执行JavaScript代码的简单代码

    Object[] params = new Object[] { "javaScriptParam" };
    
    // Every Rhino VM begins with the enter()
    // This Context is not Android's Context
    Context rhino = Context.enter();
    
    // Turn off optimization to make Rhino Android compatible
    rhino.setOptimizationLevel(-1);
    try {
        Scriptable scope = rhino.initStandardObjects();
    
        // Note the forth argument is 1, which means the JavaScript source has
        // been compressed to only one line using something like YUI
        rhino.evaluateString(scope, javaScriptCode, "JavaScript", 1, null);
    
        // Get the functionName defined in JavaScriptCode
        Object obj = scope.get(functionNameInJavaScriptCode, scope);
    
        if (obj instanceof Function) {
            Function jsFunction = (Function) obj;
    
            // Call the function with params
            Object jsResult = jsFunction.call(rhino, scope, scope, params);
            // Parse the jsResult object to a String
            String result = Context.toString(jsResult);
        }
    } finally {
        Context.exit();
    }
    

    您可以在上查看更多详细信息。

    有关不需要使用慢速WebView的JavaScript的完整实现,请参阅,这是Webkit的JavaScriptCore For Android的完整端口

    2018年更新:AndroidJSCore已弃用。但是,它的继任者具有所有相同的功能和更多功能。

    从Android调用函数非常简单:

    JSContext context = new JSContext();
    String script =
      "function factorial(x) { var f = 1; for(; x > 1; x--) f *= x; return f; }\n" +
      "var fact_a = factorial(a);\n";
    context.evaluateScript("var a = 10;");
    context.evaluateScript(script);
    JSValue fact_a = context.property("fact_a");
    System.out.println(df.format(fact_a.toNumber())); // 3628800.0
    

    只需查看code.google.com上的一个问题,目前的解决方案是加载一个JavaScript URL,例如:webview.loadUrl(“JavaScript:(function(){“+”document.getElementsByTagName('body')[0]。style.color='red';“+”})();在某些方面,一旦您看到它,它看起来非常优雅和明显,但它仍然没有直接执行JavaScript的方法那么优雅。然而,这确实证明了实现这种方法是很容易的。Android开发者的页面也谈到了这种安全风险如果
    JavascriptInterface
    只包含可以从JavaScript访问的方法,我认为没有风险,这就是为什么在JellyBean(api 17)中引入@JavascriptInterface注释的原因@peter knego我应该为
    returnResult(…)
    中的参数使用什么类型?例如,我想返回类型为HTMLCollection的
    document.getElementsByCassName('someclass')
    ,但Java中没有这种类型?如果我只使用字符串或对象作为参数类型,它将返回null和“undefined”。我不知道这对我来说是否太过分了。我只想在我的网站上解析一个HTML表。我仍在寻找这样做的方法。我有一个javascript函数,可以将表转换为json,我只需要一种在java.Hi-Eric中获取它的方法。你还忘了提到它现在被弃用,取而代之的是LiquidCore。
    JSContext context = new JSContext();
    String script =
      "function factorial(x) { var f = 1; for(; x > 1; x--) f *= x; return f; }\n" +
      "var fact_a = factorial(a);\n";
    context.evaluateScript("var a = 10;");
    context.evaluateScript(script);
    JSValue fact_a = context.property("fact_a");
    System.out.println(df.format(fact_a.toNumber())); // 3628800.0