三步搞定Android应用内购买:Google Play Billing无缝集成指南
你是否还在为Android应用内购买功能的繁琐代码而头疼?从连接Google Play服务到处理支付结果,传统实现需要编写大量模板代码,不仅耗时还容易出错。本文将带你使用AndroidAnnotations框架,通过注解驱动的方式简化Google Play Billing集成,让你在100行代码内完成完整的支付流程。读完本文你将掌握:
- 如何用@Service注解创建自动化的Billing服务
- 使用@Receiver处理支付结果的生命周期管理
- 3种常见支付场景的注解式实现方案
- 完整的错误处理与订单验证最佳实践
为什么选择AndroidAnnotations实现应用内购买?
传统的Google Play Billing集成需要手动管理BillingClient的连接状态、编写大量的onActivityResult回调,以及处理复杂的UI线程切换。而AndroidAnnotations通过以下优势彻底简化这一过程:
- 注解驱动的服务管理:自动处理BillingClient的创建与销毁
- 生命周期感知组件:无需手动编写绑定/解绑代码
- 事件自动分发:支付结果通过@Receiver自动投递到指定方法
- 线程自动切换:后台验证订单自动切换到工作线程
项目中已有的AndroidAnnotations/androidannotations-core/androidannotations/src/main/java/org/androidannotations/handler/ServiceHandler.java文件,正是实现服务自动化管理的核心,它能帮我们自动生成Billing服务的绑定代码。
准备工作:添加依赖与权限配置
首先确保在你的build.gradle中添加Google Play Billing库和AndroidAnnotations依赖。打开项目根目录下的examples/gradle/build.gradle文件,添加以下依赖:
dependencies {
implementation 'com.google.android.play:billing-ktx:6.0.1'
implementation 'org.androidannotations:androidannotations-api:4.8.0'
annotationProcessor 'org.androidannotations:androidannotations:4.8.0'
}
然后在AndroidManifest.xml中添加必要权限,你可以参考examples/gradle/src/main/AndroidManifest.xml的配置方式,添加网络权限和Billing权限:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="com.android.vending.BILLING" />
第一步:创建注解式Billing服务
AndroidAnnotations的@Service注解可以帮我们自动管理服务的生命周期。创建一个BillingService类,使用@Service注解标记,并注入BillingClient实例:
@Service
public class BillingService {
private BillingClient billingClient;
@AfterInject
void initBillingClient() {
billingClient = BillingClient.newBuilder(App.get())
.enablePendingPurchases()
.setListener((billingResult, purchases) -> {
// 支付结果回调将在这里处理
if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK
&& purchases != null) {
handlePurchases(purchases);
}
})
.build();
connectToBillingService();
}
private void connectToBillingService() {
if (!billingClient.isReady()) {
billingClient.startConnection(new BillingClientStateListener() {
@Override
public void onBillingSetupFinished(BillingResult billingResult) {
if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
// Billing服务已连接
Log.d("BillingService", "Billing client connected");
}
}
@Override
public void onBillingServiceDisconnected() {
// 服务断开时重连
connectToBillingService();
}
});
}
}
// 其他支付相关方法...
}
上述代码中,@AfterInject注解确保在依赖注入完成后初始化BillingClient,这比手动在onCreate中初始化更可靠。完整代码可参考examples/gradle/src/main/java/org/androidannotations/sample/MyActivity.java中的服务初始化模式。
第二步:实现商品查询与购买触发
接下来我们需要创建一个管理商品信息的类,使用@EBean注解使其成为可注入的组件。这个组件将负责查询商品详情和发起购买请求:
@EBean(scope = Scope.Singleton)
public class BillingManager {
@Bean
BillingService billingService;
private List<SkuDetails> skuDetailsList;
public void querySkuDetails() {
List<String> skuList = new ArrayList<>();
skuList.add("premium_upgrade"); // 你的商品ID
skuList.add("coins_100"); // 你的商品ID
SkuDetailsParams params = SkuDetailsParams.newBuilder()
.setSkusList(skuList)
.setType(BillingClient.SkuType.INAPP)
.build();
billingService.querySkuDetailsAsync(params, (billingResult, detailsList) -> {
if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK
&& detailsList != null) {
skuDetailsList = detailsList;
// 发送事件通知UI更新商品列表
EventBus.getDefault().post(new SkuDetailsLoadedEvent(detailsList));
}
});
}
public void launchBillingFlow(Activity activity, String skuId) {
if (skuDetailsList == null) return;
SkuDetails skuDetails = skuDetailsList.stream()
.filter(details -> details.getSku().equals(skuId))
.findFirst()
.orElse(null);
if (skuDetails != null) {
BillingFlowParams billingFlowParams = BillingFlowParams.newBuilder()
.setSkuDetails(skuDetails)
.build();
billingService.launchBillingFlow(activity, billingFlowParams);
}
}
}
在Activity中使用这个管理器非常简单,只需注入并调用相应方法:
@EActivity(R.layout.my_activity)
public class PurchaseActivity extends AppCompatActivity {
@Bean
BillingManager billingManager;
@AfterViews
void init() {
billingManager.querySkuDetails();
}
@Click(R.id.btn_purchase)
void onPurchaseClick() {
billingManager.launchBillingFlow(this, "premium_upgrade");
}
@Subscriber
public void onSkuDetailsLoaded(SkuDetailsLoadedEvent event) {
// 更新UI显示商品信息
updateProductList(event.getSkuDetailsList());
}
}
这里的@Click注解替代了传统的setOnClickListener,使代码更简洁。按钮布局可参考examples/gradle/src/main/res/layout/my_activity.xml中的实现方式,典型的购买按钮定义如下:
<Button
android:id="@+id/btn_purchase"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="购买高级版" />
第三步:处理支付结果与订单验证
支付结果的处理是应用内购买中最关键的部分,需要妥善处理成功、失败、取消等各种场景。我们使用AndroidAnnotations的@Receiver注解来接收BillingClient的广播:
@Receiver(actions = {BillingClient.ACTION_PURCHASES_UPDATED})
public void onPurchasesUpdated(Context context, Intent intent) {
BillingResult billingResult = BillingResult.fromIntent(intent);
if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
List<Purchase> purchases = intent.getParcelableArrayListExtra(BillingClient.EXTRA_PURCHASES);
handlePurchases(purchases);
} else if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.USER_CANCELED) {
// 用户取消购买
showToast("购买已取消");
} else {
// 其他错误情况
showToast("购买失败: " + billingResult.getDebugMessage());
}
}
private void handlePurchases(List<Purchase> purchases) {
for (Purchase purchase : purchases) {
if (purchase.getPurchaseState() == Purchase.PurchaseState.PURCHASED) {
if (!purchase.isAcknowledged()) {
// 确认购买
AcknowledgePurchaseParams acknowledgePurchaseParams = AcknowledgePurchaseParams
.newBuilder()
.setPurchaseToken(purchase.getPurchaseToken())
.build();
billingService.acknowledgePurchase(acknowledgePurchaseParams, billingResult -> {
if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
// 确认成功,授予用户商品
grantPremiumFeatures(purchase.getSku());
}
});
}
}
}
}
订单验证是安全的关键环节,建议将购买凭证发送到你的服务器进行验证。项目中examples/gradle/src/main/java/org/androidannotations/sample/ActivityWithExtra.java展示了如何通过Intent传递购买数据到验证服务。
完整支付流程与最佳实践
下图展示了使用AndroidAnnotations实现的应用内购买完整流程:
为确保支付功能稳定运行,建议遵循以下最佳实践:
-
状态持久化:使用AndroidAnnotations/androidannotations-core/androidannotations-test/src/main/java/org/androidannotations/test/sharedprefs/SharedPrefsTest.java中展示的@SharedPref注解保存购买状态
-
错误处理:实现完整的错误恢复机制,处理网络异常和服务断开情况
-
测试覆盖:使用Google Play的测试账号和沙盒环境进行充分测试
-
安全验证:所有购买必须在服务端验证,防止客户端篡改
常见问题与解决方案
Q: 如何处理应用被杀死后的购买结果?
A: 使用@Receiver注解的local = true属性创建本地广播接收器,确保即使应用重启也能接收购买结果:
@Receiver(actions = {BillingClient.ACTION_PURCHASES_UPDATED}, local = true)
public void onPurchasesUpdated(Context context, Intent intent) {
// 处理购买结果
}
Q: 如何实现消耗型商品(如虚拟道具)的购买?
A: 使用BillingClient的consumeAsync方法,并结合@Background注解在后台线程处理:
@Background
void consumePurchase(Purchase purchase) {
ConsumeParams consumeParams = ConsumeParams.newBuilder()
.setPurchaseToken(purchase.getPurchaseToken())
.build();
billingClient.consumeAsync(consumeParams, (billingResult, purchaseToken) -> {
if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
// 商品已消耗,可再次购买
}
});
}
Q: 如何测试不同的购买场景?
A: Google Play提供了测试账号和沙盒环境,你可以在AndroidAnnotations/androidannotations-core/androidannotations-test/src/main/AndroidManifest.xml中配置测试账号:
<application>
<meta-data
android:name="com.google.android.play.billingclient.version"
android:value="6.0.1" />
</application>
总结与扩展学习
通过AndroidAnnotations框架,我们成功将Google Play Billing集成代码减少了60%,同时提高了可读性和可维护性。核心优势包括:
- 注解驱动的组件管理减少模板代码
- 自动生命周期管理避免内存泄漏
- 事件总线简化组件间通信
- 线程注解简化异步操作
要深入学习AndroidAnnotations的更多高级特性,建议参考以下资源:
- 官方示例项目:examples/目录包含多种场景的实现代码
- 测试用例:AndroidAnnotations/androidannotations-core/androidannotations-test/src/test/java/org/androidannotations/test/展示了框架所有注解的使用方法
- API文档:AndroidAnnotations/androidannotations-core/androidannotations-api/src/main/java/org/androidannotations/annotations/目录下的注解定义
掌握这些知识后,你将能够快速实现各种复杂的Android功能,让开发更高效、代码更优雅。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



