ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

OpenChamber 移动端(iOS/Android)Capacitor 壳工程实践指南:从构建管线、原生能力到上架就绪

OpenChamber 移动端(iOS/Android)Capacitor 壳工程实践指南:从构建管线、原生能力到上架就绪 AI Agent人工智能代码智能体交互助手【免费下载链接】openchamberAgentic Development Environment based on OpenCode AI agent项目地址https://gitcode.com/gh_mirrors/op/openchamber点击查看免费下载导读本文围绕packages/mobile/HANDOFF.md这一交接文档展开系统讲解 OpenChamber 原生 iOS/Android 应用的完整技术栈它如何用 Capacitor 将托管式移动端 Web UIMobileApp包装成真正的原生 App如何通过with-mobile-env.mjs统一管理 Xcode/JDK/Android SDK 工具链如何实现连接引导、QR 配对、安全存储、深链、推送通知、桌面组件与 Control Center 等原生能力以及当前距 TestFlight / Play 内部测试还差哪些 CI、签名与审核事项。读完本文你将掌握 OpenChamber 移动端的构建命令、原生能力清单、平台配置要点、已知坑位与发布路线图可直接据此继续开发或补齐发布自动化。一、这个包是什么Capacitor 壳工程而不是桌面壳packages/mobile是 OpenChamber 仓库中的Capacitor 工作区它包装的是托管式移动端 Web UI即MobileApp渲染器而不是桌面端的 Electron 壳。原生 App 本质上是iOS一个WKWebViewAndroid一个Android WebView两者加载的是打进 App 包里的 Web 构建产物副本原生能力则通过 Capacitor 插件和两个 iOS App Extension 补充。基本身份信息App ID / 包名com.openchamber.app应用名称OpenChamber。Capacitor 配置capacitor.config.ts 中关键的三个插件设置Keyboard.resize: none—— 键盘弹出时 WebView 保持全高UI 通过--oc-keyboard-insetCSS 变量自行跟随键盘useNativeMobileChrome驱动而非等待内建 resize 动画结束后再调整实测内建方案有约 1.5s 延迟StatusBar覆盖 WebViewoverlayPushNotifications.presentationOptions: []—— 前台时永不显示 APNs 横幅见推送章节。渲染入口Web 构建的mobile.html入口MobileApp被复制进dist/并由 Capacitor 伺服。Capacitor 专属表面连接引导connection onboarding、Instances管理、QR 配对、小组件等只存在于 Capacitor 壳内——在普通浏览器里直接访问托管mobile.html并不会暴露这些能力。这一点在 README.md 中描述得更细移动包复用 Web 构建然后把mobile.html改写为packages/mobile/dist中的index.html确保原生 iOS/Android 启动时永远进入MobileApp而非托管的表面选择器原生 App不内嵌OpenChamber Web 服务器或 OpenCode 服务器首次启动时展示连接已有服务器的界面。运行模型要点连接保存在 App 本地可从会话抽屉底部的Instances管理首次连接界面与Instances入口都是 Capacitor 专属能力。手机与平板共用同一套导航模型左侧会话抽屉/侧栏、右侧工作区抽屉Changes / Files / Terminal / Notes / MCP无 overflow 菜单平板差异仅在会话列表是可调整宽度的常驻侧栏、头部下拉是锚定弹层。平板布局是一个实时尺寸类useTabletLayout不是设备检测任何短边 ≥ 600px 的表面都会获得平板布局工作区只有在宽度足以同时容纳侧栏、面板和可读的聊天列时才会变成侧面板WORKSPACE_PANEL_MIN_WIDTH_PX 1000。书页式折叠屏展开时命中该尺寸类折叠后自动回落手机布局Android activity 声明了匹配的configChanges因此折叠只是 resize WebView 而非重建。实现见 lib/device.ts密码保护的 OpenChamber 服务器可在移动端解锁App 会把签发的 client token 与保存的连接一并存储。二、构建管线Web 构建如何变成原生二进制HANDOFF 文档给出了完整的构建链路bun run --cwd packages/web build # web/dist → scripts/prepare-web-assets.mjs # copy web/dist → mobile/dist, mobile.html → index.html → cap sync # copy dist → native, sync plugins/config → xcodebuild / gradle assembleDebug # native binarysync在 package.json 中定义实际执行的是bun run build cap sync并且整个流程跑在移动端环境包装器里。prepare-web-assets.mjsHTML 入口重写prepare-web-assets.mjs 做的事非常直接清空并重建mobile/dist把web/dist递归复制过去然后把dist/mobile.html的内容写到dist/index.html。这样原生容器永远加载index.html即MobileApp而不是托管表面选择器。工具链包装器 with-mobile-env.mjs排错构建环境问题前必读with-mobile-env.mjs 是所有构建/部署脚本的统一入口它为子进程设置环境变量环境变量覆盖优先变量解析顺序先到先用默认/兜底值DEVELOPER_DIR$DEVELOPER_DIR→xcode-select -p→ 硬编码路径/Applications/Xcode.app/Contents/DeveloperJAVA_HOME$JAVA_HOME→ 兜底/opt/homebrew/opt/openjdk21ANDROID_HOME/ANDROID_SDK_ROOT$ANDROID_HOME→ 兜底/opt/homebrew/share/android-commandlinetoolsPATH前插$JAVA_HOME/bin与$ANDROID_HOME/platform-tools保证adb可解析设计上它有意尊重xcode-select这样 Xcode 测试版或非默认安装也能被正确使用——文档明确说明此前硬编码路径曾把构建推到错误的 Xcode / Command Line Tools 上模拟器运行时不匹配会导致xcodebuild找不到目标模拟器。换一台机器时请通过环境变量覆盖这些值而不是改脚本即使xcode-select指向 Command Line Tools包装器对移动命令的DEVELOPER_DIR处理也能覆盖到。三、命令速查根别名与包内命令根目录别名从仓库根运行bun run mobile:build # web build prepare-web-assets bun run mobile:sync # build cap sync bun run mobile:build:android:debug # sync gradle assembleDebug bun run mobile:build:ios:simulator # simulator build会临时剥离 MLKit pod见坑位 bun run mobile:open:ios # 在 Xcode 中打开 bun run mobile:open:android # 在 Android Studio 中打开 bun run type-check:mobile bun run lint:mobileAndroid 真机部署adb 方式未做根别名这些命令基于 android-device.mjs需在包目录内运行bun run --cwd packages/mobile android:devices # 列出 adb 设备期望 device 而非 unauthorized bun run --cwd packages/mobile android:install # adb install -r 安装 debug APK bun run --cwd packages/mobile android:launch # am start MainActivity bun run --cwd packages/mobile android:run # 安装 启动 bun run --cwd packages/mobile android:logcat # 应用日志典型的真机迭代流程先bun run --cwd packages/mobile build:android:debug产出 APK再android:run。APK 路径固定为android/app/build/outputs/apk/debug/app-debug.apk。脚本内部细节requireDevice()会提示开启开发者选项 USB 调试并接受授权弹窗launch通过am start -n com.openchamber.app/.MainActivity启动logcat优先按pidof过滤该 App 的日志未运行时退化为流式输出 Capacitor/Chromium 日志。iOS 模拟器辅助命令mobile:sim:{boot,install,launch,run,serve,list,kill}一组见 ios-sim.mjsboot默认启动iPhone 17 Proinstall/launch/run通过xcrun simctl操作构建产物App.appserve-sim提供模拟器画面的浏览器预览流。sim:devios-sim-dev.mjs是一键开发循环构建模拟器 App → 安装启动 → 启动serve-sim流并打印预览 URLCtrlC 停止流可传--no-build跳过慢速构建直接重跑。无头快速上手bun run build bun run sync bun run build:ios:simulator bun run build:android:debug以上命令不启动 Xcode、Android Studio、Simulator 或模拟器即可完成原生工程构建与同步。四、已实现的原生能力清单连接引导Connection onboarding服务器 URL 输入、锁定服务器的密码解锁、client-token 签发、已保存连接管理、Instances管理面板、启动时自动连接最后一次实例。删除活动实例会把运行时重置回连接界面。连接的持久化模型在 mobileConnections.ts 中有清晰注释实例元数据id/label/url/lastUsedAt hasToken标志存 localStorage绝不包含 tokenclient token 通过aparajita/capacitor-secure-storage存进系统安全存储iOS Keychain / Android Keystore按实例 URL 为键。token 写入是await后才切换运行时端点保证解锁成功即持久化成功。QR 配对基于capacitor-mlkit/barcode-scanning。Android 走 CameraX 支撑的startScan()流程条码模型打包进 App因此离线且不依赖 Google Play Services也能扫描iOS 用插件自带原生扫描器。已声明CAMERA权限与NSCameraUsageDescription。前端逻辑见 mobileQrScan.tsisQrScanSupported()检测插件存在性scanConnectionQr()统一处理权限申请拒绝返回permission-denied、Android 的事件监听式扫描与 iOS 的一次性scan()并兼容老 Android WebView 解析openchamber://失败时的字符串兜底解析。安全存储aparajita/capacitor-secure-storage存连接 token见上。深链Deep linksopenchamber://URL scheme一套可复用的意图词表deepLinks.ts被通知点击、小组件、Control Center 共同使用冷启动意图会被暂存。parseDeepLink()把原始 URL 解析成类型化DeepLinkIntentsession / new-session / sessions / status / settings / changes / view未知路由返回null而非抛错deepLinkNavigation.ts 是唯一知道如何应用意图的层模块级pending持有器保证冷启动的意图在 App ready 后仍能被消费最新意图胜出。推送通知iOS APNs Android FCM详见下一节。存在感知路由当交互式桌面/Web客户端可见时抑制该设备的推送。iOS 小组件 Control Center 通知服务扩展WidgetKit 扩展OpenChamberWidget、一个 Control Center 控制项、以及一个 NSEOpenChamberNotificationService——NSE 负责在推送到达时刷新小组件。三者共享 App Groupgroup.com.openchamber.app。原生 Chrome状态栏iOS 覆盖 安全区Android inset 主题背景、键盘处理iOS CSS insetAndroid 原生adjustResize、边缘滑动切换会话、返回键处理、App 图标角标。应用图标iOSAppIconAndroid 自适应启动图标通知小图标ic_stat_notify。五、推送/通知架构注册启动时 App 注册设备 token——iOS → APNs、Android → FCM——并打上platformios/android标签发送给已连接的服务器。转发服务器把值得通知的事件转发给已签名的 relayrelay 按 token 绑定的平台路由到 APNs 或 FCM。App 自身只需要获取并注册 token。存在感知抑制每个客户端上报前台可见性 平台当交互式桌面/Web/VSCode客户端可见时跳过移动端推送它已在应用内展示通知。门控条件是桌面的可见性而不是手机自身的可见性。前台行为iOS 通过presentationOptions: []抑制横幅服务器总是发送、无竞态可见性门控前台由 iOS 抑制展示Web/PWA 的 service worker 在窗口聚焦时抑制展示。iOS 侧还有一个值得注意的细节AppDelegate.swift中计算apnsEnvironmentdevelopment/production从内嵌的 provisioning profile 读取aps-environmententitlement无内嵌 profile 的 App Store 构建即为production该值通过__OPENCHAMBER_APNS_ENV__文档起始脚本暴露给 Web 层让服务器把每个设备 token 投递到真正认识它的 APNs 端点sandbox vs production。六、平台配置细节iOSios/App扩展OpenChamberWidgetWidgetKit部署目标 17.0与OpenChamberNotificationServiceNSE15.5两者都手工接线进App.xcodeproj/project.pbxproj并通过 copy phase 内嵌。三个 targetApp Widget NSE的 entitlements 都声明App Groupgroup.com.openchamber.app。Info.plistCFBundleURLTypes注册openchamberschemeNSCameraUsageDescription扫描配对 QR 码、NSMicrophoneUsageDescription语音输入、NSLocalNetworkUsageDescription连接局域网服务器等使用说明字符串齐备NSAppTransportSecurity对 Web 内容允许任意加载并允许本地网络。需要push entitlementaps-environment。APNsmutable-content: 1在服务器/relay 侧设置会唤醒 NSE 刷新小组件。Androidandroid/appgoogle-services.json已提交Firebase 项目openchamber-8bf7e。Google Services Gradle 插件在文件存在时条件应用build.gradle 中file(google-services.json)存在即apply plugin: com.google.gms.google-servicescapacitor/push-notifications引入firebase-messaging。ManifestAndroidManifest.xml权限INTERNET、CAMERA 可选相机 featureandroid.hardware.camera requiredfalse、POST_NOTIFICATIONSAndroid 13旧版本默认允许通知、以及语音输入所需的RECORD_AUDIOMODIFY_AUDIO_SETTINGSwindowSoftInputModeadjustResizeFCMdefault_notification_icondrawable/ic_stat_notify状态栏/通知栏小图标必须是单色剪影。自适应启动图标全出血纯色背景 ic_launcher_foreground源文件在packages/mobile/assets/可用capacitor/assets重新生成。SDK 级别variables.gradleminSdk 24、compileSdk 35、targetSdk 35满足 Play 当前要求。CI 签名预留build.gradle已预留从环境变量OPENCHAMBER_ANDROID_KEYSTORE_PATH等读取 release 签名配置的逻辑hasCiSigning为真时才启用签名为后续 CI 打带签名的 release 包铺路。七、已知坑位Quirks / gotchasiOS 模拟器 MLKitGoogleMLKit条码库没有 arm64-simulator 切片正常构建会产出只有 x86_64 的二进制无法装进 arm64-only 的 iOS 26 模拟器does not contain code for ... arm64。因此 ios-sim-build.mjs 会临时从 Podfile 剥离CapacitorMlkitBarcodeScanningpod →pod install→ 构建 arm64 模拟器二进制 → 在finally中始终恢复Podfile Pods模拟器没有摄像头剥离扫描器不损失功能前端mobileQrScan在原生插件缺失时会干净降级getScannerPlugin()返回null→isQrScanSupported()为 false。真机/TestFlight 构建则正常包含扫描器。Android WebView 版本UI 使用了color-mix()Tailwind v4 主题需要Chromium 111。过旧的 Android System WebView 会导致半透明/选区渲染错误——提醒测试人员保持 Android System WebView 更新或使用自带较新版本的设备。Capacitor 流传输锁定为 SSE原生 App 上原生 WebSocket 流在 Android 上不可靠因此 Chat 传输设置会显示选中 SSE 并禁用其他选项。Android 推送必须带google-services.json重新构建没有它register()曾直接崩溃Default FirebaseApp is not initialized。注册逻辑已门控到 iOS/Android 原生环境。混合内容capacitor.config.ts中android.allowMixedContent: true允许 Android WebViewhttps://origin访问明文 http 局域网服务器如http://192.168.x.xiOS 无此问题capacitor://schemerelay/tunnel 流量本身走 TLS。八、验证命令与预期警告bun run type-check:mobile bun run lint:mobile bun run mobile:build:android:debug bun run mobile:build:ios:simulatorWeb 继承的构建警告KaTeX 字体 URL、onnxruntime-webeval、chunk-size是预期且非致命的。九、差距CI / 发布自动化下一步工作App 目前仅能本地构建与部署还没有 CI、签名与发布管线。要推进到 TestFlight / Play 内部测试需要iOSApple Developer 账号为 App和两个扩展分别创建 App IDcom.openchamber.app、.OpenChamberWidget、.OpenChamberNotificationService各自启用App Group和App 的Push。三个 target 的签名证书 provisioning profiles扩展需要各自的 profile。App Store Connect API key 用于非交互式 TestFlight 上传xcodebuild archivenotarytool/altool或 fastlanegympilot。Runner与DEVELOPER_DIR相同 Xcode 版本的 macOS。AndroidRelease keystore作为 CI secret 保存构建签名的 AABbundleRelease——当前 debug 脚本产出的是未签名 debug APK。Play Console 应用 内部测试轨道用于自动化上传的 Play service accountfastlanesupply或 Play Developer API。google-services.json已提交因此 CI 中 FCM 构建无需额外配置。Runner带 Android SDK openjdk21的 Linux。CI 备注复用with-mobile-env.mjs的环境契约DEVELOPER_DIR、JAVA_HOME、ANDROID_HOME——在 workflow 中设置它们而不是依赖本地 Homebrew 路径。Relay/推送密钥APNs key、FCM service account属于 relay 基础设施不在 App CI 中。版本/构建号自动递增尚未自动化。十、商店审核就绪度Xcode 构建警告不会阻塞审核具体事项是商店要求而非代码质量问题。仓库内已完成当前分支iOS隐私清单PrivacyInfo.xcprivacy声明不追踪NSPrivacyTracking false无追踪域、无收集数据类型并声明必需的 UserDefaults API 原因CA92.1、C56D.1对应 App Group 快照打包的 SDK 自带各自的清单。iOSITSAppUsesNonExemptEncryption falseInfo.plist跳过每次构建的出口合规提示。iOS 相机 本地网络使用说明字符串Android SDK 级别target/compile 35、min 24满足 Play 当前要求。发布时需在控制台/基础设施完成非代码隐私政策 URL—— 两个商店都要求App 使用相机 通知。iOSApp Privacy nutrition labelApp Store Connect与 AndroidData Safety表单——声明收集了什么设备推送 tokenApp 除此之外只与用户自己的服务器通信。生产 APNsApp Store / TestFlight 构建release 构建中 App 的aps-environment必须是productionrelay 必须发送到生产 APNs而非 sandbox。演示实例 凭据供审核员使用——App 连接的是用户自己的服务器因此审核需要一个可达的测试实例App Store 2.1 / Play。Guideline 4.2最低功能要求——WebView 包装类 App 可能被严格审查请在审核备注中引用原生特性推送、小组件、Control Center、QR 配对。签名/上传按上文 CI 章节执行三个 iOS target签名 Android AAB。十一、从文档到实现关键文件索引主题文件交接文档本文主线packages/mobile/HANDOFF.md移动包自述运行模型 命令 排错packages/mobile/README.mdCapacitor 配置packages/mobile/capacitor.config.ts构建脚本与工具链包装packages/mobile/package.json、scripts/with-mobile-env.mjs、scripts/prepare-web-assets.mjs设备部署与模拟器scripts/android-device.mjs、scripts/ios-sim.mjs、scripts/ios-sim-build.mjs、scripts/ios-sim-dev.mjs深链意图与导航apps/deepLinks.ts、apps/deepLinkNavigation.tsQR 扫描与连接存储apps/mobileQrScan.ts、apps/mobileConnections.ts平板尺寸类布局lib/device.tsiOS 原生配置Info.plist、PrivacyInfo.xcprivacy、AppDelegate.swiftAndroid 原生配置AndroidManifest.xml、build.gradle、variables.gradle整体来看OpenChamber 移动端是一套以托管 Web UI 为核心、以 Capacitor 为壳、以原生插件与扩展补齐能力的典型混合应用工程构建管线通过统一的环境包装器在不同机器间可复现原生能力QR、安全存储、深链、推送、组件都对应着明确的源码实现而发布环节则清晰地拆成了仓库内已完成与发布时待办两部分为接手者提供了可直接执行的后续路线。赞分享AI Agent人工智能代码智能体交互助手【免费下载链接】openchamberAgentic Development Environment based on OpenCode AI agent项目地址https://gitcode.com/gh_mirrors/op/openchamber点击查看免费下载相关推荐OmniRoute Playground Studio 深度解析统一 AI 测试空间、四 Tab 并行比较与源码级实现OmniRoute Playground Studio 深度解析统一 AI 测试空间、四 Tab 并行比较与源码级实现 Playground Studio 是AI Agent人工智能代码智能体交互助手Kronos-Tokenizer-2k避坑指南从安装到分词K线数据的四步完整路径Kronos Tokenizer 2k避坑指南从安装到分词K线数据的四步完整路径 第一次喂 K 线数据就卡住最容易翻车的无非四处依赖安装、数据格式、序列长语言运行时标准库JIT编译编译器GeoLibre iOS 构建与发布完全指南从 Tauri v2 移动端架构到 App Store 上架实战GeoLibre iOS 构建与发布完全指南从 Tauri v2 移动端架构到 App Store 上架实战 导读 本文以 docs/ios.md httpsGIS数据可视化前端桌面应用后端上一篇PandasAI农业农村人工智能技术人工智能技术应用与优化下一篇终极指南CnCTDRAMapEditor地图编辑器从入门到精通创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表