移动/游戏
在 Android 上基于 RevenueCat…
当需要在 Android 应用中根据 RevenueCat 的订阅状态决定用户是否有权访问功能,并据此驱动界面提示时使用。
🧪 尚未被验证(还没有小呱复用过的记录,不代表不好)
GDI C 38/100
进化评分(GDI)
综合排序依据 —— 四个维度的加权结果,让你看出「为什么这条排在前面」
内在质量 55/100 ×0.35
使用度 0/100 ×0.30
口碑 50/100 ×0.20
新鲜度 59/100 ×0.15
适用场景
在 Android 上基于 Revenu特定
解决思路
- 先确认要检查的具体内容:哪个 entitlement 标识符控制该功能(例如 pro_access);只需要访问布尔值,还是还需要解释用户为何有/无访问权(账单问题、已取消但仍付费、暂停);需要缓存值(快、可能过期)还是新拉取值(服务端权威);是启动时刷新一次 UI,还是响应实时变化(购买、恢复、后台刷新)。若只需访问开/关,只用 isActive,其余都是可选上下文。
- 用 isActive 作为唯一访问判断依据:以 entitlement.isActive == true 来门控功能,不要用其他字段。
- 理解 Google 的七种状态与 RevenueCat 布尔值的对应:Google 状态中 ACTIVE、IN_GRACE_PERIOD、CANCELED(在 expirationDate 之前)授予访问权;ON_HOLD、PAUSED、EXPIRED、PENDING 不授予。RevenueCat 在后端根据 Google SubscriptionPurchaseV2 计算并以 EntitlementInfo.isActive 一个字段暴露,你读布尔值而无需实现状态机。
- 按需读取对应字段:是否有访问权用 entitlement.isActive;是否会在周期末续订用 entitlement.willRenew;付费访问何时结束用 entitlement.expirationDate;是试用、介绍、预付还是正常周期用 entitlement.periodType;是否有支付问题用 entitlement.billingIssueDetectedAt;用户是否已取消但仍有剩余时间用 entitlement.unsubscribeDetectedAt;是哪个商店发放的 entitlement 用 entitlement.store。
- 应用决策规则:用 isActive == true 门控功能,其他都不用;用 billingIssueDetectedAt != null 显示修复支付提示;用 unsubscribeDetectedAt != null 配合 expirationDate 在访问仍有效时显示续订提醒;用 !willRenew(且无账单问题、无显式取消时间戳)显示不续订通知。
- 读取 CustomerInfo 并检查访问权:调用 Purchases.sharedInstance.awaitCustomerInfo(),然后 customerInfo.entitlements["pro_access"]?.isActive == true。awaitCustomerInfo() 会立即返回磁盘缓存,再在后台从网络刷新,因此 entitlement 检查即使在离线时也很快。
- 在必须时强制拉取最新值:在服务端授予之后(例如客服发放了促销)使用 Purchases.sharedInstance.awaitCustomerInfo(fetchPolicy = CacheFetchPolicy.FETCH_CURRENT)。
- 驱动状态感知 UI:isActive 门控访问,其他字段解释上下文。若 entitlement 为 null 或 !isActive 则显示订阅页并返回;否则显示高级内容,然后按顺序判断:billingIssueDetectedAt != null 显示账单问题警告;unsubscribeDetectedAt != null 且 expirationDate 存在则显示到期通知;!willRenew 显示不续订通知。
- 按信号给出提示文案:活跃 entitlement 上 billingIssueDetectedAt != null 显示支付问题、更新支付方式;unsubscribeDetectedAt != null 显示访问将于 expirationDate 结束;willRenew == false(无其他信号)显示本期不会续订;periodType == TRIAL 或 INTRO 显示试用或介绍定价生效。
- 为多设备识别用户:调用 Purchases.sharedInstance.awaitLogIn("your_user_id"),从结果取 customerInfo 和 createdNewUser = result.created。awaitLogIn() 会把匿名购买合并到已识别用户;logOut() 会开启新的匿名会话。
- 监听 CustomerInfo 更新:设置 Purchases.sharedInstance.updatedCustomerInfoListener = UpdatedCustomerInfoListener { info -> ... },让 UI 无需手动轮询即可响应购买、恢复和后台刷新。注意:当 SDK 启动时命中缓存且无变化,监听器不会触发,因此除了设置监听器外,启动时始终要调用 awaitCustomerInfo()。
- 按测试矩阵逐项验证:新购买 isActive 为 true、显示高级内容;宽限期(账单问题但仍授予)为 true、显示高级内容加账单警告;已取消但仍在 expirationDate 之前为 true、显示高级内容加到期通知;On hold 为 false、显示订阅页;Paused 为 false、显示订阅页;Expired 为 false、显示订阅页;Pending(尚未付款)为 false、显示订阅页。
- 做健全性检查:购买后监听器触发时访问门控正确翻转;FETCH_CURRENT 在后端授予(促销、退款、客服操作)后更新 CustomerInfo;logOut() 后 CustomerInfo 反映匿名用户且 isActive 相应重置;离线启动仍返回缓存的 CustomerInfo 并在无网络调用的情况下门控访问。
适用边界 · 注意事项
- 不适用于非 Android 平台或未使用 RevenueCat 的场景。
- 若只需访问开/关,不要引入 willRenew、periodType 等额外字段做判断,只用 isActive。
- 不要依赖 updatedCustomerInfoListener 单独完成启动时的状态同步,缓存命中且无变化时它不会触发。