当前位置: 首页 > article >正文

【笔记】Trae+Andrioid Studio+Kotlin开发安卓WebView应用

文章目录

  • 简介
  • 依赖
  • 步骤
    • AS(Andriod Studio)创建项目
    • AS创建虚拟机
    • TRAE CN 修改项目
      • 新增按键捕获功能
    • 新增WebView
    • WebView加载本地资源
      • 在按键回调中向WebView注入JS代码
  • 最终关键代码
  • 吐槽

简介

使用Trae配合Andriod Studio开发一个内嵌WebView的安卓应用, 在WebView中加载本地资源, 在APP中捕获按键事件对WebView中的内容进行操作;

依赖

  • Trae CN (https://www.trae.com.cn/)
  • Andriod Studio (https://developer.android.google.cn/studio?hl=zh-cn), 以下简称AS
    • 吃内存, 占用了我大约6GB内存
    • 下载项目依赖和安卓虚拟机(约2GB)依赖网络
  • 基础的编程知识

步骤

AS(Andriod Studio)创建项目

  • 打开AS, 创建一个Empty Activity
    在这里插入图片描述
    在这里插入图片描述
  • 在AS打开新窗口后, 等待右下角进度条初始化完毕(下载依赖和编译)

AS创建虚拟机

  • 在右上角创建虚拟机
    在这里插入图片描述
    在这里插入图片描述
  • 找到镜像, 如果是灰色的, 需要点击下载图标进入下载界面(大约2G, 非常依赖网络)
    在这里插入图片描述
    在这里插入图片描述
  • 启动模板项目
    在这里插入图片描述
    在这里插入图片描述

TRAE CN 修改项目

  • 使用Trae打开该文件夹
  • 按下Ctrl+P, 在顶部打开的输入框中输入Main, 选择MainActivity.kt
    在这里插入图片描述
  • 按下Ctrl+U开启右侧AI工具

新增按键捕获功能

  • 输入提示"我想要安卓应用可以捕获键盘的上下2个方向键并打印日志信息"

    • 生成完毕后, 在提示框的上方选择"全部接受"
      在这里插入图片描述
  • 打开AS, 会自动刷新代码, 点击右上角的绿色重启按钮或者启动按钮重新编译和启动
    在这里插入图片描述
    在这里插入图片描述

  • 切换到日志查看界面
    在这里插入图片描述

  • 鼠标点击模拟器中的应用的白色区域, 后按下上下键, 可看到日志输出

新增WebView

  • 输入提示"我想将Greeting中的Text控件替换为Webview"
    • 生成完毕后, 选择"全部接受"
  • 这里有个报错信息, 把鼠标移动到红色的文字上会给出提示, 点击import修复一下
    在这里插入图片描述
  • 回到AS, 点击右上角的绿色重启按钮或者启动按钮重新编译和启动
  • 出现了网络连接的错误
    在这里插入图片描述
  • 回到TRAE, 输入提示信息界面提示"webpage not avalible"
    • 在点击"全部接受"前, 我看了修复内容, 它没添加网络权限还把地址改成google了, 这个方案是不行的, 所以点击"全部拒绝"
  • 重新输入提示"应该是没有配置网络权限, 修复一下"
    • 它给"AndroidManifest.xml"的文件内容清空了, 添加了一行权限代码, 这个方案是不行的, 所以点击"全部拒绝"
  • 重新输入提示"应该是没有配置网络权限, 添加一下相关的权限, 注意不要影响原有的配置信息"
    • 这次正确的添加了权限, 选择接受
      在这里插入图片描述
  • 回到AS重启项目, 结果提示xml有问题, 仔细一看, 它代码加错位置了, 手动调整一下, 向下挪动一行
    在这里插入图片描述
  • 还是无法打开页面
  • 回到TRAE输入提示信息"还是提示"webpage not avalible", 是不是还缺少哪个网络权限", 给出新的修复
    在这里插入图片描述
  • 重启后还是不能打开页面, 重启一下虚拟机
    在这里插入图片描述
    在这里插入图片描述
  • 还是不行, 换了百度网址也不行, 打开自带的谷歌浏览器也访问不了网络, 最后是在下拉的通知栏里重新开关wifi后解决(上一步操作没有成功停止虚拟机)
    在这里插入图片描述
  • 此时发现按键事件的捕获失效了
  • 输入提示信息"按键事件被Webview捕获了导致应用程序的无法捕获上下键了, 修复一下" (这里我之前尝试过几次提问, 最后发现是Webview优先处理了事件导致的)
    在这里插入图片描述
  • 回到AS, 编译报错了, 把提示信息MainActivity.kt:61:17 Modifier 'override' is not applicable to 'local function'发给TRAE
    • 新回复删除了override解决了报错, 但是没有解决按键的问题
  • 重新输入提示"不行, 按键事件还是没有被APP捕获到", 生成了新回复
    在这里插入图片描述
  • 重启项目, 成功解决按键问题

WebView加载本地资源

  • 输入提示"我想打印webview都请求了哪些链接"
    • 新增了一个shouldInterceptRequest方法, 这里的斜杠是多余的, 导致没能正确打印日志, 手动删除一下
      在这里插入图片描述
      在这里插入图片描述
  • 输入提示信息"我想在shouldInterceptRequest中拦截请求, 然后加载本地的资源文件"
    在这里插入图片描述
  • 输入提示"本地资源文件需要放在哪个目录, 帮我生成一个示例"
    • 这里给出了2步, 一个是手动创建本地文件夹和文件, 一个是修改MainActivity.kt(没有自动修改, 可以点击应用按钮)
      在这里插入图片描述
      在这里插入图片描述
      在这里插入图片描述
  • 还需要修改一下拦截的地址(下面的日志打印又改回错误的了, 手动修复一下)
    在这里插入图片描述
  • 有2个导入报错, 鼠标移动到红色文字上, 给出了提示信息, 点击import导入一下, 重启项目
    在这里插入图片描述

在按键回调中向WebView注入JS代码

  • 输入提示信息"我想在onKeyDown的回调中修改WebView中的显示内容"
    • 给了一个通过findViewById实现的方法, 接受后发现不能用, 退回一下
      在这里插入图片描述
  • 输入提示信息"我想在onKeyDown的回调中修改Greeting中创建的WebView中的显示内容"
    • 这次他给WebView加了个全局变量webViewInstance, 但是修改后的代码少了花括号, 手动修复一下
  • 发现没效果, 手动加了日志打印了一下日志发现webViewInstance是空的
  • 输入提示信息"webViewInstance是null, 是不是哪里有问题, 导致没赋值成功"
    • 只是加了日志, 没解决
  • 输入提示信息"Greeting 中返回 webView 的时候, webView 还没初始化吧?"
    • 发癫了, 胡乱输出
  • 输入提示信息"AndroidView 中是不是异步执行的, 导致返回的webview是null"
    • 偷懒了, 不想解决问题, 一味的加日志
  • 输入提示信息"已打印日志确认Greeting中返回的webView是null"
    • 还是加日志
      在这里插入图片描述
  • 输入提示信息"通过日志发现WebViewReturn提示webView有值, WebViewRequests处为null, 且WebViewRequests 先WebViewReturn输出, 可以确定AndroidView异步执行导致的返回null, 修复一下"
    • 这次改成了回调的方式, 成功解决
  • 输入提示信息"不要跳转到new-url, 而是执行JS代码"
    在这里插入图片描述
  • 手动修改一下
    在这里插入图片描述
  • 没注意看, 重新输入提示"不要使用webViewInstance?.loadUrl, 使用注入JS的方式"
    在这里插入图片描述
  • 发现没效果, 打开Edge, 访问"edge://inspect/#devices", chrome不行, 会超时然后显示404
    在这里插入图片描述
  • 在控制台直接粘贴JS, 发现js没有问题
  • 输入提示信息"evaluateJavascript 没有效果", 给出新修复
    在这里插入图片描述
  • 重启, 按下上键, 成功解决
    在这里插入图片描述

最终关键代码

  • MainActivity.kt
package com.example.dm2import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import com.example.dm2.ui.theme.DM2Theme
import android.util.Log
import android.view.KeyEvent
import android.webkit.WebView
import android.webkit.WebViewClient
import android.webkit.WebResourceRequest
import android.webkit.WebResourceResponse
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.viewinterop.AndroidView
import java.io.IOExceptionvar webViewInstance: WebView? = nullclass MainActivity : ComponentActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContent {DM2Theme {Surface(modifier = Modifier.fillMaxSize(),color = MaterialTheme.colorScheme.background) {Greeting("Android") { webView ->webViewInstance = webView}}}}}override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {when (keyCode) {KeyEvent.KEYCODE_DPAD_UP -> {Log.d("KeyEvent", "上方向键被按下" + webViewInstance)webViewInstance?.evaluateJavascript("document.body.innerText = new Date();", null)return true}}return super.onKeyDown(keyCode, event)}
}@Composable
fun Greeting(name: String, modifier: Modifier = Modifier, onWebViewCreated: (WebView) -> Unit = {}) {val context = LocalContext.currentAndroidView(factory = {ctx ->val webView = WebView(ctx).apply {settings.javaScriptEnabled = trueLog.d("WebViewInit", "WebView实例已创建: $this")webViewClient = object : WebViewClient() {override fun shouldInterceptRequest(view: WebView, request: WebResourceRequest): android.webkit.WebResourceResponse? {val url = request.url.toString()if (url.equals("https://www.example.com/")) {try {val inputStream = context.assets.open("example.html")return WebResourceResponse("text/html", "UTF-8", inputStream)} catch (e: IOException) {e.printStackTrace()}}Log.d("WebViewRequests", "请求链接: ${request.url}")return super.shouldInterceptRequest(view, request)}}loadUrl("https://www.example.com")isFocusable = falseisFocusableInTouchMode = falsefun onKeyDown(keyCode: Int, event: KeyEvent): Boolean {return false}}onWebViewCreated(webView)return@AndroidView webView},modifier = modifier)
}@Preview(showBackground = true)
@Composable
fun GreetingPreview() {DM2Theme {Greeting("Android")}
}
  • AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"><uses-permission android:name="android.permission.INTERNET" /><uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /><uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /><applicationandroid:allowBackup="true"android:dataExtractionRules="@xml/data_extraction_rules"android:fullBackupContent="@xml/backup_rules"android:icon="@mipmap/ic_launcher"android:label="@string/app_name"android:roundIcon="@mipmap/ic_launcher_round"android:supportsRtl="true"android:theme="@style/Theme.DM2"tools:targetApi="31"><activityandroid:name=".MainActivity"android:exported="true"android:label="@string/app_name"android:theme="@style/Theme.DM2"><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter></activity></application></manifest>
  • example.html
<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="UTF-8"><title>示例页面</title>
</head>
<body><h1>这是一个本地资源文件示例</h1><p>该文件从 Android 的 assets 目录加载。</p>
</body>
</html>

吐槽

  • java是大家闺秀, js是小伙子, kotlin简直是耍**, 那语法糖看的我抓耳挠腮

相关文章:

【笔记】Trae+Andrioid Studio+Kotlin开发安卓WebView应用

文章目录 简介依赖步骤AS(Andriod Studio)创建项目AS创建虚拟机TRAE CN 修改项目新增按键捕获功能 新增WebViewWebView加载本地资源在按键回调中向WebView注入JS代码 最终关键代码吐槽 简介 使用Trae配合Andriod Studio开发一个内嵌WebView的安卓应用, 在WebView中加载本地资源…...

Github 2025-05-30Java开源项目日报Top10

根据Github Trendings的统计,今日(2025-05-30统计)共有10个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量Java项目10C++项目1TypeScript项目1Keycloak: 现代应用程序和服务的开源身份和访问管理解决方案 创建周期:3846 天开发语言:Java协议类型:Ap…...

Github上一些使用技巧(缩写、Issue的Highlight)自用

1. GIthub中的一些缩写 LGTM ! 最近经常看到一些迷之缩写&#xff0c;感觉挺有意思的&#xff0c;但是有时候看到一些没见过的缩写还是有点懵逼&#xff0c;不过缩写确实也是很方便去review&#xff0c;这里就记录汇总一下&#xff1b;顺便加了一些git的基操单词&#xff08;加…...

TextIn OCR Frontend前端开源组件库发布!

为什么开源 TextIn OCR Frontend 前端组件库&#xff1f; 在 TextIn 社群中&#xff0c;我们时常接到用户反馈&#xff0c;调取 API 进行票据等文件批量识别后&#xff0c;需要另行完成前端工程&#xff0c;实现比对环节。为助力用户节省工程成本&#xff0c;TextIn 团队正式开…...

GitLens 教学(学习更新中)

GitLens 是什么&#xff1f; GitLens 是安装在 Visual Studio Code (VS Code) 中的一个功能极其强大的扩展程序&#xff0c;它直接内嵌在您的代码编辑器中&#xff0c;极大地增强了 VS Code 内置的 Git 功能。它的核心目标是&#xff1a; 深刻理解代码历史&#xff1a; 让您轻…...

C#中数据绑定的简单例子

数据绑定允许将控件的属性和数据链接起来——控件属性值发生改变&#xff0c;会导致数据跟着自动改变。 数据绑定还可以是双向的——控件属性值发生改变&#xff0c;会导致数据跟着自动改变&#xff1b;数据发生改变&#xff0c;也会导致控件属性值跟着自动改变。 1、数据绑定…...

VR 技术在农业领域或许是一抹新曙光​

在科技日新月异的今天&#xff0c;VR(虚拟现实)技术已不再局限于游戏、影视等娱乐范畴&#xff0c;正逐步渗透到各个传统行业&#xff0c;为其带来全新的发展契机&#xff0c;农业领域便是其中之一。VR 技术利用计算机生成三维虚拟世界&#xff0c;给予用户视觉、听觉、触觉等多…...

【JVM】Java程序运行时数据区

运行时数据区 运行时数据区是Java程序执行过程中管理的内存区域 Java 运行时数据区组成&#xff08;JVM 内存结构&#xff09; Java 虚拟机&#xff08;JVM&#xff09;的运行时数据区由以下核心部分组成&#xff1a; 线程私有&#xff1a;程序计数器、Java虚拟机栈、本地方…...

NVIDIA英伟达describe-anything软件本地电脑安装部署完整教程

describe-anything是英伟达联合其他大学开发的一款图片视频内容分析总结软件&#xff0c;可通过AI描述任意图片视频选中区域内容&#xff0c;非常强大&#xff0c;下面是describe-anything本地电脑安装部署教程。 首先电脑上安装git https://github.com/git-for-windows/git/…...

计算机视觉入门:OpenCV与YOLO目标检测

计算机视觉入门&#xff1a;OpenCV与YOLO目标检测 系统化学习人工智能网站&#xff08;收藏&#xff09;&#xff1a;https://www.captainbed.cn/flu 文章目录 计算机视觉入门&#xff1a;OpenCV与YOLO目标检测摘要引言技术原理对比1. OpenCV&#xff1a;传统图像处理与机器学…...

Java 中的 ThreadLocal 详解:从基础到源码

Java 中的 ThreadLocal 详解&#xff1a;从基础到源码 引言 在 Java 多线程编程中&#xff0c;ThreadLocal是一个经常被提及的概念。它提供了一种线程局部变量的机制&#xff0c;使得每个线程都可以独立地存储和访问自己的变量副本&#xff0c;而不会与其他线程产生冲突。本文…...

(二)开启深度学习动手之旅:先筑牢预备知识根基

1 数据操作 数据操作是深度学习的基础&#xff0c;包括数据的创建、索引、切片、运算等操作。这些操作是后续复杂模型构建和训练的前提。 入门 &#xff1a;理解如何使用NumPy创建数组&#xff0c;这是深度学习中数据存储的基本形式。掌握数组的属性&#xff08;如数据类型dt…...

Spring Boot3.4.1 集成redis

Spring Boot3.4.1 集成redis 第一步 引入依赖 <!-- redis 缓存操作 --> <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <!-- pool 对象池 …...

【Prometheus+Grafana实战:搭建监控系统(含告警配置)】

什么是Prometheus和Grafana&#xff1f; Prometheus&#xff1a;一款开源的监控告警工具&#xff0c;擅长时序数据存储和多维度查询&#xff08;通过PromQL&#xff09;&#xff0c;采用Pull模型主动抓取目标指标。Grafana&#xff1a;数据可视化平台&#xff0c;支持多种数据…...

操作系统原理第9章 磁盘存储器管理 重点内容

目录 &#xff08;一&#xff09;外存的组织方式种类 &#xff08;二&#xff09;FAT 系统&#xff08;计算&#xff09; &#xff08;三&#xff09;文件存储空间的管理方式 &#xff08;一&#xff09;外存的组织方式种类 连续组织方式 原理&#xff1a;在磁盘等外存上&…...

一文速通Python并行计算:11 Python多进程编程-进程之间的数据安全传输-基于队列和管道

一文速通 Python 并行计算&#xff1a;11 Python 多进程编程-进程之间的数据安全传输-基于队列和管道 摘要&#xff1a; Python 多进程中&#xff0c;Queue 和 Pipe 提供进程间安全通信。Queue 依赖锁和缓冲区&#xff0c;保障数据原子性和有序性&#xff1b;Pipe 实现点对点单…...

LangChain-Tool和Agent结合智谱AI大模型应用实例2

1.Tool(工具) 定义与功能 单一功能模块:Tool是完成特定任务的独立工具,每个工具专注于一项具体的操作,例如:搜索、计算、API调用等 无决策能力:工具本身不决定何时被调用,仅在被触发时执行预设操作 输入输出明确:每个工具需明确定义输入、输出参数及格式 2.Agent(…...

HTML、XML、JSON 是什么?有什么区别?又是做什么的?

在学习前端开发或者理解互联网工作原理的过程中&#xff0c;我们经常会遇到三个非常重要的概念&#xff1a;HTML、XML 和 JSON。它们看起来有点像&#xff0c;但其实干的事情完全不同。 &#x1f3c1; 一、他们是谁&#xff1f;什么时候诞生的&#xff1f; 名称全称诞生时间谁…...

C++中IO文件输入输出知识详解和注意事项

以下内容将从文件流类体系、打开模式、文本与二进制 I/O、随机访问、错误处理、性能优化等方面&#xff0c;详解 C 中文件输入输出的使用要点&#xff0c;并配以示例。 一、文件流类体系 C 标准库提供三种文件流类型&#xff0c;均定义在 <fstream> 中&#xff1a; std…...

centos7.6阿里云镜像各个版本介绍

&#xff08;水一期&#xff09; Index of /centos-vault/centos/7.6.1810/isos/x86_64/ File NameFile SizeDateParent directory/--0_README.txt2.4 KB2018-12-01 21:21CentOS-7-x86_64-DVD-1810.iso4.3 GB2018-11-26 07:55CentOS-7-x86_64-DVD-1810.torrent86.0 KB2018-12-…...

InnoDB引擎逻辑存储结构及架构

简化理解版 想象 InnoDB 是一个高效运转的仓库&#xff1a; 核心内存区 (大脑 & 高速缓存 - 干活超快的地方) 缓冲池 Buffer Pool (最最核心&#xff01;)&#xff1a; 作用&#xff1a; 相当于仓库的“高频货架”。把最常用的数据&#xff08;表数据、索引&#xff09;从…...

KVM——CPU独占

文章目录 机器现况信息配置CPU独占(pin)启用 CPU 独占&#xff08;隔离&#xff09;验证 机器现况信息 [rootkvm-server ~]# virsh list --allId 名称 状态 --------------------------- CULinux-VM 关闭- ubuntu20.04 关闭- ubuntu24.04 关闭[roo…...

第4讲、Odoo 18 模块系统源码全解与架构深度剖析【modules】

引言 Odoo 是一款强大的开源企业资源规划&#xff08;ERP&#xff09;与客户关系管理&#xff08;CRM&#xff09;系统&#xff0c;其核心竞争力之一在于高度模块化的架构设计。模块系统不仅是 Odoo 框架的基石&#xff0c;更是实现功能灵活扩展与定制的关键。本文将结合 Odoo…...

pytorch简单线性回归模型

模型五步走 1、获取数据 1. 数据预处理 2.归一化 3.转换为张量 2、定义模型 3、定义损失函数和优化器 4、模型训练 5、模型评估和调优 调优方法 6、可视化&#xff08;可选&#xff09; 示例代码 import torch import torch.nn as nn import numpy as np import matplot…...

在 HTML 文件中添加图片的常用方法

本文详解HTML图片插入方法&#xff1a;1&#xff09;通过<img>标签实现&#xff0c;必须含src和alt属性&#xff1b;2&#xff09;路径支持绝对/相对引用&#xff1b;3&#xff09;建议设置width/height保持比例&#xff1b;4&#xff09;响应式方案用srcset适配不同设备…...

四、web安全-行业术语

1. 肉鸡 所谓“肉鸡”是一种很形象的比喻&#xff0c;比喻那些可以随意被我们控制的电脑&#xff0c;对方可以是WINDOWS系统&#xff0c;也可以是UNIX/LINUX系统&#xff0c;可以是普通的个人电脑&#xff0c;也可以是大型的服务器&#xff0c;我们可以象操作自己的电脑那样来…...

Kafka核心技术解析与最佳实践指南

Apache Kafka作为分布式流处理平台的核心组件&#xff0c;以其高吞吐、低延迟和可扩展性成为现代数据架构的基石。本文基于Kafka官方文档&#xff0c;深度解析其核心技术原理&#xff0c;并结合实践经验总结关键技巧与最佳实践。 Kafka的高性能源于其精巧的架构设计&#xff0…...

Unity基础学习(十二)Unity 物理系统之范围检测

目录 一、关于范围检测的主要API&#xff1a; 1. 盒状范围检测 Physics.OverlapBox 2. 球形范围检测 Physics.OverlapSphere 3. 胶囊范围检测 Physics.OverlapCapsule 4. 盒状检测 NonAlloc 版 5. 球形检测 NonAlloc 版 6. 胶囊检测 NonAlloc 版 二、关于API中的两个重…...

JVM 的垃圾回收机制 GC

C/C 这样的编程语言中,申请内存的时候,是需要用完了,进行手动释放的 C 申请内存 1)局部变量(不需要手动释放) 2)全局变量(不需要手动释放) 3)动态申请 malloc(通过 free 进行释放的) C 申请内存 1)局部变量 2)全局变量/静态变量 3)动态申请 new 通过 delete 进行释放 …...

TypeScript 针对 iOS 不支持 JIT 的优化策略总结

# **TypeScript 针对 iOS 不支持 JIT 的优化策略总结** 由于 iOS 的 **JavaScriptCore (JSC)** 引擎 **禁用 JIT&#xff08;Just-In-Time 编译&#xff09;**&#xff0c;JavaScript 在 iOS 上的执行性能较差&#xff0c;尤其是涉及动态代码时。 **TypeScript&#xff08;T…...