本主題介紹如何脫離使用Android接口定義語(yǔ)言(AIDL)的結(jié)算服務(wù)集成。使用AIDL訪問(wèn)Google Play結(jié)算系統(tǒng)這種方式已被棄用,日后所有集成都必須使用Google Play結(jié)算庫(kù)。
注意:本主題重點(diǎn)介紹進(jìn)行遷移需要做出的最重要變更。如需詳細(xì)了解集成步驟,請(qǐng)參閱本頁(yè)面中引用的鏈接以及GitHub上托管的結(jié)算服務(wù)專用示例中的代碼段。
遷移步驟
導(dǎo)入Google Play結(jié)算庫(kù)
首先,為Google Play結(jié)算庫(kù)添加依賴項(xiàng)。如果您使用的是Gradle,則可將以下內(nèi)容添加到應(yīng)用的build.gradle文件中:
dependencies{
def billing_version="3.0.0"
implementation"com.android.billingclient:billing:$billing_version"
}
您可以刪除任何“粘合”代碼(例如IabHelper),這些代碼可能是您從以前的參考代碼中復(fù)制的。IabHelper所提供的功能現(xiàn)在已包含在Google Play結(jié)算庫(kù)中。
移除com.android.vending.BILLING權(quán)限
Google Play結(jié)算庫(kù)在其清單中嵌入了com.android.vending.BILLING權(quán)限。因此,應(yīng)用的清單中無(wú)需再明確添加此權(quán)限。
連接到Google Play結(jié)算服務(wù)
Google Play結(jié)算庫(kù)的BillingClient負(fù)責(zé)為您處理連接管理。如需進(jìn)行遷移,請(qǐng)對(duì)您的應(yīng)用做出如下更改:
創(chuàng)建BillingClient的實(shí)例。
實(shí)現(xiàn)BillingClientStateListener以接收有關(guān)服務(wù)狀態(tài)的回調(diào)。
在BillingClient實(shí)例上調(diào)用startConnection()。
移除與應(yīng)用內(nèi)購(gòu)買相關(guān)的onActivityResult()代碼,并將其移至PurchasesUpdatedListener。
以下示例是應(yīng)用在進(jìn)行這些更改前后的比較:
之前
mServiceConn=new ServiceConnection(){
Override
public void onServiceDisconnected(ComponentName name){
...
}
Override
public void onServiceConnected(ComponentName name,IBinder service){
...
}
};
Intent serviceIntent=new Intent("com.android.vending.billing.InAppBillingService.BIND");
serviceIntent.setPackage("com.android.vending");
List<ResolveInfo>intentServices=mContext.getPackageManager()
.queryIntentServices(serviceIntent,0);
if(intentServices!=null&&!intentServices.isEmpty()){
mContext.bindService(serviceIntent,mServiceConn,Context.BIND_AUTO_CREATE);
}else{
//Handle errors.
...
}
...
Override
protected void onActivityResult(int requestCode,int resultCode,Intent data){
IabResult result;
if(requestCode!=mRequestCode||data==null){
//Handle errors.
...
}
int responseCode=getResponseCodeFromIntent(data);
String purchaseData=data.getStringExtra(RESPONSE_INAPP_PURCHASE_DATA);
String dataSignature=data.getStringExtra(RESPONSE_INAPP_SIGNATURE);
if(resultCode!=Activity.RESULT_OK||responseCode!=BILLING_RESPONSE_RESULT_OK){
//Handle errors.
...
}
//Process successful purchase.
...
return true;
}
之后
JAVA
public class MyBillingImpl implements PurchasesUpdatedListener{
private BillingClient billingClient;
...
public void initialize(){
billingClient=BillingClient.newBuilder(activity).setListener(this).build();
billingClient.startConnection(new BillingClientStateListener(){
Override
public void onBillingSetupFinished(BillingResult billingResult){
//Logic from ServiceConnection.onServiceConnected should be moved here.
}
Override
public void onBillingServiceDisconnected(){
//Logic from ServiceConnection.onServiceDisconnected should be moved here.
}
});
}
Override
public void onPurchasesUpdated(
BillingResponse int responseCode, Nullable List<Purchase>purchases){
//Logic from onActivityResult should be moved here.
}
}
進(jìn)行購(gòu)買
注意:Google Play結(jié)算庫(kù)2.0版及更高版本需要查詢SKU詳細(xì)信息。
如需啟動(dòng)購(gòu)買對(duì)話框,請(qǐng)執(zhí)行以下操作:
將SKU詳細(xì)信息Bundle轉(zhuǎn)換為SkuDetailsParams。
將mService.getSkuDetails()調(diào)用改為BillingClient.querySkuDetailsAsync()
將購(gòu)買intent Bundle轉(zhuǎn)換為BillingFlowParams對(duì)象。
將mService.getBuyIntent()調(diào)用改為BillingClient.launchBillingFlow()。
從onActivityResult()移除所有與應(yīng)用內(nèi)購(gòu)買相關(guān)的代碼,并將此代碼移至PurchasesUpdatedListener。
以下示例是應(yīng)用在進(jìn)行這些更改前后的比較:
之前
//Query Skus
String skuToSell="premium_upgrade";
ArrayList<String>skus=new Arraylist>>();
skus.add(skuToSell);
Bundle querySkus=new Bundle();
querySkus.putStringArrayList(GET_SKU_DETAILS_ITEM_LIST,skus);
Bundle skuDetails=mService.getSkuDetails(3,
mContext.getPackageName(),
itemType,
querySkus);
if(!skuDetails.containsKey(RESPONSE_GET_SKU_DETAILS_LIST)){
//Handle errors.
...
}
//Launch Buy Flow
Bundle buyIntentBundle=mService.getBuyIntent(3,
mContext.getPackageName(),
skuToSell,
"Inapp",
"");
int response=getResponseCodeFromBundle(buyIntentBundle);
if(response!=BILLING_RESPONSE_RESULT_OK){
//Handle errors.
...
}
PendingIntent pendingIntent=buyIntentBundle.getParcelable(RESPONSE_BUY_INTENT);
act.startIntentSenderForResult(pendingIntent.getIntentSender(),
requestCode,
new Intent(),
Integer.valueOf(0),
Integer.valueOf(0),
Integer.valueOf(0));
//Purchase is handled in onActivityResult illustrated in the previous section.
之后
JAVA
String skuToSell="premium_upgrade";
List<String>skuList=new ArrayList>>();
skuList.add(skuToSell);
SkuDetailsParams.Builder params=SkuDetailsParams.newBuilder();
params.setSkusList(skuList).setType(SkuType.INAPP);
billingClient.querySkuDetailsAsync(params.build(),
new SkuDetailsResponseListener(){
Override
public void onSkuDetailsResponse(BillingResult billingResult,
List<SkuDetails>skuDetailsList){
//Process the result.
...
}
});
//SkuDetails object obtained above.
SkuDetails skuDetails=...;
BillingFlowParams purchaseParams=
BillingFlowParams.newBuilder()
.setSkuDetails(skuDetails)
.build();
mBillingClient.launchBillingFlow(mActivity,purchaseParams);
//Purchase is handled in onPurchasesUpdated illustrated in the previous section.
消耗所購(gòu)商品
如需使用Google Play結(jié)算庫(kù)消耗所購(gòu)商品,請(qǐng)執(zhí)行以下操作:
調(diào)用BillingClient.consumeAsync(),而不是調(diào)用consumePurchase()。
實(shí)現(xiàn)ConsumeResponseListener。
以下示例是應(yīng)用在進(jìn)行這些更改前后的比較:
之前
Override
protected void onActivityResult(int requestCode,int resultCode,Intent data){
int responseCode=data.getIntExtra(RESPONSE_CODE);
JSONObject purchaseData=
new JSONObject(data.getStringExtra("INAPP_PURCHASE_DATA"));
String token=purchaseData.get("purchaseToken");
...
//Consume purchase
int response=mService.consumePurchase(3,mContext.getPackageName(),token);
if(response!=BILLING_RESPONSE_RESULT_OK){
//Handle errors.
...
}
//Handle successful consumption.
}
之后
JAVA
public class MyBillingImpl implements...,ConsumeResponseListener{
private BillingClient billingClient;
...
public void consumePurchase(String purchaseToken){
ConsumeParams consumeParams=
ConsumeParams.newBuilder()
.setPurchaseToken(purchaseToken)
.build();
}
Override
void onConsumeResponse(BillingResult billingResult,String purchaseToken){
//Handle consumption.
...
}
}
確認(rèn)購(gòu)買交易
從Google Play結(jié)算庫(kù)2.0版開(kāi)始,您的應(yīng)用必須消耗所有所購(gòu)商品或確認(rèn)所有購(gòu)買交易。
如果您在三天內(nèi)未消耗所購(gòu)商品或確認(rèn)購(gòu)買交易,Google會(huì)自動(dòng)撤消購(gòu)買交易并向用戶退款。如需了解詳情,請(qǐng)參閱確認(rèn)購(gòu)買交易。
識(shí)別應(yīng)用外購(gòu)買
如需將應(yīng)用外購(gòu)買交易的處理遷移到Google Play結(jié)算庫(kù),請(qǐng)執(zhí)行以下操作:
確保您的應(yīng)用在其onResume()回調(diào)中調(diào)用BillingClient.queryPurchases()。
移除com.android.vending.billing.PURCHASES_UPDATED的廣播接收器,并將相應(yīng)回調(diào)代碼移至PurchasesUpdatedListener。
以前,將Google Play結(jié)算服務(wù)與AIDL集成時(shí),您的應(yīng)用需要注冊(cè)監(jiān)聽(tīng)器才能接收com.android.vending.billing.PURCHASES_UPDATED intent,用于處理應(yīng)用外購(gòu)買交易。
使用Google Play結(jié)算庫(kù)時(shí),您應(yīng)始終先在應(yīng)用的onResume()回調(diào)中調(diào)用queryPurchases(),以確保識(shí)別出應(yīng)用未運(yùn)行期間完成的所有購(gòu)買交易。在應(yīng)用運(yùn)行時(shí),結(jié)算庫(kù)會(huì)自動(dòng)監(jiān)聽(tīng)?wèi)?yīng)用外購(gòu)買交易,并通過(guò)PurchasesUpdatedListener通知您。
處理待處理的交易
從Google Play結(jié)算庫(kù)2.0版開(kāi)始,應(yīng)用必須處理某些待處理的交易,這些交易需要在購(gòu)買后執(zhí)行額外操作,然后才能授予使用權(quán)。例如,用戶可能會(huì)選擇使用現(xiàn)金在實(shí)體店購(gòu)買您的應(yīng)用內(nèi)商品。也就是說(shuō),交易是在應(yīng)用外部完成的。在這種情況下,只有在用戶完成交易后,您才能授予使用權(quán)。
如需了解詳情,請(qǐng)參閱支持待處理的交易。
開(kāi)發(fā)者載荷
開(kāi)發(fā)者載荷向來(lái)被用于各種不同用途,包括防欺詐以及將購(gòu)買交易歸因于正確的用戶。由于Google Play結(jié)算庫(kù)現(xiàn)已支持這些用例,因此從Google Play結(jié)算庫(kù)2.2版開(kāi)始,我們已棄用開(kāi)發(fā)者載荷。如需了解詳情,請(qǐng)參閱開(kāi)發(fā)者載荷。
詳細(xì)的錯(cuò)誤消息
從Google Play結(jié)算庫(kù)2.0版開(kāi)始,所有錯(cuò)誤都包含相應(yīng)的調(diào)試相關(guān)消息。這些消息可以通過(guò)調(diào)用BillingResult.getDebugMessage()獲得。