[android] Added business logic to all pass subscription screen

This commit is contained in:
Александр Зацепин 2019-11-12 19:15:35 +03:00 committed by yoksnod
parent afef35a912
commit 631e3e87c2
6 changed files with 218 additions and 120 deletions

View file

@ -14,7 +14,6 @@ import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import com.android.billingclient.api.SkuDetails;
import com.mapswithme.maps.Framework;
import com.mapswithme.maps.PrivateVariables;
import com.mapswithme.maps.R;
import com.mapswithme.maps.base.BaseAuthFragment;
import com.mapswithme.maps.bookmarks.data.BookmarkManager;
@ -23,6 +22,7 @@ import com.mapswithme.maps.dialog.AlertDialogCallback;
import com.mapswithme.maps.dialog.ResolveFragmentManagerStrategy;
import com.mapswithme.util.ConnectionState;
import com.mapswithme.util.NetworkPolicy;
import com.mapswithme.util.Utils;
import com.mapswithme.util.log.Logger;
import com.mapswithme.util.log.LoggerFactory;
import com.mapswithme.util.statistics.Statistics;
@ -34,17 +34,20 @@ abstract class AbstractBookmarkSubscriptionFragment extends BaseAuthFragment
implements PurchaseStateActivator<BookmarkSubscriptionPaymentState>,
SubscriptionUiChangeListener, AlertDialogCallback
{
static final String EXTRA_FROM = "extra_from";
private static final Logger LOGGER = LoggerFactory.INSTANCE.getLogger(LoggerFactory.Type.BILLING);
private static final String TAG = AbstractBookmarkSubscriptionFragment.class.getSimpleName();
private final static String EXTRA_CURRENT_STATE = "extra_current_state";
private final static String EXTRA_PRODUCT_DETAILS = "extra_product_details";
private static final String EXTRA_CURRENT_STATE = "extra_current_state";
private static final String EXTRA_PRODUCT_DETAILS = "extra_product_details";
private boolean mPingingResult;
private boolean mValidationResult;
@NonNull
private final PingCallback mPingCallback = new PingCallback();
@SuppressWarnings("NullableProblems")
@NonNull
private final BookmarkSubscriptionCallback mPurchaseCallback = new BookmarkSubscriptionCallback();
private BookmarkSubscriptionCallback mPurchaseCallback;
@NonNull
private BookmarkSubscriptionPaymentState mState = BookmarkSubscriptionPaymentState.NONE;
@Nullable
@ -58,13 +61,39 @@ abstract class AbstractBookmarkSubscriptionFragment extends BaseAuthFragment
public final View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState)
{
mPurchaseCallback = new BookmarkSubscriptionCallback(getSubscriptionType());
mPurchaseController = createPurchaseController();
if (savedInstanceState != null)
mPurchaseController.onRestore(savedInstanceState);
mPurchaseController.initialize(requireActivity());
mPingCallback.attach(this);
BookmarkManager.INSTANCE.addCatalogPingListener(mPingCallback);
return onSubscriptionCreateView(inflater, container, savedInstanceState);
Statistics.INSTANCE.trackPurchasePreviewShow(getSubscriptionType().getServerId(),
getSubscriptionType().getVendor(),
getSubscriptionType().getYearlyProductId(),
getExtraFrom());
View root = onSubscriptionCreateView(inflater, container, savedInstanceState);
if (root != null)
{
View restoreButton = root.findViewById(R.id.restore_purchase_btn);
restoreButton.setOnClickListener(v -> openSubscriptionManagementSettings());
View termsOfUse = root.findViewById(R.id.term_of_use_link);
termsOfUse.setOnClickListener(v -> openTermsOfUseLink());
View privacyPolicy = root.findViewById(R.id.privacy_policy_link);
privacyPolicy.setOnClickListener(v -> openPrivacyPolicyLink());
}
return root;
}
@Nullable
private String getExtraFrom()
{
if (getArguments() == null)
return null;
return getArguments().getString(EXTRA_FROM, null);
}
@Override
@ -118,7 +147,7 @@ abstract class AbstractBookmarkSubscriptionFragment extends BaseAuthFragment
mPurchaseController.queryProductDetails();
}
void launchPurchaseFlow(@NonNull String productId)
private void launchPurchaseFlow(@NonNull String productId)
{
mPurchaseController.launchPurchaseFlow(productId);
}
@ -152,7 +181,7 @@ abstract class AbstractBookmarkSubscriptionFragment extends BaseAuthFragment
return;
}
onAuthorizationFinishSuccessfully();
launchPurchaseFlow();
}
@Override
@ -248,11 +277,18 @@ abstract class AbstractBookmarkSubscriptionFragment extends BaseAuthFragment
queryProductDetails();
}
@Override
public void onPinging()
{
showButtonProgress();
}
@Override
@CallSuper
public void onPingFinish()
{
finishPinging();
hideButtonProgress();
}
@Override
@ -260,6 +296,7 @@ abstract class AbstractBookmarkSubscriptionFragment extends BaseAuthFragment
public void onValidationFinish()
{
finishValidation();
hideButtonProgress();
}
private void finishValidation()
@ -321,8 +358,68 @@ abstract class AbstractBookmarkSubscriptionFragment extends BaseAuthFragment
@Nullable ViewGroup container,
@Nullable Bundle savedInstanceState);
private void openTermsOfUseLink()
{
Utils.openUrl(requireActivity(), Framework.nativeGetTermsOfUseLink());
}
private void openPrivacyPolicyLink()
{
Utils.openUrl(requireActivity(), Framework.nativeGetPrivacyPolicyLink());
}
abstract void onSubscriptionDestroyView();
@NonNull
abstract SubscriptionType getSubscriptionType();
abstract void hideButtonProgress();
@Override
public void onValidating()
{
showButtonProgress();
}
abstract void showButtonProgress();
@Override
public boolean onBackPressed()
{
Statistics.INSTANCE.trackPurchaseEvent(Statistics.EventName.INAPP_PURCHASE_PREVIEW_CANCEL,
getSubscriptionType().getServerId());
return super.onBackPressed();
}
void pingBookmarkCatalog()
{
BookmarkManager.INSTANCE.pingBookmarkCatalog();
activateState(BookmarkSubscriptionPaymentState.PINGING);
}
@NonNull
abstract PurchaseUtils.Period getSelectedPeriod();
private void openSubscriptionManagementSettings()
{
Utils.openUrl(requireContext(), "https://play.google.com/store/account/subscriptions");
Statistics.INSTANCE.trackPurchaseEvent(Statistics.EventName.INAPP_PURCHASE_PREVIEW_RESTORE,
getSubscriptionType().getServerId());
}
void trackPayEvent()
{
Statistics.INSTANCE.trackPurchaseEvent(Statistics.EventName.INAPP_PURCHASE_PREVIEW_PAY,
getSubscriptionType().getServerId(),
Statistics.STATISTICS_CHANNEL_REALTIME);
}
private void launchPurchaseFlow()
{
ProductDetails details = getProductDetailsForPeriod(getSelectedPeriod());
launchPurchaseFlow(details.getProductId());
}
int calculateYearlySaving()
{
float pricePerMonth = getProductDetailsForPeriod(PurchaseUtils.Period.P1M).getPrice();
@ -330,8 +427,17 @@ abstract class AbstractBookmarkSubscriptionFragment extends BaseAuthFragment
return (int) (100 * (1 - pricePerYear / (pricePerMonth * PurchaseUtils.MONTHS_IN_YEAR)));
}
abstract void onAuthorizationFinishSuccessfully();
void trackYearlyProductSelected()
{
Statistics.INSTANCE.trackPurchasePreviewSelect(getSubscriptionType().getServerId(),
getSubscriptionType().getYearlyProductId());
}
void trackMonthlyProductSelected()
{
Statistics.INSTANCE.trackPurchasePreviewSelect(getSubscriptionType().getServerId(),
getSubscriptionType().getMonthlyProductId());
}
private static class PingCallback
extends StatefulPurchaseCallback<BookmarkSubscriptionPaymentState,
@ -368,10 +474,17 @@ abstract class AbstractBookmarkSubscriptionFragment extends BaseAuthFragment
AbstractBookmarkSubscriptionFragment>
implements PurchaseCallback
{
@NonNull
private final SubscriptionType mType;
@Nullable
private List<SkuDetails> mPendingDetails;
private Boolean mPendingValidationResult;
private BookmarkSubscriptionCallback(@NonNull SubscriptionType type)
{
mType = type;
}
@Override
public void onProductDetailsLoaded(@NonNull List<SkuDetails> details)
{
@ -391,8 +504,7 @@ abstract class AbstractBookmarkSubscriptionFragment extends BaseAuthFragment
@Override
public void onPaymentFailure(int error)
{
Statistics.INSTANCE.trackPurchaseStoreError(PrivateVariables.bookmarksSubscriptionServerId(),
error);
Statistics.INSTANCE.trackPurchaseStoreError(mType.getServerId(), error);
activateStateSafely(BookmarkSubscriptionPaymentState.PAYMENT_FAILURE);
}
@ -412,7 +524,7 @@ abstract class AbstractBookmarkSubscriptionFragment extends BaseAuthFragment
public void onValidationStarted()
{
Statistics.INSTANCE.trackPurchaseEvent(Statistics.EventName.INAPP_PURCHASE_STORE_SUCCESS,
PrivateVariables.bookmarksSubscriptionServerId());
mType.getServerId());
activateStateSafely(BookmarkSubscriptionPaymentState.VALIDATION);
}

View file

@ -50,9 +50,9 @@ enum AdsRemovalPaymentState
View image = view.findViewById(R.id.image);
alignPayButtonBelow(view, image == null ? R.id.title : R.id.image);
dialog.updatePaymentButtons();
Statistics.INSTANCE.trackPurchasePreviewShow(PrivateVariables.adsRemovalServerId(),
PrivateVariables.adsRemovalVendor(),
PrivateVariables.adsRemovalYearlyProductId());
Statistics.INSTANCE.trackPurchasePreviewShow(SubscriptionType.ADS_REMOVAL.getServerId(),
SubscriptionType.ADS_REMOVAL.getVendor(),
SubscriptionType.ADS_REMOVAL.getYearlyProductId());
}
},
EXPLANATION

View file

@ -4,18 +4,18 @@ import android.content.Context;
import android.content.DialogInterface;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.DialogFragment;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
import androidx.fragment.app.FragmentManager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CompoundButton;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.DialogFragment;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
import androidx.fragment.app.FragmentManager;
import com.android.billingclient.api.BillingClient;
import com.android.billingclient.api.SkuDetails;
import com.mapswithme.maps.PrivateVariables;
@ -203,9 +203,8 @@ public class AdsRemovalPurchaseDialog extends BaseMwmDialogFragment
{
ProductDetails details = getProductDetailsForPeriod(period);
getControllerOrThrow().launchPurchaseFlow(details.getProductId());
String purchaseId = PrivateVariables.adsRemovalServerId();
Statistics.INSTANCE.trackPurchasePreviewSelect(PrivateVariables.adsRemovalServerId(),
details.getProductId());
String purchaseId = SubscriptionType.ADS_REMOVAL.getServerId();
Statistics.INSTANCE.trackPurchasePreviewSelect(purchaseId, details.getProductId());
Statistics.INSTANCE.trackPurchaseEvent(Statistics.EventName.INAPP_PURCHASE_PREVIEW_PAY,
purchaseId, Statistics.STATISTICS_CHANNEL_REALTIME);
}
@ -255,7 +254,7 @@ public class AdsRemovalPurchaseDialog extends BaseMwmDialogFragment
{
super.onCancel(dialog);
Statistics.INSTANCE.trackPurchaseEvent(Statistics.EventName.INAPP_PURCHASE_PREVIEW_CANCEL,
PrivateVariables.adsRemovalServerId());
SubscriptionType.ADS_REMOVAL.getServerId());
}
@Override
@ -407,7 +406,7 @@ public class AdsRemovalPurchaseDialog extends BaseMwmDialogFragment
@Override
public void onPaymentFailure(@BillingClient.BillingResponse int error)
{
Statistics.INSTANCE.trackPurchaseStoreError(PrivateVariables.adsRemovalServerId(), error);
Statistics.INSTANCE.trackPurchaseStoreError(SubscriptionType.ADS_REMOVAL.getServerId(), error);
activateStateSafely(AdsRemovalPaymentState.PAYMENT_FAILURE);
}
@ -427,7 +426,7 @@ public class AdsRemovalPurchaseDialog extends BaseMwmDialogFragment
public void onValidationStarted()
{
Statistics.INSTANCE.trackPurchaseEvent(Statistics.EventName.INAPP_PURCHASE_STORE_SUCCESS,
PrivateVariables.adsRemovalServerId());
SubscriptionType.ADS_REMOVAL.getServerId());
activateStateSafely(AdsRemovalPaymentState.VALIDATION);
}

View file

@ -31,6 +31,8 @@ public class AllPassSubscriptionPagerFragment extends AbstractBookmarkSubscripti
@SuppressWarnings("NullableProblems")
@NonNull
private SubscriptionButton mMonthlyButton;
@NonNull
private PurchaseUtils.Period mSelectedPeriod = PurchaseUtils.Period.P1Y;
@NonNull
@Override
@ -48,9 +50,15 @@ public class AllPassSubscriptionPagerFragment extends AbstractBookmarkSubscripti
false);
mAnnualButton = root.findViewById(R.id.annual_sub_btn);
mAnnualButton.setOnClickListener(v -> {});
mAnnualButton.setOnClickListener(v -> {
mSelectedPeriod = PurchaseUtils.Period.P1Y;
pingBookmarkCatalog();
});
mMonthlyButton = root.findViewById(R.id.month_sub_btn);
mMonthlyButton.setOnClickListener(v -> {});
mMonthlyButton.setOnClickListener(v -> {
mSelectedPeriod = PurchaseUtils.Period.P1M;
pingBookmarkCatalog();
});
setTopStatusBarOffset(root);
initViewPager(root);
@ -63,10 +71,18 @@ public class AllPassSubscriptionPagerFragment extends AbstractBookmarkSubscripti
// Do nothing by default.
}
@NonNull
@Override
void onAuthorizationFinishSuccessfully()
SubscriptionType getSubscriptionType()
{
return SubscriptionType.BOOKMARKS;
}
@NonNull
@Override
PurchaseUtils.Period getSelectedPeriod()
{
return mSelectedPeriod;
}
private void setTopStatusBarOffset(@NonNull View view)
@ -141,15 +157,21 @@ public class AllPassSubscriptionPagerFragment extends AbstractBookmarkSubscripti
}
@Override
public void onValidating()
void showButtonProgress()
{
if (mSelectedPeriod == PurchaseUtils.Period.P1Y)
mAnnualButton.showProgress();
else
mMonthlyButton.showProgress();
}
@Override
public void onPinging()
void hideButtonProgress()
{
if (mSelectedPeriod == PurchaseUtils.Period.P1Y)
mAnnualButton.hideProgress();
else
mMonthlyButton.hideProgress();
}
private void updatePaymentButtons()
@ -163,6 +185,7 @@ public class AllPassSubscriptionPagerFragment extends AbstractBookmarkSubscripti
ProductDetails details = getProductDetailsForPeriod(PurchaseUtils.Period.P1Y);
String price = Utils.formatCurrencyString(details.getPrice(), details.getCurrencyCode());
mAnnualButton.setPrice(price);
mAnnualButton.setName(getString(R.string.annual_subscription_title));
String sale = getString(R.string.annual_save_component, calculateYearlySaving());
mAnnualButton.setSale(sale);
}
@ -172,6 +195,7 @@ public class AllPassSubscriptionPagerFragment extends AbstractBookmarkSubscripti
ProductDetails details = getProductDetailsForPeriod(PurchaseUtils.Period.P1M);
String price = Utils.formatCurrencyString(details.getPrice(), details.getCurrencyCode());
mMonthlyButton.setPrice(price);
mMonthlyButton.setName(getString(R.string.montly_subscription_title));
}
private class ParallaxFragmentPagerAdapter extends FragmentPagerAdapter

View file

@ -9,18 +9,12 @@ import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.cardview.widget.CardView;
import com.mapswithme.maps.Framework;
import com.mapswithme.maps.PrivateVariables;
import com.mapswithme.maps.R;
import com.mapswithme.maps.bookmarks.data.BookmarkManager;
import com.mapswithme.util.UiUtils;
import com.mapswithme.util.Utils;
import com.mapswithme.util.statistics.Statistics;
public class BookmarkSubscriptionFragment extends AbstractBookmarkSubscriptionFragment
{
static final String EXTRA_FROM = "extra_from";
private static final int DEF_ELEVATION = 0;
@Nullable
@ -38,9 +32,6 @@ public class BookmarkSubscriptionFragment extends AbstractBookmarkSubscriptionFr
annualPriceCard);
monthlyPriceCard.setOnClickListener(monthlyCardListener);
TextView restorePurchasesBtn = root.findViewById(R.id.restore_purchase_btn);
restorePurchasesBtn.setOnClickListener(v -> openSubscriptionManagementSettings());
View continueBtn = root.findViewById(R.id.continue_btn);
continueBtn.setOnClickListener(v -> onContinueButtonClicked());
@ -48,15 +39,6 @@ public class BookmarkSubscriptionFragment extends AbstractBookmarkSubscriptionFr
monthlyPriceCard.setSelected(false);
annualPriceCard.setCardElevation(getResources().getDimension(R.dimen.margin_base_plus_quarter));
View termsOfUse = root.findViewById(R.id.term_of_use_link);
termsOfUse.setOnClickListener(v -> Utils.openUrl(requireActivity(), Framework.nativeGetTermsOfUseLink()));
View privacyPolicy = root.findViewById(R.id.privacy_policy_link);
privacyPolicy.setOnClickListener(v -> Utils.openUrl(requireActivity(), Framework.nativeGetPrivacyPolicyLink()));
Statistics.INSTANCE.trackPurchasePreviewShow(PrivateVariables.bookmarksSubscriptionServerId(),
PrivateVariables.bookmarksSubscriptionVendor(),
PrivateVariables.bookmarksSubscriptionYearlyProductId(),
getExtraFrom());
return root;
}
@ -66,31 +48,17 @@ public class BookmarkSubscriptionFragment extends AbstractBookmarkSubscriptionFr
// Do nothing by default.
}
@Nullable
private String getExtraFrom()
@NonNull
@Override
SubscriptionType getSubscriptionType()
{
if (getArguments() == null)
return null;
return getArguments().getString(EXTRA_FROM, null);
}
private void openSubscriptionManagementSettings()
{
Utils.openUrl(requireContext(), "https://play.google.com/store/account/subscriptions");
Statistics.INSTANCE.trackPurchaseEvent(Statistics.EventName.INAPP_PURCHASE_PREVIEW_RESTORE,
PrivateVariables.bookmarksSubscriptionServerId());
return SubscriptionType.BOOKMARKS;
}
private void onContinueButtonClicked()
{
BookmarkManager.INSTANCE.pingBookmarkCatalog();
activateState(BookmarkSubscriptionPaymentState.PINGING);
Statistics.INSTANCE.trackPurchaseEvent(Statistics.EventName.INAPP_PURCHASE_PREVIEW_PAY,
PrivateVariables.bookmarksSubscriptionServerId(),
Statistics.STATISTICS_CHANNEL_REALTIME);
pingBookmarkCatalog();
trackPayEvent();
}
private void updatePaymentButtons()
@ -118,27 +86,12 @@ public class BookmarkSubscriptionFragment extends AbstractBookmarkSubscriptionFr
priceView.setText(price);
}
@NonNull
@Override
public boolean onBackPressed()
{
Statistics.INSTANCE.trackPurchaseEvent(Statistics.EventName.INAPP_PURCHASE_PREVIEW_CANCEL,
PrivateVariables.bookmarksSubscriptionServerId());
return super.onBackPressed();
}
private void launchPurchaseFlow()
PurchaseUtils.Period getSelectedPeriod()
{
CardView annualCard = getViewOrThrow().findViewById(R.id.annual_price_card);
PurchaseUtils.Period period = annualCard.getCardElevation() > 0 ? PurchaseUtils.Period.P1Y
: PurchaseUtils.Period.P1M;
ProductDetails details = getProductDetailsForPeriod(period);
launchPurchaseFlow(details.getProductId());
}
@Override
void onAuthorizationFinishSuccessfully()
{
launchPurchaseFlow();
return annualCard.getCardElevation() > 0 ? PurchaseUtils.Period.P1Y : PurchaseUtils.Period.P1M;
}
@Override
@ -161,19 +114,6 @@ public class BookmarkSubscriptionFragment extends AbstractBookmarkSubscriptionFr
updatePaymentButtons();
}
@Override
public void onValidating()
{
showButtonProgress();
}
@Override
public void onValidationFinish()
{
super.onValidationFinish();
hideButtonProgress();
}
@NonNull
@Override
PurchaseController<PurchaseCallback> createPurchaseController()
@ -182,25 +122,14 @@ public class BookmarkSubscriptionFragment extends AbstractBookmarkSubscriptionFr
}
@Override
public void onPinging()
{
showButtonProgress();
}
@Override
public void onPingFinish()
{
super.onPingFinish();
hideButtonProgress();
}
private void showButtonProgress()
void showButtonProgress()
{
UiUtils.hide(getViewOrThrow(), R.id.continue_btn);
UiUtils.show(getViewOrThrow(), R.id.progress);
}
private void hideButtonProgress()
@Override
void hideButtonProgress()
{
UiUtils.hide(getViewOrThrow(), R.id.progress);
UiUtils.show(getViewOrThrow(), R.id.continue_btn);
@ -245,8 +174,9 @@ public class BookmarkSubscriptionFragment extends AbstractBookmarkSubscriptionFr
mAnnualPriceCard.setCardElevation(getResources().getDimension(R.dimen.margin_base_plus_quarter));
if (!mAnnualPriceCard.isSelected())
Statistics.INSTANCE.trackPurchasePreviewSelect(PrivateVariables.bookmarksSubscriptionServerId(),
PrivateVariables.bookmarksSubscriptionYearlyProductId());
{
trackYearlyProductSelected();
}
mMonthlyPriceCard.setSelected(false);
mAnnualPriceCard.setSelected(true);
@ -275,8 +205,7 @@ public class BookmarkSubscriptionFragment extends AbstractBookmarkSubscriptionFr
mAnnualPriceCard.setCardElevation(DEF_ELEVATION);
if (!mMonthlyPriceCard.isSelected())
Statistics.INSTANCE.trackPurchasePreviewSelect(PrivateVariables.bookmarksSubscriptionServerId(),
PrivateVariables.bookmarksSubscriptionMonthlyProductId());
trackMonthlyProductSelected();
mMonthlyPriceCard.setSelected(true);
mAnnualPriceCard.setSelected(false);

View file

@ -31,6 +31,20 @@ public enum SubscriptionType
PrivateVariables.adsRemovalMonthlyProductId(),
PrivateVariables.adsRemovalWeeklyProductId());
}
@NonNull
@Override
String getYearlyProductId()
{
return PrivateVariables.adsRemovalYearlyProductId();
}
@NonNull
@Override
String getMonthlyProductId()
{
return PrivateVariables.adsRemovalMonthlyProductId();
}
},
BOOKMARKS
{
@ -56,6 +70,20 @@ public enum SubscriptionType
PrivateVariables.bookmarksSubscriptionYearlyProductId(),
PrivateVariables.bookmarksSubscriptionMonthlyProductId());
}
@NonNull
@Override
String getYearlyProductId()
{
return PrivateVariables.bookmarksSubscriptionYearlyProductId();
}
@NonNull
@Override
String getMonthlyProductId()
{
return PrivateVariables.bookmarksSubscriptionMonthlyProductId();
}
};
@NonNull
@ -66,4 +94,10 @@ public enum SubscriptionType
@NonNull
abstract String[] getProductIds();
@NonNull
abstract String getYearlyProductId();
@NonNull
abstract String getMonthlyProductId();
}