App Inventor 2 执行JavaScript代码教程 - WebView与JS交互

« 返回首页

概述

App Inventor 2的WebView组件不仅可以显示网页,还能执行JavaScript代码并与App进行双向数据交互。这极大扩展了App Inventor的能力,可以实现:

  • 复杂数学计算
  • 调用第三方JavaScript库(ECharts、Three.js等)
  • 处理XML/HTML数据
  • 实现更丰富的UI效果
  • 加密解密运算

WebView组件关键属性和方法

属性

属性 说明
HomeUrl WebView加载的页面地址
WebViewString App与WebView之间的字符串通信通道
UsesLocation 是否允许使用地理位置

方法

方法 说明
RunJavaScript(jsCode) 在WebView中执行JavaScript代码
GoBack() 后退
GoForward() 前进
Reload() 刷新页面

事件

事件 说明
WebViewStringChanged(value) 当WebViewString的值改变时触发
PageLoaded(url) 页面加载完成时触发

核心机制:WebViewString

WebViewString 是App Inventor和WebView中HTML页面之间通信的桥梁:

  • App → WebView:设置 WebView1.WebViewString = "数据"
  • WebView → App:在JavaScript中 window.AppInventor.setWebViewString("数据")
  • App接收:通过 WebViewStringChanged 事件获取

JavaScript端的接口

在HTML/JavaScript中,App Inventor提供了以下接口:

// 从WebView向App发送数据
window.AppInventor.setWebViewString("要发送的数据");

// 从App接收数据(通过WebViewString)
var received = window.AppInventor.getWebViewString();

方式一:运行JavaScript代码(RunJavaScript)

最直接的方式,无需准备HTML文件,直接执行JS代码。

示例:用JavaScript进行复杂计算

当 按钮_计算.被点击
  设 表达式 = 输入框_表达式.文本
  调用 WebView1.运行JavaScript("window.AppInventor.setWebViewString(eval('" & 表达式 & "'))")

当 WebView1.WebView字符串改变(值)
  标签_结果.文本 = "计算结果:" & 值

注意:使用 eval() 有安全风险,仅用于信任的输入。生产环境建议使用更安全的解析方式。

示例:生成UUID

当 按钮_生成UUID.被点击
  调用 WebView1.运行JavaScript("window.AppInventor.setWebViewString(crypto.randomUUID())")

当 WebView1.WebView字符串改变(值)
  标签_UUID.文本 = 值

示例:Base64编解码

当 按钮_编码.被点击
  调用 WebView1.运行JavaScript("window.AppInventor.setWebViewString(btoa('" & 输入框_文本.文本 & "'))")

当 按钮_解码.被点击
  调用 WebView1.运行JavaScript("window.AppInventor.setWebViewString(atob('" & 输入框_文本.文本 & "'))")

方式二:加载HTML文件 + JS交互

更强大的方式是加载自定义HTML文件,可以引入第三方JS库。

步骤1:创建HTML文件

创建 calculator.html 放到项目Assets中:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
body { font-family: sans-serif; padding: 10px; background: #f5f5f5; }
#result { font-size: 18px; color: #333; }
</style>
</head>
<body>
<div id="result">等待计算...</div>
<script>
// 监听来自App的数据
setInterval(function() {
  var data = window.AppInventor.getWebViewString();
  if (data && data !== "") {
    try {
      var result = calculate(data);
      document.getElementById('result').textContent = "结果: " + result;
      window.AppInventor.setWebViewString("RESULT:" + result);
    } catch(e) {
      window.AppInventor.setWebViewString("ERROR:" + e.message);
    }
    // 清空避免重复处理
    window.AppInventor.setWebViewString("");
  }
}, 100);

function calculate(expr) {
  // 安全的数学表达式计算
  return Function('"use strict"; return (' + expr + ')')();
}
</script>
</body>
</html>

步骤2:在App Inventor中加载和使用

当 Screen1.初始化
  设 WebView1.主页地址 = "file:///android_asset/calculator.html"

当 按钮_计算.被点击
  设 WebView1.WebView字符串 = 输入框_表达式.文本

当 WebView1.WebView字符串改变(值)
  如果 值 以 "RESULT:" 开头
    设 结果 = 替换文本(值, "RESULT:", "")
    标签_结果.文本 = "计算结果:" & 结果
  否则 如果 值 以 "ERROR:" 开头
    设 错误 = 替换文本(值, "ERROR:", "")
    标签_结果.文本 = "错误:" & 错误

实战案例:用ECharts绘制图表

HTML文件(echarts_demo.html)

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://cdn.jsdelivr.net/npm/echarts@5/dist/echarts.min.js"></script>
<style>
body { margin: 0; }
#chart { width: 100%; height: 300px; }
</style>
</head>
<body>
<div id="chart"></div>
<script>
var myChart = echarts.init(document.getElementById('chart'));
var option = {
  xAxis: { type: 'category', data: [] },
  yAxis: { type: 'value' },
  series: [{ type: 'line', data: [] }]
};

setInterval(function() {
  var data = window.AppInventor.getWebViewString();
  if (data && data !== "") {
    try {
      var parsed = JSON.parse(data);
      if (parsed.type === 'update') {
        option.xAxis.data = parsed.labels;
        option.series[0].data = parsed.values;
        myChart.setOption(option);
      }
    } catch(e) {}
    window.AppInventor.setWebViewString("");
  }
}, 200);
</script>
</body>
</html>

App Inventor积木块

当 Screen1.初始化
  设 WebView1.主页地址 = "file:///android_asset/echarts_demo.html"

当 按钮_更新图表.被点击
  设 数据JSON = "{""type"":""update"",""labels"":[""1月"",""2月"",""3月""],""values"":[10,20,15]}"
  设 WebView1.WebView字符串 = 数据JSON

实战案例:调用第三方JS库处理图像

HTML文件(image_processor.html)

<!DOCTYPE html>
<html>
<head>
<script src="https://cdn.jsdelivr.net/npm/tesseract.js@5/dist/tesseract.min.js"></script>
</head>
<body>
<script>
setInterval(function() {
  var data = window.AppInventor.getWebViewString();
  if (data && data.startsWith("OCR:")) {
    var imageData = data.substring(4);
    Tesseract.recognize(imageData, 'chi_sim+eng')
      .then(function(result) {
        window.AppInventor.setWebViewString("OCR_RESULT:" + result.data.text);
      });
  }
}, 500);
</script>
</body>
</html>

数据传递注意事项

1. 转义特殊字符

传递给JavaScript的字符串中如果有单引号、换行符等,需要转义:

定义 安全转义(文本) 返回 结果
  设 结果 = 替换全部 文本 中的 "'" 为 "\\'"
  设 结果 = 替换全部 结果 中的 换行符 为 "\\n"
  设 结果 = 替换全部 结果 中的 "\\" 为 "\\\\"
  返回 结果

2. 大数据量传递

WebViewString有大小限制,大数据建议分段传递或使用JSON压缩。

3. 时序问题

PageLoaded事件触发后再发送数据,确保HTML已加载完成:

当 WebView1.页面加载完成(网址)
  // 页面加载完成后才发送数据
  设 WebView1.WebView字符串 = "初始化数据"

WebView执行JS的限制

限制 说明
需要WebView可见 WebView必须加载过页面后RunJavaScript才能工作
主线程执行 JS在主线程运行,长时间运算会阻塞UI
网络限制 Assets中的HTML访问外部CDN需要网络权限
跨域限制 本地HTML文件访问外部API可能受CORS限制
字符串通信 只能通过WebViewString传递文本数据

常见问题

Q1: RunJavaScript没有反应?

确保WebView已经加载了一个页面。可以先加载一个空白页面:

当 Screen1.初始化
  设 WebView1.主页地址 = "about:blank"
  ' 或加载一个HTML文件

Q2: setWebViewString在JavaScript中不生效?

检查是否正确使用了App Inventor的接口名称:

  • window.AppInventor.setWebViewString("data")
  • window.webkit.messageHandlers...(这是iOS的)

Q3: 如何调试WebView中的JavaScript?

在HTML中添加调试输出:

// 在HTML中
function debugLog(msg) {
  document.title = "[DEBUG] " + msg;
}

// 在App Inventor中监听
 WebView1.页面加载完成(网址)
  // 可以通过document.title读取调试信息

Q4: 加载本地HTML文件时外部JS库加载不了?

确保:

  1. HTML文件放在Assets目录中
  2. 使用CDN的完整URL(https://
  3. App有INTERNET权限
  4. 或者将JS库也放到Assets中,用相对路径引用

总结

方式 适用场景 复杂度
RunJavaScript 简单计算、一次性操作
HTML+WebViewString 复杂交互、第三方库 ⭐⭐⭐
HTML+轮询 持续数据交换 ⭐⭐

推荐做法

  • 简单JS执行 → RunJavaScript
  • 需要第三方库 → 加载HTML文件 + WebViewString
  • 双向通信 → HTML轮询 + WebViewString

版权声明:MIT App Inventor 官方文档采用 CC BY-SA 4.0 授权,本文档由 ai2claw 🐝 整理。

文档反馈