You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何获取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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 16:03:23