forked from organicmaps/organicmaps
[android] Made purchase controller and validator savable to survive the screen rotation during validation process
This commit is contained in:
parent
7ab237c8e7
commit
bcd6534ef8
7 changed files with 124 additions and 5 deletions
|
@ -24,6 +24,8 @@ public class PurchaseOperationObservable implements Framework.PurchaseValidation
|
|||
private final Map<String, CoreValidationObserver> mValidationObservers = new HashMap<>();
|
||||
@NonNull
|
||||
private final List<CoreStartTransactionObserver> mTransactionObservers = new ArrayList<>();
|
||||
@NonNull
|
||||
private final Map<String, PendingResult> mValidationPendingResults = new HashMap<>();
|
||||
@SuppressWarnings("NullableProblems")
|
||||
@NonNull
|
||||
private Logger mLogger;
|
||||
|
@ -56,10 +58,15 @@ public class PurchaseOperationObservable implements Framework.PurchaseValidation
|
|||
String purchaseData = new String(tokenBytes);
|
||||
String orderId = PurchaseUtils.parseOrderId(purchaseData);
|
||||
CoreValidationObserver observer = mValidationObservers.get(orderId);
|
||||
ValidationStatus status = ValidationStatus.values()[code];
|
||||
if (observer == null)
|
||||
{
|
||||
PendingResult result = new PendingResult(status, serverId, vendorId, purchaseData);
|
||||
mValidationPendingResults.put(orderId, result);
|
||||
return;
|
||||
}
|
||||
|
||||
observer.onValidatePurchase(ValidationStatus.values()[code], serverId, vendorId, purchaseData);
|
||||
observer.onValidatePurchase(status, serverId, vendorId, purchaseData);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -70,10 +77,19 @@ public class PurchaseOperationObservable implements Framework.PurchaseValidation
|
|||
observer.onStartTransaction(success, serverId, vendorId);
|
||||
}
|
||||
|
||||
public void addValidationObserver(@NonNull String orderId, @NonNull CoreValidationObserver observer)
|
||||
public void addValidationObserver(@NonNull String orderId,
|
||||
@NonNull CoreValidationObserver observer)
|
||||
{
|
||||
mLogger.d(TAG, "Add validation observer '" + observer + "' for '" + orderId + "'");
|
||||
mValidationObservers.put(orderId, observer);
|
||||
PendingResult result = mValidationPendingResults.remove(orderId);
|
||||
if (result != null)
|
||||
{
|
||||
mLogger.d(TAG, "Post pending validation result to '" + observer + "' for '"
|
||||
+ orderId + "'");
|
||||
observer.onValidatePurchase(result.getStatus(), result.getServerId(), result.getVendorId(),
|
||||
result.getPurchaseData());
|
||||
}
|
||||
}
|
||||
|
||||
public void removeValidationObserver(@NonNull String orderId)
|
||||
|
@ -93,4 +109,49 @@ public class PurchaseOperationObservable implements Framework.PurchaseValidation
|
|||
mLogger.d(TAG, "Remove transaction observer '" + observer + "'");
|
||||
mTransactionObservers.remove(observer);
|
||||
}
|
||||
|
||||
private static class PendingResult
|
||||
{
|
||||
@NonNull
|
||||
private final ValidationStatus mStatus;
|
||||
@NonNull
|
||||
private final String mServerId;
|
||||
@NonNull
|
||||
private final String mVendorId;
|
||||
@NonNull
|
||||
private final String mPurchaseData;
|
||||
|
||||
private PendingResult(@NonNull ValidationStatus status, @NonNull String serverId,
|
||||
@NonNull String vendorId, @NonNull String purchaseData)
|
||||
{
|
||||
mStatus = status;
|
||||
mServerId = serverId;
|
||||
mVendorId = vendorId;
|
||||
mPurchaseData = purchaseData;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
ValidationStatus getStatus()
|
||||
{
|
||||
return mStatus;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
String getServerId()
|
||||
{
|
||||
return mServerId;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
String getVendorId()
|
||||
{
|
||||
return mVendorId;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
String getPurchaseData()
|
||||
{
|
||||
return mPurchaseData;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package com.mapswithme.maps.purchase;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
|
@ -128,6 +129,18 @@ abstract class AbstractPurchaseController<V, B, UiCallback extends PurchaseCallb
|
|||
|
||||
abstract void onDestroy();
|
||||
|
||||
@Override
|
||||
public void onSave(@NonNull Bundle outState)
|
||||
{
|
||||
mValidator.onSave(outState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRestore(@NonNull Bundle inState)
|
||||
{
|
||||
mValidator.onRestore(inState);
|
||||
}
|
||||
|
||||
abstract class AbstractPlayStoreBillingCallback implements PlayStoreBillingCallback
|
||||
{
|
||||
@Override
|
||||
|
|
|
@ -83,6 +83,8 @@ public class BookmarkPaymentFragment extends BaseMwmFragment
|
|||
mPurchaseController = PurchaseFactory.createBookmarkPurchaseController(requireContext(),
|
||||
mPaymentData.getProductId(),
|
||||
mPaymentData.getServerId());
|
||||
if (savedInstanceState != null)
|
||||
mPurchaseController.onRestore(savedInstanceState);
|
||||
mPurchaseController.initialize(requireActivity());
|
||||
View root = inflater.inflate(R.layout.fragment_bookmark_payment, container, false);
|
||||
TextView buyButton = root.findViewById(R.id.buy_btn);
|
||||
|
@ -196,6 +198,7 @@ public class BookmarkPaymentFragment extends BaseMwmFragment
|
|||
LOGGER.d(TAG, "onSaveInstanceState");
|
||||
outState.putInt(EXTRA_CURRENT_STATE, mState.ordinal());
|
||||
outState.putParcelable(EXTRA_PRODUCT_DETAILS, mProductDetails);
|
||||
mPurchaseController.onSave(outState);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
package com.mapswithme.maps.purchase;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Base64;
|
||||
|
||||
import com.mapswithme.maps.Framework;
|
||||
|
@ -14,10 +16,13 @@ class DefaultPurchaseValidator implements PurchaseValidator<ValidationCallback>,
|
|||
{
|
||||
private static final Logger LOGGER = LoggerFactory.INSTANCE.getLogger(LoggerFactory.Type.BILLING);
|
||||
private static final String TAG = DefaultPurchaseValidator.class.getSimpleName();
|
||||
private static final String EXTRA_VALIDATED_ORDER_ID = "extra_validated_order_id";
|
||||
@Nullable
|
||||
private ValidationCallback mCallback;
|
||||
@NonNull
|
||||
private final PurchaseOperationObservable mOperationObservable;
|
||||
@Nullable
|
||||
private String mValidatedOrderId;
|
||||
|
||||
DefaultPurchaseValidator(@NonNull PurchaseOperationObservable validationObservable)
|
||||
{
|
||||
|
@ -28,7 +33,8 @@ class DefaultPurchaseValidator implements PurchaseValidator<ValidationCallback>,
|
|||
public void validate(@Nullable String serverId, @NonNull String vendor,
|
||||
@NonNull String purchaseData)
|
||||
{
|
||||
String orderId = PurchaseUtils.parseOrderId(purchaseData);
|
||||
final String orderId = PurchaseUtils.parseOrderId(purchaseData);
|
||||
mValidatedOrderId = orderId;
|
||||
mOperationObservable.addValidationObserver(orderId, this);
|
||||
String encodedPurchaseData = Base64.encodeToString(purchaseData.getBytes(), Base64.DEFAULT);
|
||||
Framework.nativeValidatePurchase(serverId == null ? "" : serverId, vendor, encodedPurchaseData);
|
||||
|
@ -38,12 +44,28 @@ class DefaultPurchaseValidator implements PurchaseValidator<ValidationCallback>,
|
|||
public void addCallback(@NonNull ValidationCallback callback)
|
||||
{
|
||||
mCallback = callback;
|
||||
if (!TextUtils.isEmpty(mValidatedOrderId))
|
||||
mOperationObservable.addValidationObserver(mValidatedOrderId, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeCallback()
|
||||
{
|
||||
mCallback = null;
|
||||
if (!TextUtils.isEmpty(mValidatedOrderId))
|
||||
mOperationObservable.removeValidationObserver(mValidatedOrderId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSave(@NonNull Bundle outState)
|
||||
{
|
||||
outState.putString(EXTRA_VALIDATED_ORDER_ID, mValidatedOrderId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRestore(@NonNull Bundle inState)
|
||||
{
|
||||
mValidatedOrderId = inState.getString(EXTRA_VALIDATED_ORDER_ID);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -53,6 +75,7 @@ class DefaultPurchaseValidator implements PurchaseValidator<ValidationCallback>,
|
|||
LOGGER.i(TAG, "Validation code: " + status);
|
||||
String orderId = PurchaseUtils.parseOrderId(purchaseData);
|
||||
mOperationObservable.removeValidationObserver(orderId);
|
||||
mValidatedOrderId = null;
|
||||
if (mCallback != null)
|
||||
mCallback.onValidate(purchaseData, status);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package com.mapswithme.maps.purchase;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
|
@ -87,6 +88,18 @@ public class FailedBookmarkPurchaseController implements PurchaseController<Fail
|
|||
mCallback = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSave(@NonNull Bundle outState)
|
||||
{
|
||||
mValidator.onSave(outState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRestore(@NonNull Bundle inState)
|
||||
{
|
||||
mValidator.onRestore(inState);
|
||||
}
|
||||
|
||||
private class ValidationCallbackImpl implements ValidationCallback
|
||||
{
|
||||
|
||||
|
|
|
@ -1,14 +1,17 @@
|
|||
package com.mapswithme.maps.purchase;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import com.mapswithme.maps.base.Savable;
|
||||
|
||||
/**
|
||||
* Provides necessary purchase functionality to the UI. Controls whole platform-specific billing
|
||||
* process. This controller has to be used only within {@link #initialize(Activity)} and {@link #destroy()}
|
||||
* interval.
|
||||
*/
|
||||
public interface PurchaseController<T>
|
||||
public interface PurchaseController<T> extends Savable<Bundle>
|
||||
{
|
||||
/**
|
||||
* Initializes the controller.
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
package com.mapswithme.maps.purchase;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
import com.mapswithme.maps.base.Savable;
|
||||
|
||||
/**
|
||||
* Represents a purchase validator. The main of purpose is to validate existing purchase and inform
|
||||
* the client code through typed callback {@link T}.<br><br>
|
||||
|
@ -10,7 +13,7 @@ import android.support.annotation.Nullable;
|
|||
* <b>one-to-one</b>. If you need to validate different purchases you have to create different
|
||||
* implementations of this interface.
|
||||
*/
|
||||
interface PurchaseValidator<T>
|
||||
interface PurchaseValidator<T> extends Savable<Bundle>
|
||||
{
|
||||
/**
|
||||
* Validates the purchase with specified purchase data.
|
||||
|
|
Loading…
Add table
Reference in a new issue