Posts

Showing posts with the label 移动开发

A New Collection of Thoughtful Learning Apps — Now Available on iOS & Android

Image
I’m excited to share a set of mobile apps I’ve recently completed and published on both the Google Play Store and the Apple App Store. These apps are designed with a simple goal in mind: to make meaningful, structured content more accessible, whether you’re studying theology or improving your English vocabulary. 📱 Now Available on Both Platforms All apps are live and available for download: Google Play Developer Page: https://play.google.com/store/apps/dev?id=5835943159853189043 Apple App Store Developer Page: https://apps.apple.com/ca/developer/q-z-l-corp/id1888794100 📖 Theology & Confession Study Apps For those interested in Reformed theology and classical Christian teachings, I’ve developed a series of apps that present foundational texts in a clean, focused reading format: The Belgic Confession Canons of Dort Heidelberg Catechism Westminster Shorter Catechism Each app is designed to provide a distraction-free experience, making it easier to read, reflect, and revisit these im...

如何为 App Store Connect 准备应用预览视频和截图(ffmpeg 实战指南)

Image
  如何为 App Store Connect 准备应用预览视频和截图(ffmpeg 实战指南) 在通过 App Store Connect 发布应用时,截图和应用预览视频(App Preview)是非常关键的一步,也是最容易踩坑的地方。 这篇文章用最简单、实用的方式,带你一步一步搞定。 📸 应用截图(最简单) 截图其实很容易: 在 iPhone 上打开你的 App 直接截图 使用 AirDrop 传到 Mac 用 Preview 调整到要求尺寸 基本就完成了,不需要复杂工具。 🎬 应用预览视频(重点难点) 相比截图,应用预览视频有严格要求,来自 Apple: 📋 核心要求 ⏱ 时长: 不超过 30 秒 🎞 帧率: 不高于 30 fps(建议 30 fps) 📐 分辨率: 竖屏: 886 × 1920 横屏: 1920 × 886 🔊   必须包含音频(不能是静音视频) 📱 第一步:用 iPhone 录屏 使用系统自带录屏功能: 在控制中心添加“屏幕录制” 开始录制 演示你的 App 核心功能 停止录制 💡 建议:提前规划好内容,控制在 30 秒以内。 🔄 第二步:传到 Mac 通过 AirDrop 快速传输视频到电脑。 🎧 第三步:添加音频(必要) App Preview   必须有音频 ,否则容易被拒。 可以使用 iMovie: 添加背景音乐 加旁白说明 简单剪辑视频 完成后导出视频。 ⚙️ 第四步:用 ffmpeg 处理视频 这是最关键的一步,可以解决大部分审核问题。 ✂️ 裁剪到 30 秒 ffmpeg -ss 0 -t 30 -i input.mp4 -c copy trimmed.mp4 📐 调整分辨率 + 帧率 + 优化格式 ffmpeg -i trimmed.mp4 \ -vf "scale=886:1920:force_original_aspect_ratio=decrease,pad=886:1920:(ow-iw)/2:(oh-ih)/2,fps=30" \ -r 30 -vsync cfr \ -c:v libx264 -b:v 2000k -maxrate 2000k -bufsize 4000k \ -pix_fmt yuv420p \ -c:a aac -b:a 128k \ -mov...

解决 React Native iOS 缺少 iPad 图标错误(152x152 / 167x167 验证失败)

Image
解决 React Native iOS 缺少 iPad 图标错误(152x152 / 167x167) 在提交 React Native iOS 应用到 App Store 时,如果你遇到类似错误: Missing required icon file. The bundle does not contain an app icon for iPad of exactly '152x152' pixels The bundle does not contain an app icon for iPad Pro of exactly '167x167' pixels 这个问题看起来很奇怪,因为你的 Xcode 项目中已经显示支持 iPad。 🔍 现象 你可能已经看到: Deployment Info 中有 iPad 配置 iPad Orientation 已启用 但是打开 Assets.xcassets → AppIcon 时: ❌ 没有 iPad 图标槽位 最终导致 App Store 校验失败。 🧠 根本原因 这是因为配置不一致导致的: 项目设置支持 iPad ✅ AppIcon 资源仍然是 iPhone-only ❌ 在很多 React Native 项目中,默认生成的 AppIcon 并不包含 iPad 图标槽位。 ✅ 解决方案(最简单有效) 重新创建 AppIcon: 打开 Assets.xcassets 删除当前的 AppIcon 右键 → New App Icon 命名为 AppIcon 新的 AppIcon 会自动包含: iPad 图标(152x152) iPad Pro 图标(167x167) 🖼️ 必须提供的图标 你至少需要提供: 152 × 152(iPad) 167 × 167(iPad Pro) 将对应 PNG 图片拖入即可。 ⚠️ 重要检查 确保项目确实支持 iPad: Build Settings → Targeted Device Family = 1,2 含义: 1 = iPhone 2 ...

解决 React Native Android Gradle 构建错误的经验分享

Image
解决 React Native Android Gradle 构建错误的经验分享 最近在开发 React Native Android 项目时,遇到了顽固的 Gradle 构建错误,主要集中在插件解析和本地构建缓存缺失等问题,比如 com.facebook.react.settings 和 foojay-resolver 相关报错。 问题表现 执行 Gradle clean 时提示插件解析失败 本地构建产物缺失或损坏 报错涉及 metadata.bin 和 FoojayToolchainsPlugin 解决步骤 停止所有正在运行的 Gradle 进程: ./gradlew stop 删除本地 native 构建缓存: rm -rf .cxx 清理并重新构建项目,同时刷新依赖: ./gradlew clean build --refresh-dependencies 最终效果 按照上述步骤操作后,构建顺利通过,所有插件和本地依赖相关错误都被解决。如果你也遇到类似问题,不妨试试这套方法!

解决 Android 模拟器空间不足导致 installDebug 失败问题

Image
解决 Android 模拟器空间不足导致 installDebug 失败问题 如果你在运行 npm run android 时遇到以下错误: Execution failed for task ':app:installDebug'. ... java.io.IOException: Requested internal only, but not enough space 那么问题通常很简单: 🚨 Android 模拟器空间不足 💡 问题原因 Android 虚拟设备(AVD)默认的内部存储空间通常只有 2GB–6GB,很容易被占满: 多次安装 Debug APK Gradle 构建缓存 系统更新和缓存文件 最终导致无法再安装应用。 ✅ 我的解决方法(最有效) 直接扩大模拟器存储空间: 打开 Android Studio 进入 Device Manager 编辑已有模拟器或创建新模拟器 点击 Show Advanced Settings 将 Internal Storage 设置为 16 GB 保存并重启模拟器 设置为 16GB 后,问题即可彻底解决。 ⚡ 临时解决方案 如果只是临时应急,可以: 清空模拟器数据(Wipe Data) 手动卸载应用: adb uninstall your.package.name 但这些只是短期解决方案。 🧠 开发建议 开发环境建议至少分配 12GB–16GB 存储 关闭 Snapshot(避免保存“满磁盘状态”) 定期清理构建: cd android ./gradlew clean ✅ 总结 如果看到错误: Requested internal only, but not enough space 这 不是代码问题 ,而是模拟器磁盘空间不足。 根本解决方案: 将 AVD 内部存储提升到 16GB。 这是最稳定、最彻底的解决办法。

解决 React Native Modal 中 ScrollView 无法滚动的问题(最佳 Modal 结构)

Image
解决 React Native Modal 中 ScrollView 无法滚动的问题(最佳 Modal 结构) 在使用 React Native 开发应用时,一个很常见的问题是: 在 Modal 组件中放入 ScrollView , 虽然滚动条显示出来了,但内容却无法正常滚动。 很多开发者会发现,Modal 打开后 ScrollView 看起来是可以滚动的, 但是手指滑动时内容却几乎不动,或者滚动非常困难。 这个问题通常是因为 Modal 的 Overlay 层拦截了触摸事件 。 如果 Overlay 使用 TouchableOpacity 或 Pressable 并包裹整个 Modal 内容, 那么滚动手势会被 Overlay 捕获,从而导致 ScrollView 无法接收到滚动事件。 问题示例 很多项目中的 Modal 结构通常像这样: <TouchableOpacity style={styles.overlay} onPress={onClose}> <TouchableOpacity style={styles.modal}> <ScrollView> ... </ScrollView> </TouchableOpacity> </TouchableOpacity> 在这种结构下,最外层的 TouchableOpacity 会捕获触摸手势。当用户尝试滚动时, 触摸事件会先被 Overlay 处理,从而阻止 ScrollView 的滚动行为。 结果就是: 滚动条存在,但滚动不流畅甚至无法滚动。 正确的 Modal 结构模式 正确的解决方案是: 不要用 Touchable 包裹整个 Modal , 而是将 背景点击区域 与 Modal 内容区域 分离。 我们可以在背景上放一个独立的 Pressable, 用于点击关闭 Modal,而 Modal 内容本身保持普通 View。 <Modal visible={visible} transparent animationType="fade" onRequestClose={onC...

解决 react-native-tts Android 构建失败:Could not find method jcenter()

Image
解决 react-native-tts Android 构建失败:Could not find method jcenter() 在运行 React Native Android 项目时,我遇到了如下构建错误: A problem occurred evaluating project ':react-native-tts'. > Could not find method jcenter() for arguments [] on repository container of type 错误发生在执行以下命令时: ./gradlew app:installDebug 根据错误信息,问题最终定位到了以下文件: node_modules/react-native-tts/android/build.gradle 问题原因分析 jcenter() 已经被 Gradle 官方弃用,并在较新的 Gradle 版本中被移除。 但部分较老的 React Native 第三方库仍然在 Android 配置中使用 jcenter() ,这会直接导致 Android 构建失败。 本次出问题的正是 react-native-tts 这个库。 为什么不能直接改 node_modules? 直接修改 node_modules 中的代码虽然可以暂时解决问题,但并不可靠。 以下操作都会导致修改丢失: 重新执行 npm install 重新执行 yarn install 删除并重建 node_modules 因此,我们需要一种 可重复、可维护、对团队友好 的解决方案。 正确的解决方案:patch-package patch-package 是一个非常实用的工具,可以让我们对第三方依赖进行补丁修复,并在每次安装依赖时自动应用这些修改。 在 react-native-tts 官方修复之前,这是一个非常稳妥的方案。 修复步骤详解 1. 安装 patch-package npm install patch-package --save-dev 或者使用 Yarn: yarn add patch-package --d...

解决 adb install 时 INSTALL_FAILED_UPDATE_INCOMPATIBLE 签名不匹配错误

Image
解决 adb install 时 INSTALL_FAILED_UPDATE_INCOMPATIBLE 签名不匹配错误 在使用 React Native 构建 Android Release APK 后,通过 adb 安装时,可能会遇到如下错误: adb: failed to install app-release.apk: Failure [INSTALL_FAILED_UPDATE_INCOMPATIBLE: Existing package signatures do not match newer version] 这个问题并不是编译失败,而是 Android 安装机制阻止了不同签名的应用覆盖安装 。 为什么会出现这个错误? Android 系统要求:同一个包名的 App,在更新时必须使用相同的签名证书。 如果你之前安装的是: Debug 版本(默认签名) 或者使用了不同的 Release Keystore 而现在你安装的是新的 Release APK(使用了不同签名),系统就会拒绝更新,从而出现此错误。 解决方法 方法 1:卸载旧应用(最简单) adb uninstall com.westminstershortercatechismqa adb install app-release.apk 卸载后再安装即可正常运行。 方法 2:使用统一的 Release Keystore 如果你希望以后可以直接覆盖安装(升级 App),需要保证每次构建 Release 都使用同一个 keystore。 在 android/app/build.gradle 中配置: android { signingConfigs { release { storeFile file("release.keystore") storePassword "your_password" keyAlias "your_alias" keyPassword "your_password" } } buildTypes { release { ...

React Native 使用 TypeScript + Hermes 时 Android Release 构建报错解决方案

Image
React Native 使用 TypeScript + Hermes 时 Android Release 构建报错解决方案 如果你把 React Native 项目的入口文件从 index.js 改成了 index.ts ,然后在构建 Android Release 版本时失败,这篇文章可以帮你解决。 常见的报错包括: Task ':app:createBundleReleaseJsAndAssets' property 'entryFile' specifies file 'index.js' which doesn't exist. 或者: java.lang.OutOfMemoryError: Metaspace Execution failed for task ':react-native-xxx:lintVitalAnalyzeRelease' 这通常是由于入口文件未正确配置,以及 Gradle 内存不足导致的。下面是完整修复步骤。 1. 修复入口文件路径错误 React Native 默认查找 index.js ,如果你使用 TypeScript,需要告诉 Gradle 使用 index.ts 。 打开 android/app/build.gradle ,在 react {} 配置中加入: react { entryFile = file("../../index.ts") } 同时确认 package.json 中的入口文件: "main": "index.ts" 并在 metro.config.js 中支持 TypeScript: resolver: { sourceExts: ["js", "json", "ts", "tsx"] } 2. 解决 Gradle Metaspace 内存不足 Android 在 Release 构建时会运行 Lint 分析 React Native 库的 Kotlin 文件,默认内存太小会导致崩溃。 编辑 an...