当前位置:

首页 > 编程开发 > Android与JS进行交互的实现方法

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

1. 交互方式总结 先说几个核心判断。Android 调用 JS 代码,主流方案有两种:一种是 WebView 的 loadUrl(),另一种是 evaluateJa vascript()。而 JS 反过来调用 Android 代码,则有三种常见手段:通过 addJa vascriptInterfa

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能满足大多数场景
本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系bd@zhengruan.com
作者最新文章
编程开发
相关文章 更多
WPS 表格怎么删除表格内多余空格
WPS 表格怎么删除表格内多余空格

WPS表格中多余空格会导致数据匹配失败。本文详解如何区分首尾空格与业务分隔空格,使用查找替换和TRIM函数安全清理数据,并处理全角空格等隐藏字符,确保数据清洗后字段含义准确。

会声会影怎么区分内嵌字幕和独立字幕轨道
会声会影怎么区分内嵌字幕和独立字幕轨道

遇到视频字幕无法单独选中或删除?本文详解如何在会声会影中通过时间轴对象、轨道隐藏测试及字幕文件逻辑,准确区分内嵌硬字幕与独立软字幕轨道,并提供对应的修改、删除或遮盖技巧。

WPS 表格跨工作表引用数据怎么做
WPS 表格跨工作表引用数据怎么做

学习如何在WPS表格中跨工作表引用数据。掌握点选生成公式、SUMIF跨表汇总、绝对引用锁定及改名后的维护技巧,避免常见报错,提升报表制作效率。

会声会影多重修整视频:一次性剪辑多个片段的详细教程
会声会影多重修整视频:一次性剪辑多个片段的详细教程

面向需要从长视频中提取多个精彩片段的用户,利用会声会影的“多重修整视频”功能可避免反复切割素材的繁琐。本文详解如何在同一对话框内标记多段起止点,通过设置开始与结束标记批量生成独立片段,并介绍快速搜索定位技巧,帮助用户高效完成视频筛选与剪辑工作。

iPhone如何在AppStore下载立刻MV
iPhone如何在AppStore下载立刻MV

想在iPhone上使用立刻MV制作AI音乐视频?本指南详解如何在App Store准确搜索“立刻MV”,核对开发者ZhongManZhiSheng及iOS 17.0系统要求,完成安全下载与安装,并介绍首次启动后的核心功能入口。

会声会影剪辑教程:利用黄色标记快速截取视频片段
会声会影剪辑教程:利用黄色标记快速截取视频片段

面向使用会声会影进行基础视频编辑的用户,解决从长视频中精准截取所需片段的痛点。本文详细介绍利用时间轴上的黄色标记功能进行非破坏性剪辑的操作路径:包括将素材插入视频轨,通过拖动素材首尾端点设定起始与结束位置,从而快速分离出目标片段并预览效果。该方法操作直观,适合新手快速掌握视频裁剪技巧。

会声会影2023内嵌视频字幕怎么处理
会声会影2023内嵌视频字幕怎么处理

遇到会声会影2023中点不中的视频字幕?这通常是内嵌字幕。本文教你快速判断字幕类型,并在没有无字幕源文件时,使用裁剪、色块遮挡和模糊效果进行应急处理,避免画面出现难看的修补痕迹。

WPS 表格打开文件提示格式不兼容怎么处理
WPS 表格打开文件提示格式不兼容怎么处理

遇到WPS表格打开文件提示格式不兼容怎么办?本文教你通过保留副本、另存为转换、修复入口测试及特殊功能排查,安全处理xls/xlsx等格式差异,避免数据丢失。

Lovart中文版网页怎么登录及界面功能介绍
Lovart中文版网页怎么登录及界面功能介绍

新手如何登录Lovart中文版网页?本文详解账号授权步骤,拆解创意工作区、画布预览与对话输入三大核心模块,演示如何用自然语言生成图片及进行局部编辑,助你快速掌握AI设计工具的基础用法。

Windows10安装缺少驱动找不到硬盘解决方案
Windows10安装缺少驱动找不到硬盘解决方案

Windows 10安装时显示“找不到任何驱动器”或提示缺少驱动?本文详解如何通过BIOS确认硬盘状态、核对VMD/RAID存储模式,以及在安装界面正确加载厂商提供的存储控制器驱动(.inf),避免盲目切换设置导致原系统无法启动。

查看更多
精品专题 更多
装机必备
装机必备

正软商城装机必备专区,精选办公、浏览器、安全防护、影音播放、压缩解压、设计创作和系统工具等电脑常用正版软件,帮助用户快速完成新电脑软件配置。

Windows
Windows

正软商城Windows软件专区,汇集适用于Windows电脑的办公、设计、安全防护、影音播放、开发工具和系统优化软件,提供软件介绍、系统要求、正版授权及购买下载服务。

PDF教程
PDF教程

正软商城PDF教程频道提供PDF编辑、转换、合并、拆分、压缩及格式处理方法,同时介绍常用PDF软件和工具的使用技巧。

Mac软件 更多
IntelliJ IDEA macOS版
IntelliJ IDEA macOS版
Mac

IntelliJ IDEA 是 JetBrains 推出的专业集成开发环境,重点服务于 Java、Kotlin 与 JVM 项目开发。软件集成代码补全、静态检查、重构、调试、测试、版本控制及构建工具,并可借助插件扩展语言和框架支持。

PyCharm macOS版
PyCharm macOS版
Mac

JetBrains PyCharm 是面向 Python 开发者的集成开发环境,提供智能补全、代码检查、重构、调试、测试、版本控制及虚拟环境管理功能。Mac 版兼容 Intel 与 Apple 芯片,核心功能可免费使用。

WebStorm macOS版
WebStorm macOS版
Mac

JetBrains WebStorm 是面向 JavaScript、TypeScript 和现代 Web 技术的专业集成开发环境,可智能理解项目结构,提供代码补全、重构、错误检查、运行调试、测试及 Git 工具。

WINDOWS 更多
IntelliJ IDEA Windows版
IntelliJ IDEA Windows版
Windows

JetBrains IntelliJ IDEA 是以 Java、Kotlin 和 JVM 项目为核心的专业集成开发环境,提供智能补全、代码检查、安全重构、调试、测试、版本控制及构建工具集成。统一发行版的核心功能可免费用于商业和非商业项目,

PhpStorm Windows版
PhpStorm Windows版
Windows

PhpStorm 是 JetBrains 面向 PHP 与现代 Web 开发打造的专业集成开发环境,提供代码补全、静态检查、重构、调试、测试、数据库、版本控制及前端语言支持。Windows 用户可直接下载安装程序,

PyCharm Windows版
PyCharm Windows版
Windows

PyCharm 是 JetBrains 推出的 Python 集成开发环境,提供智能代码补全、错误检查、重构、调试、测试、Git、终端及 Jupyter Notebook 支持。统一版安装后可体验 30 天 Pro 功能,