PAYATHON 2026

Google In-app Billing 最新版本及 Kotlin 示例问题

数据阿明

结论

这份 IInAppBillingService.aidl 属于旧式 In-app Billing Version 3 接口体系。不过,仅凭 AIDL 文件无法断定项目运行时使用的一定是 Version 3。实际使用的协议版本取决于调用方法时传入的 apiVersion,例如:

service.isBillingSupported(3, packageName, "inapp")

还需要注意:

  • In-app Billing Version 3 是旧版 AIDL 协议,不是当前 Google Play Billing Library 的最新版本。
  • TrivialDrive 及其 /util helper classes 是早期 Java 示例,不是正式发布的 Billing Library。
  • Android Studio 3.2.1 的 SDK Manager 中找不到该组件很正常。通过 SDK Manager 下载示例和 AIDL 文件的方式已经淘汰。
  • 新项目应通过 Gradle 引入 Google Play Billing Library,并使用 BillingClient API。
  • Kotlin 可以直接调用 AIDL 生成的接口,但新项目不建议继续采用 Version 3。

1. 如何确认项目是否使用 In-app Billing Version 3

AIDL 文件中的注释写着:

Minimum API version supported by this interface is 3.

这句话表示该接口最低支持 Version 3,并不意味着所有调用都固定使用 Version 3。接口中的主要方法都会接收一个 apiVersion 参数:

int isBillingSupported(int apiVersion, String packageName, String type);

因此,需要检查项目调用这些方法的位置,例如:

mService.isBillingSupported(3, getPackageName(), "inapp");
mService.getSkuDetails(3, getPackageName(), "inapp", querySkus);
mService.getBuyIntent(3, getPackageName(), sku, "inapp", payload);

只有调用时传入的第一个参数为 3,才能确认这次请求使用的是 Billing API Version 3。

旧版 TrivialDrive 的 helper classes 可能会将这个值定义为常量:

private static final int BILLING_API_VERSION = 3;

也可能直接将数值写在调用代码中。检查项目时,可以搜索:

isBillingSupported(
getSkuDetails(
getBuyIntent(
getPurchases(
consumePurchase(
BILLING_API_VERSION

这里需要区分两种版本:

  • apiVersion = 3:Google Play 服务端 AIDL 协议版本。
  • com.android.billingclient:billing:x.y.z:Google Play Billing Library 的 Maven 依赖版本。

它们使用的不是同一套版本编号。

2. 如何下载 TrivialDrive 示例

旧文档中的“Download the Sample Application”指的是早期 Android SDK Manager 提供的下载方式。当时可以通过类似下面的路径安装:

SDK Manager
└── Extras
    └── Google Play Billing Library

安装完成后,通常可以在 Android SDK 的 extras 目录中找到示例、AIDL 文件和 helper classes。

这种分发方式已经过时。因此,在 Android Studio 3.2.1 或其他版本的 SDK Manager 中看不到该条目,并不代表安装出了问题。相关组件可能已经从 SDK Manager 仓库中移除。

现在应优先从 Google 官方 GitHub 示例仓库获取代码:

https://github.com/android/play-billing-samples

可以在网页中选择 Code → Download ZIP,也可以使用 Git:

git clone https://github.com/android/play-billing-samples.git

该仓库目前的内容可能已经不包含最早的 TrivialDrive。如果必须研究旧版 AIDL 示例,可以查看仓库的历史提交、旧标签或归档分支。旧示例适合用来理解历史代码,不适合作为新应用的开发基础。

3. Version 3 是否为最新版本

不是。

Version 3 是 2012 年前后推出的旧式 In-app Billing AIDL API。后来,Google 提供了独立的 Google Play Billing Library。应用可以通过 BillingClient 接入,无须再手动复制 IInAppBillingService.aidl 和 IabHelper。

Billing Library 会持续发布新版本,因此,准确的最新版本号应以 Google 官方 release notes 和 Maven 仓库为准,不能根据 TrivialDrive、AIDL 文件注释或旧文章判断。官方发布说明地址是:

https://developer.android.com/google/play/billing/release-notes

新项目通常采用以下依赖形式:

dependencies {
    implementation("com.android.billingclient:billing:<已核实的版本号>")
}

如果所选版本仍提供 Kotlin 扩展,可以按照对应版本的官方说明加入:

dependencies {
    implementation("com.android.billingclient:billing-ktx:<相同版本号>")
}

正式项目中不要使用 + 自动获取最新版本:

// 不建议
implementation("com.android.billingclient:billing:+")

显式锁定版本可以保证构建结果可复现,也能防止依赖升级后突然出现兼容性问题。

4. 能否从 /util helper classes 找到版本号

可以从中找到实际传入的 Billing API 版本,但不能将 helper classes 的版本视为 Google Play Billing Library 的正式版本。

旧版 TrivialDrive 中的 IabHelper、IabResult、Inventory、Purchase 和 SkuDetails 等类只是示例项目附带的辅助代码,主要用于:

  • 绑定 IInAppBillingService
  • 检查 Billing 支持情况
  • 查询商品和购买记录
  • 发起购买流程
  • 消耗一次性商品
  • 解析返回的 Bundle 和 JSON

要确定代码调用的 AIDL API 版本,应查看 IabHelper 传给服务方法的第一个参数,而不是寻找 helper library 自身的版本号。例如:

mService.isBillingSupported(3, mContext.getPackageName(), ITEM_TYPE_INAPP);

这里的 3 表示该调用使用 Version 3。

5. /util 下的 helper classes 是否只有 Java 版本

经典 TrivialDrive 示例中的 helper classes 主要使用 Java 编写。它们既不是 Android SDK 的必要组成部分,也不是必须逐行移植的标准库。

虽然可以将这些类转换成 Kotlin,但新项目不建议这样做,原因包括:

  • AIDL Version 3 的接入方式已经过时。
  • 示例 helper 不是长期维护的正式 API。
  • 旧代码可能没有处理现代 Billing Library 要求的购买确认、待处理交易和生命周期问题。
  • 旧示例中的安全校验无法替代服务器端购买验证。

如果需要 Kotlin 实现,应优先查看官方 play-billing-samples 仓库中的 Kotlin 示例,并使用 BillingClient。

6. Kotlin 能否调用 Billing Version 3 AIDL API

可以。AIDL 编译后会生成 Java 和 Kotlin 都能调用的 Binder 接口。下面是旧式 Version 3 的最小连接方式,仅适用于维护遗留项目或了解历史代码:

private var billingService: IInAppBillingService? = null

private val serviceConnection = object : ServiceConnection {
    override fun onServiceConnected(name: ComponentName?, binder: IBinder?) {
        billingService = IInAppBillingService.Stub.asInterface(binder)

        val response = billingService?.isBillingSupported(
            3,
            packageName,
            "inapp"
        )

        if (response == 0) {
            // Version 3 billing is supported for one-time products.
        }
    }

    override fun onServiceDisconnected(name: ComponentName?) {
        billingService = null
    }
}

private fun connectBillingService() {
    val intent = Intent("com.android.vending.billing.InAppBillingService.BIND").apply {
        setPackage("com.android.vending")
    }

    bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE)
}

override fun onDestroy() {
    if (billingService != null) {
        unbindService(serviceConnection)
        billingService = null
    }

    super.onDestroy()
}

查询旧式 SKU 信息时,也需要明确传入 3:

val skuBundle = Bundle().apply {
    putStringArrayList(
        "ITEM_ID_LIST",
        arrayListOf("premium_upgrade")
    )
}

val result = billingService?.getSkuDetails(
    3,
    packageName,
    "inapp",
    skuBundle
)

val responseCode = result?.getInt("RESPONSE_CODE")
val details = result?.getStringArrayList("DETAILS_LIST")

这段代码只能证明该调用使用了 Version 3,不能说明它符合当前 Google Play 的发布要求。

新项目应如何选择

如果要维护很早以前发布的应用,可以先检查 apiVersion 参数,确认旧代码是否使用 Version 3,再制定迁移方案。

新项目则建议采用以下方案:

  1. 通过 Gradle 引入官方 Google Play Billing Library。
  2. 使用 BillingClient 建立连接。
  3. 使用当前的商品详情查询 API 获取商品信息。
  4. 使用 launchBillingFlow() 发起购买。
  5. 在 PurchasesUpdatedListener 中处理结果。
  6. 对非消耗型商品执行购买确认。
  7. 对消耗型商品调用消费 API。
  8. 在可信服务器上验证购买状态,不要只依赖客户端返回的结果。
  9. 根据官方 release notes 核对当前版本、迁移要求和 Google Play 的提交期限。

旧版 IInAppBillingService.aidl 和 TrivialDrive 可以帮助理解 Version 3,但不能作为当前 Billing Library 的下载方式、版本依据或新项目模板。

备注:内容仅供参考。