如何获取In App Review API的错误回调以处理边缘场景?
In App Review API 边缘场景处理方案:用户已评分/配额上限
Google官方的In App Review API并未提供直接回调来区分「用户已评分」或「配额达上限」这两种场景,但可以通过本地状态记录和间接逻辑判断覆盖大部分情况,以下是具体实现方案:
一、核心思路
官方API刻意隐藏这类细节以避免开发者做诱导性操作,因此我们通过本地存储+流程回调结合的方式处理:
- 「用户已评分」:本地标记用户是否完成过评分流程,发起请求前先校验标记
- 「配额达上限」:记录上次请求时间,设置90天的保守间隔阈值(参考官方建议),避免频繁触发请求
二、具体实现
1. 本地状态管理工具类
用SharedPreferences存储关键状态:
object ReviewPreferences { private const val PREF_NAME = "review_prefs" private const val KEY_LAST_REQUEST_TIME = "last_review_request" private const val KEY_USER_RATED = "user_has_rated" private const val REVIEW_INTERVAL = 90 * 24 * 60 * 60 * 1000L // 90天间隔 fun isReviewAllowed(context: Context): Boolean { val lastRequest = getLastRequestTime(context) val currentTime = System.currentTimeMillis() return currentTime - lastRequest > REVIEW_INTERVAL && !hasUserRated(context) } fun getLastRequestTime(context: Context): Long { return context.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE) .getLong(KEY_LAST_REQUEST_TIME, 0L) } fun setLastRequestTime(context: Context, time: Long) { context.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE) .edit() .putLong(KEY_LAST_REQUEST_TIME, time) .apply() } fun hasUserRated(context: Context): Boolean { return context.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE) .getBoolean(KEY_USER_RATED, false) } fun markUserRated(context: Context, rated: Boolean) { context.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE) .edit() .putBoolean(KEY_USER_RATED, rated) .apply() } }
2. 改造评分启动函数
加入前置校验和场景处理回调:
fun Activity.launchInAppReview( onComplete: () -> Unit, onFailed: () -> Unit, onRestricted: () -> Unit // 处理已评分/配额超限的回调 ) { // 前置校验:不满足条件直接触发限制回调 if (!ReviewPreferences.isReviewAllowed(this)) { onRestricted() return } val reviewManager = if (BuildConfig.DEBUG) { FakeReviewManager(this) } else { ReviewManagerFactory.create(this) } reviewManager.requestReviewFlow().addOnCompleteListener { task -> if (task.isSuccessful) { val reviewInfo = task.result // 记录本次请求时间 ReviewPreferences.setLastRequestTime(this, System.currentTimeMillis()) reviewManager.launchReviewFlow(this, reviewInfo).addOnCompleteListener { // 假设用户完成流程即标记为已评分(可根据业务调整逻辑) ReviewPreferences.markUserRated(this, true) onComplete() }.addOnFailureListener { onFailed() } } else { // 尝试解析异常信息(非官方标准,仅作辅助判断) task.exception?.let { e -> if (e.message?.contains("quota") == true || e.message?.contains("rated") == true) { onRestricted() } else { onFailed() } } ?: onFailed() } }.addOnFailureListener { e -> e.message?.let { msg -> if (msg.contains("quota") || msg.contains("rated")) { onRestricted() } else { onFailed() } } ?: onFailed() } }
三、补充说明
- 异常解析局限性:Play Core库的异常信息并非官方约定标准,不同版本可能变化,仅作为辅助判断,不要依赖其作为核心逻辑
- 手动评分同步问题:如果用户直接在Play商店手动评分,本地标记无法自动同步。若需精准同步,需通过服务器调用Play Developer API查询用户评分状态(客户端无法直接调用该API)
- 配额阈值调整:90天是官方建议的保守间隔,实际配额可能更灵活,但遵循该阈值可最大程度避免触发限制
内容的提问来源于stack exchange,提问作者J.K
相关产品推荐
相关产品推荐

