diff --git a/OsmAnd/res/layout/osmlive_cancelled_dialog_fragment.xml b/OsmAnd/res/layout/osmlive_gone_dialog_fragment.xml similarity index 100% rename from OsmAnd/res/layout/osmlive_cancelled_dialog_fragment.xml rename to OsmAnd/res/layout/osmlive_gone_dialog_fragment.xml diff --git a/OsmAnd/src/net/osmand/plus/chooseplan/OsmLiveCancelledDialog.java b/OsmAnd/src/net/osmand/plus/chooseplan/OsmLiveCancelledDialog.java deleted file mode 100644 index 788b605eec..0000000000 --- a/OsmAnd/src/net/osmand/plus/chooseplan/OsmLiveCancelledDialog.java +++ /dev/null @@ -1,242 +0,0 @@ -package net.osmand.plus.chooseplan; - -import android.app.Activity; -import android.app.Dialog; -import android.content.Context; -import android.graphics.Color; -import android.graphics.drawable.ColorDrawable; -import android.os.Build; -import android.os.Bundle; -import android.view.ContextThemeWrapper; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.view.Window; -import android.widget.ProgressBar; - -import androidx.annotation.ColorRes; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.core.content.ContextCompat; -import androidx.fragment.app.FragmentActivity; -import androidx.fragment.app.FragmentManager; - -import net.osmand.PlatformUtil; -import net.osmand.plus.OsmandApplication; -import net.osmand.plus.settings.backend.OsmandSettings; -import net.osmand.plus.settings.backend.OsmandSettings.OsmandPreference; -import net.osmand.plus.R; -import net.osmand.plus.activities.MapActivity; -import net.osmand.plus.base.BaseOsmAndDialogFragment; -import net.osmand.plus.chooseplan.ChoosePlanDialogFragment.OsmAndFeature; -import net.osmand.plus.inapp.InAppPurchaseHelper; -import net.osmand.plus.inapp.InAppPurchaseHelper.InAppPurchaseListener; -import net.osmand.plus.inapp.InAppPurchaseHelper.InAppPurchaseTaskType; -import net.osmand.plus.widgets.TextViewEx; - -import org.apache.commons.logging.Log; - -import static net.osmand.plus.inapp.InAppPurchaseHelper.SUBSCRIPTION_HOLDING_TIME_MSEC; - -public class OsmLiveCancelledDialog extends BaseOsmAndDialogFragment implements InAppPurchaseListener { - public static final String TAG = OsmLiveCancelledDialog.class.getSimpleName(); - private static final Log LOG = PlatformUtil.getLog(OsmLiveCancelledDialog.class); - - private OsmandApplication app; - private InAppPurchaseHelper purchaseHelper; - - private boolean nightMode; - private View osmLiveButton; - - private final OsmAndFeature[] osmLiveFeatures = { - OsmAndFeature.DAILY_MAP_UPDATES, - OsmAndFeature.UNLIMITED_DOWNLOADS, - OsmAndFeature.WIKIPEDIA_OFFLINE, - OsmAndFeature.WIKIVOYAGE_OFFLINE, - OsmAndFeature.CONTOUR_LINES_HILLSHADE_MAPS, - OsmAndFeature.SEA_DEPTH_MAPS, - OsmAndFeature.UNLOCK_ALL_FEATURES, - }; - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - app = getMyApplication(); - purchaseHelper = app.getInAppPurchaseHelper(); - nightMode = isNightMode(getMapActivity() != null); - } - - @NonNull - @Override - public Dialog onCreateDialog(Bundle savedInstanceState) { - Activity ctx = requireActivity(); - int themeId = nightMode ? R.style.OsmandDarkTheme_DarkActionbar : R.style.OsmandLightTheme_DarkActionbar_LightStatusBar; - Dialog dialog = new Dialog(ctx, themeId); - Window window = dialog.getWindow(); - if (window != null) { - window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); - if (!getSettings().DO_NOT_USE_ANIMATIONS.get()) { - window.getAttributes().windowAnimations = R.style.Animations_Alpha; - } - if (Build.VERSION.SDK_INT >= 21) { - window.setStatusBarColor(ContextCompat.getColor(ctx, getStatusBarColor())); - } - } - return dialog; - } - - @Nullable - @Override - public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - Context ctx = getContext(); - if (ctx == null) { - return null; - } - int themeRes = nightMode ? R.style.OsmandDarkTheme_DarkActionbar : R.style.OsmandLightTheme_DarkActionbar_LightStatusBar; - View view = LayoutInflater.from(new ContextThemeWrapper(getContext(), themeRes)) - .inflate(R.layout.osmlive_cancelled_dialog_fragment, container, false); - - view.findViewById(R.id.button_close).setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - dismiss(); - } - }); - - TextViewEx infoDescr = (TextViewEx) view.findViewById(R.id.info_description); - StringBuilder descr = new StringBuilder(); - descr.append(getString(R.string.purchase_cancelled_dialog_descr)); - for (OsmAndFeature feature : osmLiveFeatures) { - descr.append("\n").append("— ").append(feature.toHumanString(ctx)); - } - infoDescr.setText(descr); - - osmLiveButton = view.findViewById(R.id.card_button); - - return view; - } - - @Nullable - public MapActivity getMapActivity() { - Activity activity = getActivity(); - if (activity instanceof MapActivity) { - return (MapActivity) activity; - } - return null; - } - - @Override - public void onResume() { - super.onResume(); - - MapActivity mapActivity = getMapActivity(); - if (mapActivity != null) { - mapActivity.disableDrawer(); - } - - boolean requestingInventory = purchaseHelper != null && purchaseHelper.getActiveTask() == InAppPurchaseTaskType.REQUEST_INVENTORY; - setupOsmLiveButton(requestingInventory); - - OsmandPreference firstTimeShown = app.getSettings().LIVE_UPDATES_PURCHASE_CANCELLED_FIRST_DLG_SHOWN; - OsmandPreference secondTimeShown = app.getSettings().LIVE_UPDATES_PURCHASE_CANCELLED_SECOND_DLG_SHOWN; - if (!firstTimeShown.get()) { - firstTimeShown.set(true); - } else if (!secondTimeShown.get()) { - secondTimeShown.set(true); - } - } - - @Override - public void onPause() { - super.onPause(); - - MapActivity mapActivity = getMapActivity(); - if (mapActivity != null) { - mapActivity.enableDrawer(); - } - } - - @ColorRes - protected int getStatusBarColor() { - return nightMode ? R.color.status_bar_wikivoyage_dark : R.color.status_bar_wikivoyage_light; - } - - @Override - public void onError(InAppPurchaseTaskType taskType, String error) { - if (taskType == InAppPurchaseTaskType.REQUEST_INVENTORY) { - setupOsmLiveButton(false); - } - } - - @Override - public void onGetItems() { - } - - @Override - public void onItemPurchased(String sku, boolean active) { - } - - @Override - public void showProgress(InAppPurchaseTaskType taskType) { - if (taskType == InAppPurchaseTaskType.REQUEST_INVENTORY) { - setupOsmLiveButton(true); - } - } - - @Override - public void dismissProgress(InAppPurchaseTaskType taskType) { - if (taskType == InAppPurchaseTaskType.REQUEST_INVENTORY) { - setupOsmLiveButton(false); - } - } - - private void setupOsmLiveButton(boolean progress) { - if (osmLiveButton != null) { - ProgressBar progressBar = (ProgressBar) osmLiveButton.findViewById(R.id.card_button_progress); - TextViewEx buttonTitle = (TextViewEx) osmLiveButton.findViewById(R.id.card_button_title); - TextViewEx buttonSubtitle = (TextViewEx) osmLiveButton.findViewById(R.id.card_button_subtitle); - buttonTitle.setText(getString(R.string.osm_live_plan_pricing)); - buttonSubtitle.setVisibility(View.GONE); - if (progress) { - buttonTitle.setVisibility(View.GONE); - progressBar.setVisibility(View.VISIBLE); - osmLiveButton.setOnClickListener(null); - } else { - buttonTitle.setVisibility(View.VISIBLE); - progressBar.setVisibility(View.GONE); - osmLiveButton.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - dismiss(); - FragmentActivity activity = getActivity(); - if (activity != null) { - ChoosePlanDialogFragment.showOsmLiveInstance(activity.getSupportFragmentManager()); - } - } - }); - } - } - } - - public static boolean shouldShowDialog(OsmandApplication app) { - OsmandSettings settings = app.getSettings(); - long cancelledTime = settings.LIVE_UPDATES_PURCHASE_CANCELLED_TIME.get(); - boolean firstTimeShown = settings.LIVE_UPDATES_PURCHASE_CANCELLED_FIRST_DLG_SHOWN.get(); - boolean secondTimeShown = settings.LIVE_UPDATES_PURCHASE_CANCELLED_SECOND_DLG_SHOWN.get(); - return cancelledTime > 0 - && (!firstTimeShown - || (System.currentTimeMillis() - cancelledTime > SUBSCRIPTION_HOLDING_TIME_MSEC - && !secondTimeShown)); - } - - public static void showInstance(@NonNull FragmentManager fm) { - try { - if (fm.findFragmentByTag(OsmLiveCancelledDialog.TAG) == null) { - OsmLiveCancelledDialog fragment = new OsmLiveCancelledDialog(); - fragment.show(fm, OsmLiveCancelledDialog.TAG); - } - } catch (RuntimeException e) { - LOG.error("showInstance", e); - } - } -} diff --git a/OsmAnd/src/net/osmand/plus/inapp/InAppPurchaseHelper.java b/OsmAnd/src/net/osmand/plus/inapp/InAppPurchaseHelper.java index 86336723fb..d855e36ab3 100644 --- a/OsmAnd/src/net/osmand/plus/inapp/InAppPurchaseHelper.java +++ b/OsmAnd/src/net/osmand/plus/inapp/InAppPurchaseHelper.java @@ -28,6 +28,7 @@ import net.osmand.plus.inapp.InAppPurchases.InAppPurchase; import net.osmand.plus.inapp.InAppPurchases.InAppPurchase.PurchaseState; import net.osmand.plus.inapp.InAppPurchases.InAppPurchaseLiveUpdatesOldSubscription; import net.osmand.plus.inapp.InAppPurchases.InAppSubscription; +import net.osmand.plus.inapp.InAppPurchases.InAppSubscription.SubscriptionState; import net.osmand.plus.inapp.InAppPurchases.InAppSubscriptionIntroductoryInfo; import net.osmand.plus.inapp.InAppPurchases.InAppSubscriptionList; import net.osmand.plus.inapp.util.BillingManager; @@ -35,7 +36,7 @@ import net.osmand.plus.inapp.util.BillingManager.BillingUpdatesListener; import net.osmand.plus.liveupdates.CountrySelectionFragment; import net.osmand.plus.liveupdates.CountrySelectionFragment.CountryItem; import net.osmand.plus.settings.backend.OsmandSettings; -import net.osmand.plus.settings.backend.OsmandSettings.OsmandPreference; +import net.osmand.plus.settings.backend.OsmandSettings.CommonPreference; import net.osmand.util.Algorithms; import org.json.JSONArray; @@ -60,12 +61,10 @@ public class InAppPurchaseHelper { private static final String TAG = InAppPurchaseHelper.class.getSimpleName(); private boolean mDebugLog = false; - public static final long SUBSCRIPTION_HOLDING_TIME_MSEC = 1000 * 60 * 60 * 24 * 3; // 3 days - private InAppPurchases purchases; private long lastValidationCheckTime; private boolean inventoryRequested; - private final Map subscriptionStateMap = new HashMap<>(); + private Map subscriptionStateMap = new HashMap<>(); private static final long PURCHASE_VALIDATION_PERIOD_MSEC = 1000 * 60 * 60 * 24; // daily // (arbitrary) request code for the purchase flow @@ -121,32 +120,6 @@ public class InAppPurchaseHelper { PURCHASE_DEPTH_CONTOURS } - public enum SubscriptionState { - UNDEFINED("undefined"), - ACTIVE("active"), - CANCELLED("cancelled"), - IN_GRACE_PERIOD("in_grace_period"), - ON_HOLD("on_hold"), - PAUSED("paused"), - EXPIRED("expired"); - - private final String name; - - SubscriptionState(@NonNull String name) { - this.name = name; - } - - @NonNull - public static SubscriptionState getByName(@NonNull String name) { - for (SubscriptionState state : SubscriptionState.values()) { - if (state.name.equals(name)) { - return state; - } - } - return UNDEFINED; - } - } - public interface InAppRunnable { // return true if done and false if async task started boolean run(InAppPurchaseHelper helper); @@ -222,16 +195,6 @@ public class InAppPurchaseHelper { return false; } - public List getSubscriptionsByState(@NonNull SubscriptionState state) { - List res = new ArrayList<>(); - for (Entry entry : subscriptionStateMap.entrySet()) { - if (entry.getValue() == state) { - res.add(entry.getKey()); - } - } - return res; - } - private BillingManager getBillingManager() { return billingManager; } @@ -490,6 +453,15 @@ public class InAppPurchaseHelper { } } } + for (Entry entry : subscriptionStateMap.entrySet()) { + SubscriptionState state = entry.getValue(); + if (state == SubscriptionState.PAUSED || state == SubscriptionState.ON_HOLD) { + String sku = entry.getKey(); + if (!result.contains(sku)) { + result.add(sku); + } + } + } return result; } @@ -594,26 +566,17 @@ public class InAppPurchaseHelper { } } } - OsmandPreference subscriptionCancelledTime = ctx.getSettings().LIVE_UPDATES_PURCHASE_CANCELLED_TIME; if (!subscribedToLiveUpdates && ctx.getSettings().LIVE_UPDATES_PURCHASED.get()) { - if (subscriptionCancelledTime.get() == 0) { - subscriptionCancelledTime.set(System.currentTimeMillis()); - ctx.getSettings().LIVE_UPDATES_PURCHASE_CANCELLED_FIRST_DLG_SHOWN.set(false); - ctx.getSettings().LIVE_UPDATES_PURCHASE_CANCELLED_SECOND_DLG_SHOWN.set(false); - } else if (System.currentTimeMillis() - subscriptionCancelledTime.get() > SUBSCRIPTION_HOLDING_TIME_MSEC) { - ctx.getSettings().LIVE_UPDATES_PURCHASED.set(false); - if (!isDepthContoursPurchased(ctx)) { - ctx.getSettings().getCustomRenderBooleanProperty("depthContours").set(false); - } + ctx.getSettings().LIVE_UPDATES_PURCHASED.set(false); + if (!isDepthContoursPurchased(ctx)) { + ctx.getSettings().getCustomRenderBooleanProperty("depthContours").set(false); } } else if (subscribedToLiveUpdates) { - subscriptionCancelledTime.set(0L); ctx.getSettings().LIVE_UPDATES_PURCHASED.set(true); } lastValidationCheckTime = System.currentTimeMillis(); - logDebug("User " + (subscribedToLiveUpdates ? "HAS" : "DOES NOT HAVE") - + " live updates purchased."); + logDebug("User " + (subscribedToLiveUpdates ? "HAS" : "DOES NOT HAVE") + " live updates purchased."); OsmandSettings settings = ctx.getSettings(); settings.INAPPS_READ.set(true); @@ -683,12 +646,24 @@ public class InAppPurchaseHelper { } } if (inAppPurchase instanceof InAppSubscription) { + InAppSubscription s = (InAppSubscription) inAppPurchase; + + SubscriptionState state = subscriptionStateMap.get(inAppPurchase.getSku()); + s.setState(state == null ? SubscriptionState.UNDEFINED : state); + CommonPreference statePref = ctx.getSettings().registerStringPreference( + s.getSku() + "_state", SubscriptionState.UNDEFINED.getStateStr()).makeGlobal(); + s.setPrevState(SubscriptionState.getByStateStr(statePref.get())); + statePref.set(s.getState().getStateStr()); + if (s.getState().isGone() && s.hasStateChanged()) { + ctx.getSettings().LIVE_UPDATES_EXPIRED_FIRST_DLG_SHOWN_TIME.set(0L); + ctx.getSettings().LIVE_UPDATES_EXPIRED_SECOND_DLG_SHOWN_TIME.set(0L); + } + String introductoryPrice = skuDetails.getIntroductoryPrice(); String introductoryPricePeriod = skuDetails.getIntroductoryPricePeriod(); String introductoryPriceCycles = skuDetails.getIntroductoryPriceCycles(); long introductoryPriceAmountMicros = skuDetails.getIntroductoryPriceAmountMicros(); if (!Algorithms.isEmpty(introductoryPrice)) { - InAppSubscription s = (InAppSubscription) inAppPurchase; try { s.setIntroductoryInfo(new InAppSubscriptionIntroductoryInfo(s, introductoryPrice, introductoryPriceAmountMicros, introductoryPricePeriod, introductoryPriceCycles)); @@ -877,6 +852,7 @@ public class InAppPurchaseHelper { } if (subscriptionsStateJson != null) { inventoryRequested = true; + Map subscriptionStateMap = new HashMap<>(); try { JSONArray subArrJson = new JSONArray(subscriptionsStateJson); for (int i = 0; i < subArrJson.length(); i++) { @@ -884,12 +860,13 @@ public class InAppPurchaseHelper { String sku = subObj.getString("sku"); String state = subObj.getString("state"); if (!Algorithms.isEmpty(sku) && !Algorithms.isEmpty(state)) { - subscriptionStateMap.put(sku, SubscriptionState.getByName(state)); + subscriptionStateMap.put(sku, SubscriptionState.getByStateStr(state)); } } } catch (JSONException e) { logError("Json parsing error", e); } + InAppPurchaseHelper.this.subscriptionStateMap = subscriptionStateMap; } exec(InAppPurchaseTaskType.REQUEST_INVENTORY, new InAppRunnable() { @Override @@ -948,9 +925,8 @@ public class InAppPurchaseHelper { ctx.getSettings().LIVE_UPDATES_PURCHASED.set(true); ctx.getSettings().getCustomRenderBooleanProperty("depthContours").set(true); - ctx.getSettings().LIVE_UPDATES_PURCHASE_CANCELLED_TIME.set(0L); - ctx.getSettings().LIVE_UPDATES_PURCHASE_CANCELLED_FIRST_DLG_SHOWN.set(false); - ctx.getSettings().LIVE_UPDATES_PURCHASE_CANCELLED_SECOND_DLG_SHOWN.set(false); + ctx.getSettings().LIVE_UPDATES_EXPIRED_FIRST_DLG_SHOWN_TIME.set(0L); + ctx.getSettings().LIVE_UPDATES_EXPIRED_SECOND_DLG_SHOWN_TIME.set(0L); notifyDismissProgress(InAppPurchaseTaskType.PURCHASE_LIVE_UPDATES); notifyItemPurchased(sku, active);