草庐IT

javascript - 我们如何在我们的 android 应用程序中执行 javascript 函数并获取返回值?

coder 2023-11-30 原文

我们如何在我们的 android 应用程序中执行 javascript 函数并获取返回值?

我们想在按钮按下事件上执行 javascript,我们需要将参数传递给脚本并获取返回值,所以我们使用“WebChromeClient”来实现它, 但是我们得到的异常是“SyntaxError: Parse error at undefined:1”

以下是我的代码

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.webkit.JsResult;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;

public class FirstTab extends Activity 
{


    private WebView webView;

    public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
             setContentView(R.layout.regis);

            try{

                webView = (WebView) findViewById(R.id.webView1);
                webView.getSettings().setJavaScriptEnabled(true);
                webView.setWebChromeClient(new MyWebChromeClient());
                String customHtml = "<html><head><title>iSales</title><script type=\"text/javascript\"> function fieldsOnDelete(){ var x=123; return \"JIJO\"; } </script></head><body>hi</body></html>";
                webView.loadData(customHtml, "text/html","UTF-8");  

                }catch(Exception e)
                {
                     Log.v("JAC LOG",e.toString());
                }

        }
    public void onResume()
    {
        super.onResume();

            final Button button = (Button) findViewById(R.id.button1);
             button.setOnClickListener(new View.OnClickListener() {
             public void onClick(View v) {
                 try{
                    webView.loadUrl("javascript:alert(javascript:fieldsOnDelete())");
                 }
                 catch(Exception e)
                 {
                     Log.v("JAC LOG",e.toString());

                 }
              } 
             });
    }


    final class MyWebChromeClient extends WebChromeClient {
        @Override
        public boolean onJsAlert(WebView view, String url, String message, JsResult result) {

        Log.v("LogTag", message);
          result.confirm();
          return true;
        }
    }


}

最佳答案

您可以使用 mWebView.loadUrl("javascript:checkName"); 调用方法...

然后您可以使用 addJavascriptInterface() 将 Java 对象添加到 Javascript 环境中。让您的 Java 脚本调用该 Java 对象的方法以提供其“返回值”。

EDIT1:或者您可以使用以下 hack:

将此客户端添加到您的 WebView:

final class MyWebChromeClient extends WebChromeClient {
        @Override
        public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
            Log.d("LogTag", message);
            result.confirm();
            return true;
        }
    }

现在在你的 java 脚本调用中做:

webView.loadUrl("javascript:alert(functionThatReturnsSomething)");

现在在 onJsAlert 调用中“message”将包含返回值。

编辑2:

因此,如果我们在调用加载 URL 后立即调用 javascript 方法是行不通的,因为页面加载需要时间。所以我创建了一个测试程序来测试...

以下是我的 html 文件(名为 test.html)存储在 Assets 文件夹中:

<html>
<head>
<script language="javascript">
    function fieldsOnDelete(message) {
        alert("i am called with " + message);
        window.myjava.returnValue(message + " JIJO");
    }
</script>
<title>iSales android</title>


</head>
<body></body>
</html>
</body>
</html>

以下是我的 java 类,我将把它作为接口(interface)添加到 java 脚本,它会接收返回值:

public class MyJS {

    public void returnValue(String string){
        Log.d(this.getClass().getSimpleName(), string);
    }

}

下面是我的 Activity 课:

public class CheckWebView extends Activity {

    private WebView webView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_check_web_view);
        webView = (WebView) findViewById(R.id.webview);

        webView.setWebChromeClient(new WebChromeClient() {
            @Override
            public void onConsoleMessage(String message, int lineNumber,
                    String sourceID) {
                super.onConsoleMessage(message, lineNumber, sourceID);
                Log.d(this.getClass().getCanonicalName(), "message " + message
                        + "   :::line number " + lineNumber + "   :::source id "
                        + sourceID);
            }

            @Override
            public boolean onConsoleMessage(ConsoleMessage consoleMessage) {
                // TODO Auto-generated method stub

                onConsoleMessage(consoleMessage.message(),
                        consoleMessage.lineNumber(), consoleMessage.sourceId());

                Log.d(this.getClass().getCanonicalName(), "message::::: "
                        + consoleMessage.message());

                return super.onConsoleMessage(consoleMessage);
            }
        });

        webView.addJavascriptInterface(new MyJS(), "myjava");
        webView.getSettings().setJavaScriptEnabled(true);
        webView.getSettings().setPluginsEnabled(true);
        webView.getSettings().setAllowFileAccess(true);

        webView.loadUrl("file:///android_asset/test.html");

    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.activity_check_web_view, menu);
        return true;
    }

    /* (non-Javadoc)
     * @see android.app.Activity#onOptionsItemSelected(android.view.MenuItem)
     */
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        webView.loadUrl("javascript:fieldsOnDelete('name');");
        return super.onOptionsItemSelected(item);
    }

}

这里的关键是调用从 assets 文件夹加载 html 文件和调用 javascript:method 之间应该有一些时间间隔。在这里,我从 onOptionsItemSelected 调用它,它工作正常。如果我将 webView.loadUrl("javascript:fieldsOnDelete('name');"); 移动到onCreate() 方法的末尾显示错误,它找不到 fieldsOnDelete() 方法...

希望对你有帮助...

编辑3:

在您的代码中替换以下内容

webView.loadUrl("javascript:alert(javascript:fieldsOnDelete())");

webView.loadUrl("javascript:alert(fieldsOnDelete())");

然后尝试...

关于javascript - 我们如何在我们的 android 应用程序中执行 javascript 函数并获取返回值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13527624/

有关javascript - 我们如何在我们的 android 应用程序中执行 javascript 函数并获取返回值?的更多相关文章

  1. ruby - 如何在 Ruby 中顺序创建 PI - 2

    出于纯粹的兴趣,我很好奇如何按顺序创建PI,而不是在过程结果之后生成数字,而是让数字在过程本身生成时显示。如果是这种情况,那么数字可以自行产生,我可以对以前看到的数字实现垃圾收集,从而创建一个无限系列。结果只是在Pi系列之后每秒生成一个数字。这是我通过互联网筛选的结果:这是流行的计算机友好算法,类机器算法:defarccot(x,unity)xpow=unity/xn=1sign=1sum=0loopdoterm=xpow/nbreakifterm==0sum+=sign*(xpow/n)xpow/=x*xn+=2sign=-signendsumenddefcalc_pi(digits

  2. ruby - 在 Ruby 程序执行时阻止 Windows 7 PC 进入休眠状态 - 2

    我需要在客户计算机上运行Ruby应用程序。通常需要几天才能完成(复制大备份文件)。问题是如果启用sleep,它会中断应用程序。否则,计算机将持续运行数周,直到我下次访问为止。有什么方法可以防止执行期间休眠并让Windows在执行后休眠吗?欢迎任何疯狂的想法;-) 最佳答案 Here建议使用SetThreadExecutionStateWinAPI函数,使应用程序能够通知系统它正在使用中,从而防止系统在应用程序运行时进入休眠状态或关闭显示。像这样的东西:require'Win32API'ES_AWAYMODE_REQUIRED=0x0

  3. ruby-openid:执行发现时未设置@socket - 2

    我在使用omniauth/openid时遇到了一些麻烦。在尝试进行身份验证时,我在日志中发现了这一点:OpenID::FetchingError:Errorfetchinghttps://www.google.com/accounts/o8/.well-known/host-meta?hd=profiles.google.com%2Fmy_username:undefinedmethod`io'fornil:NilClass重要的是undefinedmethodio'fornil:NilClass来自openid/fetchers.rb,在下面的代码片段中:moduleNetclass

  4. ruby - 将差异补丁应用于字符串/文件 - 2

    对于具有离线功能的智能手机应用程序,我正在为Xml文件创建单向文本同步。我希望我的服务器将增量/差异(例如GNU差异补丁)发送到目标设备。这是计划:Time=0Server:hasversion_1ofXmlfile(~800kiB)Client:hasversion_1ofXmlfile(~800kiB)Time=1Server:hasversion_1andversion_2ofXmlfile(each~800kiB)computesdeltaoftheseversions(=patch)(~10kiB)sendspatchtoClient(~10kiBtransferred)Cl

  5. ruby - 如何在 buildr 项目中使用 Ruby 代码? - 2

    如何在buildr项目中使用Ruby?我在很多不同的项目中使用过Ruby、JRuby、Java和Clojure。我目前正在使用我的标准Ruby开发一个模拟应用程序,我想尝试使用Clojure后端(我确实喜欢功能代码)以及JRubygui和测试套件。我还可以看到在未来的不同项目中使用Scala作为后端。我想我要为我的项目尝试一下buildr(http://buildr.apache.org/),但我注意到buildr似乎没有设置为在项目中使用JRuby代码本身!这看起来有点傻,因为该工具旨在统一通用的JVM语言并且是在ruby中构建的。除了将输出的jar包含在一个独特的、仅限ruby​​

  6. ruby - 什么是填充的 Base64 编码字符串以及如何在 ruby​​ 中生成它们? - 2

    我正在使用的第三方API的文档状态:"[O]urAPIonlyacceptspaddedBase64encodedstrings."什么是“填充的Base64编码字符串”以及如何在Ruby中生成它们。下面的代码是我第一次尝试创建转换为Base64的JSON格式数据。xa=Base64.encode64(a.to_json) 最佳答案 他们说的padding其实就是Base64本身的一部分。它是末尾的“=”和“==”。Base64将3个字节的数据包编码为4个编码字符。所以如果你的输入数据有长度n和n%3=1=>"=="末尾用于填充n%

  7. ruby - 如何指定 Rack 处理程序 - 2

    Rackup通过Rack的默认处理程序成功运行任何Rack应用程序。例如:classRackAppdefcall(environment)['200',{'Content-Type'=>'text/html'},["Helloworld"]]endendrunRackApp.new但是当最后一行更改为使用Rack的内置CGI处理程序时,rackup给出“NoMethodErrorat/undefinedmethod`call'fornil:NilClass”:Rack::Handler::CGI.runRackApp.newRack的其他内置处理程序也提出了同样的反对意见。例如Rack

  8. ruby - 在 Ruby 中编写命令行实用程序 - 2

    我想用ruby​​编写一个小的命令行实用程序并将其作为gem分发。我知道安装后,Guard、Sass和Thor等某些gem可以从命令行自行运行。为了让gem像二进制文件一样可用,我需要在我的gemspec中指定什么。 最佳答案 Gem::Specification.newdo|s|...s.executable='name_of_executable'...endhttp://docs.rubygems.org/read/chapter/20 关于ruby-在Ruby中编写命令行实用程序

  9. ruby-on-rails - 如何在 ruby​​ 中使用两个参数异步运行 exe? - 2

    exe应该在我打开页面时运行。异步进程需要运行。有什么方法可以在ruby​​中使用两个参数异步运行exe吗?我已经尝试过ruby​​命令-system()、exec()但它正在等待过程完成。我需要用参数启动exe,无需等待进程完成是否有任何ruby​​gems会支持我的问题? 最佳答案 您可以使用Process.spawn和Process.wait2:pid=Process.spawn'your.exe','--option'#Later...pid,status=Process.wait2pid您的程序将作为解释器的子进程执行。除

  10. ruby-on-rails - Rails 应用程序之间的通信 - 2

    我构建了两个需要相互通信和发送文件的Rails应用程序。例如,一个Rails应用程序会发送请求以查看其他应用程序数据库中的表。然后另一个应用程序将呈现该表的json并将其发回。我还希望一个应用程序将存储在其公共(public)目录中的文本文件发送到另一个应用程序的公共(public)目录。我从来没有做过这样的事情,所以我什至不知道从哪里开始。任何帮助,将不胜感激。谢谢! 最佳答案 无论Rails是什么,几乎所有Web应用程序都有您的要求,大多数现代Web应用程序都需要相互通信。但是有一个小小的理解需要你坚持下去,网站不应直接访问彼此

随机推荐