【问题标题】:Call Android methods from JavaScript从 JavaScript 调用 Android 方法
【发布时间】:2014-05-18 16:13:42
【问题描述】:

我搜索了,但没有找到答案。我正在使用 HTML5 和 JavaScript 开发基于 webview 的 Android 应用程序。我可以从 JavaScript 调用 Android 方法,例如 makeToast()

【问题讨论】:

标签: javascript android html webview


【解决方案1】:

您可以通过将 JavaScript 接口添加到您的 WebView 并将特定方法公开给在您的 Web 视图中运行的 JavaScript 代码来实现此目的。换句话说,您需要将对 Android 的 Toast 类的调用封装在您在 Activity/Fragment 中创建的方法中。

activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <WebView android:id="@+id/web_view"
                android:layout_width="fill_parent"
                android:layout_height="fill_parent"/>

</RelativeLayout>

MainActivity.java

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        WebView webView = (WebView)findViewById(R.id.web_view);
        webView.loadUrl("file:///android_asset/web.html");

        webView.getSettings().setJavaScriptEnabled(true);
        webView.addJavascriptInterface(new WebViewJavaScriptInterface(this), "app");
    }

    /*
     * JavaScript Interface. Web code can access methods in here 
     * (as long as they have the @JavascriptInterface annotation)
     */
    public class WebViewJavaScriptInterface{

        private Context context;

        /*
         * Need a reference to the context in order to sent a post message
         */
        public WebViewJavaScriptInterface(Context context){
            this.context = context;
        }

        /* 
         * This method can be called from Android. @JavascriptInterface 
         * required after SDK version 17. 
         */
        @JavascriptInterface
        public void makeToast(String message, boolean lengthLong){
            Toast.makeText(context, message, (lengthLong ? Toast.LENGTH_LONG : Toast.LENGTH_SHORT)).show();
        }
    }

}

资产/web.html

<!DOCTYPE html>
<html>
<head>
    <title>JavaScript View</title>

    <script type="text/javascript">

        function showToast(){
            var message = document.getElementById("message").value;
            var lengthLong = document.getElementById("length").checked;

            /* 
                Call the 'makeToast' method in the Java code. 
                'app' is specified in MainActivity.java when 
                adding the JavaScript interface. 
             */
            app.makeToast(message, lengthLong);
            return false;
        }

        /* 
            Call the 'showToast' method when the form gets 
            submitted (by pressing button or return key on keyboard). 
         */
        window.onload = function(){
            var form = document.getElementById("form");
            form.onsubmit = showToast;
        }
    </script>
</head>

<body>

<form id="form">
    Message: <input id="message" name="message" type="text"/><br />
    Long: <input id="length" name="length" type="checkbox" /><br />

    <input type="submit" value="Make Toast" />
</form>

</body>
</html>

【讨论】:

  • 太棒了,这正是我所需要的。谢谢!
  • @Ian,这看起来正是我正在寻找的,但是当我从我的 JavaScript 中调用该方法时出现错误,如下所示:(function(event){appInterface.reloadSite();return false;})。这是在 HTML IMG 元素上使用 onClick="appInterface.reloadSite();return false;" 调用的,我的 JavaScript 界面是使用 mWebView.addJavascriptInterface(new WebViewJavaScriptInterface(this), "appInterface"); 创建的,不幸的是 Chrome 的调试检查器控制台中的错误不是很有帮助。
  • 抱歉,我不确定。也许 Java 代码缺少 @JavascriptInterface 注释??
  • 我有两个方法要从 JavaScript onClick 事件中调用,并且在 WebViewJavaScriptInterface 类中的定义之前都有 @JavascriptInterace。如何从 JavaScript 调用方法(通过回调或其他方式)是否有什么特别需要的,或者我可以直接通过我描述的 onClick 事件调用?
  • 我发现了我的问题...我调用的方法做了需要在 UI 线程中运行的事情。似乎任何通过 JavaScript 接口运行的东西都会在它自己的线程中运行,所以你需要使用RunOnUiThread() - 如stackoverflow.com/questions/5161951/… 中所述 - 做任何影响视图等的事情。
【解决方案2】:
【解决方案3】:

只是因为它更方便(布局):

<?xml version="1.0" encoding="utf-8"?>
<WebView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/webView"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" />

【讨论】:

  • 你在说什么?
  • 我说如果WebView在屏幕上拉伸的话,在RelativeLayout中插入WebView是没有意义的。 WebView 逻辑上用作根元素。
【解决方案4】:

创建 Main Activity 代码后,您需要创建 Javascript 代码并从中调用 WebviewInterface,让我们看看示例:

public class MainActivity extends AppCompatActivity {

String TAG = "MainActivity";
Context context;
WebView mWebView;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    context = this;

    mWebView = (WebView) findViewById(R.id.webview);
    initWebView();

    String ENROLLMENT_URL = "file:///android_asset/about_page.html";
    mWebView.loadUrl(ENROLLMENT_URL);

}

@SuppressLint({ "SetJavaScriptEnabled" })
private void initWebView() {
    mWebView.getSettings().setJavaScriptEnabled(true);
    mWebView.setWebChromeClient(new WebChromeClient());
    mWebView.addJavascriptInterface(new WebviewInterface(), "Interface");
}

public class WebviewInterface {
    @JavascriptInterface
    public void javaMehod(String val) {
        Log.i(TAG, val);
        Toast.makeText(context, val, Toast.LENGTH_SHORT).show();
    }
}
}

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.legendblogs.android.MainActivity">

<WebView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/webview"/>


</RelativeLayout>

Look at this link to see full example https://www.legendblogs.com/blog/how-to-call-native-java-methods-from-webview-javascript/121764

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-09-16
    • 1970-01-01
    • 2016-05-07
    • 2012-02-07
    • 2012-05-07
    • 2015-05-13
    • 2015-08-18
    相关资源
    最近更新 更多