![JAR search and dependency download from the Maven repository](/logo.png)
com.badlogic.gdx.pay.android.googleplay.AndroidGooglePlayPurchaseManager Maven / Gradle / Ivy
/*******************************************************************************
* Copyright 2011 See AUTHORS file.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
package com.badlogic.gdx.pay.android.googleplay;
import android.app.Activity;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import com.badlogic.gdx.backends.android.AndroidApplication;
import com.badlogic.gdx.pay.Information;
import com.badlogic.gdx.pay.Offer;
import com.badlogic.gdx.pay.OfferType;
import com.badlogic.gdx.pay.PurchaseManager;
import com.badlogic.gdx.pay.PurchaseManagerConfig;
import com.badlogic.gdx.pay.PurchaseObserver;
import com.badlogic.gdx.pay.Transaction;
import com.badlogic.gdx.pay.android.googleplay.billing.AsyncExecutor;
import com.badlogic.gdx.pay.android.googleplay.billing.GoogleInAppBillingService;
import com.badlogic.gdx.pay.android.googleplay.billing.GoogleInAppBillingService.ConnectionListener;
import com.badlogic.gdx.pay.android.googleplay.billing.GoogleInAppBillingService.PurchaseRequestCallback;
import com.badlogic.gdx.pay.android.googleplay.billing.NewThreadSleepAsyncExecutor;
import com.badlogic.gdx.pay.android.googleplay.billing.V3GoogleInAppBillingService;
import com.badlogic.gdx.pay.android.googleplay.billing.converter.PurchaseResponseActivityResultConverter;
import com.badlogic.gdx.utils.Logger;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* The purchase manager implementation for Google Play (Android).
*
* @author noblemaster
*/
public class AndroidGooglePlayPurchaseManager implements PurchaseManager {
public static final String PURCHASE_TYPE_IN_APP = "inapp";
public static final String LOG_TAG = "GdxPay/AndroidPlay";
public static final String GOOGLE_MARKET_NAME = "com.google.market";
public static final String GOOGLE_PLAY_STORE_NAME = "com.android.vending";
private final GoogleInAppBillingService googleInAppBillingService;
Logger logger = new Logger(LOG_TAG);
private final Map informationMap = new ConcurrentHashMap<>();
private PurchaseObserver observer;
private PurchaseManagerConfig purchaseManagerConfig;
public AndroidGooglePlayPurchaseManager(GoogleInAppBillingService googleInAppBillingService) {
this.googleInAppBillingService = googleInAppBillingService;
}
@SuppressWarnings("unused") // Unit tested with reflection. (as in IAP.java)
public AndroidGooglePlayPurchaseManager(Activity activity, int activityRequestCode) {
if (!(activity instanceof AndroidApplication)) {
throw new IllegalArgumentException("Bootstrapping gdx-pay only supported with AndroidApplication activity.");
}
AndroidApplication application = (AndroidApplication) activity;
PurchaseResponseActivityResultConverter converter = new PurchaseResponseActivityResultConverter(this);
AsyncExecutor executor = new NewThreadSleepAsyncExecutor();
googleInAppBillingService = new V3GoogleInAppBillingService(application, activityRequestCode, converter, executor);
}
@Override
public void install(final PurchaseObserver observer, final PurchaseManagerConfig purchaseManagerConfig, final boolean autoFetchInformation) {
assertConfigSupported(purchaseManagerConfig);
this.observer = observer;
this.purchaseManagerConfig = purchaseManagerConfig;
if (googleInAppBillingService.isListeningForConnections()) {
// TODO: scenario not unit tested, test this!
googleInAppBillingService.disconnect();
}
googleInAppBillingService.requestConnect(new ConnectionListener() {
@Override
public void connected() {
onServiceConnected(observer, autoFetchInformation);
}
@Override
public void disconnected(GdxPayException exception) {
observer.handleInstallError(new GdxPayException("Failed to bind to service", exception));
}
});
}
private void assertConfigSupported(PurchaseManagerConfig purchaseManagerConfig) {
for(int i=0; i < purchaseManagerConfig.getOfferCount(); i++) {
Offer offer = purchaseManagerConfig.getOffer(i);
if (offer.getType() != OfferType.ENTITLEMENT) {
throw new IllegalArgumentException("Unsupported offer: " + offer + ", only " + OfferType.ENTITLEMENT + " is supported");
}
}
}
/**
* Detect if running on Phone which has Google Play installed.
*
* Used when purchase system is installed via IAP class.
* If Google changes the package identifier of Google Play, this method will not return the
* new name.
*/
public static boolean isRunningViaGooglePlay(Activity activity) {
PackageManager packageManager = activity.getPackageManager();
List packages = packageManager
.getInstalledPackages(PackageManager.GET_UNINSTALLED_PACKAGES);
for (PackageInfo packageInfo : packages) {
String packageName = packageInfo.packageName;
if (packageName.equals(GOOGLE_MARKET_NAME) || packageName.equals(GOOGLE_PLAY_STORE_NAME)) {
return true;
}
}
return false;
}
protected void runAsync(Runnable runnable) {
new Thread(runnable).start();
}
private void loadSkusAndFillPurchaseInformation() {
List productIds = productIdStringList();
Map skuDetails = googleInAppBillingService.getProductsDetails(productIds);
informationMap.clear();
informationMap.putAll(skuDetails);
}
private List productIdStringList() {
List list = new ArrayList<>();
for (int i = 0; i < purchaseManagerConfig.getOfferCount(); i++) {
Offer offer = purchaseManagerConfig.getOffer(i);
list.add(offer.getIdentifier());
}
return list;
}
@Override
public boolean installed() {
return googleInAppBillingService.isListeningForConnections();
}
@Override
public void dispose() {
googleInAppBillingService.disconnect();
clearCaches();
observer = null;
}
@Override
public void purchase(String identifier) {
assertInstalled();
googleInAppBillingService.startPurchaseRequest(identifier, new PurchaseRequestCallback() {
@Override
public void purchaseSuccess(Transaction transaction) {
if (observer != null) {
observer.handlePurchase(transaction);
}
}
@Override
public void purchaseError(GdxPayException exception) {
if (observer != null) {
observer.handlePurchaseError(exception);
}
}
@Override
public void purchaseCanceled() {
if (observer != null) {
observer.handlePurchaseCanceled();
}
}
});
}
// TODO: call in new thread if called from UI thread (check if this is necessary).
@Override
public void purchaseRestore() {
try {
List transactions = googleInAppBillingService.getPurchases();
if (observer != null) {
observer.handleRestore(transactions.toArray(new Transaction[transactions.size()]));
}
} catch(GdxPayException e) {
if (observer != null) {
observer.handleRestoreError(e);
}
}
}
@Override
public Information getInformation(String identifier) {
Information information = informationMap.get(identifier);
if (information == null) {
return Information.UNAVAILABLE;
}
return information;
}
@Override
public String storeName() {
return PurchaseManagerConfig.STORE_NAME_ANDROID_GOOGLE;
}
private void clearCaches() {
informationMap.clear();
}
private void onServiceConnected(final PurchaseObserver observer, final boolean autofetchInformation) {
runAsync(new Runnable() {
@Override
public void run() {
try {
if (autofetchInformation) {
loadSkusAndFillPurchaseInformation();
}
} catch (Exception e) {
// TODO: this situation not yet unit-tested.
logger.error("Failed to load skus in onServiceConnected()", e);
}
observer.handleInstall();
}
});
}
private void assertInstalled() {
if (!installed()) {
throw new GdxPayException("Payment system must be installed to perform this action.");
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy