package com.jdroid.android.google.inappbilling;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentTransaction;
import com.jdroid.android.application.AbstractApplication;
import com.jdroid.android.activity.AbstractFragmentActivity;
import com.jdroid.android.exception.DefaultExceptionHandler;
import com.jdroid.android.exception.DialogErrorDisplayer;
import com.jdroid.android.fragment.AbstractFragment;
import com.jdroid.java.exception.ErrorCodeException;
import com.jdroid.java.utils.LoggerUtils;
import org.slf4j.Logger;
import java.io.Serializable;
import java.util.List;
public class InAppBillingHelperFragment extends AbstractFragment implements InAppBillingClientListener {
private static final String MANAGED_PRODUCT_TYPES = "managedProductTypes";
private static final String SUBSCRIPTIONS_PRODUCT_TYPES = "subscriptionsProductTypes";
private static final String SILENT_MODE = "silentMode";
private static final Logger LOGGER = LoggerUtils.getLogger(InAppBillingHelperFragment.class);
private InAppBillingClient inAppBillingClient;
private List<ProductType> managedProductTypes;
private List<ProductType> subscriptionsProductTypes;
private Boolean silentMode;
public static void add(FragmentActivity activity,
Class<? extends InAppBillingHelperFragment> inAppBillingHelperFragmentClass, Boolean silentMode,
Fragment targetFragment) {
add(activity, inAppBillingHelperFragmentClass, InAppBillingAppModule.get().getInAppBillingContext().getManagedProductTypes(),
InAppBillingAppModule.get().getInAppBillingContext().getSubscriptionsProductTypes(), silentMode, targetFragment);
}
public static void add(FragmentActivity activity,
Class<? extends InAppBillingHelperFragment> inAppBillingHelperFragmentClass,
List<ProductType> managedProductTypes, List<ProductType> subscriptionsProductTypes, Boolean silentMode,
Fragment targetFragment) {
if (!managedProductTypes.isEmpty() || (!subscriptionsProductTypes.isEmpty() && (get(activity) == null))) {
AbstractFragmentActivity abstractFragmentActivity = (AbstractFragmentActivity)activity;
InAppBillingHelperFragment inAppBillingHelperFragment = abstractFragmentActivity.instanceFragment(
inAppBillingHelperFragmentClass, null);
inAppBillingHelperFragment.setTargetFragment(targetFragment, 0);
Bundle args = new Bundle();
args.putSerializable(MANAGED_PRODUCT_TYPES, (Serializable)managedProductTypes);
args.putSerializable(SUBSCRIPTIONS_PRODUCT_TYPES, (Serializable)subscriptionsProductTypes);
args.putBoolean(SILENT_MODE, silentMode);
inAppBillingHelperFragment.setArguments(args);
FragmentTransaction fragmentTransaction = abstractFragmentActivity.getSupportFragmentManager().beginTransaction();
fragmentTransaction.add(0, inAppBillingHelperFragment, InAppBillingHelperFragment.class.getSimpleName());
fragmentTransaction.commit();
}
}
/**
* @see com.jdroid.android.fragment.AbstractFragment#onCreate(android.os.Bundle)
*/
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
managedProductTypes = getArgument(MANAGED_PRODUCT_TYPES);
subscriptionsProductTypes = getArgument(SUBSCRIPTIONS_PRODUCT_TYPES);
silentMode = getArgument(SILENT_MODE);
inAppBillingClient = new InAppBillingClient(getActivity());
// TODO The use cases logic should be replicated here. With the current approach, if an error happens on while
// the app is on the background, when the fragment is resumed, the error dialog is not displayed to the user
inAppBillingClient.setInAppBillingClientListener(this);
inAppBillingClient.startSetup();
}
/**
* @see com.jdroid.android.google.inappbilling.InAppBillingClientListener#onSetupFinished()
*/
@Override
public void onSetupFinished() {
inAppBillingClient.queryInventory(managedProductTypes, subscriptionsProductTypes);
}
public InAppBillingListener getInAppBillingListener() {
return (InAppBillingListener)getTargetFragment();
}
@Override
public void onSetupFailed(ErrorCodeException errorCodeException) {
AbstractApplication.get().getExceptionHandler().logHandledException(errorCodeException);
if (!silentMode) {
createErrorDisplayer(errorCodeException).displayError(errorCodeException);
}
}
@Override
public void onQueryInventoryFinished(Inventory inventory) {
InAppBillingListener inAppBillingListener = getInAppBillingListener();
if (inAppBillingListener != null) {
inAppBillingListener.onProductsLoaded(inventory.getProducts());
for (Product each : inventory.getProductToConsume()) {
inAppBillingClient.consume(each);
}
}
}
@Override
public void onQueryInventoryFailed(ErrorCodeException errorCodeException) {
AbstractApplication.get().getExceptionHandler().logHandledException(errorCodeException);
if (!silentMode) {
errorCodeException.setDescription(getString(R.string.jdroid_failedToLoadPurchases));
createErrorDisplayer(errorCodeException).displayError(errorCodeException);
}
}
public void launchPurchaseFlow(Product product) {
inAppBillingClient.launchInAppPurchaseFlow(getActivity(), product.getId(), product.getDeveloperPayload());
InAppBillingAppModule.get().getAnalyticsSender().trackInAppBillingPurchaseTry(product);
}
@Override
public void onPurchaseFinished(final Product product) {
InAppBillingListener inAppBillingListener = getInAppBillingListener();
if (inAppBillingListener != null) {
inAppBillingListener.onPurchased(product);
if (product.isWaitingToConsume()) {
inAppBillingClient.consume(product);
}
}
}
@Override
public void onPurchaseFailed(ErrorCodeException errorCodeException) {
if (DefaultExceptionHandler.matchAnyErrorCode(errorCodeException, InAppBillingErrorCode.USER_CANCELED)) {
LOGGER.warn(errorCodeException.getMessage());
} else if (DefaultExceptionHandler.matchAnyErrorCode(errorCodeException, InAppBillingErrorCode.DEVELOPER_ERROR,
InAppBillingErrorCode.ITEM_UNAVAILABLE)) {
AbstractApplication.get().getExceptionHandler().logHandledException(errorCodeException);
} else {
DialogErrorDisplayer.markAsNotGoBackOnError(errorCodeException);
AbstractApplication.get().getExceptionHandler().logHandledException(errorCodeException);
createErrorDisplayer(errorCodeException).displayError(errorCodeException);
}
}
@Override
public void onConsumeFinished(Product product) {
InAppBillingListener inAppBillingListener = getInAppBillingListener();
if (inAppBillingListener != null) {
inAppBillingListener.onConsumed(product);
}
}
@Override
public void onConsumeFailed(ErrorCodeException errorCodeException) {
AbstractApplication.get().getExceptionHandler().logHandledException(errorCodeException);
if (!silentMode) {
createErrorDisplayer(errorCodeException).displayError(errorCodeException);
}
}
/**
* @see android.support.v4.app.Fragment#onActivityResult(int, int, android.content.Intent)
*/
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (inAppBillingClient != null) {
// Pass on the activity result to the helper for handling
if (!inAppBillingClient.handleActivityResult(requestCode, resultCode, data)) {
// not handled, so handle it ourselves (here's where you'd perform any handling of activity results not
// related to in-app billing...
super.onActivityResult(requestCode, resultCode, data);
}
} else {
super.onActivityResult(requestCode, resultCode, data);
}
}
/**
* @see com.jdroid.android.fragment.AbstractFragment#onDestroy()
*/
@Override
public void onDestroy() {
super.onDestroy();
if (inAppBillingClient != null) {
inAppBillingClient.dispose();
inAppBillingClient = null;
}
}
public static InAppBillingHelperFragment get(FragmentActivity activity) {
return ((AbstractFragmentActivity)activity).getFragment(InAppBillingHelperFragment.class);
}
public static void removeTarget(FragmentActivity activity) {
InAppBillingHelperFragment inAppBillingHelperFragment = InAppBillingHelperFragment.get(activity);
if (inAppBillingHelperFragment != null) {
inAppBillingHelperFragment.setTargetFragment(null, 0);
}
}
}