Android WebView图片替换功能实现方法

Android WebView图片替换功能实现方法 在Android应用中使用WebView加载HTML页面时,实现图片点击替换功能需要特殊的配置,因为WebView对文件操作有更严格的安全限制。本文档总结了完整的实现方法。 问题描述 当HTML页面中包含图片点击替换功能(使用<input type="file">)时: 在浏览器中可以正常工作 在Android WebView中默认无法工作(文件选择器不会弹出) 解决方案 1. 添加必要的权限 在AndroidManifest.xml中添加文件访问权限: 1 2 3 4 5 6 7 8 9 10 11 <?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.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_MEDIA_IMAGES" /> </manifest> 2. MainActivity配置 在MainActivity.kt中完整配置WebView以支持文件上传: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 package com....

2025-08-05 · 3 min

Android状态栏和导航栏非沉浸式实现方法

Android状态栏和导航栏非沉浸式实现方法 在Android应用开发中,特别是使用Jetpack Compose时,实现非沉浸式状态栏和导航栏(即保持它们的颜色与应用内容分离)需要一些特定的技术。本文档总结了在Jetpack Compose应用中实现黑色非沉浸式状态栏和导航栏的方法。 实现方法 1. 禁用默认的沉浸式行为 首先,需要禁用Android默认的沉浸式行为,这可以通过WindowCompat.setDecorFitsSystemWindows方法实现: 1 2 // 禁用沉浸式状态栏 WindowCompat.setDecorFitsSystemWindows(window, true) 这告诉系统窗口装饰(状态栏和导航栏)应该被考虑在内,内容不应该延伸到这些区域下方。 2. 控制状态栏和导航栏外观 在现代Android开发中,推荐使用WindowInsetsController来控制状态栏和导航栏的外观,而不是直接设置颜色: 1 2 3 4 5 6 // 获取窗口控制器 val windowInsetsController = WindowCompat.getInsetsController(window, window.decorView) // 设置为深色模式(深色背景,浅色图标) windowInsetsController.isAppearanceLightStatusBars = false windowInsetsController.isAppearanceLightNavigationBars = false isAppearanceLightStatusBars = false和isAppearanceLightNavigationBars = false表示状态栏和导航栏使用深色背景,因此系统会使用浅色(白色)图标来确保可见性。 注意:旧的方式 window.statusBarColor 和 window.navigationBarColor 已被弃用,不推荐使用。 3. 使用分层布局处理内容区域 为了确保内容不会被状态栏和导航栏遮盖,可以使用Compose的Box布局创建分层UI: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 // 使用Box布局,底层是黑色背景 Box( modifier = Modifier ....

2025-08-05 · 2 min

Cloudflare Workers + KV Mock API 部署踩坑总结

Cloudflare Workers + KV Mock API 部署踩坑总结 1. 环境变量 DB_JSON 超过 5.1KB 限制 问题:直接用 wrangler secret put DB_JSON < db.json 注入大文件时报错:Text binding ‘DB_JSON’ is too large。 解决:改用 Cloudflare KV 存储大数据,Worker 运行时从 KV 读取。 2. wrangler.toml 配置格式错误 问题:[[kv_namespaces]] 下写了 name、type、account_id 等字段,导致 warning。 解决:[[kv_namespaces]] 下只保留 binding 和 id,其他字段放到文件顶层。 3. 写入 KV 时命令格式错误 问题:用 wrangler kv:key put 或 wrangler kv:namespace create 等老版本命令,或参数顺序、语法不对。 解决:新版 wrangler 用空格分隔,如: 创建命名空间:wrangler kv namespace create DB 写入数据:wrangler kv key put --binding=DB DB_JSON "$(Get-Content -Raw db....

2025-08-05 · 1 min

Cloudflare Workers + Vue 项目部署全流程踩坑复盘

Cloudflare Workers + Vue 项目部署全流程踩坑复盘 1. 目标与环境 Vue3 + Vite + TypeScript + TailwindCSS mock API(json-server 数据)支持 多平台自动化部署(GitHub Pages、Deno Deploy、Cloudflare Workers) 统一 API base 配置,环境变量区分开发/生产 2. CI/CD 文件与平台 .github/workflows/ci-cd.yml:GitHub Pages 自动部署,含 base 路径 patch .github/workflows/deno-deploy.yml:Deno Deploy 自动部署,支持静态+mock API .github/workflows/cloudflare-pages.yml:Cloudflare Pages 部署(后期未用) .github/workflows/cloudflare-workers.yml:Cloudflare Workers 自动部署,mock API 支持 3. 主要问题与解决办法 3.1 wrangler.toml 配置与 secrets 注入 问题:wrangler.toml 里 account_id = "${{ secrets.CF_ACCOUNT_ID }}" 只有 wrangler-action@v4+ 支持,v3 需写死账号ID。 解决:升级 wrangler-action 到 v3,配合 wrangler 4.x,支持 secrets 注入。 3....

2025-08-05 · 2 min

Cloudflare Workers + Vue 项目部署踩坑与解决方案总结

Cloudflare Workers + Vue 项目部署踩坑与解决方案总结 1. CI/CD 及多环境部署目标 需求:Vue3 + Vite 项目,支持 GitHub Actions 自动部署到 Cloudflare Workers,mock API(json-server 数据)可用,静态资源与 API 一体化。 2. 主要问题与解决办法 2.1 wrangler.toml 配置与 secrets 注入 问题:wrangler.toml 里 account_id = "${{ secrets.CF_ACCOUNT_ID }}" 只有 wrangler-action@v4+ 支持,v3 需写死账号ID。 解决:升级 wrangler-action 到 v3,配合 wrangler 4.x,支持 secrets 注入。 2.2 wrangler 4.x 静态资源绑定 问题:assets = "./dist" 报类型错误,需对象格式,且字段应为 directory。 解决:用 [assets]\ndirectory = "./dist"。 2.3 mock 数据 DB_JSON 注入 问题1:直接用 $GITHUB_ENV 注入 base64,内容过长会被截断,导致 atob 报错。 问题2:wrangler....

2025-08-05 · 1 min

Expo 迁移故障排除与学习总结

🔧 Expo 迁移故障排除与学习总结 📋 文档概述 本文档记录了从 React Native CLI 项目迁移到 Expo Bare Workflow 过程中遇到的所有问题、解决方案和学习要点,供未来参考和复盘使用。 项目背景: 原项目:React Native 0.71.10 + 复杂原生模块(RFID功能) 目标:Expo SDK 50 Bare Workflow 迁移时间:2025年7月23日 🚀 完整迁移步骤与方案 阶段1:项目分析与准备 1.1 原项目结构分析 1 2 3 4 5 6 7 8 9 10 11 12 13 原项目结构 (App/): ├── app/ # 主要应用代码 │ ├── App.tsx # 应用入口 │ ├── components/ # 组件库 │ ├── navigation/ # 导航配置 │ ├── redux/ # 状态管理 │ └── ....

2025-08-05 · 11 min

Expo 迁移检查清单

Expo 迁移检查清单 ✅ 迁移前准备 备份原项目 (App_backup) 安装 Expo CLI (npm install -g @expo/cli) 确保 Node.js 版本 >= 16 阅读完整迁移计划文档 📦 项目结构迁移 创建新的 Expo Bare 项目 复制 app/ 目录到新项目 复制 deps/ 目录 复制配置文件 (tsconfig.json, .eslintrc.js 等) 复制 patches/ 目录 设置正确的路径别名 (@app, @deps) 🔧 配置文件更新 更新 app.json - 添加 Expo 特定配置 配置 eas.json - 构建配置 更新 metro.config.js - 使用 Expo Metro 配置 更新 babel.config.js - 使用 babel-preset-expo 创建 RFID 模块插件 (plugins/rfid-module-plugin.js) 📚 依赖迁移 SQLite 替换 react-native-quick-sqlite → expo-sqlite 更新 app/logger/logsDB....

2025-08-05 · 2 min

Expo 迁移计划

Expo 迁移计划 迁移策略:使用 Expo Bare Workflow 由于项目包含大量自定义原生模块和不兼容的依赖,建议使用 Expo Bare Workflow 进行迁移。 第一阶段:环境准备 1. 安装 Expo CLI 1 npm install -g @expo/cli 2. 创建备份 1 2 # 创建项目备份 cp -r App App_backup 3. 分析不兼容的依赖 需要替换的依赖: react-native-quick-sqlite → expo-sqlite react-native-fs → expo-file-system react-native-device-info → expo-device + expo-application react-native-vision-camera → expo-camera react-native-image-picker → expo-image-picker @react-native-async-storage/async-storage → @react-native-async-storage/async-storage (兼容) react-native-document-picker → expo-document-picker react-native-share → expo-sharing 保持不变的依赖: @react-navigation/* (完全兼容) react-redux, @reduxjs/toolkit (完全兼容) react-native-svg (兼容) react-native-reanimated (兼容) react-native-gesture-handler (兼容) 需要特殊处理的: react-native-paper (需要确保版本兼容) pouchdb* 相关包 (可能需要调整) 自定义RFID模块 (需要保留原生代码) 第二阶段:初始化 Expo Bare Workflow 1....

2025-08-05 · 2 min

Git 提交合并(Squash)操作复盘总结

Git 提交合并(Squash)操作复盘总结 ✅ 场景目标 把某个提交(如 6fc6e37)及其之后的所有提交合并成一条提交,保留历史,简化 log。 🧭 思路总览 Git 只能按提交拓扑结构操作,不能直接按时间合并。正确做法如下: ✅ 操作步骤 1️⃣ 找到合并起点的前一个提交 用 git log --oneline --date=iso 或 git log --graph 找到目标提交(如 6fc6e37)的前一个提交(如 8d1bacb)。 2️⃣ 切换到目标分支 1 git checkout main 3️⃣ 软重置到前一个提交 1 git reset --soft 8d1bacb 这样会把从 6fc6e37 开始到最新的所有更改变成未提交状态。 4️⃣ 新建一个合并提交 1 git commit -m "合并 Cloudflare Workers 相关提交" 可以整理多个提交说明合并进 message。 5️⃣ 强推远程(如已推送过) 1 git push origin main --force 🧼 效果验证 git log --oneline 检查历史是否简化 git log --graph 检查提交结构 git status 检查无未提交内容 ⚠️ 注意事项 项目 注意点 重写历史 一定会改变 Git 提交 ID,不可逆 多人协作 强推前要先告知团队,避免他人拉取冲突 推荐备份 操作前创建备份分支:git checkout -b backup-before-squash 🧠 总结口诀 🔁 找前一条 → 软重置 → 合新提交 → 强推远端...

2025-08-05 · 1 min

iTest 音频转录器调试与解决复盘

用户脚本 iTest 音频转录器 调试与解决复盘 1. 初始问题描述 用户创建了一个 Tampermonkey 脚本,旨在 iTest 网站上,利用 vosk-browser 库对听力音频进行离线语音识别。脚本在运行时抛出 TypeError: Vosk.Recognizer is not a constructor 的错误,导致转录功能完全失败。 2. 问题分析与调试历程 整个调试过程可以分为几个关键阶段,每个阶段都基于上一个阶段的错误信息进行了新的假设和尝试。 阶段一:初步诊断 - 错误的 API 调用对象 错误信息: TypeError: Vosk.Recognizer is not a constructor 原始代码: new Vosk.Recognizer({ sampleRate: ... }); 分析与假设: 这个错误表明 Vosk.Recognizer 不是一个有效的构造函数。根据许多现代JS库的设计模式(例如 Chart.js),通常会从一个父实例(如模型实例)上创建子组件(如识别器)。因此,我们假设 Recognizer 构造函数应该在 model 实例上。 尝试的解决方案: 将代码修改为 new model.Recognizer({ sampleRate: ... }); 结果: 失败。新的错误信息出现。 阶段二:二次诊断 - API 签名错误 错误信息: TypeError: model.Recognizer is not a constructor 分析与假设: 这个新错误否定了阶段一的假设。这说明 Recognizer 构造函数既不在全局的 Vosk 对象上,也不在 model 实例上。此时,我们重新审视了 vosk-browser 较新版本的文档,发现一个可能的正确用法:构造函数是 Vosk....

2025-08-05 · 2 min