跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客GitHub 精选镜像工具UI配色美学隐私政策关于联系
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
KotlinAI大前端java

Android Kotlin 开发内嵌 WebView 应用及按键交互实践

综述由AI生成使用 Android Studio 和 Kotlin 开发内嵌 WebView 的安卓应用。内容包括项目创建、WebView 集成、本地资源加载以及通过按键事件向 WebView 注入 JavaScript 代码的实现细节。解决了异步初始化导致的空指针问题及网络权限配置问题,实现了在 APP 层捕获按键操作 WebView 内容的功能。

FlinkHero发布于 2026/4/5更新于 2026/5/2430 浏览
Android Kotlin 开发内嵌 WebView 应用及按键交互实践

简介

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

环境准备

  • Android Studio (AS)
  • 基础的编程知识

实现步骤

AS 创建项目

  1. 打开 AS,创建一个 Empty Activity 项目。
  2. 等待依赖下载和编译初始化完毕。

AS 创建虚拟机

  1. 启动模板项目。
  2. 找到镜像,如果是灰色的需要点击下载(依赖网络)。
  3. 在右上角创建虚拟机并启动。

集成 WebView

  1. 将 Greeting 中的 Text 控件替换为 WebView。
  2. 配置网络权限。若无法打开页面,检查 AndroidManifest.xml 是否添加了 INTERNET 等权限。
  3. 解决按键事件被 WebView 优先处理的问题,确保 APP 层能捕获上下键。
  4. 修复异步执行导致的 WebView 实例为空问题,采用回调方式初始化 WebView 实例。

按键事件处理

  1. 重写 onKeyDown 方法捕获键盘方向键。
  2. 在按键回调中向 WebView 注入 JS 代码修改显示内容。
  3. 注意处理 WebView 初始化的时序问题,避免空指针异常。

加载本地资源

  1. 本地资源文件需放在 assets 目录。
  2. 在 shouldInterceptRequest 中拦截请求,加载本地资源文件。
  3. 打印日志确认请求链接和资源加载情况。

核心代码

MainActivity.kt

package com.example.dm2

import android.os.Bundle
import android.util.Log
import android.view.KeyEvent
import android.webkit.WebResourceRequest
import android.webkit.WebResourceResponse
import android.webkit.WebView
import android.webkit.WebViewClient
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
 androidx.compose.ui.Modifier
 androidx.compose.ui.platform.LocalContext
 androidx.compose.ui.tooling.preview.Preview
 androidx.compose.ui.viewinterop.AndroidView
 java.io.IOException

 webViewInstance: WebView? = 

  : () {
      {
        .onCreate(savedInstanceState)
        setContent {
            DM2Theme {
                Surface(
                    modifier = Modifier.fillMaxSize(),
                    color = MaterialTheme.colorScheme.background
                ) {
                    Greeting() { webView ->
                        webViewInstance = webView
                    }
                }
            }
        }
    }

     :  {
         (keyCode) {
            KeyEvent.KEYCODE_DPAD_UP -> {
                Log.d(,  + webViewInstance)
                webViewInstance?.evaluateJavascript(, )
                 
            }
        }
         .onKeyDown(keyCode, event)
    }
}


 {
     context = LocalContext.current
    AndroidView(
        factory = { ctx ->
             webView = WebView(ctx).apply {
                settings.javaScriptEnabled = 
                Log.d(, )
                webViewClient =  : WebViewClient() {
                     : WebResourceResponse? {
                         url = request.url.toString()
                         (url.equals()) {
                             {
                                 inputStream = context.assets.()
                                 WebResourceResponse(, , inputStream)
                            }  (e: IOException) {
                                e.printStackTrace()
                            }
                        }
                        Log.d(, )
                         .shouldInterceptRequest(view, request)
                    }
                }
                loadUrl()
                isFocusable = 
                isFocusableInTouchMode = 
            }
            onWebViewCreated(webView)
             webView
        },
        modifier = modifier
    )
}



 {
    DM2Theme {
        Greeting()
    }
}
import
import
import
import
import
var
null
class
MainActivity
ComponentActivity
override
fun onCreate(savedInstanceState: Bundle?)
super
"Android"
override
fun onKeyDown(keyCode: Int, event: KeyEvent?)
Boolean
when
"KeyEvent"
"上方向键被按下"
"document.body.innerText = new Date();"
null
return
true
return
super
@Composable
fun Greeting(name: String, modifier: Modifier = Modifier, onWebViewCreated: (WebView) -> Unit = {})
val
val
true
"WebViewInit"
"WebView 实例已创建:$this"
object
override
fun shouldInterceptRequest(view: WebView, request: WebResourceRequest)
val
if
"https://www.example.com/"
try
val
open
"example.html"
return
"text/html"
"UTF-8"
catch
"WebViewRequests"
"请求链接:${request.url}"
return
super
"https://www.example.com"
false
false
return
@AndroidView
@Preview(showBackground = true)
@Composable
fun GreetingPreview()
"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" />

    <application
        android: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">
        <activity
            android: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>

目录

  1. 简介
  2. 环境准备
  3. 实现步骤
  4. AS 创建项目
  5. AS 创建虚拟机
  6. 集成 WebView
  7. 按键事件处理
  8. 加载本地资源
  9. 核心代码
  10. MainActivity.kt
  11. AndroidManifest.xml
  12. example.html
  • 💰 8折买阿里云服务器限时8折了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 🤖 一键搭建Deepseek满血版了解详情
  • 一键打造专属AI 智能体了解详情
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • Linux 远程连接 Windows 桌面配置指南
  • Python 内置函数 enumerate() 详解与实战
  • 使用 Spring Session 配合 Redis 管理 HTTP Session
  • Linux 基础入门:常用命令与系统管理指南
  • 基于MATLAB的三维A星算法无人机导航与路径规划
  • 快速排序非递归实现详解
  • 构建企业级 AI 大模型的关键步骤与框架
  • Flood Fill 算法详解:DFS/BFS 实现与经典应用
  • Kafka 核心架构与分布式存储深度解析
  • Python AI 入门与学习路线指南
  • C++ 继承机制详解:栈实现、名称隐藏与默认成员函数
  • C++ 核心特性解析:引用、内联函数与 nullptr
  • 基于 ClaudeCode 和 Figma-MCP 的 UI 设计 1:1 前端还原方案
  • 仿 RabbitMQ 实现消息队列项目:交换机路由、队列隔离与消息可靠投递
  • 基于 Segment Anything 模型的图像分割部署与测试
  • 基于 Web 的学校田径运动会管理系统开发与实现开题答辩问答
  • 龙虾机器人(OpenClaw)本地部署技术指南
  • 任意文件读取漏洞的深入利用与敏感文件路径分析
  • MOOTDX 快速上手指南:Python 量化投资入门
  • Flutter 三方库 web_ffi 的鸿蒙化适配指南

相关免费在线工具

  • RSA密钥对生成器

    生成新的随机RSA私钥和公钥pem证书。 在线工具,RSA密钥对生成器在线工具,online

  • Keycode 信息

    查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online

  • Escape 与 Native 编解码

    JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online

  • Mermaid 预览与可视化编辑

    基于 Mermaid.js 实时预览流程图、时序图等图表,支持源码编辑与即时渲染。 在线工具,Mermaid 预览与可视化编辑在线工具,online

  • JavaScript / HTML 格式化

    使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online

  • JavaScript 压缩与混淆

    Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online