商城首页欢迎来到中国正版软件门户

您的位置: 首页 > 文章列表 > 编程开发 > Android与JS进行交互的实现方法

Android与JS进行交互的实现方法

  发布于2026-07-23 阅读(0)

扫一扫,手机访问

1. 交互方式总结

先说几个核心判断。Android 调用 JS 代码,主流方案有两种:一种是 WebView 的 loadUrl(),另一种是 evaluateJa vascript()。而 JS 反过来调用 Android 代码,则有三种常见手段:通过 addJa vascriptInterface() 做对象映射,通过 WebViewClient 的 shouldOverrideUrlLoading() 拦截 url,或者通过 WebChromeClient 拦截 JS 对话框方法(onJsAlert、onJsConfirm、onJsPrompt)。

这些方法背后的沟通桥梁,其实就是 WebView 本身。

2. Android 调用 JS 代码

2.1 通过 WebView 的 loadUrl()

先准备好 HTML 文件,比如叫 ja vascript.html,放在 assets 目录下。

        JS Interaction        This is a Web View    

然后看 MainActivity.ja va:

package com.example.webviewtest;import android.os.Bundle;import android.view.View;import android.webkit.WebSettings;import android.webkit.WebView;import android.widget.Button;import androidx.appcompat.app.AppCompatActivity;public class MainActivity extends AppCompatActivity {    @Override    protected void onCreate(Bundle sa vedInstanceState) {        super.onCreate(sa vedInstanceState);        setContentView(R.layout.activity_main);        WebView mWebView = findViewById(R.id.webview);        WebSettings webSettings = mWebView.getSettings();        // 允许在 WebView 中执行 JS        webSettings.setJa vaScriptEnabled(true);        // 载入 url        mWebView.loadUrl("file:///android_asset/ja vascript.html");        Button button = findViewById(R.id.button);        button.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                // 调用 JS 的 callJS() 方法                mWebView.loadUrl("ja vascript:callJS()");            }        });    }}

布局文件 activity_main.xml 就不多说了,直接贴出来:

        

这里的关键点在于:只用 loadUrl() 传入字符串 "ja vascript:callJS()",就能调用 JS 中的 callJS() 方法。但必须注意,这个操作会导致页面刷新,而且拿不到 JS 的返回值。

2.2 通过 WebView 的 evaluateJa vascript()

这个方法跟 loadUrl() 相比,优势很明显:

  • 执行效率更高,因为不会触发页面刷新;
  • 但只适用于 Android 4.4 及以上版本;
  • 能拿到 JS 的返回值。

把上面的 HTML 稍微改一下,让 JS 返回一个字符串:

        JS Interaction        This is a Web View    

MainActivity.ja va 对应修改如下:

package com.example.webviewtest;import android.app.AlertDialog;import android.content.DialogInterface;import android.os.Bundle;import android.view.View;import android.webkit.ValueCallback;import android.webkit.WebSettings;import android.webkit.WebView;import android.widget.Button;import androidx.appcompat.app.AppCompatActivity;public class MainActivity extends AppCompatActivity {    @Override    protected void onCreate(Bundle sa vedInstanceState) {        super.onCreate(sa vedInstanceState);        setContentView(R.layout.activity_main);        WebView mWebView = findViewById(R.id.webview);        WebSettings webSettings = mWebView.getSettings();        webSettings.setJa vaScriptEnabled(true);        mWebView.loadUrl("file:///android_asset/ja vascript.html");        Button button = findViewById(R.id.button);        button.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                mWebView.evaluateJa vascript("ja vascript:callJS()", new ValueCallback() {                    @Override                    public void onReceiveValue(String value) {                        // 注意:evaluateJa vascript() 返回的值会被封装成 JSON 格式的字符串                        // 如果 JS 返回 "Hello from Ja vaScript!",Android 端会收到 "\"Hello from Ja vaScript!\""                        // 所以需要手动去掉引号                        String result = value != null ? value.replace("\"", "") : "";                        AlertDialog.Builder b = new AlertDialog.Builder(MainActivity.this);                        b.setTitle("Alert");                        b.setMessage(result);                        b.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {                            @Override                            public void onClick(DialogInterface dialog, int which) {                                dialog.dismiss();                            }                        });                        b.setCancelable(false);                        b.create().show();                    }                });            }        });    }}

evaluateJa vascript() 有两个参数:第一个是 JS 方法字符串,第二个是回调接口,用于接收 JS 执行的返回值。

实际开发中,建议在 Android 4.4 以下用 loadUrl(),4.4 及以上用 evaluateJa vascript()。可以这样判断:

final int version = Build.VERSION.SDK_INT;if (version < Build.VERSION_CODES.KITKAT) {        mWebView.loadUrl("ja vascript:callJS()");    } else {        mWebView.evaluateJa vascript("ja vascript:callJS()", new ValueCallback() {            @Override            public void onReceiveValue(String value) {            }        });}

还有一点:最好在 WebView 页面加载完成之后,再调用 JS 代码,比如在 WebViewClient 的 onPageFinished() 方法中执行。

2.3 两种方法的对比

调用方式优点缺点使用建议
loadUrl()简单执行效率低,获取返回值麻烦Android 4.4 以下用这个方法
evaluateJa vascript()执行效率高向下兼容性差(Android 4.4 以上可用)Android 4.4 以上用这个方法

3. JS 调用 Android 代码

3.1 通过 WebView 的 addJa vascriptInterface() 进行对象映射

步骤一:定义一个类,注入到 JS 中。

package com.example.webviewtest;import android.webkit.Ja vascriptInterface;public class JsObject {    // 注意:Android 4.2 及以上版本,只有添加了 @Ja vascriptInterface 注解的 public 方法才能被 JS 访问    @Ja vascriptInterface    public void hello(String msg) {        System.out.println(" JS 调用了 Android 的 hello 方法");    }}

步骤二:在 assets 目录下创建 ja vascript.html。

        JS Interaction    

步骤三:在 Android 中通过 addJa vascriptInterface() 方法将 Ja va 对象注入 WebView 的 Ja vaScript 环境。

package com.example.webviewtest;import android.os.Bundle;import android.webkit.WebSettings;import android.webkit.WebView;import androidx.appcompat.app.AppCompatActivity;public class MainActivity extends AppCompatActivity {    WebView mWebView;    @Override    protected void onCreate(Bundle sa vedInstanceState) {        super.onCreate(sa vedInstanceState);        setContentView(R.layout.activity_main);        mWebView = findViewById(R.id.webview);        WebSettings webSettings = mWebView.getSettings();        webSettings.setJa vaScriptEnabled(true);        // 参数1:注入的 Ja va 对象        // 参数2:暴露在 JS 中的实例名        mWebView.addJa vascriptInterface(new JsObject(), "test");        mWebView.loadUrl("file:///android_asset/ja vascript.html");    }}

布局文件:

    

这样,点击 HTML 中的 button 就会触发 callAndroid(),进而调用 test 实例的 hello() 方法。这个方案简单易用,但有一个历史遗留问题:在 Android 4.2 以下版本存在安全漏洞。Google 从 Android 4.2 开始要求被调用的方法必须用 @Ja vascriptInterface 注解来防范漏洞攻击,但在 4.2 以下版本这个注解无效,仍然存在风险。如果需要在低版本上使用,通常需要配合拦截 prompt() 的方式进行漏洞修复。

3.2 通过 WebViewClient 的 shouldOverrideUrlLoading() 方法拦截 url

ja vascript.html 内容如下:

        JS Interaction    

MainActivity.ja va:

package com.example.webviewtest;import android.net.Uri;import android.os.Build;import android.os.Bundle;import android.util.Log;import android.webkit.WebResourceRequest;import android.webkit.WebSettings;import android.webkit.WebView;import android.webkit.WebViewClient;import androidx.appcompat.app.AppCompatActivity;import ja va.util.Set;public class MainActivity extends AppCompatActivity {    private static final String TAG = MainActivity.class.getSimpleName();    @Override    protected void onCreate(Bundle sa vedInstanceState) {        super.onCreate(sa vedInstanceState);        setContentView(R.layout.activity_main);        WebView mWebView = findViewById(R.id.webview);        WebSettings webSettings = mWebView.getSettings();        webSettings.setJa vaScriptEnabled(true);        mWebView.loadUrl("file:///android_asset/ja vascript.html");        mWebView.setWebViewClient(new WebViewClient() {            // 旧重载方法在 Android 7.0 以上已废弃            @Override            public boolean shouldOverrideUrlLoading(WebView view, String url) {                return super.shouldOverrideUrlLoading(view, url);            }            @Override            public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {                // 传入进来的 url = "js://webview?arg1=111&arg2=222"                Uri uri;                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {                    uri = request.getUrl();                } else {                    uri = Uri.parse(request.toString());                }                // 先判断 scheme                if ("js".equals(uri.getScheme())) {                    // 再判断 authority                    if ("webview".equals(uri.getAuthority())) {                        // 执行对应的代码                        Log.d(TAG, "JS 调用了 Android 的方法");                        Set sets = uri.getQueryParameterNames();                        for (String key : sets) {                            Log.d(TAG, "param:" + uri.getQueryParameter(key));                        }                        return true;                    }                }                return super.shouldOverrideUrlLoading(view, request);            }        });    }}

核心原理就是通过解析 URL 的协议来执行相应的 Android 代码。这个方案没有 addJa vascriptInterface() 的安全漏洞,但如果 JS 想获取 Android 方法的返回值,就比较麻烦了——只能通过 WebView 的 loadUrl() 去调用 JS 中的方法,把返回值传过去。

// Android:mWebView.loadUrl("ja vascript:returnResult(" + result + ")");// JS:ja vascript.htmlfunction returnResult(result){    alert("result is" + result);}

3.3 通过 WebChromeClient 的 onJsAlert()、onJsConfirm()、onJsPrompt() 方法回调拦截

JS 中三个常用的对话框方法:

  • alert():弹出警告框,没有返回值,文本中加 \n 可以换行;
  • confirm():弹出确认框,返回 true 或 false;
  • prompt():弹出输入框,可以任意设置返回值,返回点击确认后的字符串,取消则返回 null。

这三个方法分别会触发 WebChromeClient 的 onJsAlert()、onJsConfirm()、onJsPrompt() 方法。最常用的是 prompt(),因为只有它能返回任意类型的值。看一个例子:

ja vascript.html:

        JS Interactiion    

MainActivity.ja va:

package com.example.webviewtest;import android.net.Uri;import android.os.Bundle;import android.util.Log;import android.webkit.JsPromptResult;import android.webkit.WebChromeClient;import android.webkit.WebSettings;import android.webkit.WebView;import androidx.appcompat.app.AppCompatActivity;import ja va.util.Set;public class MainActivity extends AppCompatActivity {    private static final String TAG = MainActivity.class.getSimpleName();    @Override    protected void onCreate(Bundle sa vedInstanceState) {        super.onCreate(sa vedInstanceState);        setContentView(R.layout.activity_main);        WebView mWebView = findViewById(R.id.webview);        WebSettings webSettings = mWebView.getSettings();        webSettings.setJa vaScriptEnabled(true);        mWebView.loadUrl("file:///android_asset/ja vascript.html");        mWebView.setWebChromeClient(new WebChromeClient() {            @Override            public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result) {                // 传入进来的 url = "js://webview?arg1=8&arg2=9"                Uri uri = Uri.parse(message);                if (uri.getScheme().equals("js")) {                    if (uri.getAuthority().equals("webview")) {                        // 执行对应的代码                        Log.d(TAG, "JS 调用了 Android 的方法");                        Set sets = uri.getQueryParameterNames();                        for (String key : sets) {                            Log.d(TAG, "param:" + uri.getQueryParameter(key));                        }                        // JsPromptResult 用于把结果返回给 JS                        result.confirm("JS 调用 Android 的方法成功啦!");                    }                    return true;                }                return super.onJsPrompt(view, url, message, defaultValue, result);            }        });    }}

3.4 三种方法的对比

调用方式优点缺点使用场景
通过 WebView 的 addJa vascriptInterface() 进行对象映射简单Android 4.2 以下存在漏洞Android 4.2 以上用这个方法
通过 WebViewClient 的 shouldOverrideUrlLoading() 方法拦截 url没有漏洞问题相对复杂,需要解析 url不需要 Android 端的方法的返回值的场景
通过 WebChromeClient 的 onJsAlert()、onJsConfirm()、onJsPrompt() 方法回调拦截没有漏洞问题相对复杂,需要解析 url能满足大多数场景
本文转载于:https://www.jb51.net/javascript/356077fsm.htm 如有侵犯,请联系zhengruancom@outlook.com删除。
免责声明:正软商城发布此文仅为传递信息,不代表正软商城认同其观点或证实其描述。

热门关注