Nunulo Android 日常客户端,使用 Kotlin、Jetpack Compose、高德地图 SDK 和系统照片选择器。
- Nunulo 公开稳定服务已上线,当前正式版本为
v0.2.5;历史 APK 不代表当前版本。 main正在形成第一期v0.3.0候选客户端;尚未创建正式 tag 或 Release,线上 APK 仍是v0.2.5。v0.2.0-test.1的地图空状态错误写死上海,且必须在登记页手动点击定位;该版本已被当前修复取代,不能继续作为地图与定位验收基线。- 构建默认使用
https://nunulo.lumokato.com;需要切换本地或其他测试环境时,通过 Gradle 属性、环境变量或未提交的local.properties显式提供NUNULO_API_BASE_URL。 - 当前中期展示版身份为
0.3.0-preview.4(versionCode=15);首次安装或会话失效时直接进入登录页,支持公开注册或邀请码注册。Linux 自动测试、构建与界面回归是本轮门禁;物理设备上的原生地图、拍照和断网恢复保留为后续 L4 证据。正式0.3.0必须使用更高的versionCode。 - 中期展示版仍默认连接当前线上
v0.2.5API:登录、动态、记录详情、点赞、评论、通知、成员、合集和导出沿用兼容路径;伙伴、正式目录、发现、足迹及新多图发布等一期能力要等 API 安全迁移和部署后才具备完整在线数据链。客户端按页面显示局部失败,不把次要新接口的404误判为整次登录失败。 - 当前里程碑:真实 PostGIS CI、外部四角色多人链路、并发、R2 数据链与 Android 模拟器闭环已通过;继续完善物理设备拍照、定位、断网与进程恢复回归。
- Android namespace、applicationId 和 Kotlin 包路径统一使用
com.lumokato.nunulo,不保留旧包升级兼容。
从 android 目录使用仓库固定的 Gradle Wrapper:
.\gradlew.bat :app:testDebugUnitTest :app:assembleDebug网络请求、HTTP 状态错误和 refresh token 协调已从 Compose 页面中提取为可单测边界;401 使用明确状态码判断,并发失效请求只执行一次 refresh,非鉴权失败不会被误重试。
第一期本地客户端使用动态、发现、记录、伙伴、我的五个入口,通知位于顶栏。动态提供热门 / 最新与关注范围;发现聚合物件类型、作品、角色、活动、专题和达到阈值的世界地区,并按需打开地区地图;伙伴页支持稳定编号、跨用户补登记确认和相遇关系。详情继续支持点赞、评论、举报、本人编辑删除和加入合集。
活动使用独立全屏浏览页,支持按活动、地点或系列搜索,按近期 / 往期和线上 / 线下筛选;往期活动保留在归档中,官方与成员共建状态始终明确。发现页只展示少量近期活动,不再用不断增长的活动清单挤占作品与世界地区内容。活动聚合页显示时间、单一地点、当前可见记录中的成员 / 伙伴 / 角色统计和真实动态,不为了凑模块生成参与数据,也不强制加载交互地图。
作品、组合与角色使用独立全屏目录,支持中文、日文、罗马字、别名和所属层级搜索,并可按类型与关注范围筛选;发现首页只保留少量精选入口。打开目录项后显示规范名、必要别名、所属作品 / 组合、关注状态,以及当前可见真实记录中去重后的成员、伙伴、地点和活动统计;无结果时可直接提交目录候选,不生成虚构地点、伙伴或排行。
记录详情会逐位显示出镜伙伴的确认状态与独立关系隐私。记录作者和伙伴所有者可以在“公开显示 / 仅相关成员”之间切换,或经明确确认后移除该段出镜关系;这些操作不会改变伙伴资料本身的隐私,也不会删除伙伴、照片或其他记录。Owner / Admin 在 Android 中不因此获得额外治理操作,完整治理继续位于独立 Web Admin。
“我的 → 收藏”提供可完整管理的照片记录册:可以创建合集、填写说明和三档可见性、打开查看真实收录、编辑、逐条移出和删除合集。移出或删除只改变合集关系,原记录、照片、评论与互动全部保留;空合集显示真实空态,不会误载发现动态。
“我的 → 社区”提供可浏览的成员目录:可按显示名、用户名和简介搜索,筛选已关注成员,并从成员卡打开完整主页。成员主页显示头像、简介、真实关注统计和当前账号有权查看的照片记录;个人身份区可编辑自己的显示名、简介和头像。关注、取消关注和屏蔽继续服从服务端权限与幂等边界。即使旧生产 API 忽略作者筛选参数,客户端仍会按返回记录的真实作者再次过滤,不会把其他成员内容混入个人主页。
记录支持应用内相机和系统相册 1–9 图,实时拍摄默认推荐 1 张;每张图先计算 SHA-256 并独立上传,失败可逐图重试,成功图片可重排封面。照片 EXIF/GNSS 优先于设备 GPS;仍无位置时可地图补点或无地点发布。记录可关联多个伙伴、物件类型、作品、角色、可选活动和单一地点,不保留旧单图 / 自由 tag 协议。
个人足迹显示本人家位置和去过的地点;世界入口默认先展示地区卡片,只有用户主动打开时才加载地图。x86_64 或缺少高德 Android Key 时,足迹、世界地区和地点补录都只显示真实坐标与明确说明,不初始化不受支持的原生地图,也不绘制伪造底图或随机点。
高德原生 Android Key 通过 Gradle 属性、环境变量或未提交的 local.properties 提供:
AMAP_ANDROID_KEY_DEBUG=<绑定 com.lumokato.nunulo 与 debug SHA-1 的 Android Key>
AMAP_ANDROID_KEY_RELEASE=<绑定 com.lumokato.nunulo 与 release SHA-1 的 Android Key>
NUNULO_API_BASE_URL=<API 基址>debug 与 release 构建必须分别显式提供对应的 Android Key。Web/JS Key 不会被读取。没有 Key 时应用显示明确的地图不可用状态,不伪造地图。真实凭据、APK、照片和设备数据不进入仓库。
个人 release 使用稳定的项目外 keystore,通过以下 Gradle 属性或环境变量注入:
NUNULO_RELEASE_KEYSTORE_PATH=<keystore 路径>
NUNULO_RELEASE_STORE_PASSWORD=<store password>
NUNULO_RELEASE_KEY_ALIAS=<alias>
NUNULO_RELEASE_KEY_PASSWORD=<key password>当前稳定版不承担早期测试 APK 的原位升级兼容义务。release 必须使用独立、稳定的项目签名,并为该签名创建对应的高德 Android Key;不得为了覆盖历史 debug 安装而复用 debug 证书。
推送与应用版本一致的 v* tag 时,GitHub Actions 在测试、签名、包名、版本号和地图 Key 校验通过后创建正式 Release,并上传固定名称 nunulo-android.apk 与 nunulo-android.sha256。普通分支推送只保留 CI artifact,不会自动创建公开下载。
选择或拍摄的照片会复制到应用私有目录并立即保存草稿。应用被强停或上传中断后会恢复照片顺序、成功/失败状态、地点、坐标、类别、伙伴、活动、备注和请求号;已成功照片不会重传,中断中的照片会变为可重试状态,不可恢复的本地空照片不会残留。重复登记由 API 幂等与照片 checksum 复用共同保护。用户可在登记页手工修改经纬度或主动清除草稿。
Linux 界面回归直接渲染生产 Compose 组件和完整旅程状态。当前基准覆盖登录、窄屏注册、动态离线与真实长内容、发现内容、记录空态/关系地点/无定位/部分上传失败/发布确认、目录无结果、互动详情、长伙伴资料、个人足迹,以及普通成员和 Owner 角色边界;后续新增主旅程和异常状态必须继续补图,不以当前数量作为上限:
.\gradlew.bat :app:validateDebugScreenshotTest产品与验收状态以 C:/Dev/Nunulo/nunulo-docs/docs/主线/当前真实状态.md 为准。