forked from organicmaps/organicmaps
[android] Added purchase controller abstraction
This commit is contained in:
parent
2a0aa3f97b
commit
36da010799
12 changed files with 256 additions and 65 deletions
android/src/com/mapswithme/maps
|
@ -72,8 +72,9 @@ import com.mapswithme.maps.maplayer.subway.SubwayManager;
|
|||
import com.mapswithme.maps.maplayer.traffic.OnTrafficLayerToggleListener;
|
||||
import com.mapswithme.maps.maplayer.traffic.TrafficManager;
|
||||
import com.mapswithme.maps.maplayer.traffic.widget.TrafficButton;
|
||||
import com.mapswithme.maps.purchase.BillingFactory;
|
||||
import com.mapswithme.maps.purchase.BillingManager;
|
||||
import com.mapswithme.maps.purchase.PurchaseFactory;
|
||||
import com.mapswithme.maps.purchase.PurchaseController;
|
||||
import com.mapswithme.maps.purchase.PurchaseControllerProvider;
|
||||
import com.mapswithme.maps.routing.NavigationController;
|
||||
import com.mapswithme.maps.routing.RoutePointInfo;
|
||||
import com.mapswithme.maps.routing.RoutingBottomMenuListener;
|
||||
|
@ -146,7 +147,8 @@ public class MwmActivity extends BaseMwmFragmentActivity
|
|||
FloatingSearchToolbarController.SearchToolbarListener,
|
||||
OnTrafficLayerToggleListener,
|
||||
OnSubwayLayerToggleListener,
|
||||
BookmarkManager.BookmarksCatalogListener
|
||||
BookmarkManager.BookmarksCatalogListener,
|
||||
PurchaseControllerProvider
|
||||
{
|
||||
private static final Logger LOGGER = LoggerFactory.INSTANCE.getLogger(LoggerFactory.Type.MISC);
|
||||
private static final String TAG = MwmActivity.class.getSimpleName();
|
||||
|
@ -232,7 +234,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
|
|||
private PlacePageTracker mPlacePageTracker;
|
||||
@SuppressWarnings("NullableProblems")
|
||||
@NonNull
|
||||
private BillingManager mBillingManager;
|
||||
private PurchaseController mPurchaseController;
|
||||
@NonNull
|
||||
private final OnClickListener mOnMyPositionClickListener = new CurrentPositionClickListener();
|
||||
|
||||
|
@ -551,7 +553,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
|
|||
|
||||
SharingHelper.INSTANCE.initialize();
|
||||
|
||||
mBillingManager = BillingFactory.ADS_REMOVAL.createBillingManager(this, "android.test.purchased");
|
||||
mPurchaseController = PurchaseFactory.ADS_REMOVAL.createPurchaseController(this, "ads.removal.monthly.test");
|
||||
|
||||
//TODO: uncomment after correct visible rect calculation.
|
||||
//mVisibleRectMeasurer = new VisibleRectMeasurer(new VisibleRectListener() {
|
||||
|
@ -1346,7 +1348,6 @@ public class MwmActivity extends BaseMwmFragmentActivity
|
|||
protected void onStart()
|
||||
{
|
||||
super.onStart();
|
||||
mBillingManager.initialize();
|
||||
SearchEngine.INSTANCE.addListener(this);
|
||||
Framework.nativeSetMapObjectListener(this);
|
||||
BookmarkManager.INSTANCE.addLoadingListener(this);
|
||||
|
@ -1358,13 +1359,13 @@ public class MwmActivity extends BaseMwmFragmentActivity
|
|||
if (mNavigationController != null)
|
||||
TrafficManager.INSTANCE.attach(mNavigationController);
|
||||
mPlacePage.onActivityStarted();
|
||||
mPurchaseController.start(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop()
|
||||
{
|
||||
super.onStop();
|
||||
mBillingManager.destroy();
|
||||
SearchEngine.INSTANCE.removeListener(this);
|
||||
Framework.nativeRemoveMapObjectListener();
|
||||
BookmarkManager.INSTANCE.removeLoadingListener(this);
|
||||
|
@ -1374,6 +1375,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
|
|||
TrafficManager.INSTANCE.detachAll();
|
||||
mToggleMapLayerController.detachCore();
|
||||
mPlacePage.onActivityStopped();
|
||||
mPurchaseController.stop();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1877,6 +1879,13 @@ public class MwmActivity extends BaseMwmFragmentActivity
|
|||
});
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public PurchaseController getPurchaseController()
|
||||
{
|
||||
return mPurchaseController;
|
||||
}
|
||||
|
||||
private void adjustMenuLineFrameVisibility(@Nullable final Runnable completion)
|
||||
{
|
||||
final RoutingController controller = RoutingController.get();
|
||||
|
|
|
@ -27,8 +27,6 @@ import com.mapswithme.maps.location.LocationHelper;
|
|||
import com.mapswithme.maps.location.TrackRecorder;
|
||||
import com.mapswithme.maps.maplayer.subway.SubwayManager;
|
||||
import com.mapswithme.maps.maplayer.traffic.TrafficManager;
|
||||
import com.mapswithme.maps.purchase.BillingFactory;
|
||||
import com.mapswithme.maps.purchase.PurchaseValidator;
|
||||
import com.mapswithme.maps.routing.RoutingController;
|
||||
import com.mapswithme.maps.scheduling.ConnectivityJobScheduler;
|
||||
import com.mapswithme.maps.scheduling.ConnectivityListener;
|
||||
|
@ -76,8 +74,6 @@ public class MwmApplication extends Application
|
|||
@SuppressWarnings("NullableProblems")
|
||||
@NonNull
|
||||
private PushwooshHelper mPushwooshHelper;
|
||||
@NonNull
|
||||
private final PurchaseValidator mPurchaseValidator = BillingFactory.ADS_REMOVAL.createPurchaseManager();
|
||||
|
||||
private boolean mFrameworkInitialized;
|
||||
private boolean mPlatformInitialized;
|
||||
|
@ -285,7 +281,6 @@ public class MwmApplication extends Application
|
|||
RoutingController.get().initialize();
|
||||
TrafficManager.INSTANCE.initialize();
|
||||
SubwayManager.from(this).initialize();
|
||||
mPurchaseValidator.initialize();
|
||||
mFrameworkInitialized = true;
|
||||
}
|
||||
|
||||
|
@ -425,12 +420,6 @@ public class MwmApplication extends Application
|
|||
MyTracker.initTracker();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public PurchaseValidator getPurchaseValidator()
|
||||
{
|
||||
return mPurchaseValidator;
|
||||
}
|
||||
|
||||
public static void onUpgrade()
|
||||
{
|
||||
Counters.resetAppSessionCounters();
|
||||
|
|
|
@ -0,0 +1,69 @@
|
|||
package com.mapswithme.maps.purchase;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
abstract class AbstractPurchaseController<V, B> implements PurchaseController
|
||||
{
|
||||
@NonNull
|
||||
private final PurchaseValidator<V> mValidator;
|
||||
@NonNull
|
||||
private final BillingManager<B> mBillingManager;
|
||||
|
||||
AbstractPurchaseController(@NonNull PurchaseValidator<V> validator,
|
||||
@NonNull BillingManager<B> billingManager)
|
||||
{
|
||||
mValidator = validator;
|
||||
mBillingManager = billingManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void start(@NonNull Activity activity)
|
||||
{
|
||||
mValidator.initialize();
|
||||
mBillingManager.initialize(activity);
|
||||
onStart(activity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void stop()
|
||||
{
|
||||
mValidator.destroy();
|
||||
mBillingManager.destroy();
|
||||
onStop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPurchaseDone()
|
||||
{
|
||||
return mValidator.hasActivePurchase();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPurchaseSupported()
|
||||
{
|
||||
return mBillingManager.isBillingSupported();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void launchPurchaseFlow(@NonNull String productId)
|
||||
{
|
||||
mBillingManager.launchBillingFlowForProduct(productId);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
PurchaseValidator<V> getValidator()
|
||||
{
|
||||
return mValidator;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
BillingManager<B> getBillingManager()
|
||||
{
|
||||
return mBillingManager;
|
||||
}
|
||||
|
||||
abstract void onStart(@NonNull Activity activity);
|
||||
|
||||
abstract void onStop();
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
package com.mapswithme.maps.purchase;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
class AdPurchaseController extends AbstractPurchaseController<AdValidationCallback, PlayStoreBillingCallback>
|
||||
{
|
||||
@NonNull
|
||||
private final AdValidationCallback mValidationCallback;
|
||||
|
||||
AdPurchaseController(@NonNull PurchaseValidator<AdValidationCallback> validator,
|
||||
@NonNull BillingManager<PlayStoreBillingCallback> billingManager)
|
||||
{
|
||||
super(validator, billingManager);
|
||||
mValidationCallback = new StubAdValidationCallback();
|
||||
}
|
||||
|
||||
@Override
|
||||
void onStart(@NonNull Activity activity)
|
||||
{
|
||||
getValidator().addCallback(mValidationCallback);
|
||||
}
|
||||
|
||||
@Override
|
||||
void onStop()
|
||||
{
|
||||
getValidator().removeCallback(mValidationCallback);
|
||||
}
|
||||
|
||||
private static class StubAdValidationCallback implements AdValidationCallback
|
||||
{
|
||||
|
||||
@Override
|
||||
public void onValidate(@NonNull AdValidationStatus status)
|
||||
{
|
||||
// Do nothing by default.
|
||||
}
|
||||
}
|
||||
}
|
|
@ -13,6 +13,12 @@ class AdSubscriptionValidator implements PurchaseValidator<AdValidationCallback>
|
|||
Framework.nativeSetSubscriptionValidationListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy()
|
||||
{
|
||||
Framework.nativeSetSubscriptionValidationListener(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validate(@NonNull String purchaseToken)
|
||||
{
|
||||
|
@ -20,9 +26,9 @@ class AdSubscriptionValidator implements PurchaseValidator<AdValidationCallback>
|
|||
}
|
||||
|
||||
@Override
|
||||
public void hasActivePurchase()
|
||||
public boolean hasActivePurchase()
|
||||
{
|
||||
Framework.nativeHasActiveSubscription();
|
||||
return Framework.nativeHasActiveSubscription();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -1,34 +0,0 @@
|
|||
package com.mapswithme.maps.purchase;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import com.android.billingclient.api.BillingClient;
|
||||
|
||||
public enum BillingFactory
|
||||
{
|
||||
ADS_REMOVAL
|
||||
{
|
||||
@NonNull
|
||||
@Override
|
||||
public PurchaseValidator createPurchaseManager()
|
||||
{
|
||||
return new AdSubscriptionValidator();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public BillingManager createBillingManager(@NonNull Activity activity,
|
||||
@NonNull String... productIds)
|
||||
{
|
||||
return new PlayStoreBillingManager(activity, BillingClient.SkuType.SUBS, productIds);
|
||||
}
|
||||
};
|
||||
|
||||
@NonNull
|
||||
public abstract PurchaseValidator createPurchaseManager();
|
||||
|
||||
@NonNull
|
||||
public abstract BillingManager createBillingManager(@NonNull Activity activity,
|
||||
@NonNull String... productIds);
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
package com.mapswithme.maps.purchase;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.annotation.UiThread;
|
||||
|
@ -12,7 +13,7 @@ public interface BillingManager<T>
|
|||
/**
|
||||
* Initializes the current billing manager.
|
||||
*/
|
||||
void initialize();
|
||||
void initialize(@NonNull Activity context);
|
||||
|
||||
/**
|
||||
* Destroys the billing manager.
|
||||
|
|
|
@ -25,8 +25,8 @@ public class PlayStoreBillingManager implements BillingManager<PlayStoreBillingC
|
|||
{
|
||||
private final static Logger LOGGER = LoggerFactory.INSTANCE.getLogger(LoggerFactory.Type.MISC);
|
||||
private final static String TAG = PlayStoreBillingManager.class.getSimpleName();
|
||||
@NonNull
|
||||
private final Activity mActivity;
|
||||
@Nullable
|
||||
private Activity mActivity;
|
||||
@Nullable
|
||||
private BillingClient mBillingClient;
|
||||
@Nullable
|
||||
|
@ -42,19 +42,18 @@ public class PlayStoreBillingManager implements BillingManager<PlayStoreBillingC
|
|||
@NonNull
|
||||
private final List<Runnable> mPendingRequests = new ArrayList<>();
|
||||
|
||||
PlayStoreBillingManager(@NonNull Activity activity,
|
||||
@NonNull @BillingClient.SkuType String productType,
|
||||
PlayStoreBillingManager(@NonNull @BillingClient.SkuType String productType,
|
||||
@NonNull String... productIds)
|
||||
{
|
||||
mActivity = activity;
|
||||
mProductIds = Collections.unmodifiableList(Arrays.asList(productIds));
|
||||
mProductType = productType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize()
|
||||
public void initialize(@NonNull Activity context)
|
||||
{
|
||||
LOGGER.i(TAG, "Creating play store billing client...");
|
||||
mActivity = context;
|
||||
mBillingClient = BillingClient.newBuilder(mActivity).setListener(this).build();
|
||||
mConnection = new PlayStoreBillingConnection(mBillingClient, this);
|
||||
mConnection.open();
|
||||
|
@ -63,6 +62,7 @@ public class PlayStoreBillingManager implements BillingManager<PlayStoreBillingC
|
|||
@Override
|
||||
public void destroy()
|
||||
{
|
||||
mActivity = null;
|
||||
mConnection.close();
|
||||
mPendingRequests.clear();
|
||||
}
|
||||
|
@ -153,6 +153,15 @@ public class PlayStoreBillingManager implements BillingManager<PlayStoreBillingC
|
|||
return mBillingClient;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private Activity getActivityOrThrow()
|
||||
{
|
||||
if (mActivity == null)
|
||||
throw new IllegalStateException("Manager must be initialized! Call 'initialize' method first.");
|
||||
|
||||
return mActivity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConnected()
|
||||
{
|
||||
|
@ -214,7 +223,7 @@ public class PlayStoreBillingManager implements BillingManager<PlayStoreBillingC
|
|||
.setType(mProductType)
|
||||
.build();
|
||||
|
||||
int responseCode = getClientOrThrow().launchBillingFlow(mActivity, params);
|
||||
int responseCode = getClientOrThrow().launchBillingFlow(getActivityOrThrow(), params);
|
||||
LOGGER.i(TAG, "Launch billing flow response: " + responseCode);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
package com.mapswithme.maps.purchase;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
/**
|
||||
* Provides necessary purchase functionality to the UI. Controls whole platform-specific billing
|
||||
* process. This controller has to be used only within {@link #start(Activity)} and {@link #stop()}
|
||||
* interval.
|
||||
*/
|
||||
public interface PurchaseController
|
||||
{
|
||||
/**
|
||||
* Starts the controller.
|
||||
* @param activity the activity which controller serves.
|
||||
*/
|
||||
void start(@NonNull Activity activity);
|
||||
|
||||
/**
|
||||
* Stops the controller.
|
||||
*/
|
||||
void stop();
|
||||
|
||||
/**
|
||||
* Indicates whether the purchase already done or not.
|
||||
*/
|
||||
boolean isPurchaseDone();
|
||||
|
||||
/**
|
||||
* Indicates whether the purchase flow is supported by this device or not.
|
||||
*/
|
||||
boolean isPurchaseSupported();
|
||||
|
||||
/**
|
||||
* Launches the purchase flow for the specified product.
|
||||
*
|
||||
* @param id of the product which is going to be purchased.
|
||||
*/
|
||||
void launchPurchaseFlow(@NonNull String productId);
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
package com.mapswithme.maps.purchase;
|
||||
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
public interface PurchaseControllerProvider
|
||||
{
|
||||
@NonNull
|
||||
public PurchaseController getPurchaseController();
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
package com.mapswithme.maps.purchase;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import com.android.billingclient.api.BillingClient;
|
||||
|
||||
public enum PurchaseFactory
|
||||
{
|
||||
ADS_REMOVAL
|
||||
{
|
||||
@NonNull
|
||||
@Override
|
||||
public PurchaseValidator<AdValidationCallback> createPurchaseValidator()
|
||||
{
|
||||
return new AdSubscriptionValidator();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public BillingManager<PlayStoreBillingCallback> createBillingManager
|
||||
(@NonNull Activity activity, @NonNull String... productIds)
|
||||
{
|
||||
return new PlayStoreBillingManager(BillingClient.SkuType.SUBS, productIds);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PurchaseController createPurchaseController(@NonNull Activity activity,
|
||||
@NonNull String... productIds)
|
||||
{
|
||||
BillingManager<PlayStoreBillingCallback> billingManager
|
||||
= createBillingManager(activity, productIds);
|
||||
PurchaseValidator<AdValidationCallback> validator = createPurchaseValidator();
|
||||
return new AdPurchaseController(validator, billingManager);
|
||||
}
|
||||
};
|
||||
|
||||
@NonNull
|
||||
public abstract PurchaseValidator createPurchaseValidator();
|
||||
|
||||
@NonNull
|
||||
public abstract BillingManager createBillingManager(@NonNull Activity activity,
|
||||
@NonNull String... productIds);
|
||||
|
||||
public abstract PurchaseController createPurchaseController(@NonNull Activity activity,
|
||||
@NonNull String... productIds);
|
||||
}
|
|
@ -9,13 +9,18 @@ import android.support.annotation.NonNull;
|
|||
* <b>one-to-one</b>. If you need to validate different purchases you have to create different
|
||||
* implementations of this interface.
|
||||
*/
|
||||
public interface PurchaseValidator<T>
|
||||
interface PurchaseValidator<T>
|
||||
{
|
||||
/**
|
||||
* Initializes validator for further work.
|
||||
* Initializes the validator for further work.
|
||||
*/
|
||||
void initialize();
|
||||
|
||||
/**
|
||||
* Destroys this validator.
|
||||
*/
|
||||
void destroy();
|
||||
|
||||
/**
|
||||
* Validates the purchase with specified token.
|
||||
*
|
||||
|
@ -26,7 +31,7 @@ public interface PurchaseValidator<T>
|
|||
/**
|
||||
* Indicates whether the app has active purchase or not.
|
||||
*/
|
||||
void hasActivePurchase();
|
||||
boolean hasActivePurchase();
|
||||
|
||||
/**
|
||||
* Ads observer of validation.
|
||||
|
|
Loading…
Add table
Reference in a new issue