消费型被管理产品是指可以多次购买的产品,例如游戏中的货币,游戏寿命,开机状态等。
在此示例中,我们将实现4种不同的耗材管理产品 "item1", "item2", "item3", "item4"。
摘要步骤:
将应用内结算库添加到您的项目(AIDL文件)中。
在AndroidManifest.xml文件中添加所需的权限。
将签名的APK部署到Google Developers Console。
定义您的产品。
实施代码。
测试应用内结算(可选)。
首先,我们需要将AIDL文件添加到您的项目中,如此处的Google文档中所述。
IInAppBillingService.aidl是一个Android接口定义语言(AIDL)文件,用于定义应用内结算第3版服务的接口。您将使用此接口通过调用IPC方法调用来发出计费请求。
添加AIDL文件后,在中添加BILLING权限AndroidManifest.xml:
<!-- Required permission for implementing In-app Billing --> <uses-permission android:name="com.android.vending.BILLING" />
生成签名的APK,并将其上传到Google Developers Console。这是必需的,以便我们可以在那里开始定义我们的应用内产品。
用不同的productID定义所有产品,并为每个产品设置价格。有2种类型的产品(被管理产品和订阅)。如前所述,我们将实施4种不同的消耗品管理产品 "item1", "item2", "item3", "item4"。
完成上述所有步骤之后,您现在就可以开始在自己的活动中实现代码本身了。
主要活动:
public class MainActivity extends Activity { IInAppBillingService inAppBillingService; ServiceConnection serviceConnection; //每个项目的productID。您应该在Google Developers Console中定义它们。 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(); } } }
实施代码后,您可以通过将apk部署到beta / alpha通道进行测试,并让其他用户为您测试代码。但是,在测试模式下无法进行真正的应用内购买。您必须先将您的应用/游戏发布到Play商店,以便完全激活所有产品。
有关测试应用内结算的更多信息,请点击此处。