Android 消耗性应用程式内购买
示例
消费型被管理产品是指可以多次购买的产品,例如游戏中的货币,游戏寿命,开机状态等。
在此示例中,我们将实现4种不同的耗材管理产品"item1","item2","item3","item4"。
摘要步骤:
将应用内结算库添加到您的项目(AIDL文件)中。
在AndroidManifest.xml文件中添加所需的权限。
将签名的APK部署到GoogleDevelopersConsole。
定义您的产品。
实施代码。
测试应用内结算(可选)。
第1步:
首先,我们需要将AIDL文件添加到您的项目中,如此处的Google文档中所述。
IInAppBillingService.aidl是一个Android接口定义语言(AIDL)文件,用于定义应用内结算第3版服务的接口。您将使用此接口通过调用IPC方法调用来发出计费请求。
第2步:
添加AIDL文件后,在中添加BILLING权限AndroidManifest.xml:
<!-- Required permission for implementing In-app Billing --> <uses-permission android:name="com.android.vending.BILLING" />
第三步:
生成签名的APK,并将其上传到GoogleDevelopersConsole。这是必需的,以便我们可以在那里开始定义我们的应用内产品。
步骤4:
用不同的productID定义所有产品,并为每个产品设置价格。有2种类型的产品(被管理产品和订阅)。如前所述,我们将实施4种不同的消耗品管理产品"item1","item2","item3","item4"。
步骤5:
完成上述所有步骤之后,您现在就可以开始在自己的活动中实现代码本身了。
主要活动:
public class MainActivity extends Activity {
IInAppBillingService inAppBillingService;
ServiceConnection serviceConnection;
//每个项目的productID。您应该在GoogleDevelopersConsole中定义它们。
final String item1 = "item1";
final String item2 = "item2";
final String item3 = "item3";
final String item4 = "item4";
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//根据您的布局文件实例化视图。
final Button buy1 = (Button) findViewById(R.id.buy1);
final Button buy2 = (Button) findViewById(R.id.buy2);
final Button buy3 = (Button) findViewById(R.id.buy3);
final Button buy4 = (Button) findViewById(R.id.buy4);
//每个按钮的setOnClickListener()。
//buyItem()这是我们将用来启动PurchaseFlow的方法。
buy1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
buyItem(item1);
}
});
buy2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
buyItem(item2);
}
});
buy3.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
buyItem(item3);
}
});
buy4.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
buyItem(item4);
}
});
//附加服务连接。
serviceConnection = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
inAppBillingService = null;
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
inAppBillingService = IInAppBillingService.Stub.asInterface(service);
}
};
//绑定服务。
Intent serviceIntent = new Intent("com.android.vending.billing.InAppBillingService.BIND");
serviceIntent.setPackage("com.android.vending");
bindService(serviceIntent, serviceConnection, BIND_AUTO_CREATE);
//获取每个产品的价格,并将价格设置为文本
//每个按钮,以便用户知道每个项目的价格。
if (inAppBillingService != null) {
//注意:您需要在此处创建一个新线程,因为
//getSkuDetails()触发网络请求,该请求可以
//如果它是从主线程调用的,则会导致应用程序滞后。
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
ArrayList<String> skuList = new ArrayList<>();
skuList.add(item1);
skuList.add(item2);
skuList.add(item3);
skuList.add(item4);
Bundle querySkus = new Bundle();
querySkus.putStringArrayList("ITEM_ID_LIST", skuList);
try {
Bundle skuDetails = inAppBillingService.getSkuDetails(3, getPackageName(), "inapp", querySkus);
int response = skuDetails.getInt("RESPONSE_CODE");
if (response == 0) {
ArrayList<String> responseList = skuDetails.getStringArrayList("DETAILS_LIST");
for (String thisResponse : responseList) {
JSONObject object = new JSONObject(thisResponse);
String sku = object.getString("productId");
String price = object.getString("price");
switch (sku) {
case item1:
buy1.setText(price);
break;
case item2:
buy2.setText(price);
break;
case item3:
buy3.setText(price);
break;
case item4:
buy4.setText(price);
break;
}
}
}
} catch (RemoteException | JSONException e) {
e.printStackTrace();
}
}
});
thread.start();
}
}
//通过传递用户想要购买的商品的productID作为参数来启动PurchaseFlow。
private void buyItem(String productID) {
if (inAppBillingService != null) {
try {
Bundle buyIntentBundle = inAppBillingService.getBuyIntent(3, getPackageName(), productID, "inapp", "bGoa+V7g/yqDXvKRqq+JTFn4uQZbPiQJo4pf9RzJ");
PendingIntent pendingIntent = buyIntentBundle.getParcelable("BUY_INTENT");
startIntentSenderForResult(pendingIntent.getIntentSender(), 1003, new Intent(), 0, 0, 0);
} catch (RemoteException |IntentSender.SendIntentExceptione) {
e.printStackTrace();
}
}
}
//在onDestroy()中解除服务绑定。如果您不取消绑定,则打开
//服务连接可能会导致设备性能下降。
@Override
public void onDestroy() {
super.onDestroy();
if (inAppBillingService != null) {
unbindService(serviceConnection);
}
}
//在此处检查应用内购买是否成功。如果成功的话
//然后使用产品,然后让应用进行所需的更改。
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 1003 && resultCode == RESULT_OK) {
final String purchaseData = data.getStringExtra("INAPP_PURCHASE_DATA");
//注意:您需要在此处创建一个新线程,因为
//abusePurchase()触发网络请求,该请求可以
//如果它是从主线程调用的,则会导致应用程序滞后。
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
try {
JSONObject jo = new JSONObject(purchaseData);
//获取所购买商品的productID。
String sku = jo.getString("productId");
String productName = null;
//增加硬币()这里是在游戏中用作示例的方法
//如果购买成功,则增加游戏内货币。
//您应该在此处实现自己的代码,然后让该应用程序应用
//购买成功后需要进行的更改。
switch (sku) {
case item1:
productName = "Item 1";
increaseCoins(2000);
break;
case item2:
productName = "Item 2";
increaseCoins(8000);
break;
case item3:
productName = "Item 3";
increaseCoins(18000);
break;
case item4:
productName = "Item 4";
increaseCoins(30000);
break;
}
//进行购买,以便用户能够再次购买相同的产品。
inAppBillingService.consumePurchase(3, getPackageName(), jo.getString("purchaseToken"));
Toast.makeText(MainActivity.this, productName + " is successfully purchased. Excellent choice, master!", Toast.LENGTH_LONG).show();
} catch (JSONException | RemoteException e) {
Toast.makeText(MainActivity.this, "无法解析购买数据。", Toast.LENGTH_LONG).show();
e.printStackTrace();
}
}
});
thread.start();
}
}
}步骤6:
实施代码后,您可以通过将apk部署到beta/alpha通道进行测试,并让其他用户为您测试代码。但是,在测试模式下无法进行真正的应用内购买。您必须先将您的应用/游戏发布到Play商店,以便完全激活所有产品。
有关测试应用内结算的更多信息,请点击此处。