Files
daycard-app/开发测试记录-20260714.md

230 lines
10 KiB
Markdown
Raw Normal View History

# 橘视厅酒店版 App 开发与测试记录
> 日期:2026-07-14
> 项目:MediaApp(橘视厅酒店版)
> 版本:v1.0
---
## 一、概述
本次开发围绕天卡(日卡)激活 → 设备鉴权 → 微信支付 → 发卡 → 播放的完整链路进行联调与修复,并完成了权益持久化/静默鉴权、播放器画面比例、UI 美化等优化。
---
## 二、问题修复记录
### 2.1 激活请求无法到达后端
- **现象**:点击激活后请求未到达后端,错误仅以弹窗形式出现,无法定位原因。
- **修复**:
- 新增 `FileLogger` 工具类,持久化日志到 `Android/data/com.pukka.mediaapp/files/logs/daycard.log`。
- 新增 `FileLoggingInterceptor`,拦截 OkHttp 请求/响应写入日志文件。
- 在 `SignManager`(激活/init/refresh/heartbeat)、`PaymentViewModel`(鉴权/下单/轮询)关键路径加入 `FileLogger` 调用。
- **结果**:通过 `adb pull` 拉取日志后成功定位问题,激活流程恢复正常。
### 2.2 Gson `code` 字段冲突
- **现象**:后端返回的 JSON 中 `code` 字段被 Gson 解析为重复键,导致业务码判断异常。
- **原因**:`BaseResponse` 子类(`CheckBenefitsResponse`、`CreateOrderResponse` 等)各自声明了 `override val code/msg`,与父类产生重复 JSON 字段。
- **修复**:移除所有子类中的 `code`/`msg` 声明,统一继承 `BaseResponse()`。
- **文件**:`DayCardModels.kt`
### 2.3 支付弹窗渲染异常
- **现象**:支付弹窗仅显示"微信扫码支付"6 个字,其余区域空白,所有按钮不可点击。
- **原因**:240dp×240dp 的二维码 `FrameLayout` 在加载/错误状态下未隐藏,将按钮挤出可视区域。
- **修复**:
- 给 `FrameLayout` 添加 `android:id="@+id/flQrcode"`。
- 在 `showPaymentDialog`/加载/错误分支设置 `flQrcode.visibility = GONE`,在 `showQrCode` 中设为 `VISIBLE`。
- **文件**:`dialog_payment.xml`、`DetailActivity.kt`
### 2.4 天卡库存不足提示
- **现象**:天卡卡池为空时,后端返回 HTTP 200 + `{"code":500,"msg":"天卡库存不足,请补充库存后再试"}`,前端需正确识别。
- **修复**:前端按 JSON `code` 字段判断(而非 HTTP 状态码),`code === 500` 且 `msg` 包含"库存不足"时弹出错误提示。
- **备注**:抢卡失败时会产生孤儿订单(status=PENDING),由后端超时定时任务 `DayCardOrderTimeoutTask` 清理为 CANCELLED。
### 2.5 发卡成功但返回播放地址异常
- **现象**:支付成功、发卡成功后,获取播放地址异常。
- **原因**:绑定与鉴权链路问题(橘视厅平台订购关系)。
- **修复**:平台侧订购关系修正后恢复正常。
---
## 三、权益持久化与静默鉴权
### 3.1 背景
成功获取播放地址后,切换其它电影点击播放仍弹出支付提示窗。虽然流程很快走完,但体验不佳。需实现有效期内权益持久化 + 静默鉴权。
### 3.2 实现方案
#### SignManager 权益缓存(`DayCardSignUtil.kt`)
| 方法 | 说明 |
|------|------|
| `cacheBenefits(thirdCardNo, expireAt)` | 缓存卡号 + 过期时间到 SharedPreferences `jst_sign` |
| `getCachedThirdCardNo()` | 读取缓存卡号,过期返回空串 |
| `clearBenefits()` | 清除权益缓存 |
| `parseExpireAtToMillis()` | 解析多种时间格式为毫秒时间戳 |
- 过期时间兜底:解析失败时使用 `SIGN_TTL` 作为默认有效期。
#### PaymentViewModel(`PaymentViewModel.kt`)
- **缓存命中**:`startPaymentFlow()` 开头同步检查 `getCachedThirdCardNo()`,非空则直接发射 `HasPermission`,不发起网络请求、不弹窗。
- **缓存写入**:三处调用 `cacheBenefits()`:
1. `checkBenefits` 返回 ACTIVE 时
2. 轮询支付成功后首次 `checkBenefits` 返回 ACTIVE 时
3. 轮询支付成功后重试 `checkBenefits` 返回 ACTIVE 时
- **缓存清除**:SDK 初始化失败时调用 `clearBenefits()`(卡号可能已失效,下次播放重新鉴权)。
- **修复**:移除了之前重复的 `flowJob = viewModelScope.launch` 嵌套问题。
#### DetailActivity 静默播放(`DetailActivity.kt`)
| 状态 | 原行为 | 新行为 |
|------|--------|--------|
| `CheckingPermission` | 弹支付窗"正在检查播放权限" | 静默,不弹窗不提示 |
| `HasPermission` | 弹窗"已有播放权限" | 直接播放,无弹窗无 Toast |
| `CreatingOrder` | 弹窗加载 | 弹窗加载(仅无权益路径触发) |
| `WaitingForPayment` | 展示二维码 | 展示二维码(不变) |
| `PaymentSuccess` | 弹窗"支付成功" | 关闭弹窗直接播放,无 Toast |
| `Error` | 弹窗显示错误 | 弹窗显示错误,重置播放标志 |
- `playWithThirdCardNo` / `fetchVideoUrlFromSdk`:移除所有加载 Toast,仅保留错误 Toast(LENGTH_LONG)。
- `startPaymentFlow()`:移除"正在检查播放权限..." Toast。
- **最终效果**:天卡有效期内切换电影点播放,完全静默,直接进入播放器。
### 3.3 链路时序
```
首次播放(无缓存):
点击播放 → checkBenefits(网络) → ACTIVE → cacheBenefits → 播放
点击播放 → checkBenefits(网络) → UNBOUND → createOrder → 二维码 → 支付 → 轮询PAID → checkBenefits → cacheBenefits → 播放
后续播放(缓存有效):
点击播放 → getCachedThirdCardNo(本地) → HasPermission → 播放 [全程无网络、无弹窗]
缓存过期/SDK失败:
点击播放 → getCachedThirdCardNo 返回空 → checkBenefits(网络) → 重新走鉴权流程
```
---
## 四、App 名称与播放器
### 4.1 App 名称
- `strings.xml` 中 `app_name` 从"媒资展示"改为"橘视厅酒店版"。
### 4.2 播放器画面比例
- `activity_player.xml` 中 `StyledPlayerView` 的 `resize_mode` 从 `fill`(拉伸填充)改为 `fit`(保持原始比例,不拉伸)。
- 非 16:9 内容会自动上下/左右留黑边。
---
## 五、UI 布局优化
### 5.1 新增 Drawable(8 个)
| 文件 | 用途 |
|------|------|
| `bg_poster_rounded.xml` | 海报四角圆角裁切背景 |
| `bg_poster_rounded_top.xml` | 海报顶部圆角(卡片用) |
| `bg_play_button.xml` | 播放按钮橙色渐变 + 24dp 大圆角 |
| `bg_nav_selected.xml` | 导航选中胶囊背景 |
| `bg_section_bar.xml` | 楼层标题橙色竖条指示器 |
| `bg_button_secondary.xml` | 次要按钮半透明圆角 |
| `bg_dialog.xml` | 支付弹窗渐变背景 + 16dp 圆角 |
| `bg_qrcode_white.xml` | 二维码白底圆角 |
### 5.2 更新 Drawable(4 个)
| 文件 | 变更 |
|------|------|
| `bg_card.xml` | 纯色 → 渐变层次感,圆角 8→10dp |
| `bg_card_focus.xml` | 焦点边框白色 → 橙色 |
| `bg_button_accent.xml` | 纯色 → 渐变,圆角 8→20dp |
| `bg_search_input.xml` | 圆角优化 |
### 5.3 布局优化
| 布局文件 | 优化内容 |
|----------|----------|
| `item_content.xml` | 海报圆角裁切,标题/评分字号增大,间距优化 |
| `activity_detail.xml` | 海报 120→150dp 加圆角,播放按钮渐变大圆角(140×52dp),信息区间加分割线,整体字号增大 |
| `item_nav.xml` | 选中态从下划线改为橙色胶囊背景 |
| `item_section.xml` | 楼层标题前加橙色竖条指示器 |
| `activity_home.xml` | 顶栏底部加分割线 |
| `item_search_result.xml` | 海报圆角,字号增大,间距优化 |
| `activity_list.xml` | 侧边栏间距优化 |
| `dialog_payment.xml` | 渐变背景,二维码白底圆角,主按钮渐变,关闭按钮改次要样式 |
### 5.4 代码优化
| 文件 | 变更 |
|------|------|
| `AdapterUtils.kt` | 焦点边框白色 → 橙色,圆角 8→10dp,聚焦时 `bringToFront` |
| `NavAdapter.kt` | 选中态从 `BottomLineDrawable` 下划线改为 `bg_nav_selected` 胶囊背景 |
---
## 六、测试情况
| 测试项 | 结果 | 备注 |
|--------|------|------|
| 设备激活 | ✅ 通过 | 卸载重装后可正常激活 |
| 鉴权 → 播放(有权益) | ✅ 通过 | 缓存命中后静默播放 |
| 鉴权 → 支付 → 播放(无权益) | ✅ 通过 | 二维码展示 → 支付 → 发卡 → 播放 |
| 天卡库存不足 | ✅ 通过 | 正确提示"天卡库存不足" |
| 切换电影重复播放 | ✅ 通过 | 有效期内不弹窗,直接播放 |
| SDK 初始化失败 | ✅ 通过 | 清除缓存,Toast 提示错误 |
| 播放器 16:9 | ✅ 通过 | 不拉伸,保持原始比例 |
| App 名称显示 | ✅ 通过 | 显示"橘视厅酒店版" |
| UI 布局美观度 | ✅ 通过 | 圆角海报、渐变卡片、橙色焦点态 |
---
## 七、关键文件清单
```
MediaApp/app/src/main/java/com/pukka/mediaapp/
├── network/
│ ├── DayCardSignUtil.kt # SignManager + 权益缓存 + Retrofit 客户端
│ └── DayCardApiService.kt # API 接口定义
├── viewmodel/
│ └── PaymentViewModel.kt # 支付/鉴权流程状态机
├── ui/
│ ├── DetailActivity.kt # 详情页 + 静默播放逻辑
│ ├── VideoPlayerActivity.kt # ExoPlayer 播放器
│ └── adapter/
│ ├── AdapterUtils.kt # 焦点高亮 + 主题色
│ ├── ContentAdapter.kt # 内容卡片适配器
│ └── NavAdapter.kt # 导航适配器
├── model/daycard/
│ └── DayCardModels.kt # 响应模型(BaseResponse 继承)
└── utils/
└── FileLogger.kt # 文件日志工具
MediaApp/app/src/main/res/
├── layout/ # 全部布局文件(已优化)
├── drawable/ # 14 个 drawable(8 新增 + 4 更新 + 2 原有)
├── values/
│ ├── colors.xml # 颜色定义
│ ├── dimens.xml # 尺寸定义
│ ├── strings.xml # 字符串(app_name 已改)
│ └── themes.xml # 主题
```
---
## 八、待办与后续
- [ ] 天卡过期后自动重新走鉴权流程的体验验证(长期测试)
- [ ] 支付弹窗在弱网环境下的超时处理优化
- [ ] UI 在不同分辨率 TV 盒子上的适配验证
- [ ] 考虑权益缓存过期前提前静默刷新(避免过期瞬间首次播放有延迟)