(Y>jyB(
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
z
zkEwB7@@suRQ=vMoDbt5~5%_V-Iam=4tbyu@7^2O&gnaPdmrYNNi9Y717?82Z$aqEj
zw_nnonq`3ITt-wB@gQZ-uBQ6XhrWzG7BQ0(`g)Aw=hBCz3ArxS(2u4oxk!qMKBsD4
zizbU%#-p#_!P#e3fu2glxrmtSjyLltfh*L(!$?aixB<2|^1C89v
zkaQh-FwxO4IhR6g^z&5@zSi5&MaiA06Y~_+A&b~%410S9Lwg=NL_-#F$>CUcGXs2o
zY-_FbD_`ne$RLhc7z!)626~u;N}zfeWekbA@WCN&Vg~w`b{e31c;w|x@&tui1zoy?
zgLn({Fr~yq(JKu?B#7)Eas|`84N@vTG7`npnptI$o_n;55xz=_
zV3Ub@#q|{Uqn(i7tKts$rCLb^H0N?B+V*z${ln1~!10*7A5{u#i`~&W9%T+u80A^XF
z>7y<8vqMt;k{wH6|E9120Q|F`hHlALDH4D`z&2IVfiv3!aLy!!Y0Lv~gh2sqGle7<
zg96HK$6$fM3|`?M3=(LYlr0PrD1XFYus|Xh`M>&K{qGEYc?4Ku2AeVbWCYAuI;WKY
z#bD(B>VH2{Cz_xCr~X&}tN&FcE;dZzyRmY^@&mVJ^C^0r<*6Gh|NYo2s{hshz9-fj
zue1D<`d|I8{#XASai9x@Vy*Jg$#JvAFK}E3ZJlh13eo{AB9t*gPGK0KNf)5;gA9zI
zg4h723@Fk8GV6cD(~c1A$&FA?R&yo%S4BR7DFTYv0GYLAjQOXoWFpw&WHmQ}?&0lE
z4^b+eltuWlD*NZNA_s^BI6ZYZFtwC&wlRs$(bOljoCc$gD&M0C{l1sb-2JaRtQICNI=&K^
Date: Tue, 24 Apr 2018 12:35:59 +0300
Subject: [PATCH 27/38] added recyclerview and improve travel cards
---
OsmAnd/res/layout/fragment_explore_tab.xml | 19 +++-----
.../res/layout/wikivoyage_open_beta_card.xml | 14 +++++-
.../layout/wikivoyage_start_editing_card.xml | 20 +++++++--
OsmAnd/res/values/colors.xml | 1 +
.../explore/ExploreTabFragment.java | 12 ++---
.../explore/travelcards/BaseTravelCard.java | 39 ++++++++--------
.../travelcards/OpenBetaTravelCard.java | 36 +++++----------
.../travelcards/StartEditingTravelCard.java | 44 +++++++------------
8 files changed, 88 insertions(+), 97 deletions(-)
diff --git a/OsmAnd/res/layout/fragment_explore_tab.xml b/OsmAnd/res/layout/fragment_explore_tab.xml
index 34316e6ef0..8a663f6d42 100644
--- a/OsmAnd/res/layout/fragment_explore_tab.xml
+++ b/OsmAnd/res/layout/fragment_explore_tab.xml
@@ -6,20 +6,11 @@
android:gravity="center"
android:orientation="vertical">
-
-
-
-
-
-
-
+ android:layout_height="match_parent"
+ android:clipToPadding="false"
+ android:paddingBottom="@dimen/map_markers_recycler_view_padding_bottom"/>
diff --git a/OsmAnd/res/layout/wikivoyage_open_beta_card.xml b/OsmAnd/res/layout/wikivoyage_open_beta_card.xml
index 19812ccf03..93b709dd03 100644
--- a/OsmAnd/res/layout/wikivoyage_open_beta_card.xml
+++ b/OsmAnd/res/layout/wikivoyage_open_beta_card.xml
@@ -7,7 +7,7 @@
android:layout_gravity="center_horizontal"
android:layout_marginBottom="@dimen/list_content_padding"
android:layout_marginTop="@dimen/list_content_padding"
- android:background="@drawable/wikivoyage_card_bg">
+ android:background="@drawable/travel_card_bg">
-
+
diff --git a/OsmAnd/res/layout/wikivoyage_start_editing_card.xml b/OsmAnd/res/layout/wikivoyage_start_editing_card.xml
index b770ca7272..c2b9a4b6c0 100644
--- a/OsmAnd/res/layout/wikivoyage_start_editing_card.xml
+++ b/OsmAnd/res/layout/wikivoyage_start_editing_card.xml
@@ -1,12 +1,13 @@
+ android:background="@drawable/travel_card_bg">
+ android:layout_height="wrap_content"
+ android:background="@color/wikivoyage_start_editing_background">
@@ -58,7 +60,17 @@
android:layout_height="1dp"
android:background="?attr/wikivoyage_card_divider_color" />
-
+
diff --git a/OsmAnd/res/values/colors.xml b/OsmAnd/res/values/colors.xml
index eaa0b79144..f5b86303db 100644
--- a/OsmAnd/res/values/colors.xml
+++ b/OsmAnd/res/values/colors.xml
@@ -428,5 +428,6 @@
#212121
#cccccc
#727272
+ #339966
\ No newline at end of file
diff --git a/OsmAnd/src/net/osmand/plus/wikivoyage/explore/ExploreTabFragment.java b/OsmAnd/src/net/osmand/plus/wikivoyage/explore/ExploreTabFragment.java
index 62eafee287..7bf579e6fc 100644
--- a/OsmAnd/src/net/osmand/plus/wikivoyage/explore/ExploreTabFragment.java
+++ b/OsmAnd/src/net/osmand/plus/wikivoyage/explore/ExploreTabFragment.java
@@ -3,6 +3,8 @@ package net.osmand.plus.wikivoyage.explore;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
+import android.support.v7.widget.LinearLayoutManager;
+import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -27,18 +29,16 @@ public class ExploreTabFragment extends BaseOsmAndFragment {
final View mainView = inflater.inflate(R.layout.fragment_explore_tab, container, false);
- LinearLayout linearLayout = (LinearLayout) mainView.findViewById(R.id.cards_list);
+
ArrayList items = new ArrayList<>();
- BaseTravelCard openBetaTravelCard = new OpenBetaTravelCard(app, getFragmentManager(), nightMode);
+ BaseTravelCard openBetaTravelCard = new OpenBetaTravelCard(app, nightMode, getFragmentManager());
BaseTravelCard startEditingTravelCard = new StartEditingTravelCard(app, nightMode);
items.add(openBetaTravelCard);
items.add(startEditingTravelCard);
- for (BaseTravelCard item : items) {
- item.inflate(app, linearLayout, nightMode);
- }
-
+ final RecyclerView rv = (RecyclerView) mainView.findViewById(R.id.recycler_view);
+ rv.setLayoutManager(new LinearLayoutManager(getContext()));
return mainView;
}
}
diff --git a/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/BaseTravelCard.java b/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/BaseTravelCard.java
index 40d0001abf..5acc09860d 100644
--- a/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/BaseTravelCard.java
+++ b/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/BaseTravelCard.java
@@ -4,44 +4,45 @@ import android.graphics.drawable.Drawable;
import android.support.annotation.ColorInt;
import android.support.annotation.ColorRes;
import android.support.annotation.DrawableRes;
+import android.support.annotation.NonNull;
import android.support.v4.content.ContextCompat;
-import android.view.ViewGroup;
+import android.support.v7.widget.RecyclerView;
import net.osmand.plus.OsmandApplication;
+import net.osmand.plus.R;
public abstract class BaseTravelCard {
- protected static final int INVALID_POSITION = -1;
-
protected OsmandApplication app;
-
- protected int position = INVALID_POSITION;
protected boolean nightMode;
- public abstract void inflate(OsmandApplication app, ViewGroup container, boolean nightMode);
+ public BaseTravelCard(OsmandApplication app, boolean nightMode) {
+ this.app = app;
+ this.nightMode = nightMode;
+ }
+
+ public abstract void bindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder);
+
+ public abstract int getCardType();
@ColorInt
protected int getResolvedColor(@ColorRes int colorId) {
return ContextCompat.getColor(app, colorId);
}
- protected Drawable getIcon(@DrawableRes int drawableRes, @ColorRes int color) {
- return app.getIconsCache().getIcon(drawableRes, color);
+ protected Drawable getContentIcon(@DrawableRes int icon) {
+ return getColoredIcon(icon, R.color.icon_color);
}
- protected Drawable getIcon(@DrawableRes int drawableRes) {
- return app.getIconsCache().getIcon(drawableRes);
+ protected Drawable getActiveIcon(@DrawableRes int icon) {
+ return getColoredIcon(icon, R.color.wikivoyage_active_light, R.color.wikivoyage_active_dark);
}
- protected Drawable getIcon(int iconId, int colorLightId, int colorDarkId) {
- return app.getIconsCache().getIcon(iconId, nightMode ? colorLightId : colorDarkId);
+ protected Drawable getColoredIcon(@DrawableRes int icon, @ColorRes int colorLight, @ColorRes int colorDark) {
+ return getColoredIcon(icon, nightMode ? colorDark : colorLight);
}
- protected void onLeftButtonClickAction() {
-
+ protected Drawable getColoredIcon(@DrawableRes int icon, @ColorRes int color) {
+ return app.getIconsCache().getIcon(icon, color);
}
-
- protected void onRightButtonClickAction() {
-
- }
-}
+}
\ No newline at end of file
diff --git a/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/OpenBetaTravelCard.java b/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/OpenBetaTravelCard.java
index 2dce41f604..86aa1a1247 100644
--- a/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/OpenBetaTravelCard.java
+++ b/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/OpenBetaTravelCard.java
@@ -1,10 +1,11 @@
package net.osmand.plus.wikivoyage.explore.travelcards;
+import android.support.annotation.NonNull;
import android.support.v4.app.FragmentManager;
+import android.support.v7.widget.RecyclerView;
import android.view.ContextThemeWrapper;
import android.view.LayoutInflater;
import android.view.View;
-import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
@@ -14,47 +15,34 @@ import net.osmand.plus.dialogs.ChoosePlanDialogFragment;
public class OpenBetaTravelCard extends BaseTravelCard {
- private FragmentManager fm;
+ private FragmentManager fragmentManager;
- public OpenBetaTravelCard(OsmandApplication app, FragmentManager fm, boolean nightMode) {
- this.app = app;
- this.fm = fm;
- this.nightMode = nightMode;
+ public OpenBetaTravelCard(OsmandApplication app, boolean nightMode, FragmentManager fragmentManager) {
+ super(app, nightMode);
+ this.fragmentManager = fragmentManager;
}
- public OpenBetaTravelCard(OsmandApplication app, FragmentManager fm, int position, boolean nightMode) {
- this.app = app;
- this.fm = fm;
- this.position = position;
- this.nightMode = nightMode;
- }
@Override
- public void inflate(OsmandApplication app, ViewGroup container, boolean nightMode) {
+ public void bindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder) {
final int themeRes = nightMode ? R.style.OsmandDarkTheme : R.style.OsmandLightTheme;
View view = LayoutInflater.from(new ContextThemeWrapper(app, themeRes))
- .inflate(R.layout.wikivoyage_open_beta_card, container, false);
+ .inflate(R.layout.wikivoyage_open_beta_card, null, false);
ImageView imageView = (ImageView) view.findViewById(R.id.background_image);
- imageView.setImageDrawable(getIcon(R.drawable.img_help_wikivoyage_articles));
+ imageView.setImageResource(R.drawable.img_help_wikivoyage_articles);
((TextView) view.findViewById(R.id.title)).setText(R.string.welcome_to_open_beta);
((TextView) view.findViewById(R.id.description)).setText(R.string.welcome_to_open_beta_description);
((TextView) view.findViewById(R.id.left_bottom_button_text)).setText(R.string.get_unlimited_access);
view.findViewById(R.id.left_bottom_button).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
- onLeftButtonClickAction();
+ ChoosePlanDialogFragment.showFreeVersionInstance(fragmentManager);
}
});
-
- if (position != INVALID_POSITION) {
- container.addView(view, position);
- } else {
- container.addView(view);
- }
}
@Override
- protected void onLeftButtonClickAction() {
- ChoosePlanDialogFragment.showFreeVersionInstance(fm);
+ public int getCardType() {
+ return 0;
}
}
diff --git a/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/StartEditingTravelCard.java b/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/StartEditingTravelCard.java
index 5263a1ebde..44082c160b 100644
--- a/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/StartEditingTravelCard.java
+++ b/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/StartEditingTravelCard.java
@@ -1,12 +1,13 @@
package net.osmand.plus.wikivoyage.explore.travelcards;
import android.net.Uri;
+import android.support.annotation.NonNull;
import android.support.customtabs.CustomTabsIntent;
import android.support.v4.content.ContextCompat;
+import android.support.v7.widget.RecyclerView;
import android.view.ContextThemeWrapper;
import android.view.LayoutInflater;
import android.view.View;
-import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
@@ -16,46 +17,33 @@ import net.osmand.plus.R;
public class StartEditingTravelCard extends BaseTravelCard {
public StartEditingTravelCard(OsmandApplication app, boolean nightMode) {
- this.app = app;
- this.nightMode = nightMode;
- }
-
- public StartEditingTravelCard(OsmandApplication app, int position, boolean nightMode) {
- this.app = app;
- this.position = position;
- this.nightMode = nightMode;
+ super(app, nightMode);
}
@Override
- public void inflate(OsmandApplication app, ViewGroup container, boolean nightMode) {
+ public void bindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder) {
final int themeRes = nightMode ? R.style.OsmandDarkTheme : R.style.OsmandLightTheme;
View view = LayoutInflater.from(new ContextThemeWrapper(app, themeRes))
- .inflate(R.layout.wikivoyage_start_editing_card, container, false);
+ .inflate(R.layout.wikivoyage_open_beta_card, null, false);
ImageView imageView = (ImageView) view.findViewById(R.id.background_image);
- imageView.setImageDrawable(getIcon(R.drawable.img_help_wikivoyage_contribute));
- ((TextView) view.findViewById(R.id.title)).setText(R.string.start_editing_card_image_text);
- ((TextView) view.findViewById(R.id.description)).setText(R.string.start_editing_card_description);
- ((TextView) view.findViewById(R.id.left_bottom_button_text)).setText(R.string.start_editing);
+ imageView.setImageResource(R.drawable.img_help_wikivoyage_articles);
+ ((TextView) view.findViewById(R.id.title)).setText(R.string.welcome_to_open_beta);
+ ((TextView) view.findViewById(R.id.description)).setText(R.string.welcome_to_open_beta_description);
+ ((TextView) view.findViewById(R.id.left_bottom_button_text)).setText(R.string.get_unlimited_access);
view.findViewById(R.id.left_bottom_button).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
- onLeftButtonClickAction();
+ CustomTabsIntent customTabsIntent = new CustomTabsIntent.Builder()
+ .setToolbarColor(ContextCompat.getColor(app, nightMode ? R.color.actionbar_dark_color : R.color.actionbar_light_color))
+ .build();
+ String text = "https://" + app.getLanguage().toLowerCase() + ".m.wikivoyage.org";
+ customTabsIntent.launchUrl(app, Uri.parse(text));
}
});
-
- if (position != INVALID_POSITION) {
- container.addView(view, position);
- } else {
- container.addView(view);
- }
}
@Override
- protected void onLeftButtonClickAction() {
- CustomTabsIntent customTabsIntent = new CustomTabsIntent.Builder()
- .setToolbarColor(ContextCompat.getColor(app, nightMode ? R.color.actionbar_dark_color : R.color.actionbar_light_color))
- .build();
- String text = "https://" + app.getLanguage().toLowerCase() + ".m.wikivoyage.org";
- customTabsIntent.launchUrl(app, Uri.parse(text));
+ public int getCardType() {
+ return 1;
}
}
From cf0f9b32744f21bb5f7244d712af2e517df6b652 Mon Sep 17 00:00:00 2001
From: Alex Sytnyk
Date: Tue, 24 Apr 2018 13:13:59 +0300
Subject: [PATCH 28/38] Add missing elements to travel_download_update_card
---
.../res/layout/travel_download_update_card.xml | 16 ++++++++++++++--
1 file changed, 14 insertions(+), 2 deletions(-)
diff --git a/OsmAnd/res/layout/travel_download_update_card.xml b/OsmAnd/res/layout/travel_download_update_card.xml
index 3ef484826b..d2958d5ba6 100644
--- a/OsmAnd/res/layout/travel_download_update_card.xml
+++ b/OsmAnd/res/layout/travel_download_update_card.xml
@@ -25,7 +25,7 @@
android:layout_height="wrap_content"
android:layout_marginEnd="@dimen/content_padding"
android:layout_marginRight="@dimen/content_padding"
- android:layout_marginTop="2dp"
+ android:layout_marginTop="4dp"
android:layout_weight="1"
android:ellipsize="end"
android:maxLines="1"
@@ -56,11 +56,12 @@
@@ -103,6 +104,16 @@
osmand:typeface="@string/font_roboto_regular"
tools:text="255 Mb • Update 11 April"/>
+
+
@@ -139,6 +150,7 @@
From 6c222d94b60939f7d2b173c824f93aa28af18617 Mon Sep 17 00:00:00 2001
From: Chumva
Date: Tue, 24 Apr 2018 13:47:26 +0300
Subject: [PATCH 29/38] fix text on background image
---
.../layout/wikivoyage_start_editing_card.xml | 25 ++++++++++---------
1 file changed, 13 insertions(+), 12 deletions(-)
diff --git a/OsmAnd/res/layout/wikivoyage_start_editing_card.xml b/OsmAnd/res/layout/wikivoyage_start_editing_card.xml
index c2b9a4b6c0..da3d54da58 100644
--- a/OsmAnd/res/layout/wikivoyage_start_editing_card.xml
+++ b/OsmAnd/res/layout/wikivoyage_start_editing_card.xml
@@ -15,21 +15,15 @@
android:layout_gravity="center_horizontal"
android:orientation="vertical">
-
-
-
+ android:background="@color/wikivoyage_start_editing_background"
+ android:orientation="horizontal">
-
+
+
+
Date: Tue, 24 Apr 2018 13:49:58 +0300
Subject: [PATCH 30/38] rename color for image background
---
OsmAnd/res/layout/wikivoyage_start_editing_card.xml | 3 ++-
OsmAnd/res/values/colors.xml | 2 +-
2 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/OsmAnd/res/layout/wikivoyage_start_editing_card.xml b/OsmAnd/res/layout/wikivoyage_start_editing_card.xml
index da3d54da58..3cda6efb73 100644
--- a/OsmAnd/res/layout/wikivoyage_start_editing_card.xml
+++ b/OsmAnd/res/layout/wikivoyage_start_editing_card.xml
@@ -18,7 +18,7 @@
#212121
#cccccc
#727272
- #339966
+ #339966
\ No newline at end of file
From ad514f2d2900fe90659ceac01d4fbffd3d13a52c Mon Sep 17 00:00:00 2001
From: Chumva
Date: Tue, 24 Apr 2018 14:08:05 +0300
Subject: [PATCH 31/38] add holders for cards
---
OsmAnd/res/layout/bottom_buttons.xml | 55 -------------------
.../res/layout/wikivoyage_open_beta_card.xml | 2 +-
.../layout/wikivoyage_start_editing_card.xml | 2 +-
.../explore/ExploreTabFragment.java | 1 -
.../travelcards/OpenBetaTravelCard.java | 46 ++++++++++------
.../travelcards/StartEditingTravelCard.java | 53 +++++++++++-------
6 files changed, 64 insertions(+), 95 deletions(-)
delete mode 100644 OsmAnd/res/layout/bottom_buttons.xml
diff --git a/OsmAnd/res/layout/bottom_buttons.xml b/OsmAnd/res/layout/bottom_buttons.xml
deleted file mode 100644
index ad2e474496..0000000000
--- a/OsmAnd/res/layout/bottom_buttons.xml
+++ /dev/null
@@ -1,55 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/OsmAnd/res/layout/wikivoyage_open_beta_card.xml b/OsmAnd/res/layout/wikivoyage_open_beta_card.xml
index 93b709dd03..5ba3eefd55 100644
--- a/OsmAnd/res/layout/wikivoyage_open_beta_card.xml
+++ b/OsmAnd/res/layout/wikivoyage_open_beta_card.xml
@@ -52,7 +52,7 @@
android:background="?attr/wikivoyage_card_divider_color" />
items = new ArrayList<>();
BaseTravelCard openBetaTravelCard = new OpenBetaTravelCard(app, nightMode, getFragmentManager());
diff --git a/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/OpenBetaTravelCard.java b/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/OpenBetaTravelCard.java
index 86aa1a1247..44ac5ba3f3 100644
--- a/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/OpenBetaTravelCard.java
+++ b/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/OpenBetaTravelCard.java
@@ -3,8 +3,6 @@ package net.osmand.plus.wikivoyage.explore.travelcards;
import android.support.annotation.NonNull;
import android.support.v4.app.FragmentManager;
import android.support.v7.widget.RecyclerView;
-import android.view.ContextThemeWrapper;
-import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
@@ -22,23 +20,37 @@ public class OpenBetaTravelCard extends BaseTravelCard {
this.fragmentManager = fragmentManager;
}
-
@Override
public void bindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder) {
- final int themeRes = nightMode ? R.style.OsmandDarkTheme : R.style.OsmandLightTheme;
- View view = LayoutInflater.from(new ContextThemeWrapper(app, themeRes))
- .inflate(R.layout.wikivoyage_open_beta_card, null, false);
- ImageView imageView = (ImageView) view.findViewById(R.id.background_image);
- imageView.setImageResource(R.drawable.img_help_wikivoyage_articles);
- ((TextView) view.findViewById(R.id.title)).setText(R.string.welcome_to_open_beta);
- ((TextView) view.findViewById(R.id.description)).setText(R.string.welcome_to_open_beta_description);
- ((TextView) view.findViewById(R.id.left_bottom_button_text)).setText(R.string.get_unlimited_access);
- view.findViewById(R.id.left_bottom_button).setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- ChoosePlanDialogFragment.showFreeVersionInstance(fragmentManager);
- }
- });
+ if (viewHolder instanceof OpenBetaTravelVH) {
+ final OpenBetaTravelVH holder = (OpenBetaTravelVH) viewHolder;
+ holder.title.setText(R.string.welcome_to_open_beta);
+ holder.description.setText(R.string.welcome_to_open_beta_description);
+ holder.backgroundImage.setImageResource(R.drawable.img_help_wikivoyage_articles);
+ holder.button.setText(R.string.get_unlimited_access);
+ holder.button.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ ChoosePlanDialogFragment.showFreeVersionInstance(fragmentManager);
+ }
+ });
+ }
+ }
+
+ class OpenBetaTravelVH extends RecyclerView.ViewHolder {
+
+ final TextView title;
+ final TextView description;
+ final TextView button;
+ final ImageView backgroundImage;
+
+ OpenBetaTravelVH(final View itemView) {
+ super(itemView);
+ title = (TextView) itemView.findViewById(R.id.title);
+ description = (TextView) itemView.findViewById(R.id.description);
+ button = (TextView) itemView.findViewById(R.id.bottom_button_text);
+ backgroundImage = (ImageView) itemView.findViewById(R.id.background_image);
+ }
}
@Override
diff --git a/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/StartEditingTravelCard.java b/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/StartEditingTravelCard.java
index 44082c160b..c8ef49aa16 100644
--- a/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/StartEditingTravelCard.java
+++ b/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/StartEditingTravelCard.java
@@ -5,8 +5,6 @@ import android.support.annotation.NonNull;
import android.support.customtabs.CustomTabsIntent;
import android.support.v4.content.ContextCompat;
import android.support.v7.widget.RecyclerView;
-import android.view.ContextThemeWrapper;
-import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
@@ -22,24 +20,39 @@ public class StartEditingTravelCard extends BaseTravelCard {
@Override
public void bindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder) {
- final int themeRes = nightMode ? R.style.OsmandDarkTheme : R.style.OsmandLightTheme;
- View view = LayoutInflater.from(new ContextThemeWrapper(app, themeRes))
- .inflate(R.layout.wikivoyage_open_beta_card, null, false);
- ImageView imageView = (ImageView) view.findViewById(R.id.background_image);
- imageView.setImageResource(R.drawable.img_help_wikivoyage_articles);
- ((TextView) view.findViewById(R.id.title)).setText(R.string.welcome_to_open_beta);
- ((TextView) view.findViewById(R.id.description)).setText(R.string.welcome_to_open_beta_description);
- ((TextView) view.findViewById(R.id.left_bottom_button_text)).setText(R.string.get_unlimited_access);
- view.findViewById(R.id.left_bottom_button).setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- CustomTabsIntent customTabsIntent = new CustomTabsIntent.Builder()
- .setToolbarColor(ContextCompat.getColor(app, nightMode ? R.color.actionbar_dark_color : R.color.actionbar_light_color))
- .build();
- String text = "https://" + app.getLanguage().toLowerCase() + ".m.wikivoyage.org";
- customTabsIntent.launchUrl(app, Uri.parse(text));
- }
- });
+ if (viewHolder instanceof OpenBetaTravelVH) {
+ final OpenBetaTravelVH holder = (OpenBetaTravelVH) viewHolder;
+ holder.title.setText(R.string.start_editing_card_image_text);
+ holder.description.setText(R.string.start_editing_card_description);
+ holder.backgroundImage.setImageResource(R.drawable.img_help_wikivoyage_contribute);
+ holder.button.setText(R.string.start_editing);
+ holder.button.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ CustomTabsIntent customTabsIntent = new CustomTabsIntent.Builder()
+ .setToolbarColor(ContextCompat.getColor(app, nightMode ? R.color.actionbar_dark_color : R.color.actionbar_light_color))
+ .build();
+ String text = "https://" + app.getLanguage().toLowerCase() + ".m.wikivoyage.org";
+ customTabsIntent.launchUrl(app, Uri.parse(text));
+ }
+ });
+ }
+ }
+
+ class OpenBetaTravelVH extends RecyclerView.ViewHolder {
+
+ final TextView title;
+ final TextView description;
+ final TextView button;
+ final ImageView backgroundImage;
+
+ OpenBetaTravelVH(final View itemView) {
+ super(itemView);
+ title = (TextView) itemView.findViewById(R.id.title);
+ description = (TextView) itemView.findViewById(R.id.description);
+ button = (TextView) itemView.findViewById(R.id.bottom_button_text);
+ backgroundImage = (ImageView) itemView.findViewById(R.id.background_image);
+ }
}
@Override
From 1fbebc10f3fe52d87cccf16c5ade160edd0d2df5 Mon Sep 17 00:00:00 2001
From: Chumva
Date: Tue, 24 Apr 2018 14:09:45 +0300
Subject: [PATCH 32/38] remove unused xml bg file
---
OsmAnd/res/drawable/wikivoyage_card_bg.xml | 12 ------------
1 file changed, 12 deletions(-)
delete mode 100644 OsmAnd/res/drawable/wikivoyage_card_bg.xml
diff --git a/OsmAnd/res/drawable/wikivoyage_card_bg.xml b/OsmAnd/res/drawable/wikivoyage_card_bg.xml
deleted file mode 100644
index 5691ef7ce2..0000000000
--- a/OsmAnd/res/drawable/wikivoyage_card_bg.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
- -
-
-
- -
-
-
-
-
-
-
\ No newline at end of file
From befed088979d8f8914fc0fd5ab5a369939d6376c Mon Sep 17 00:00:00 2001
From: Chumva
Date: Tue, 24 Apr 2018 14:18:23 +0300
Subject: [PATCH 33/38] change holder in StartEditingTravelCard
---
.../explore/travelcards/StartEditingTravelCard.java | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/StartEditingTravelCard.java b/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/StartEditingTravelCard.java
index c8ef49aa16..cce59cd217 100644
--- a/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/StartEditingTravelCard.java
+++ b/OsmAnd/src/net/osmand/plus/wikivoyage/explore/travelcards/StartEditingTravelCard.java
@@ -20,8 +20,8 @@ public class StartEditingTravelCard extends BaseTravelCard {
@Override
public void bindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder) {
- if (viewHolder instanceof OpenBetaTravelVH) {
- final OpenBetaTravelVH holder = (OpenBetaTravelVH) viewHolder;
+ if (viewHolder instanceof StartEditingTravelVH) {
+ final StartEditingTravelVH holder = (StartEditingTravelVH) viewHolder;
holder.title.setText(R.string.start_editing_card_image_text);
holder.description.setText(R.string.start_editing_card_description);
holder.backgroundImage.setImageResource(R.drawable.img_help_wikivoyage_contribute);
@@ -39,14 +39,14 @@ public class StartEditingTravelCard extends BaseTravelCard {
}
}
- class OpenBetaTravelVH extends RecyclerView.ViewHolder {
+ class StartEditingTravelVH extends RecyclerView.ViewHolder {
final TextView title;
final TextView description;
final TextView button;
final ImageView backgroundImage;
- OpenBetaTravelVH(final View itemView) {
+ StartEditingTravelVH(final View itemView) {
super(itemView);
title = (TextView) itemView.findViewById(R.id.title);
description = (TextView) itemView.findViewById(R.id.description);
From 1656154b7a74a0fa7011214c39602faae938ad09 Mon Sep 17 00:00:00 2001
From: Chumva
Date: Tue, 24 Apr 2018 14:37:00 +0300
Subject: [PATCH 34/38] refactored ExploreTabFragment
---
.../osmand/plus/wikivoyage/explore/ExploreTabFragment.java | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/OsmAnd/src/net/osmand/plus/wikivoyage/explore/ExploreTabFragment.java b/OsmAnd/src/net/osmand/plus/wikivoyage/explore/ExploreTabFragment.java
index 38f7f4af52..0a584c615a 100644
--- a/OsmAnd/src/net/osmand/plus/wikivoyage/explore/ExploreTabFragment.java
+++ b/OsmAnd/src/net/osmand/plus/wikivoyage/explore/ExploreTabFragment.java
@@ -31,8 +31,8 @@ public class ExploreTabFragment extends BaseOsmAndFragment {
ArrayList items = new ArrayList<>();
- BaseTravelCard openBetaTravelCard = new OpenBetaTravelCard(app, nightMode, getFragmentManager());
- BaseTravelCard startEditingTravelCard = new StartEditingTravelCard(app, nightMode);
+ OpenBetaTravelCard openBetaTravelCard = new OpenBetaTravelCard(app, nightMode, getFragmentManager());
+ StartEditingTravelCard startEditingTravelCard = new StartEditingTravelCard(app, nightMode);
items.add(openBetaTravelCard);
items.add(startEditingTravelCard);
From 9e916d50f1d92487f41705935d78825ae9df960b Mon Sep 17 00:00:00 2001
From: Dmitriy Prodchenko
Date: Tue, 24 Apr 2018 17:25:58 +0300
Subject: [PATCH 35/38] Change headline font weight, change line height, Open
on map and Wikipedia buttons padding
---
OsmAnd/assets/article_style.css | 30 +++++++++++++++---------------
1 file changed, 15 insertions(+), 15 deletions(-)
diff --git a/OsmAnd/assets/article_style.css b/OsmAnd/assets/article_style.css
index d2c1dc8b34..68e84add81 100755
--- a/OsmAnd/assets/article_style.css
+++ b/OsmAnd/assets/article_style.css
@@ -50,8 +50,8 @@ body {
h1 {
font-size: 2em;
color: #212121;
- font-family: serif;
- letter-spacing: 0.03em;
+ font-family: RobotoSlab-Regular;
+ letter-spacing: 0.02em;
word-wrap: break-word;
padding-top: 5%;
font-weight: normal;
@@ -59,14 +59,14 @@ h1 {
h2 {
font-size: 1.5em;
- color: #575757;
+ color: #454545;
font-family: RobotoSlab-Regular;
+ font-weight:100;
word-wrap: break-word;
- margin-top: 3%;
- padding-bottom: 3%;
- /* font-weight: bold; */
+ padding-top: 2%;
+ padding-bottom: 4%;
line-height: 1.6em;
- letter-spacing: 0.01em;
+ letter-spacing: 0.015em;
border-bottom: 1px solid #eaecf0;
width: 100%;
}
@@ -105,7 +105,7 @@ h3 {
font-family: sans-serif;
word-wrap: break-word;
font-weight: bold;
- margin-top: 3%;
+ margin-top: 5%;
margin-bottom: 3%;
line-height: 1.6em;
}
@@ -113,7 +113,7 @@ h3 {
p {
font-family: sans-serif;
font-size: 1.1em;
- line-height: 1.5em;
+ line-height: 1.6em;
}
ul {
@@ -162,8 +162,8 @@ pre {
.geo {
background-color: #fafafa;
border: 1px solid #e6e6e6;
- border-radius: 5px;
- padding: 3% 3% 3% 3%;
+ border-radius: 4px;
+ padding: 10px 10px 10px 10px;
color: #237bff;
font-size: 0.9em;
font-weight: bold;
@@ -178,8 +178,8 @@ pre {
}
td {
- display: inline-block;
- word-wrap: break-word;
+ display: inline-block;
+ word-wrap: break-word;
}
.thumb-tright, .thumbinner {
@@ -196,6 +196,6 @@ td {
}
.content {
- display: none;
- overflow: hidden;
+ display: none;
+ overflow: hidden;
}
From 78cf001d3230947007a4d42758d89c892eb5bb37 Mon Sep 17 00:00:00 2001
From: Alexey Kulish
Date: Tue, 24 Apr 2018 18:21:05 +0300
Subject: [PATCH 36/38] Fix choose plan UI. Refactored InAppHelper.
---
OsmAnd/res/layout/free_version_banner.xml | 232 +------
.../layout/purchase_dialog_card_button.xml | 8 +
.../res/layout/purchase_dialog_fragment.xml | 33 +-
OsmAnd/res/values/sizes.xml | 3 +-
OsmAnd/res/values/strings.xml | 2 +-
OsmAnd/res/values/styles.xml | 4 +
.../src/net/osmand/plus/AppInitializer.java | 2 +
.../net/osmand/plus/OsmandApplication.java | 9 +-
.../src/net/osmand/plus/OsmandSettings.java | 2 +
.../osmand/plus/activities/MapActivity.java | 50 +-
.../activities/OsmandActionBarActivity.java | 8 +-
.../OsmandInAppPurchaseActivity.java | 166 +++++
.../dialogs/ChoosePlanDialogFragment.java | 360 ++++++----
.../plus/download/DownloadActivity.java | 298 ++------
.../ui/DownloadResourceGroupFragment.java | 23 +-
.../ui/FreeVersionDialogFragment.java | 44 --
.../osmand/plus/helpers/DiscountHelper.java | 19 +-
...ppHelper.java => InAppPurchaseHelper.java} | 653 ++++++++----------
.../plus/liveupdates/LiveUpdatesFragment.java | 64 +-
.../plus/liveupdates/OsmLiveActivity.java | 38 +-
.../liveupdates/SubscriptionFragment.java | 73 +-
21 files changed, 963 insertions(+), 1128 deletions(-)
create mode 100644 OsmAnd/src/net/osmand/plus/activities/OsmandInAppPurchaseActivity.java
delete mode 100644 OsmAnd/src/net/osmand/plus/download/ui/FreeVersionDialogFragment.java
rename OsmAnd/src/net/osmand/plus/inapp/{InAppHelper.java => InAppPurchaseHelper.java} (55%)
diff --git a/OsmAnd/res/layout/free_version_banner.xml b/OsmAnd/res/layout/free_version_banner.xml
index b63fa910ef..e7aaf90465 100644
--- a/OsmAnd/res/layout/free_version_banner.xml
+++ b/OsmAnd/res/layout/free_version_banner.xml
@@ -1,10 +1,9 @@
-
+ android:orientation="vertical"
+ android:paddingLeft="@dimen/list_content_padding"
+ android:paddingRight="@dimen/list_content_padding">
-
-
-
-
-
-
-
+ android:padding="4dp">
-
-
-
-
-
-
-
+ android:layout_weight="1"
+ android:text="@string/free_version_title"/>
+
-
+ android:layout_margin="4dp"
+ tools:text="@string/free_version_message"/>
-
+
+
+ android:layout_height="match_parent"
+ android:max="10"
+ android:progressDrawable="@drawable/number_of_downloads_progress_bar_drawable"
+ android:saveEnabled="false"
+ tools:progress="6"/>
+ android:layout_height="match_parent"
+ android:orientation="horizontal"/>
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/OsmAnd/res/layout/purchase_dialog_card_button.xml b/OsmAnd/res/layout/purchase_dialog_card_button.xml
index 82efb29fd2..7e70c781ac 100644
--- a/OsmAnd/res/layout/purchase_dialog_card_button.xml
+++ b/OsmAnd/res/layout/purchase_dialog_card_button.xml
@@ -13,11 +13,19 @@
android:background="?attr/selectableItemBackground"
android:minHeight="@dimen/card_button_min_size"
android:orientation="vertical"
+ android:gravity="center"
android:paddingBottom="@dimen/list_header_padding"
android:paddingLeft="@dimen/list_content_padding"
android:paddingRight="@dimen/list_content_padding"
android:paddingTop="@dimen/list_header_padding">
+
+
+
+
-
-
-
-
diff --git a/OsmAnd/res/values/sizes.xml b/OsmAnd/res/values/sizes.xml
index 8e64ef25e5..a27a0f0ca0 100644
--- a/OsmAnd/res/values/sizes.xml
+++ b/OsmAnd/res/values/sizes.xml
@@ -7,7 +7,8 @@
28sp
64dp
48dp
- 52dp
+ 58dp
+ 32dp
36dp
6dp
diff --git a/OsmAnd/res/values/strings.xml b/OsmAnd/res/values/strings.xml
index 6de7ce50e6..abc6573c3d 100644
--- a/OsmAnd/res/values/strings.xml
+++ b/OsmAnd/res/values/strings.xml
@@ -23,7 +23,7 @@
Unlimited downloads
Wikipedia offline
- Contour lines + Sea depth
+ Contour lines & Hillshade maps
Unlock all OsmAnd features
Choose plan
diff --git a/OsmAnd/res/values/styles.xml b/OsmAnd/res/values/styles.xml
index 452ed64aae..066abeb850 100644
--- a/OsmAnd/res/values/styles.xml
+++ b/OsmAnd/res/values/styles.xml
@@ -575,6 +575,10 @@
- true
+
+
diff --git a/OsmAnd/src/net/osmand/plus/AppInitializer.java b/OsmAnd/src/net/osmand/plus/AppInitializer.java
index 2355e3c986..b844e88320 100644
--- a/OsmAnd/src/net/osmand/plus/AppInitializer.java
+++ b/OsmAnd/src/net/osmand/plus/AppInitializer.java
@@ -31,6 +31,7 @@ import net.osmand.plus.download.DownloadActivity;
import net.osmand.plus.download.ui.AbstractLoadLocalIndexTask;
import net.osmand.plus.helpers.AvoidSpecificRoads;
import net.osmand.plus.helpers.WaypointHelper;
+import net.osmand.plus.inapp.InAppPurchaseHelper;
import net.osmand.plus.liveupdates.LiveUpdatesHelper;
import net.osmand.plus.mapmarkers.MapMarkersDbHelper;
import net.osmand.plus.monitoring.LiveMonitoringHelper;
@@ -421,6 +422,7 @@ public class AppInitializer implements IProgress {
e.printStackTrace();
}
app.applyTheme(app);
+ app.inAppPurchaseHelper = startupInit(new InAppPurchaseHelper(app), InAppPurchaseHelper.class);
app.poiTypes = startupInit(MapPoiTypes.getDefaultNoInit(), MapPoiTypes.class);
app.routingHelper = startupInit(new RoutingHelper(app), RoutingHelper.class);
app.resourceManager = startupInit(new ResourceManager(app), ResourceManager.class);
diff --git a/OsmAnd/src/net/osmand/plus/OsmandApplication.java b/OsmAnd/src/net/osmand/plus/OsmandApplication.java
index 48b0755ec8..1bc966c65d 100644
--- a/OsmAnd/src/net/osmand/plus/OsmandApplication.java
+++ b/OsmAnd/src/net/osmand/plus/OsmandApplication.java
@@ -19,7 +19,6 @@ import android.support.multidex.MultiDex;
import android.support.multidex.MultiDexApplication;
import android.support.v7.app.AlertDialog;
import android.text.format.DateFormat;
-import android.util.Log;
import android.view.View;
import android.view.accessibility.AccessibilityManager;
import android.widget.ImageView;
@@ -46,7 +45,7 @@ import net.osmand.plus.dialogs.RateUsBottomSheetDialog;
import net.osmand.plus.download.DownloadIndexesThread;
import net.osmand.plus.helpers.AvoidSpecificRoads;
import net.osmand.plus.helpers.WaypointHelper;
-import net.osmand.plus.inapp.InAppHelper;
+import net.osmand.plus.inapp.InAppPurchaseHelper;
import net.osmand.plus.mapcontextmenu.other.RoutePreferencesMenu;
import net.osmand.plus.mapmarkers.MapMarkersDbHelper;
import net.osmand.plus.monitoring.LiveMonitoringHelper;
@@ -120,6 +119,7 @@ public class OsmandApplication extends MultiDexApplication {
GeocodingLookupService geocodingLookupService;
QuickSearchHelper searchUICore;
TravelDbHelper travelDbHelper;
+ InAppPurchaseHelper inAppPurchaseHelper;
RoutingConfiguration.Builder defaultRoutingConfig;
private Locale preferredLocale = null;
@@ -166,7 +166,6 @@ public class OsmandApplication extends MultiDexApplication {
// if(!osmandSettings.FOLLOW_THE_ROUTE.get()) {
// targetPointsHelper.clearPointToNavigate(false);
// }
- InAppHelper.initialize(this);
initExternalLibs();
startApplication();
System.out.println("Time to start application " + (System.currentTimeMillis() - timeToStart) + " ms. Should be less < 800 ms");
@@ -396,6 +395,10 @@ public class OsmandApplication extends MultiDexApplication {
return travelDbHelper;
}
+ public InAppPurchaseHelper getInAppPurchaseHelper() {
+ return inAppPurchaseHelper;
+ }
+
public CommandPlayer getPlayer() {
return player;
}
diff --git a/OsmAnd/src/net/osmand/plus/OsmandSettings.java b/OsmAnd/src/net/osmand/plus/OsmandSettings.java
index 38133f48fd..a55d451289 100644
--- a/OsmAnd/src/net/osmand/plus/OsmandSettings.java
+++ b/OsmAnd/src/net/osmand/plus/OsmandSettings.java
@@ -976,6 +976,8 @@ public class OsmandSettings {
public final OsmandPreference DISCOUNT_TOTAL_SHOW = new IntPreference("discount_total_show", 0).makeGlobal();
public final OsmandPreference DISCOUNT_SHOW_DATETIME_MS = new LongPreference("show_discount_datetime_ms", 0).makeGlobal();
+ public final OsmandPreference TRAVEL_ARTICLES_PURCHASED = new BooleanPreference("travel_articles_purchased", false).makeGlobal();
+
// this value string is synchronized with settings_pref.xml preference name
public final OsmandPreference USER_OSM_BUG_NAME =
new StringPreference("user_osm_bug_name", "NoName/OsmAnd").makeGlobal();
diff --git a/OsmAnd/src/net/osmand/plus/activities/MapActivity.java b/OsmAnd/src/net/osmand/plus/activities/MapActivity.java
index 31c0075fdc..f8483d0aa8 100644
--- a/OsmAnd/src/net/osmand/plus/activities/MapActivity.java
+++ b/OsmAnd/src/net/osmand/plus/activities/MapActivity.java
@@ -92,7 +92,8 @@ import net.osmand.plus.helpers.ExternalApiHelper;
import net.osmand.plus.helpers.ImportHelper;
import net.osmand.plus.helpers.ImportHelper.ImportGpxBottomSheetDialogFragment;
import net.osmand.plus.helpers.WakeLockHelper;
-import net.osmand.plus.inapp.InAppHelper;
+import net.osmand.plus.inapp.InAppPurchaseHelper;
+import net.osmand.plus.inapp.InAppPurchaseHelper.InAppPurchaseTaskType;
import net.osmand.plus.mapcontextmenu.AdditionalActionsBottomSheetDialogFragment;
import net.osmand.plus.mapcontextmenu.MapContextMenu;
import net.osmand.plus.mapcontextmenu.MapContextMenuFragment;
@@ -204,7 +205,7 @@ public class MapActivity extends OsmandActionBarActivity implements DownloadEven
private boolean permissionGranted;
private boolean mIsDestroyed = false;
- private InAppHelper inAppHelper;
+ private InAppPurchaseHelper inAppPurchaseHelper;
private Timer splashScreenTimer;
private ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
@@ -1214,8 +1215,8 @@ public class MapActivity extends OsmandActionBarActivity implements DownloadEven
if (atlasMapRendererView != null) {
atlasMapRendererView.handleOnDestroy();
}
- if (inAppHelper != null) {
- inAppHelper.stop();
+ if (inAppPurchaseHelper != null) {
+ inAppPurchaseHelper.stop();
}
mIsDestroyed = true;
}
@@ -1513,7 +1514,7 @@ public class MapActivity extends OsmandActionBarActivity implements DownloadEven
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
- if (inAppHelper != null && inAppHelper.onActivityResultHandled(requestCode, resultCode, data)) {
+ if (inAppPurchaseHelper != null && inAppPurchaseHelper.onActivityResultHandled(requestCode, resultCode, data)) {
return;
}
for (ActivityResultListener listener : activityResultListeners) {
@@ -1920,43 +1921,4 @@ public class MapActivity extends OsmandActionBarActivity implements DownloadEven
DESTINATION_SELECTION,
INTERMEDIATE_SELECTION
}
-
- public InAppHelper execInAppTask(@NonNull InAppHelper.InAppRunnable runnable) {
- if (inAppHelper != null) {
- inAppHelper.stop();
- }
- if (Version.isGooglePlayEnabled(app)) {
- inAppHelper = new InAppHelper(getMyApplication(), false);
- inAppHelper.addListener(new InAppHelper.InAppListener() {
- @Override
- public void onError(String error) {
- inAppHelper = null;
- }
-
- @Override
- public void onGetItems() {
- inAppHelper = null;
- }
-
- @Override
- public void onItemPurchased(String sku) {
- inAppHelper = null;
- }
-
- @Override
- public void showProgress() {
-
- }
-
- @Override
- public void dismissProgress() {
-
- }
- });
- inAppHelper.exec(runnable);
- return inAppHelper;
- } else {
- return null;
- }
- }
}
diff --git a/OsmAnd/src/net/osmand/plus/activities/OsmandActionBarActivity.java b/OsmAnd/src/net/osmand/plus/activities/OsmandActionBarActivity.java
index 19bc1c2597..5162339969 100644
--- a/OsmAnd/src/net/osmand/plus/activities/OsmandActionBarActivity.java
+++ b/OsmAnd/src/net/osmand/plus/activities/OsmandActionBarActivity.java
@@ -1,5 +1,6 @@
package net.osmand.plus.activities;
+import android.annotation.SuppressLint;
import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;
import android.support.v4.content.ContextCompat;
@@ -11,7 +12,8 @@ import android.view.ViewGroup;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
-public class OsmandActionBarActivity extends AppCompatActivity {
+@SuppressLint("Registered")
+public class OsmandActionBarActivity extends OsmandInAppPurchaseActivity {
protected boolean haveHomeButton = true;
@@ -50,8 +52,4 @@ public class OsmandActionBarActivity extends AppCompatActivity {
setupHomeButton();
}
}
-
- public OsmandApplication getMyApplication() {
- return (OsmandApplication) getApplication();
- }
}
diff --git a/OsmAnd/src/net/osmand/plus/activities/OsmandInAppPurchaseActivity.java b/OsmAnd/src/net/osmand/plus/activities/OsmandInAppPurchaseActivity.java
new file mode 100644
index 0000000000..65f307d60e
--- /dev/null
+++ b/OsmAnd/src/net/osmand/plus/activities/OsmandInAppPurchaseActivity.java
@@ -0,0 +1,166 @@
+package net.osmand.plus.activities;
+
+import android.annotation.SuppressLint;
+import android.content.ActivityNotFoundException;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Bundle;
+import android.support.annotation.Nullable;
+import android.support.v7.app.AppCompatActivity;
+
+import net.osmand.PlatformUtil;
+import net.osmand.plus.OsmandApplication;
+import net.osmand.plus.Version;
+import net.osmand.plus.inapp.InAppPurchaseHelper;
+import net.osmand.plus.inapp.InAppPurchaseHelper.InAppPurchaseListener;
+import net.osmand.plus.inapp.InAppPurchaseHelper.InAppPurchaseTaskType;
+
+import org.apache.commons.logging.Log;
+
+import static net.osmand.plus.OsmandApplication.SHOW_PLUS_VERSION_INAPP_PARAM;
+
+@SuppressLint("Registered")
+public class OsmandInAppPurchaseActivity extends AppCompatActivity implements InAppPurchaseListener {
+ private static final Log LOG = PlatformUtil.getLog(OsmandInAppPurchaseActivity.class);
+
+ private InAppPurchaseHelper purchaseHelper;
+
+ @Override
+ protected void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ if (isInAppPurchaseAllowed() && isInAppPurchaseSupported()) {
+ purchaseHelper = getMyApplication().getInAppPurchaseHelper();
+ }
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ initInAppPurchaseHelper();
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ deinitInAppPurchaseHelper();
+ }
+
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ // Pass on the activity result to the helper for handling
+ if (purchaseHelper == null || !purchaseHelper.onActivityResultHandled(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);
+ }
+ }
+
+ private void initInAppPurchaseHelper() {
+ deinitInAppPurchaseHelper();
+
+ if (purchaseHelper != null) {
+ purchaseHelper.addListener(this);
+ if (purchaseHelper.needRequestInventory()) {
+ purchaseHelper.requestInventory();
+ }
+ }
+ }
+
+ private void deinitInAppPurchaseHelper() {
+ if (purchaseHelper != null) {
+ purchaseHelper.removeListener(this);
+ purchaseHelper.stop();
+ }
+ }
+
+ public void purchaseFullVersion() {
+ OsmandApplication app = getMyApplication();
+ if (Version.isFreeVersion(app)) {
+ if (app.getRemoteBoolean(SHOW_PLUS_VERSION_INAPP_PARAM, true)) {
+ if (purchaseHelper != null) {
+ app.logEvent(this, "in_app_purchase_redirect");
+ purchaseHelper.purchaseFullVersion(this);
+ }
+ } else {
+ app.logEvent(this, "paid_version_redirect");
+ Intent intent = new Intent(Intent.ACTION_VIEW,
+ Uri.parse(Version.getUrlWithUtmRef(app, "net.osmand.plus")));
+ try {
+ startActivity(intent);
+ } catch (ActivityNotFoundException e) {
+ LOG.error("ActivityNotFoundException", e);
+ }
+ }
+ }
+ }
+
+ public void purchaseDepthContours() {
+ if (purchaseHelper != null) {
+ getMyApplication().logEvent(this, "depth_contours_purchase_redirect");
+ purchaseHelper.purchaseDepthContours(this);
+ }
+ }
+
+ public OsmandApplication getMyApplication() {
+ return (OsmandApplication) getApplication();
+ }
+
+ @Nullable
+ public InAppPurchaseHelper getPurchaseHelper() {
+ return purchaseHelper;
+ }
+
+ public boolean isInAppPurchaseAllowed() {
+ return false;
+ }
+
+ public boolean isInAppPurchaseSupported() {
+ return Version.isGooglePlayEnabled(getMyApplication());
+ }
+
+ @Override
+ public void onError(InAppPurchaseTaskType taskType, String error) {
+ onInAppPurchaseError(taskType, error);
+ }
+
+ @Override
+ public void onGetItems() {
+ onInAppPurchaseGetItems();
+ }
+
+ @Override
+ public void onItemPurchased(String sku) {
+ onInAppPurchaseItemPurchased(sku);
+ }
+
+ @Override
+ public void showProgress(InAppPurchaseTaskType taskType) {
+ showInAppPurchaseProgress(taskType);
+ }
+
+ @Override
+ public void dismissProgress(InAppPurchaseTaskType taskType) {
+ dismissInAppPurchaseProgress(taskType);
+ }
+
+ public void onInAppPurchaseError(InAppPurchaseTaskType taskType, String error) {
+ // not implemented
+ }
+
+ public void onInAppPurchaseGetItems() {
+ // not implemented
+ }
+
+ public void onInAppPurchaseItemPurchased(String sku) {
+ // not implemented
+ }
+
+ public void showInAppPurchaseProgress(InAppPurchaseTaskType taskType) {
+ // not implemented
+ }
+
+ public void dismissInAppPurchaseProgress(InAppPurchaseTaskType taskType) {
+ // not implemented
+ }
+}
diff --git a/OsmAnd/src/net/osmand/plus/dialogs/ChoosePlanDialogFragment.java b/OsmAnd/src/net/osmand/plus/dialogs/ChoosePlanDialogFragment.java
index bc50903aaa..737dede9e3 100644
--- a/OsmAnd/src/net/osmand/plus/dialogs/ChoosePlanDialogFragment.java
+++ b/OsmAnd/src/net/osmand/plus/dialogs/ChoosePlanDialogFragment.java
@@ -6,11 +6,14 @@ import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
+import android.os.Build;
import android.os.Bundle;
+import android.support.annotation.ColorRes;
import android.support.annotation.LayoutRes;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.FragmentManager;
+import android.support.v4.content.ContextCompat;
import android.text.TextUtils;
import android.view.ContextThemeWrapper;
import android.view.LayoutInflater;
@@ -18,68 +21,117 @@ import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.widget.LinearLayout;
+import android.widget.ProgressBar;
import android.widget.TextView;
import net.osmand.AndroidUtils;
import net.osmand.PlatformUtil;
import net.osmand.plus.OsmandApplication;
+import net.osmand.plus.OsmandPlugin;
import net.osmand.plus.R;
import net.osmand.plus.Version;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.base.BaseOsmAndDialogFragment;
-import net.osmand.plus.download.DownloadActivity;
import net.osmand.plus.download.DownloadValidationManager;
-import net.osmand.plus.inapp.InAppHelper;
+import net.osmand.plus.inapp.InAppPurchaseHelper;
+import net.osmand.plus.inapp.InAppPurchaseHelper.InAppPurchaseListener;
+import net.osmand.plus.inapp.InAppPurchaseHelper.InAppPurchaseTaskType;
import net.osmand.plus.liveupdates.OsmLiveActivity;
+import net.osmand.plus.srtmplugin.SRTMPlugin;
import net.osmand.plus.widgets.TextViewEx;
import org.apache.commons.logging.Log;
import static net.osmand.plus.OsmandApplication.SHOW_PLUS_VERSION_INAPP_PARAM;
-public class ChoosePlanDialogFragment extends BaseOsmAndDialogFragment {
+public class ChoosePlanDialogFragment extends BaseOsmAndDialogFragment implements InAppPurchaseListener {
public static final String TAG = ChoosePlanDialogFragment.class.getSimpleName();
private static final Log LOG = PlatformUtil.getLog(ChoosePlanDialogFragment.class);
private static final String PLAN_TYPE_KEY = "plan_type";
+ private OsmandApplication app;
+ private InAppPurchaseHelper purchaseHelper;
+
private boolean nightMode;
private PlanType planType;
- private OsmAndFeature[] osmandLiveFeatures = {
- OsmAndFeature.UNLIMITED_DOWNLOADS,
- OsmAndFeature.DAILY_MAP_UPDATES,
- OsmAndFeature.WIKIPEDIA_OFFLINE,
- OsmAndFeature.WIKIVOYAGE_OFFLINE,
- OsmAndFeature.CONTOUR_LINES_SEA_DEPTH,
- OsmAndFeature.DONATION_TO_OSM,
-// OsmAndFeature.UNLOCK_ALL_FEATURES,
- };
-
- private OsmAndFeature[] osmandUnlimitedFeatures = {
- OsmAndFeature.UNLIMITED_DOWNLOADS,
- OsmAndFeature.MONTHLY_MAP_UPDATES,
- OsmAndFeature.WIKIPEDIA_OFFLINE,
- OsmAndFeature.WIKIVOYAGE_OFFLINE,
- };
+ private View osmLiveCardButton;
+ private View planTypeCardButton;
public enum PlanType {
- FREE_VERSION_BANNER(OsmAndFeature.UNLIMITED_DOWNLOADS, OsmAndFeature.UNLIMITED_DOWNLOADS);
+ FREE_VERSION_BANNER(
+ new OsmAndFeature[]{
+ 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,
+ OsmAndFeature.DONATION_TO_OSM,
+ },
+ new OsmAndFeature[]{
+ OsmAndFeature.DAILY_MAP_UPDATES,
+ OsmAndFeature.UNLIMITED_DOWNLOADS,
+ },
+ new OsmAndFeature[]{
+ OsmAndFeature.WIKIPEDIA_OFFLINE,
+ OsmAndFeature.WIKIVOYAGE_OFFLINE,
+ OsmAndFeature.UNLIMITED_DOWNLOADS,
+ OsmAndFeature.MONTHLY_MAP_UPDATES,
+ },
+ new OsmAndFeature[]{});
- private final OsmAndFeature osmandLiveFeature;
- private final OsmAndFeature osmandUnlimitedFeature;
+ private final OsmAndFeature[] osmLiveFeatures;
+ private final OsmAndFeature[] planTypeFeatures;
+ private final OsmAndFeature[] selectedOsmLiveFeatures;
+ private final OsmAndFeature[] selectedPlanTypeFeatures;
- PlanType(OsmAndFeature osmandLiveFeature, OsmAndFeature osmandUnlimitedFeature) {
- this.osmandLiveFeature = osmandLiveFeature;
- this.osmandUnlimitedFeature = osmandUnlimitedFeature;
+ PlanType(OsmAndFeature[] osmLiveFeatures, OsmAndFeature[] selectedOsmLiveFeatures,
+ OsmAndFeature[] planTypeFeatures, OsmAndFeature[] selectedPlanTypeFeatures) {
+ this.osmLiveFeatures = osmLiveFeatures;
+ this.planTypeFeatures = planTypeFeatures;
+ this.selectedOsmLiveFeatures = selectedOsmLiveFeatures;
+ this.selectedPlanTypeFeatures = selectedPlanTypeFeatures;
}
- public OsmAndFeature getOsmandLiveFeature() {
- return osmandLiveFeature;
+ public OsmAndFeature[] getOsmLiveFeatures() {
+ return osmLiveFeatures;
}
- public OsmAndFeature getOsmandUnlimitedFeature() {
- return osmandUnlimitedFeature;
+ public OsmAndFeature[] getPlanTypeFeatures() {
+ return planTypeFeatures;
+ }
+
+ public OsmAndFeature[] getSelectedOsmLiveFeatures() {
+ return selectedOsmLiveFeatures;
+ }
+
+ public OsmAndFeature[] getSelectedPlanTypeFeatures() {
+ return selectedPlanTypeFeatures;
+ }
+
+ public boolean hasSelectedOsmLiveFeature(OsmAndFeature feature) {
+ if (selectedOsmLiveFeatures != null) {
+ for (OsmAndFeature f : selectedOsmLiveFeatures) {
+ if (feature == f) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ public boolean hasSelectedPlanTypeFeature(OsmAndFeature feature) {
+ if (selectedPlanTypeFeatures != null) {
+ for (OsmAndFeature f : selectedPlanTypeFeatures) {
+ if (feature == f) {
+ return true;
+ }
+ }
+ }
+ return false;
}
}
@@ -89,7 +141,8 @@ public class ChoosePlanDialogFragment extends BaseOsmAndDialogFragment {
MONTHLY_MAP_UPDATES(R.string.monthly_map_updates),
UNLIMITED_DOWNLOADS(R.string.unlimited_downloads),
WIKIPEDIA_OFFLINE(R.string.wikipedia_offline),
- CONTOUR_LINES_SEA_DEPTH(R.string.contour_lines_sea_depth),
+ CONTOUR_LINES_HILLSHADE_MAPS(R.string.contour_lines_hillshade_maps),
+ SEA_DEPTH_MAPS(R.string.index_item_depth_contours_osmand_ext),
UNLOCK_ALL_FEATURES(R.string.unlock_all_features),
DONATION_TO_OSM(R.string.donation_to_osm);
@@ -103,9 +156,27 @@ public class ChoosePlanDialogFragment extends BaseOsmAndDialogFragment {
return ctx.getString(key);
}
+ public boolean isFeaturePurchased(OsmandApplication ctx) {
+ switch (this) {
+ case DAILY_MAP_UPDATES:
+ case MONTHLY_MAP_UPDATES:
+ case UNLIMITED_DOWNLOADS:
+ case WIKIPEDIA_OFFLINE:
+ case UNLOCK_ALL_FEATURES:
+ case DONATION_TO_OSM:
+ return false;
+ case WIKIVOYAGE_OFFLINE:
+ return ctx.getSettings().TRAVEL_ARTICLES_PURCHASED.get();
+ case CONTOUR_LINES_HILLSHADE_MAPS:
+ boolean srtmEnabled = OsmandPlugin.getEnabledPlugin(SRTMPlugin.class) != null;
+ return srtmEnabled && ctx.getSettings().DEPTH_CONTOURS_PURCHASED.get();
+ }
+ return false;
+ }
+
public static OsmAndFeature[] possibleValues() {
return new OsmAndFeature[]{WIKIVOYAGE_OFFLINE, DAILY_MAP_UPDATES, MONTHLY_MAP_UPDATES, UNLIMITED_DOWNLOADS,
- WIKIPEDIA_OFFLINE, CONTOUR_LINES_SEA_DEPTH, UNLOCK_ALL_FEATURES, DONATION_TO_OSM};
+ WIKIPEDIA_OFFLINE, CONTOUR_LINES_HILLSHADE_MAPS, UNLOCK_ALL_FEATURES, DONATION_TO_OSM};
}
}
@@ -113,6 +184,9 @@ public class ChoosePlanDialogFragment extends BaseOsmAndDialogFragment {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+ app = getMyApplication();
+ purchaseHelper = app.getInAppPurchaseHelper();
+
Bundle args = getArguments();
if (args == null) {
args = savedInstanceState;
@@ -130,13 +204,16 @@ public class ChoosePlanDialogFragment extends BaseOsmAndDialogFragment {
@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
- int themeId = nightMode ? R.style.OsmandDarkTheme : R.style.OsmandLightTheme;
+ int themeId = nightMode ? R.style.OsmandDarkTheme_DarkActionbar : R.style.OsmandLightTheme_DarkActionbar_LightStatusBar;
Dialog dialog = new Dialog(getContext(), themeId);
Window window = dialog.getWindow();
if (window != null) {
if (!getSettings().DO_NOT_USE_ANIMATIONS.get()) {
window.getAttributes().windowAnimations = R.style.Animations_Alpha;
}
+ if (Build.VERSION.SDK_INT >= 21) {
+ window.setStatusBarColor(ContextCompat.getColor(getContext(), getStatusBarColor()));
+ }
}
return dialog;
}
@@ -169,68 +246,28 @@ public class ChoosePlanDialogFragment extends BaseOsmAndDialogFragment {
switch (planType) {
case FREE_VERSION_BANNER: {
- infoDescription.setText(ctx.getString(R.string.free_version_message,
+ infoDescription.setText(getString(R.string.free_version_message,
DownloadValidationManager.MAXIMUM_AVAILABLE_FREE_DOWNLOADS));
- //infoDescription.setVisibility(View.GONE);
- //View freeVersionInfoView = inflate(R.layout.purchase_dialog_info_free_version, infoContainer);
- //initFreeVersionInfoView(ctx, freeVersionInfoView);
- //infoContainer.addView(freeVersionInfoView);
-
break;
}
}
- cardsContainer.addView(buildOsmAndLiveCard(ctx, cardsContainer));
- cardsContainer.addView(buildOsmAndUnlimitedCard(ctx, cardsContainer));
+ cardsContainer.addView(buildOsmLiveCard(ctx, cardsContainer));
+ cardsContainer.addView(buildPlanTypeCard(ctx, cardsContainer));
return view;
}
- /*
- private void initFreeVersionInfoView(Context ctx, View freeVersionInfoView) {
- TextView downloadsLeftTextView = (TextView) freeVersionInfoView.findViewById(R.id.downloadsLeftTextView);
- ProgressBar downloadsLeftProgressBar = (ProgressBar) freeVersionInfoView.findViewById(R.id.downloadsLeftProgressBar);
- TextView freeVersionDescriptionTextView = (TextView) freeVersionInfoView
- .findViewById(R.id.freeVersionDescriptionTextView);
-
- OsmandSettings settings = getMyApplication().getSettings();
- final Integer mapsDownloaded = settings.NUMBER_OF_FREE_DOWNLOADS.get();
- downloadsLeftProgressBar.setProgress(mapsDownloaded);
- int downloadsLeft = DownloadValidationManager.MAXIMUM_AVAILABLE_FREE_DOWNLOADS - mapsDownloaded;
- downloadsLeft = Math.max(downloadsLeft, 0);
- downloadsLeftTextView.setText(ctx.getString(R.string.downloads_left_template, downloadsLeft));
- downloadsLeftProgressBar.setMax(DownloadValidationManager.MAXIMUM_AVAILABLE_FREE_DOWNLOADS);
- freeVersionDescriptionTextView.setText(ctx.getString(R.string.free_version_message,
- DownloadValidationManager.MAXIMUM_AVAILABLE_FREE_DOWNLOADS));
-
- LinearLayout marksLinearLayout = (LinearLayout) freeVersionInfoView.findViewById(R.id.marksLinearLayout);
- Space spaceView = new Space(ctx);
- LinearLayout.LayoutParams layoutParams =
- new LinearLayout.LayoutParams(0, ViewGroup.LayoutParams.MATCH_PARENT, 1);
- spaceView.setLayoutParams(layoutParams);
- marksLinearLayout.addView(spaceView);
- int markWidth = (int) (1 * ctx.getResources().getDisplayMetrics().density);
- int colorBlack = ctx.getResources().getColor(nightMode ? R.color.wikivoyage_bg_dark : R.color.wikivoyage_bg_light);
- for (int i = 1; i < DownloadValidationManager.MAXIMUM_AVAILABLE_FREE_DOWNLOADS; i++) {
- View markView = new View(ctx);
- layoutParams = new LinearLayout.LayoutParams(markWidth, ViewGroup.LayoutParams.MATCH_PARENT);
- markView.setLayoutParams(layoutParams);
- markView.setBackgroundColor(colorBlack);
- marksLinearLayout.addView(markView);
- spaceView = new Space(ctx);
- layoutParams = new LinearLayout.LayoutParams(0,
- ViewGroup.LayoutParams.MATCH_PARENT, 1);
- spaceView.setLayoutParams(layoutParams);
- marksLinearLayout.addView(spaceView);
- }
+ @ColorRes
+ protected int getStatusBarColor() {
+ return nightMode ? R.color.status_bar_wikivoyage_dark : R.color.status_bar_wikivoyage_light;
}
- */
private View inflate(@LayoutRes int layoutId, @Nullable ViewGroup container) {
- int themeRes = nightMode ? R.style.OsmandDarkTheme : R.style.OsmandLightTheme;
+ int themeRes = nightMode ? R.style.OsmandDarkTheme_DarkActionbar : R.style.OsmandLightTheme_DarkActionbar_LightStatusBar;
return LayoutInflater.from(new ContextThemeWrapper(getContext(), themeRes))
.inflate(layoutId, container, false);
}
- private ViewGroup buildOsmAndLiveCard(@NonNull Context ctx, ViewGroup container) {
+ private ViewGroup buildOsmLiveCard(@NonNull Context ctx, ViewGroup container) {
ViewGroup cardView = (ViewGroup) inflate(R.layout.purchase_dialog_active_card, container);
TextView headerTitle = (TextView) cardView.findViewById(R.id.header_title);
TextView headerDescr = (TextView) cardView.findViewById(R.id.header_descr);
@@ -238,11 +275,10 @@ public class ChoosePlanDialogFragment extends BaseOsmAndDialogFragment {
headerDescr.setText(R.string.osm_live_subscription);
ViewGroup rowsContainer = (ViewGroup) cardView.findViewById(R.id.rows_container);
View featureRowDiv = null;
- for (OsmAndFeature feature : osmandLiveFeatures) {
+ for (OsmAndFeature feature : planType.getOsmLiveFeatures()) {
String featureName = feature.toHumanString(ctx);
-// View featureRow = inflate(planType.osmandLiveFeature == feature
-// ? R.layout.purchase_dialog_card_selected_row : R.layout.purchase_dialog_card_row, cardView);
- View featureRow = inflate(R.layout.purchase_dialog_card_row, cardView);
+ View featureRow = inflate(planType.hasSelectedOsmLiveFeature(feature)
+ ? R.layout.purchase_dialog_card_selected_row : R.layout.purchase_dialog_card_row, cardView);
TextViewEx titleView = (TextViewEx) featureRow.findViewById(R.id.title);
titleView.setText(featureName);
featureRowDiv = featureRow.findViewById(R.id.div);
@@ -257,29 +293,49 @@ public class ChoosePlanDialogFragment extends BaseOsmAndDialogFragment {
TextViewEx cardDescription = (TextViewEx) cardView.findViewById(R.id.card_descr);
cardDescription.setText(R.string.osm_live_payment_desc);
- View cardButton = cardView.findViewById(R.id.card_button);
- TextViewEx buttonTitle = (TextViewEx) cardButton.findViewById(R.id.card_button_title);
- TextViewEx buttonSubtitle = (TextViewEx) cardButton.findViewById(R.id.card_button_subtitle);
- if (!InAppHelper.hasPrices(getMyApplication())) {
- buttonTitle.setText(ctx.getString(R.string.purchase_subscription_title, ctx.getString(R.string.osm_live_default_price)));
- } else {
- buttonTitle.setText(ctx.getString(R.string.purchase_subscription_title, InAppHelper.getLiveUpdatesPrice()));
- }
- buttonSubtitle.setText(R.string.osm_live_month_cost_desc);
- cardButton.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- subscript();
- dismiss();
- }
- });
+ osmLiveCardButton = cardView.findViewById(R.id.card_button);
+ InAppPurchaseHelper purchaseHelper = app.getInAppPurchaseHelper();
+ boolean requestingInventory = purchaseHelper != null && purchaseHelper.getActiveTask() == InAppPurchaseTaskType.REQUEST_INVENTORY;
+ setupOsmLiveCardButton(requestingInventory);
+
return cardView;
}
+ private void setupOsmLiveCardButton(boolean progress) {
+ if (osmLiveCardButton != null) {
+ ProgressBar progressBar = (ProgressBar) osmLiveCardButton.findViewById(R.id.card_button_progress);
+ TextViewEx buttonTitle = (TextViewEx) osmLiveCardButton.findViewById(R.id.card_button_title);
+ TextViewEx buttonSubtitle = (TextViewEx) osmLiveCardButton.findViewById(R.id.card_button_subtitle);
+ if (!purchaseHelper.hasPrices()) {
+ buttonTitle.setText(getString(R.string.purchase_subscription_title, getString(R.string.osm_live_default_price)));
+ } else {
+ buttonTitle.setText(getString(R.string.purchase_subscription_title, purchaseHelper.getLiveUpdatesPrice()));
+ }
+ buttonSubtitle.setText(R.string.osm_live_month_cost_desc);
+ if (progress) {
+ buttonTitle.setVisibility(View.GONE);
+ buttonSubtitle.setVisibility(View.GONE);
+ progressBar.setVisibility(View.VISIBLE);
+ osmLiveCardButton.setOnClickListener(null);
+ } else {
+ buttonTitle.setVisibility(View.VISIBLE);
+ buttonSubtitle.setVisibility(View.VISIBLE);
+ progressBar.setVisibility(View.GONE);
+ osmLiveCardButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ subscript();
+ dismiss();
+ }
+ });
+ }
+ }
+ }
+
private void subscript() {
Activity ctx = getActivity();
if (ctx != null) {
- getMyApplication().logEvent(ctx, "click_subscribe_live_osm");
+ app.logEvent(ctx, "click_subscribe_live_osm");
Intent intent = new Intent(ctx, OsmLiveActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
intent.putExtra(OsmLiveActivity.OPEN_SUBSCRIPTION_INTENT_PARAM, true);
@@ -287,7 +343,7 @@ public class ChoosePlanDialogFragment extends BaseOsmAndDialogFragment {
}
}
- private ViewGroup buildOsmAndUnlimitedCard(@NonNull Context ctx, ViewGroup container) {
+ private ViewGroup buildPlanTypeCard(@NonNull Context ctx, ViewGroup container) {
ViewGroup cardView = (ViewGroup) inflate(R.layout.purchase_dialog_card, container);
TextView headerTitle = (TextView) cardView.findViewById(R.id.header_title);
TextView headerDescr = (TextView) cardView.findViewById(R.id.header_descr);
@@ -295,9 +351,9 @@ public class ChoosePlanDialogFragment extends BaseOsmAndDialogFragment {
headerDescr.setText(R.string.in_app_purchase);
ViewGroup rowsContainer = (ViewGroup) cardView.findViewById(R.id.rows_container);
View featureRow = null;
- for (OsmAndFeature feature : osmandUnlimitedFeatures) {
+ for (OsmAndFeature feature : planType.getPlanTypeFeatures()) {
String featureName = feature.toHumanString(ctx);
- featureRow = inflate(planType.osmandUnlimitedFeature == feature
+ featureRow = inflate(planType.hasSelectedPlanTypeFeature(feature)
? R.layout.purchase_dialog_card_selected_row : R.layout.purchase_dialog_card_row, cardView);
TextViewEx titleView = (TextViewEx) featureRow.findViewById(R.id.title);
titleView.setText(featureName);
@@ -309,28 +365,46 @@ public class ChoosePlanDialogFragment extends BaseOsmAndDialogFragment {
TextViewEx cardDescription = (TextViewEx) cardView.findViewById(R.id.card_descr);
cardDescription.setText(R.string.in_app_purchase_desc_ex);
- View cardButton = cardView.findViewById(R.id.card_button);
- TextViewEx buttonTitle = (TextViewEx) cardButton.findViewById(R.id.card_button_title);
- TextViewEx buttonSubtitle = (TextViewEx) cardButton.findViewById(R.id.card_button_subtitle);
- if (!InAppHelper.hasPrices(getMyApplication())) {
- buttonTitle.setText(ctx.getString(R.string.purchase_unlim_title, ctx.getString(R.string.full_version_price)));
- } else {
- buttonTitle.setText(ctx.getString(R.string.purchase_unlim_title, InAppHelper.getFullVersionPrice()));
- }
- buttonSubtitle.setText(R.string.in_app_purchase_desc);
- cardButton.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- purchaseFullVersion();
- dismiss();
- }
- });
+ planTypeCardButton = cardView.findViewById(R.id.card_button);
+ InAppPurchaseHelper purchaseHelper = app.getInAppPurchaseHelper();
+ boolean requestingInventory = purchaseHelper != null && purchaseHelper.getActiveTask() == InAppPurchaseTaskType.REQUEST_INVENTORY;
+ setupPlanTypeCardButton(requestingInventory);
+
return cardView;
}
+ private void setupPlanTypeCardButton(boolean progress) {
+ if (planTypeCardButton != null) {
+ ProgressBar progressBar = (ProgressBar) planTypeCardButton.findViewById(R.id.card_button_progress);
+ TextViewEx buttonTitle = (TextViewEx) planTypeCardButton.findViewById(R.id.card_button_title);
+ TextViewEx buttonSubtitle = (TextViewEx) planTypeCardButton.findViewById(R.id.card_button_subtitle);
+ if (!purchaseHelper.hasPrices()) {
+ buttonTitle.setText(getString(R.string.purchase_unlim_title, getString(R.string.full_version_price)));
+ } else {
+ buttonTitle.setText(getString(R.string.purchase_unlim_title, purchaseHelper.getFullVersionPrice()));
+ }
+ buttonSubtitle.setText(R.string.in_app_purchase_desc);
+ if (progress) {
+ buttonTitle.setVisibility(View.GONE);
+ buttonSubtitle.setVisibility(View.GONE);
+ progressBar.setVisibility(View.VISIBLE);
+ planTypeCardButton.setOnClickListener(null);
+ } else {
+ buttonTitle.setVisibility(View.VISIBLE);
+ buttonSubtitle.setVisibility(View.VISIBLE);
+ progressBar.setVisibility(View.GONE);
+ planTypeCardButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ purchaseFullVersion();
+ dismiss();
+ }
+ });
+ }
+ }
+ }
+
public void purchaseFullVersion() {
- /*
- OsmandApplication app = getMyApplication();
if (app.getRemoteBoolean(SHOW_PLUS_VERSION_INAPP_PARAM, true)) {
app.logEvent(getActivity(), "in_app_purchase_redirect_from_banner");
} else {
@@ -338,12 +412,13 @@ public class ChoosePlanDialogFragment extends BaseOsmAndDialogFragment {
}
if (Version.isFreeVersion(app)) {
if (app.getRemoteBoolean(SHOW_PLUS_VERSION_INAPP_PARAM, true)) {
- if (inAppHelper != null) {
- app.logEvent(this, "in_app_purchase_redirect");
- inAppHelper.purchaseFullVersion(this);
+ InAppPurchaseHelper purchaseHelper = app.getInAppPurchaseHelper();
+ if (purchaseHelper != null) {
+ app.logEvent(getActivity(), "in_app_purchase_redirect");
+ purchaseHelper.purchaseFullVersion(getActivity());
}
} else {
- app.logEvent(this, "paid_version_redirect");
+ app.logEvent(getActivity(), "paid_version_redirect");
Intent intent = new Intent(Intent.ACTION_VIEW,
Uri.parse(Version.getUrlWithUtmRef(app, "net.osmand.plus")));
try {
@@ -353,7 +428,6 @@ public class ChoosePlanDialogFragment extends BaseOsmAndDialogFragment {
}
}
}
- */
}
@Override
@@ -391,6 +465,38 @@ public class ChoosePlanDialogFragment extends BaseOsmAndDialogFragment {
}
}
+ @Override
+ public void onError(InAppPurchaseTaskType taskType, String error) {
+ if (taskType == InAppPurchaseTaskType.REQUEST_INVENTORY) {
+ setupOsmLiveCardButton(false);
+ setupPlanTypeCardButton(false);
+ }
+ }
+
+ @Override
+ public void onGetItems() {
+ }
+
+ @Override
+ public void onItemPurchased(String sku) {
+ }
+
+ @Override
+ public void showProgress(InAppPurchaseTaskType taskType) {
+ if (taskType == InAppPurchaseTaskType.REQUEST_INVENTORY) {
+ setupOsmLiveCardButton(true);
+ setupPlanTypeCardButton(true);
+ }
+ }
+
+ @Override
+ public void dismissProgress(InAppPurchaseTaskType taskType) {
+ if (taskType == InAppPurchaseTaskType.REQUEST_INVENTORY) {
+ setupOsmLiveCardButton(false);
+ setupPlanTypeCardButton(false);
+ }
+ }
+
public static void showFreeVersionInstance(@NonNull FragmentManager fm) {
PlanType planType = PlanType.FREE_VERSION_BANNER;
showInstance(fm, planType);
diff --git a/OsmAnd/src/net/osmand/plus/download/DownloadActivity.java b/OsmAnd/src/net/osmand/plus/download/DownloadActivity.java
index 2ad07ae837..1a2fb4fddc 100644
--- a/OsmAnd/src/net/osmand/plus/download/DownloadActivity.java
+++ b/OsmAnd/src/net/osmand/plus/download/DownloadActivity.java
@@ -1,12 +1,11 @@
package net.osmand.plus.download;
import android.Manifest;
-import android.content.ActivityNotFoundException;
+import android.annotation.SuppressLint;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
-import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.StatFs;
@@ -21,7 +20,6 @@ import android.support.v4.content.ContextCompat;
import android.support.v4.view.ViewPager;
import android.support.v4.widget.Space;
import android.support.v7.app.AlertDialog;
-import android.support.v7.widget.AppCompatButton;
import android.text.method.LinkMovementMethod;
import android.view.LayoutInflater;
import android.view.MenuItem;
@@ -54,17 +52,15 @@ import net.osmand.plus.activities.TabActivity;
import net.osmand.plus.base.BasicProgressAsyncTask;
import net.osmand.plus.base.BottomSheetDialogFragment;
import net.osmand.plus.dialogs.ChoosePlanDialogFragment;
-import net.osmand.plus.dialogs.ChoosePlanDialogFragment.PlanType;
import net.osmand.plus.download.DownloadIndexesThread.DownloadEvents;
import net.osmand.plus.download.ui.ActiveDownloadsDialogFragment;
import net.osmand.plus.download.ui.DownloadResourceGroupFragment;
-import net.osmand.plus.download.ui.FreeVersionDialogFragment;
import net.osmand.plus.download.ui.LocalIndexesFragment;
import net.osmand.plus.download.ui.UpdatesIndexFragment;
import net.osmand.plus.helpers.FileNameTranslationHelper;
-import net.osmand.plus.inapp.InAppHelper;
-import net.osmand.plus.inapp.InAppHelper.InAppListener;
-import net.osmand.plus.liveupdates.OsmLiveActivity;
+import net.osmand.plus.inapp.InAppPurchaseHelper;
+import net.osmand.plus.inapp.InAppPurchaseHelper.InAppPurchaseListener;
+import net.osmand.plus.inapp.InAppPurchaseHelper.InAppPurchaseTaskType;
import net.osmand.plus.openseamapsplugin.NauticalMapsPlugin;
import net.osmand.plus.srtmplugin.SRTMPlugin;
import net.osmand.plus.views.controls.PagerSlidingTabStrip;
@@ -83,10 +79,8 @@ import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
-import static net.osmand.plus.OsmandApplication.SHOW_PLUS_VERSION_INAPP_PARAM;
-
public class DownloadActivity extends AbstractDownloadActivity implements DownloadEvents,
- OnRequestPermissionsResultCallback, InAppListener {
+ OnRequestPermissionsResultCallback {
private static final Log LOG = PlatformUtil.getLog(DownloadActivity.class);
public static final int UPDATES_TAB_NUMBER = 2;
@@ -122,8 +116,6 @@ public class DownloadActivity extends AbstractDownloadActivity implements Downlo
protected WorldRegion downloadItem;
protected String downloadTargetFileName;
- private InAppHelper inAppHelper;
-
private boolean srtmDisabled;
private boolean srtmNeedsInstallation;
private boolean nauticalPluginDisabled;
@@ -196,11 +188,9 @@ public class DownloadActivity extends AbstractDownloadActivity implements Downlo
visibleBanner = new BannerAndDownloadFreeVersion(findViewById(R.id.mainLayout), this, true);
if (shouldShowFreeVersionBanner(getMyApplication())) {
- visibleBanner.setUpdatingPrices(true);
+ visibleBanner.updateFreeVersionBanner();
}
- startInAppHelper();
-
final Intent intent = getIntent();
if (intent != null && intent.getExtras() != null) {
filter = intent.getExtras().getString(FILTER_KEY);
@@ -209,65 +199,60 @@ public class DownloadActivity extends AbstractDownloadActivity implements Downlo
}
}
- @Override
- protected void onActivityResult(int requestCode, int resultCode, Intent data) {
- // Pass on the activity result to the helper for handling
- if (inAppHelper == null || !inAppHelper.onActivityResultHandled(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);
- }
+ public boolean isInAppPurchaseAllowed() {
+ return true;
}
@Override
- public void onDestroy() {
- super.onDestroy();
- stopInAppHelper();
- }
-
- public void startInAppHelper() {
- stopInAppHelper();
-
- if (Version.isGooglePlayEnabled(getMyApplication())) {
- inAppHelper = new InAppHelper(getMyApplication(), true);
- inAppHelper.addListener(this);
- inAppHelper.start(false);
- }
- }
-
- public void stopInAppHelper() {
- if (inAppHelper != null) {
- inAppHelper.removeListener(this);
- inAppHelper.stop();
- }
- }
-
- public void purchaseFullVersion() {
- OsmandApplication app = getMyApplication();
- if (Version.isFreeVersion(app)) {
- if (app.getRemoteBoolean(SHOW_PLUS_VERSION_INAPP_PARAM, true)) {
- if (inAppHelper != null) {
- app.logEvent(this, "in_app_purchase_redirect");
- inAppHelper.purchaseFullVersion(this);
- }
- } else {
- app.logEvent(this, "paid_version_redirect");
- Intent intent = new Intent(Intent.ACTION_VIEW,
- Uri.parse(Version.getUrlWithUtmRef(app, "net.osmand.plus")));
- try {
- startActivity(intent);
- } catch (ActivityNotFoundException e) {
- LOG.error("ActivityNotFoundException", e);
- }
+ public void onInAppPurchaseError(InAppPurchaseTaskType taskType, String error) {
+ visibleBanner.updateFreeVersionBanner();
+ for (WeakReference ref : fragSet) {
+ Fragment f = ref.get();
+ if (f instanceof InAppPurchaseListener && f.isAdded()) {
+ ((InAppPurchaseListener) f).onError(taskType, error);
}
}
}
- public void purchaseDepthContours() {
- if (inAppHelper != null) {
- getMyApplication().logEvent(this, "depth_contours_purchase_redirect");
- inAppHelper.purchaseDepthContours(this);
+ @Override
+ public void onInAppPurchaseGetItems() {
+ visibleBanner.updateFreeVersionBanner();
+ for (WeakReference ref : fragSet) {
+ Fragment f = ref.get();
+ if (f instanceof InAppPurchaseListener && f.isAdded()) {
+ ((InAppPurchaseListener) f).onGetItems();
+ }
+ }
+ }
+
+ @Override
+ public void onInAppPurchaseItemPurchased(String sku) {
+ visibleBanner.updateFreeVersionBanner();
+ for (WeakReference ref : fragSet) {
+ Fragment f = ref.get();
+ if (f instanceof InAppPurchaseListener && f.isAdded()) {
+ ((InAppPurchaseListener) f).onItemPurchased(sku);
+ }
+ }
+ }
+
+ @Override
+ public void showInAppPurchaseProgress(InAppPurchaseTaskType taskType) {
+ for (WeakReference ref : fragSet) {
+ Fragment f = ref.get();
+ if (f instanceof InAppPurchaseListener && f.isAdded()) {
+ ((InAppPurchaseListener) f).showProgress(taskType);
+ }
+ }
+ }
+
+ @Override
+ public void dismissInAppPurchaseProgress(InAppPurchaseTaskType taskType) {
+ for (WeakReference ref : fragSet) {
+ Fragment f = ref.get();
+ if (f instanceof InAppPurchaseListener && f.isAdded()) {
+ ((InAppPurchaseListener) f).dismissProgress(taskType);
+ }
}
}
@@ -369,59 +354,6 @@ public class DownloadActivity extends AbstractDownloadActivity implements Downlo
}
}
- @Override
- public void onError(String error) {
- visibleBanner.setUpdatingPrices(false);
- for (WeakReference ref : fragSet) {
- Fragment f = ref.get();
- if (f instanceof InAppListener && f.isAdded()) {
- ((InAppListener) f).onError(error);
- }
- }
- }
-
- @Override
- public void onGetItems() {
- visibleBanner.setUpdatingPrices(false);
- for (WeakReference ref : fragSet) {
- Fragment f = ref.get();
- if (f instanceof InAppListener && f.isAdded()) {
- ((InAppListener) f).onGetItems();
- }
- }
- }
-
- @Override
- public void onItemPurchased(String sku) {
- visibleBanner.setUpdatingPrices(false);
- for (WeakReference ref : fragSet) {
- Fragment f = ref.get();
- if (f instanceof InAppListener && f.isAdded()) {
- ((InAppListener) f).onItemPurchased(sku);
- }
- }
- }
-
- @Override
- public void showProgress() {
- for (WeakReference ref : fragSet) {
- Fragment f = ref.get();
- if (f instanceof InAppListener && f.isAdded()) {
- ((InAppListener) f).showProgress();
- }
- }
- }
-
- @Override
- public void dismissProgress() {
- for (WeakReference ref : fragSet) {
- Fragment f = ref.get();
- if (f instanceof InAppListener && f.isAdded()) {
- ((InAppListener) f).dismissProgress();
- }
- }
- }
-
@Override
@UiThread
public void downloadInProgress() {
@@ -478,26 +410,15 @@ public class DownloadActivity extends AbstractDownloadActivity implements Downlo
}
- public static class FreeVersionDialog {
+ public static class FreeVersionBanner {
private final View freeVersionBanner;
private final View freeVersionBannerTitle;
- private boolean updatingPrices;
- private final View priceInfoLayout;
private final TextView freeVersionDescriptionTextView;
private final TextView downloadsLeftTextView;
private final ProgressBar downloadsLeftProgressBar;
-// private final View laterButton;
-// private final View buttonsLinearLayout;
-
- private final View fullVersionProgress;
- private final AppCompatButton fullVersionButton;
- private final View osmLiveProgress;
- private final AppCompatButton osmLiveButton;
private DownloadActivity ctx;
- private boolean dialog;
-
private OnClickListener onCollapseListener = new OnClickListener() {
@Override
public void onClick(View v) {
@@ -511,45 +432,26 @@ public class DownloadActivity extends AbstractDownloadActivity implements Downlo
}
};
- public FreeVersionDialog(View view, final DownloadActivity ctx, boolean dialog) {
+ public FreeVersionBanner(View view, final DownloadActivity ctx) {
this.ctx = ctx;
- this.dialog = dialog;
freeVersionBanner = view.findViewById(R.id.freeVersionBanner);
downloadsLeftTextView = (TextView) freeVersionBanner.findViewById(R.id.downloadsLeftTextView);
downloadsLeftProgressBar = (ProgressBar) freeVersionBanner.findViewById(R.id.downloadsLeftProgressBar);
- priceInfoLayout = freeVersionBanner.findViewById(R.id.priceInfoLayout);
freeVersionDescriptionTextView = (TextView) freeVersionBanner
.findViewById(R.id.freeVersionDescriptionTextView);
freeVersionBannerTitle = freeVersionBanner.findViewById(R.id.freeVersionBannerTitle);
- // laterButton = freeVersionBanner.findViewById(R.id.laterButton);
- // buttonsLinearLayout = freeVersionBanner.findViewById(R.id.buttonsLinearLayout);
-
- fullVersionProgress = freeVersionBanner.findViewById(R.id.fullVersionProgress);
- fullVersionButton = (AppCompatButton) freeVersionBanner.findViewById(R.id.fullVersionButton);
- osmLiveProgress = freeVersionBanner.findViewById(R.id.osmLiveProgress);
- osmLiveButton = (AppCompatButton) freeVersionBanner.findViewById(R.id.osmLiveButton);
- }
-
- public void setUpdatingPrices(boolean updatingPrices) {
- this.updatingPrices = updatingPrices;
- updateFreeVersionBanner();
}
private void collapseBanner() {
freeVersionDescriptionTextView.setVisibility(View.GONE);
- // buttonsLinearLayout.setVisibility(View.GONE);
- priceInfoLayout.setVisibility(View.GONE);
freeVersionBannerTitle.setVisibility(View.VISIBLE);
}
public void expandBanner() {
freeVersionDescriptionTextView.setVisibility(View.VISIBLE);
- // buttonsLinearLayout.setVisibility(View.VISIBLE);
- priceInfoLayout.setVisibility(View.VISIBLE);
freeVersionBannerTitle.setVisibility(View.VISIBLE);
}
-
public void initFreeVersionBanner() {
if (!shouldShowFreeVersionBanner(ctx.getMyApplication())) {
freeVersionBanner.setVisibility(View.GONE);
@@ -559,33 +461,6 @@ public class DownloadActivity extends AbstractDownloadActivity implements Downlo
downloadsLeftProgressBar.setMax(DownloadValidationManager.MAXIMUM_AVAILABLE_FREE_DOWNLOADS);
freeVersionDescriptionTextView.setText(ctx.getString(R.string.free_version_message,
DownloadValidationManager.MAXIMUM_AVAILABLE_FREE_DOWNLOADS));
- fullVersionButton.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- OsmandApplication app = ctx.getMyApplication();
- if (app.getRemoteBoolean(SHOW_PLUS_VERSION_INAPP_PARAM, true)) {
- app.logEvent(ctx, "in_app_purchase_redirect_from_banner");
- } else {
- app.logEvent(ctx, "paid_version_redirect_from_banner");
- }
- ctx.purchaseFullVersion();
- DialogFragment f = (DialogFragment) ctx.getSupportFragmentManager()
- .findFragmentByTag(FreeVersionDialogFragment.TAG);
- if (f != null) {
- f.dismiss();
- }
- }
- });
- osmLiveButton.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- ctx.getMyApplication().logEvent(ctx, "click_subscribe_live_osm");
- Intent intent = new Intent(ctx, OsmLiveActivity.class);
- intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
- intent.putExtra(OsmLiveActivity.OPEN_SUBSCRIPTION_INTENT_PARAM, true);
- ctx.startActivity(intent);
- }
- });
LinearLayout marksLinearLayout = (LinearLayout) freeVersionBanner.findViewById(R.id.marksLinearLayout);
Space spaceView = new Space(ctx);
@@ -609,11 +484,7 @@ public class DownloadActivity extends AbstractDownloadActivity implements Downlo
}
updateFreeVersionBanner();
- if(dialog) {
- expandBanner();
- } else {
- collapseBanner();
- }
+ collapseBanner();
}
public void updateFreeVersionBanner() {
@@ -630,28 +501,7 @@ public class DownloadActivity extends AbstractDownloadActivity implements Downlo
int downloadsLeft = DownloadValidationManager.MAXIMUM_AVAILABLE_FREE_DOWNLOADS - mapsDownloaded;
downloadsLeft = Math.max(downloadsLeft, 0);
downloadsLeftTextView.setText(ctx.getString(R.string.downloads_left_template, downloadsLeft));
- if(!dialog) {
- freeVersionBanner.findViewById(R.id.bannerTopLayout).setOnClickListener(onCollapseListener);
- }
-
- if (InAppHelper.hasPrices(ctx.getMyApplication()) || !updatingPrices) {
- if (!InAppHelper.hasPrices(ctx.getMyApplication())) {
- fullVersionButton.setText(ctx.getString(R.string.get_for, ctx.getString(R.string.full_version_price)));
- osmLiveButton.setText(ctx.getString(R.string.get_for_month, ctx.getString(R.string.osm_live_default_price)));
- } else {
- fullVersionButton.setText(ctx.getString(R.string.get_for, InAppHelper.getFullVersionPrice()));
- osmLiveButton.setText(ctx.getString(R.string.get_for_month, InAppHelper.getLiveUpdatesPrice()));
- }
- fullVersionProgress.setVisibility(View.GONE);
- fullVersionButton.setVisibility(View.VISIBLE);
- osmLiveProgress.setVisibility(View.GONE);
- osmLiveButton.setVisibility(View.VISIBLE);
- } else {
- fullVersionProgress.setVisibility(View.VISIBLE);
- fullVersionButton.setVisibility(View.GONE);
- osmLiveProgress.setVisibility(View.VISIBLE);
- osmLiveButton.setVisibility(View.GONE);
- }
+ freeVersionBanner.findViewById(R.id.bannerTopLayout).setOnClickListener(onCollapseListener);
}
private void setMinimizedFreeVersionBanner(boolean minimize) {
@@ -668,7 +518,6 @@ public class DownloadActivity extends AbstractDownloadActivity implements Downlo
final Integer mapsDownloaded = settings.NUMBER_OF_FREE_DOWNLOADS.get() + activeTasks;
downloadsLeftProgressBar.setProgress(mapsDownloaded);
}
-
}
public static class BannerAndDownloadFreeVersion {
@@ -681,26 +530,24 @@ public class DownloadActivity extends AbstractDownloadActivity implements Downlo
private final DownloadActivity ctx;
private boolean showSpace;
- private FreeVersionDialog freeVersionDialog;
+ private FreeVersionBanner freeVersionBanner;
public BannerAndDownloadFreeVersion(View view, final DownloadActivity ctx, boolean showSpace) {
this.ctx = ctx;
this.showSpace = showSpace;
- freeVersionDialog = new FreeVersionDialog(view, ctx, false);
+ freeVersionBanner = new FreeVersionBanner(view, ctx);
downloadProgressLayout = view.findViewById(R.id.downloadProgressLayout);
progressBar = (ProgressBar) view.findViewById(R.id.progressBar);
leftTextView = (TextView) view.findViewById(R.id.leftTextView);
rightTextView = (TextView) view.findViewById(R.id.rightTextView);
-
-
- freeVersionDialog.initFreeVersionBanner();
+ freeVersionBanner.initFreeVersionBanner();
updateBannerInProgress();
}
- public void setUpdatingPrices(boolean updatingPrices) {
- freeVersionDialog.setUpdatingPrices(updatingPrices);
+ public void updateFreeVersionBanner() {
+ freeVersionBanner.updateFreeVersionBanner();
}
public void updateBannerInProgress() {
@@ -715,13 +562,13 @@ public class DownloadActivity extends AbstractDownloadActivity implements Downlo
} else {
downloadProgressLayout.setVisibility(View.VISIBLE);
}
- freeVersionDialog.updateFreeVersionBanner();
+ freeVersionBanner.updateFreeVersionBanner();
} else {
boolean indeterminate = basicProgressAsyncTask.isIndeterminate();
String message = basicProgressAsyncTask.getDescription();
int percent = basicProgressAsyncTask.getProgressPercentage();
- freeVersionDialog.setMinimizedFreeVersionBanner(true);
- freeVersionDialog.updateAvailableDownloads();
+ freeVersionBanner.setMinimizedFreeVersionBanner(true);
+ freeVersionBanner.updateAvailableDownloads();
downloadProgressLayout.setVisibility(View.VISIBLE);
downloadProgressLayout.setOnClickListener(new OnClickListener() {
@Override
@@ -735,27 +582,14 @@ public class DownloadActivity extends AbstractDownloadActivity implements Downlo
rightTextView.setText(null);
} else {
progressBar.setProgress(percent);
-// final String format = ctx.getString(R.string.downloading_number_of_files);
leftTextView.setText(message);
rightTextView.setText(percent + "%");
}
}
}
-
-
- public void hideDownloadProgressLayout() {
- downloadProgressLayout.setVisibility(View.GONE);
- }
-
- public void showDownloadProgressLayout() {
- downloadProgressLayout.setVisibility(View.VISIBLE);
- }
-
-
-
-
}
+ @SuppressLint("StaticFieldLeak")
public void reloadLocalIndexes() {
AsyncTask> task = new AsyncTask>() {
@Override
diff --git a/OsmAnd/src/net/osmand/plus/download/ui/DownloadResourceGroupFragment.java b/OsmAnd/src/net/osmand/plus/download/ui/DownloadResourceGroupFragment.java
index acafce29f7..ffaf81b24b 100644
--- a/OsmAnd/src/net/osmand/plus/download/ui/DownloadResourceGroupFragment.java
+++ b/OsmAnd/src/net/osmand/plus/download/ui/DownloadResourceGroupFragment.java
@@ -1,5 +1,6 @@
package net.osmand.plus.download.ui;
+import android.annotation.SuppressLint;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.content.res.Resources;
@@ -41,8 +42,9 @@ import net.osmand.plus.download.DownloadResourceGroup.DownloadResourceGroupType;
import net.osmand.plus.download.DownloadResources;
import net.osmand.plus.download.DownloadValidationManager;
import net.osmand.plus.download.IndexItem;
-import net.osmand.plus.inapp.InAppHelper;
-import net.osmand.plus.inapp.InAppHelper.InAppListener;
+import net.osmand.plus.inapp.InAppPurchaseHelper;
+import net.osmand.plus.inapp.InAppPurchaseHelper.InAppPurchaseListener;
+import net.osmand.plus.inapp.InAppPurchaseHelper.InAppPurchaseTaskType;
import net.osmand.util.Algorithms;
import org.json.JSONException;
@@ -55,7 +57,7 @@ import java.util.List;
import java.util.Map;
public class DownloadResourceGroupFragment extends DialogFragment implements DownloadEvents,
- InAppListener, OnChildClickListener {
+ InAppPurchaseListener, OnChildClickListener {
public static final int RELOAD_ID = 0;
public static final int SEARCH_ID = 1;
public static final String TAG = "RegionDialogFragment";
@@ -67,6 +69,7 @@ public class DownloadResourceGroupFragment extends DialogFragment implements Dow
protected DownloadResourceGroupAdapter listAdapter;
private DownloadResourceGroup group;
private DownloadActivity activity;
+ private InAppPurchaseHelper purchaseHelper;
private Toolbar toolbar;
private View searchView;
private View restorePurchasesView;
@@ -75,6 +78,7 @@ public class DownloadResourceGroupFragment extends DialogFragment implements Dow
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+ purchaseHelper = getDownloadActivity().getPurchaseHelper();
boolean isLightTheme = getMyApplication().getSettings().OSMAND_THEME.get() == OsmandSettings.OSMAND_LIGHT_THEME;
int themeId = isLightTheme ? R.style.OsmandLightTheme : R.style.OsmandDarkTheme;
setStyle(STYLE_NO_FRAME, themeId);
@@ -152,7 +156,7 @@ public class DownloadResourceGroupFragment extends DialogFragment implements Dow
}
private void addRestorePurchasesRow() {
- if (!openAsDialog() && !InAppHelper.isInAppIntentoryRead()) {
+ if (!openAsDialog() && purchaseHelper != null && !purchaseHelper.hasInventory()) {
restorePurchasesView = activity.getLayoutInflater().inflate(R.layout.restore_purchases_list_footer, null);
((ImageView) restorePurchasesView.findViewById(R.id.icon)).setImageDrawable(
getMyApplication().getIconsCache().getThemedIcon(R.drawable.ic_action_reset_to_default_dark));
@@ -160,7 +164,7 @@ public class DownloadResourceGroupFragment extends DialogFragment implements Dow
@Override
public void onClick(View v) {
restorePurchasesView.findViewById(R.id.progressBar).setVisibility(View.VISIBLE);
- activity.startInAppHelper();
+ purchaseHelper.requestInventory();
}
});
listView.addFooterView(restorePurchasesView);
@@ -205,7 +209,7 @@ public class DownloadResourceGroupFragment extends DialogFragment implements Dow
}
}
if (restorePurchasesView != null && restorePurchasesView.findViewById(R.id.container).getVisibility() == View.GONE
- && !InAppHelper.isInAppIntentoryRead()) {
+ && purchaseHelper != null && !purchaseHelper.hasInventory()) {
if (worldBaseMapItem != null && worldBaseMapItem.isDownloaded()) {
restorePurchasesView.findViewById(R.id.container).setVisibility(View.VISIBLE);
}
@@ -260,6 +264,7 @@ public class DownloadResourceGroupFragment extends DialogFragment implements Dow
alertDialog.show();
}
+ @SuppressLint("StaticFieldLeak")
private void doSubscribe(final String email) {
new AsyncTask() {
@@ -329,7 +334,7 @@ public class DownloadResourceGroupFragment extends DialogFragment implements Dow
}
@Override
- public void onError(String error) {
+ public void onError(InAppPurchaseTaskType taskType, String error) {
}
@Override
@@ -346,11 +351,11 @@ public class DownloadResourceGroupFragment extends DialogFragment implements Dow
}
@Override
- public void showProgress() {
+ public void showProgress(InAppPurchaseTaskType taskType) {
}
@Override
- public void dismissProgress() {
+ public void dismissProgress(InAppPurchaseTaskType taskType) {
if (restorePurchasesView != null && restorePurchasesView.findViewById(R.id.container).getVisibility() == View.VISIBLE) {
restorePurchasesView.findViewById(R.id.progressBar).setVisibility(View.GONE);
}
diff --git a/OsmAnd/src/net/osmand/plus/download/ui/FreeVersionDialogFragment.java b/OsmAnd/src/net/osmand/plus/download/ui/FreeVersionDialogFragment.java
deleted file mode 100644
index 5cabbd16e7..0000000000
--- a/OsmAnd/src/net/osmand/plus/download/ui/FreeVersionDialogFragment.java
+++ /dev/null
@@ -1,44 +0,0 @@
-package net.osmand.plus.download.ui;
-
-import android.app.Dialog;
-import android.os.Bundle;
-import android.support.annotation.NonNull;
-import android.support.v4.app.DialogFragment;
-import android.support.v7.app.AlertDialog;
-import android.support.v7.view.ContextThemeWrapper;
-import android.view.View;
-
-import net.osmand.plus.OsmandApplication;
-import net.osmand.plus.R;
-import net.osmand.plus.Version;
-import net.osmand.plus.download.DownloadActivity;
-import net.osmand.plus.download.DownloadActivity.FreeVersionDialog;
-
-import static net.osmand.plus.OsmandApplication.SHOW_PLUS_VERSION_INAPP_PARAM;
-
-public class FreeVersionDialogFragment extends DialogFragment {
- public static final String TAG = "FreeVersionDialogFragment";
- private FreeVersionDialog dialog;
-
- @NonNull
- @Override
- public Dialog onCreateDialog(Bundle savedInstanceState) {
- OsmandApplication app = (OsmandApplication) getActivity().getApplication();
- app.activateFetchedRemoteParams();
-
- AlertDialog.Builder builder = new AlertDialog.Builder(new ContextThemeWrapper(getActivity(), R.style.OsmandDarkTheme));
- builder.setNegativeButton(R.string.later, null);
- View view = getActivity().getLayoutInflater().inflate(R.layout.free_version_banner, null);
- builder.setView(view);
-
- dialog = new DownloadActivity.FreeVersionDialog(view, getDownloadActivity(), true);
- dialog.initFreeVersionBanner();
- dialog.expandBanner();
- return builder.create();
- }
-
- DownloadActivity getDownloadActivity() {
- return (DownloadActivity) getActivity();
- }
-
-}
\ No newline at end of file
diff --git a/OsmAnd/src/net/osmand/plus/helpers/DiscountHelper.java b/OsmAnd/src/net/osmand/plus/helpers/DiscountHelper.java
index f8037fa806..239eac2c6b 100644
--- a/OsmAnd/src/net/osmand/plus/helpers/DiscountHelper.java
+++ b/OsmAnd/src/net/osmand/plus/helpers/DiscountHelper.java
@@ -14,7 +14,7 @@ import net.osmand.plus.OsmandSettings;
import net.osmand.plus.R;
import net.osmand.plus.Version;
import net.osmand.plus.activities.MapActivity;
-import net.osmand.plus.inapp.InAppHelper;
+import net.osmand.plus.inapp.InAppPurchaseHelper;
import net.osmand.plus.liveupdates.OsmLiveActivity;
import net.osmand.plus.views.mapwidgets.MapInfoWidgetsFactory.TopToolbarController;
import net.osmand.plus.views.mapwidgets.MapInfoWidgetsFactory.TopToolbarControllerType;
@@ -109,7 +109,8 @@ public class DiscountHelper {
if (url.startsWith(INAPP_PREFIX) && url.length() > INAPP_PREFIX.length()) {
String inAppSku = url.substring(INAPP_PREFIX.length());
- if (InAppHelper.isPurchased(app, inAppSku)) {
+ InAppPurchaseHelper purchaseHelper = app.getInAppPurchaseHelper();
+ if (purchaseHelper != null && purchaseHelper.isPurchased(inAppSku)) {
return;
}
}
@@ -210,15 +211,11 @@ public class DiscountHelper {
private static void openUrl(final MapActivity mapActivity, String url) {
if (url.startsWith(INAPP_PREFIX)) {
- if (url.contains(InAppHelper.SKU_FULL_VERSION_PRICE)) {
- mapActivity.execInAppTask(new InAppHelper.InAppRunnable() {
- @Override
- public void run(InAppHelper helper) {
- mapActivity.getMyApplication().logEvent(mapActivity, "in_app_purchase_redirect");
- helper.purchaseFullVersion(mapActivity);
- }
- });
- } else if (url.contains(InAppHelper.SKU_LIVE_UPDATES)){
+ if (url.contains(InAppPurchaseHelper.SKU_FULL_VERSION_PRICE)) {
+ OsmandApplication app = mapActivity.getMyApplication();
+ app.logEvent(mapActivity, "in_app_purchase_redirect");
+ app.getInAppPurchaseHelper().purchaseFullVersion(mapActivity);
+ } else if (url.contains(InAppPurchaseHelper.SKU_LIVE_UPDATES)){
Intent intent = new Intent(mapActivity, OsmLiveActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
intent.putExtra(OsmLiveActivity.OPEN_SUBSCRIPTION_INTENT_PARAM, true);
diff --git a/OsmAnd/src/net/osmand/plus/inapp/InAppHelper.java b/OsmAnd/src/net/osmand/plus/inapp/InAppPurchaseHelper.java
similarity index 55%
rename from OsmAnd/src/net/osmand/plus/inapp/InAppHelper.java
rename to OsmAnd/src/net/osmand/plus/inapp/InAppPurchaseHelper.java
index 51ab4e5539..65e8cb08be 100644
--- a/OsmAnd/src/net/osmand/plus/inapp/InAppHelper.java
+++ b/OsmAnd/src/net/osmand/plus/inapp/InAppPurchaseHelper.java
@@ -1,5 +1,6 @@
package net.osmand.plus.inapp;
+import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Intent;
import android.os.AsyncTask;
@@ -26,29 +27,29 @@ import net.osmand.util.Algorithms;
import org.json.JSONException;
import org.json.JSONObject;
+import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
-public class InAppHelper {
+public class InAppPurchaseHelper {
// Debug tag, for logging
- static final String TAG = "InAppHelper";
+ private static final String TAG = InAppPurchaseHelper.class.getSimpleName();
boolean mDebugLog = false;
- private static boolean mSubscribedToLiveUpdates = false;
- private static boolean mFullVersionPurchased = false;
- private static boolean mDepthContoursPurchased = false;
- private static String mLiveUpdatesPrice;
- private static long lastValidationCheckTime;
- private static String mFullVersionPrice;
- private static String mDepthContoursPrice;
+ private long lastValidationCheckTime;
+ private String liveUpdatesPrice;
+ private String fullVersionPrice;
+ private String depthContoursPrice;
public static final String SKU_FULL_VERSION_PRICE = "osmand_full_version_price";
+
private static final String SKU_LIVE_UPDATES_FULL = "osm_live_subscription_2";
private static final String SKU_LIVE_UPDATES_FREE = "osm_free_live_subscription_2";
private static final String SKU_DEPTH_CONTOURS_FULL = "net.osmand.seadepth_plus";
private static final String SKU_DEPTH_CONTOURS_FREE = "net.osmand.seadepth";
+
public static String SKU_LIVE_UPDATES;
public static String SKU_DEPTH_CONTOURS;
@@ -58,27 +59,25 @@ public class InAppHelper {
// The helper object
private IabHelper mHelper;
- private boolean stopAfterResult = false;
- private boolean isDeveloperVersion = false;
- private boolean forceRequestInventory = false;
+ private boolean isDeveloperVersion;
private String token = "";
- private boolean inventoryRequesting = false;
- private boolean stopRequested = false;
+ private InAppPurchaseTaskType activeTask;
+ private boolean processingTask = false;
private OsmandApplication ctx;
- private List listeners = new ArrayList<>();
+ private List listeners = new ArrayList<>();
/* base64EncodedPublicKey should be YOUR APPLICATION'S PUBLIC KEY
- * (that you got from the Google Play developer console). This is not your
- * developer public key, it's the *app-specific* public key.
- *
- * Instead of just storing the entire literal string here embedded in the
- * program, construct the key at runtime from pieces or
- * use bit manipulation (for example, XOR with some other string) to hide
- * the actual key. The key itself is not secret information, but we don't
- * want to make it easy for an attacker to replace the public key with one
- * of their own and then fake messages from the server.
- */
+ * (that you got from the Google Play developer console). This is not your
+ * developer public key, it's the *app-specific* public key.
+ *
+ * Instead of just storing the entire literal string here embedded in the
+ * program, construct the key at runtime from pieces or
+ * use bit manipulation (for example, XOR with some other string) to hide
+ * the actual key. The key itself is not secret information, but we don't
+ * want to make it easy for an attacker to replace the public key with one
+ * of their own and then fake messages from the server.
+ */
private static final String BASE64_ENCODED_PUBLIC_KEY = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAgk8cEx" +
"UO4mfEwWFLkQnX1Tkzehr4SnXLXcm2Osxs5FTJPEgyTckTh0POKVMrxeGLn0KoTY2NTgp1U/inp" +
"wccWisPhVPEmw9bAVvWsOkzlyg1kv03fJdnAXRBSqDDPV6X8Z3MtkPVqZkupBsxyIllEILKHK06" +
@@ -86,60 +85,64 @@ public class InAppHelper {
"I+ftJO46a1XkNh1dO2anUiQ8P/H4yOTqnMsXF7biyYuiwjXPOcy0OMhEHi54Dq6Mr3u5ZALOAkc" +
"YTjh1H/ZgqIHy5ZluahINuDE76qdLYMXrDMQIDAQAB";
- public interface InAppListener {
- void onError(String error);
+ public interface InAppPurchaseListener {
+ void onError(InAppPurchaseTaskType taskType, String error);
void onGetItems();
void onItemPurchased(String sku);
- void showProgress();
+ void showProgress(InAppPurchaseTaskType taskType);
- void dismissProgress();
+ void dismissProgress(InAppPurchaseTaskType taskType);
+ }
+
+ public enum InAppPurchaseTaskType {
+ REQUEST_INVENTORY,
+ PURCHASE_FULL_VERSION,
+ PURCHASE_LIVE_UPDATES,
+ PURCHASE_DEPTH_CONTOURS
}
public interface InAppRunnable {
- void run(InAppHelper helper);
+ // return true if done and false if async task started
+ boolean run(InAppPurchaseHelper helper);
}
public String getToken() {
return token;
}
- public static boolean isSubscribedToLiveUpdates() {
- return mSubscribedToLiveUpdates;
+ public InAppPurchaseTaskType getActiveTask() {
+ return activeTask;
}
- public static boolean isFullVersionPurchased() {
- return mFullVersionPurchased;
+ public boolean isSubscribedToLiveUpdates() {
+ return ctx.getSettings().LIVE_UPDATES_PURCHASED.get();
}
- public static boolean isDepthContoursPurchased() {
- return mDepthContoursPurchased;
+ public String getLiveUpdatesPrice() {
+ return liveUpdatesPrice;
}
- public static String getLiveUpdatesPrice() {
- return mLiveUpdatesPrice;
+ public String getFullVersionPrice() {
+ return fullVersionPrice;
}
- public static String getDepthContoursPrice() {
- return mDepthContoursPrice;
+ public String getDepthContoursPrice() {
+ return depthContoursPrice;
}
- public static String getFullVersionPrice() {
- return mFullVersionPrice;
- }
-
- public static String getSkuLiveUpdates() {
+ public String getSkuLiveUpdates() {
return SKU_LIVE_UPDATES;
}
- public static boolean hasPrices(OsmandApplication app) {
- return !Algorithms.isEmpty(mLiveUpdatesPrice)
- && (!Version.isFreeVersion(app) || !Algorithms.isEmpty(mFullVersionPrice));
+ public boolean hasPrices() {
+ return !Algorithms.isEmpty(liveUpdatesPrice)
+ && (!Version.isFreeVersion(ctx) || !Algorithms.isEmpty(fullVersionPrice));
}
- public static void initialize(OsmandApplication ctx) {
+ private void initialize() {
if (SKU_LIVE_UPDATES == null) {
if (Version.isFreeVersion(ctx)) {
SKU_LIVE_UPDATES = SKU_LIVE_UPDATES_FREE;
@@ -156,26 +159,22 @@ public class InAppHelper {
}
}
- public InAppHelper(OsmandApplication ctx, boolean forceRequestInventory) {
+ public InAppPurchaseHelper(OsmandApplication ctx) {
this.ctx = ctx;
- this.forceRequestInventory = forceRequestInventory;
-
- isDeveloperVersion = Version.isDeveloperVersion(ctx);
- if (isDeveloperVersion) {
- mSubscribedToLiveUpdates = true;
- mFullVersionPurchased = true;
- mDepthContoursPurchased = true;
+ this.isDeveloperVersion = Version.isDeveloperVersion(ctx);
+ if (this.isDeveloperVersion) {
ctx.getSettings().LIVE_UPDATES_PURCHASED.set(true);
ctx.getSettings().FULL_VERSION_PURCHASED.set(true);
ctx.getSettings().DEPTH_CONTOURS_PURCHASED.set(true);
}
+ initialize();
}
- public static boolean isInAppIntentoryRead() {
+ public boolean hasInventory() {
return lastValidationCheckTime != 0;
}
- public static boolean isPurchased(OsmandApplication ctx, String inAppSku) {
+ public boolean isPurchased(String inAppSku) {
OsmandSettings settings = ctx.getSettings();
if (inAppSku.equals(SKU_FULL_VERSION_PRICE)) {
return settings.FULL_VERSION_PURCHASED.get();
@@ -187,11 +186,18 @@ public class InAppHelper {
return false;
}
- public void exec(final @NonNull InAppRunnable runnable) {
- this.stopAfterResult = true;
+ private void exec(final @NonNull InAppPurchaseTaskType taskType, final @NonNull InAppRunnable runnable) {
+ if (isDeveloperVersion || !Version.isGooglePlayEnabled(ctx)) {
+ return;
+ }
+
+ if (processingTask) {
+ logError("Already processing task: " + taskType + ". Exit.");
+ return;
+ }
// Create the helper, passing it our context and the public key to verify signatures with
- logDebug("Creating InAppHelper.");
+ logDebug("Creating InAppPurchaseHelper.");
mHelper = new IabHelper(ctx, BASE64_ENCODED_PUBLIC_KEY);
// enable debug logging (for a production application, you should set this to false).
@@ -201,6 +207,8 @@ public class InAppHelper {
// will be called once setup completes.
logDebug("Starting setup.");
try {
+ processingTask = true;
+ activeTask = taskType;
mHelper.startSetup(new IabHelper.OnIabSetupFinishedListener() {
public void onIabSetupFinished(IabResult result) {
logDebug("Setup finished.");
@@ -208,166 +216,165 @@ public class InAppHelper {
if (!result.isSuccess()) {
// Oh noes, there was a problem.
//complain("Problem setting up in-app billing: " + result);
- notifyError(result.getMessage());
- if (stopAfterResult) {
- stop();
- }
+ notifyError(taskType, result.getMessage());
+ stop(true);
return;
}
// Have we been disposed of in the meantime? If so, quit.
- if (mHelper == null) return;
+ if (mHelper == null) {
+ stop(true);
+ return;
+ }
- runnable.run(InAppHelper.this);
+ processingTask = !runnable.run(InAppPurchaseHelper.this);
}
});
} catch (Exception e) {
logError("exec Error", e);
- if (stopAfterResult) {
- stop();
- }
+ stop(true);
}
}
- public void start(final boolean stopAfterResult) {
- this.stopAfterResult = stopAfterResult;
+ public boolean needRequestInventory() {
+ return !ctx.getSettings().BILLING_PURCHASE_TOKEN_SENT.get()
+ || System.currentTimeMillis() - lastValidationCheckTime > PURCHASE_VALIDATION_PERIOD_MSEC;
+ }
- // Create the helper, passing it our context and the public key to verify signatures with
- logDebug("Creating InAppHelper.");
- mHelper = new IabHelper(ctx, BASE64_ENCODED_PUBLIC_KEY);
-
- // enable debug logging (for a production application, you should set this to false).
- mHelper.enableDebugLogging(false);
-
- // Start setup. This is asynchronous and the specified listener
- // will be called once setup completes.
- logDebug("Starting setup.");
- try {
- mHelper.startSetup(new IabHelper.OnIabSetupFinishedListener() {
- public void onIabSetupFinished(IabResult result) {
- logDebug("Setup finished.");
-
- if (!result.isSuccess()) {
- // Oh noes, there was a problem.
- //complain("Problem setting up in-app billing: " + result);
- notifyError(result.getMessage());
- if (stopAfterResult) {
- stop();
- }
- return;
- }
-
- // Have we been disposed of in the meantime? If so, quit.
- if (mHelper == null) return;
-
- // IAB is fully set up. Now, let's get an inventory of stuff we own if needed.
- if (forceRequestInventory || (!isDeveloperVersion &&
- (!mSubscribedToLiveUpdates
- || !ctx.getSettings().BILLING_PURCHASE_TOKEN_SENT.get()
- || System.currentTimeMillis() - lastValidationCheckTime > PURCHASE_VALIDATION_PERIOD_MSEC))) {
-
- logDebug("Setup successful. Querying inventory.");
- List skus = new ArrayList<>();
- skus.add(SKU_LIVE_UPDATES);
- skus.add(SKU_DEPTH_CONTOURS);
- skus.add(SKU_FULL_VERSION_PRICE);
- try {
- inventoryRequesting = true;
- mHelper.queryInventoryAsync(true, skus, mGotInventoryListener);
- } catch (Exception e) {
- inventoryRequesting = false;
- logError("queryInventoryAsync Error", e);
- notifyDismissProgress();
- if (stopAfterResult) {
- stop();
- }
- }
- } else {
- notifyDismissProgress();
- if (stopAfterResult) {
- stop();
- }
- }
+ public void requestInventory() {
+ notifyShowProgress(InAppPurchaseTaskType.REQUEST_INVENTORY);
+ exec(InAppPurchaseTaskType.REQUEST_INVENTORY, new InAppRunnable() {
+ @Override
+ public boolean run(InAppPurchaseHelper helper) {
+ logDebug("Setup successful. Querying inventory.");
+ List skus = new ArrayList<>();
+ skus.add(SKU_LIVE_UPDATES);
+ skus.add(SKU_DEPTH_CONTOURS);
+ skus.add(SKU_FULL_VERSION_PRICE);
+ try {
+ mHelper.queryInventoryAsync(true, skus, mGotInventoryListener);
+ return false;
+ } catch (Exception e) {
+ logError("queryInventoryAsync Error", e);
+ notifyDismissProgress(InAppPurchaseTaskType.REQUEST_INVENTORY);
+ stop(true);
}
- });
- } catch (Exception e) {
- logError("start Error", e);
- if (stopAfterResult) {
- stop();
+ return true;
}
- }
+ });
+ }
+
+ public void purchaseFullVersion(final Activity activity) {
+ notifyShowProgress(InAppPurchaseTaskType.PURCHASE_FULL_VERSION);
+ exec(InAppPurchaseTaskType.PURCHASE_FULL_VERSION, new InAppRunnable() {
+ @Override
+ public boolean run(InAppPurchaseHelper helper) {
+ try {
+ mHelper.launchPurchaseFlow(activity,
+ SKU_FULL_VERSION_PRICE, RC_REQUEST, mPurchaseFinishedListener);
+ return false;
+ } catch (Exception e) {
+ complain("Cannot launch full version purchase!");
+ logError("purchaseFullVersion Error", e);
+ stop(true);
+ }
+ return true;
+ }
+ });
+ }
+
+ public void purchaseLiveUpdates(Activity activity, String email, String userName,
+ String countryDownloadName, boolean hideUserName) {
+ notifyShowProgress(InAppPurchaseTaskType.PURCHASE_LIVE_UPDATES);
+ new LiveUpdatesPurchaseTask(activity, email, userName, countryDownloadName, hideUserName)
+ .executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void) null);
+ }
+
+ public void purchaseDepthContours(final Activity activity) {
+ notifyShowProgress(InAppPurchaseTaskType.PURCHASE_DEPTH_CONTOURS);
+ exec(InAppPurchaseTaskType.PURCHASE_DEPTH_CONTOURS, new InAppRunnable() {
+ @Override
+ public boolean run(InAppPurchaseHelper helper) {
+ try {
+ mHelper.launchPurchaseFlow(activity,
+ SKU_DEPTH_CONTOURS, RC_REQUEST, mPurchaseFinishedListener);
+ return false;
+ } catch (Exception e) {
+ complain("Cannot launch depth contours purchase!");
+ logError("purchaseDepthContours Error", e);
+ stop(true);
+ }
+ return true;
+ }
+ });
}
// Listener that's called when we finish querying the items and subscriptions we own
private QueryInventoryFinishedListener mGotInventoryListener = new QueryInventoryFinishedListener() {
public void onQueryInventoryFinished(IabResult result, Inventory inventory) {
logDebug("Query inventory finished.");
- inventoryRequesting = false;
// Have we been disposed of in the meantime? If so, quit.
- if (mHelper == null) return;
+ if (mHelper == null) {
+ stop(true);
+ return;
+ }
// Is it a failure?
- if (result.isFailure() || stopRequested) {
+ if (result.isFailure()) {
logError("Failed to query inventory: " + result);
- notifyError(result.getMessage());
- if (stopAfterResult || stopRequested) {
- stop();
- }
+ notifyError(InAppPurchaseTaskType.REQUEST_INVENTORY, result.getMessage());
+ stop(true);
return;
}
logDebug("Query inventory was successful.");
- /*
+ /*
* Check for items we own. Notice that for each purchase, we check
- * the developer payload to see if it's correct! See
- * verifyDeveloperPayload().
- */
+ * the developer payload to see if it's correct! See
+ * verifyDeveloperPayload().
+ */
// Do we have the live updates?
Purchase liveUpdatesPurchase = inventory.getPurchase(SKU_LIVE_UPDATES);
- mSubscribedToLiveUpdates = isDeveloperVersion || (liveUpdatesPurchase != null && liveUpdatesPurchase.getPurchaseState() == 0);
- if (mSubscribedToLiveUpdates) {
- ctx.getSettings().LIVE_UPDATES_PURCHASED.set(true);
- }
+ boolean subscribedToLiveUpdates = (liveUpdatesPurchase != null && liveUpdatesPurchase.getPurchaseState() == 0);
+ //subscribedToLiveUpdates = false;
+ ctx.getSettings().LIVE_UPDATES_PURCHASED.set(subscribedToLiveUpdates);
Purchase fullVersionPurchase = inventory.getPurchase(SKU_FULL_VERSION_PRICE);
- mFullVersionPurchased = isDeveloperVersion || (fullVersionPurchase != null && fullVersionPurchase.getPurchaseState() == 0);
- if (mFullVersionPurchased) {
+ boolean fullVersionPurchased = (fullVersionPurchase != null && fullVersionPurchase.getPurchaseState() == 0);
+ if (fullVersionPurchased) {
ctx.getSettings().FULL_VERSION_PURCHASED.set(true);
}
Purchase depthContoursPurchase = inventory.getPurchase(SKU_DEPTH_CONTOURS);
- mDepthContoursPurchased = isDeveloperVersion || (depthContoursPurchase != null && depthContoursPurchase.getPurchaseState() == 0);
- if (mDepthContoursPurchased) {
+ boolean depthContoursPurchased = (depthContoursPurchase != null && depthContoursPurchase.getPurchaseState() == 0);
+ if (depthContoursPurchased) {
ctx.getSettings().DEPTH_CONTOURS_PURCHASED.set(true);
}
lastValidationCheckTime = System.currentTimeMillis();
- logDebug("User " + (mSubscribedToLiveUpdates ? "HAS" : "DOES NOT HAVE")
+ logDebug("User " + (subscribedToLiveUpdates ? "HAS" : "DOES NOT HAVE")
+ " live updates purchased.");
if (inventory.hasDetails(SKU_LIVE_UPDATES)) {
SkuDetails liveUpdatesDetails = inventory.getSkuDetails(SKU_LIVE_UPDATES);
- mLiveUpdatesPrice = liveUpdatesDetails.getPrice();
+ liveUpdatesPrice = liveUpdatesDetails.getPrice();
}
-
- if (inventory.hasDetails(SKU_DEPTH_CONTOURS)) {
- SkuDetails depthContoursDetails = inventory.getSkuDetails(SKU_DEPTH_CONTOURS);
- mDepthContoursPrice = depthContoursDetails.getPrice();
- }
-
if (inventory.hasDetails(SKU_FULL_VERSION_PRICE)) {
SkuDetails fullPriceDetails = inventory.getSkuDetails(SKU_FULL_VERSION_PRICE);
- mFullVersionPrice = fullPriceDetails.getPrice();
+ fullVersionPrice = fullPriceDetails.getPrice();
+ }
+ if (inventory.hasDetails(SKU_DEPTH_CONTOURS)) {
+ SkuDetails depthContoursDetails = inventory.getSkuDetails(SKU_DEPTH_CONTOURS);
+ depthContoursPrice = depthContoursDetails.getPrice();
}
-
OsmandSettings settings = ctx.getSettings();
settings.INAPPS_READ.set(true);
boolean needSendToken = false;
- if (!isDeveloperVersion && liveUpdatesPurchase != null) {
+ if (liveUpdatesPurchase != null) {
if ((Algorithms.isEmpty(settings.BILLING_USER_ID.get()) || Algorithms.isEmpty(settings.BILLING_USER_TOKEN.get()))
&& !Algorithms.isEmpty(liveUpdatesPurchase.getDeveloperPayload())) {
String payload = liveUpdatesPurchase.getDeveloperPayload();
@@ -390,11 +397,9 @@ public class InAppHelper {
final OnRequestResultListener listener = new OnRequestResultListener() {
@Override
public void onResult(String result) {
- notifyDismissProgress();
+ notifyDismissProgress(InAppPurchaseTaskType.REQUEST_INVENTORY);
notifyGetItems();
- if (stopAfterResult || stopRequested) {
- stop();
- }
+ stop(true);
logDebug("Initial inapp query finished");
}
};
@@ -407,159 +412,107 @@ public class InAppHelper {
}
};
- public void purchaseFullVersion(final Activity activity) {
- if (mHelper == null) {
- //complain("In-app hepler is not initialized!");
- notifyError("In-app hepler is not initialized!");
- if (stopAfterResult) {
- stop();
- }
- return;
+ @SuppressLint("StaticFieldLeak")
+ private class LiveUpdatesPurchaseTask extends AsyncTask {
+
+ private WeakReference activity;
+
+ private String email;
+ private String userName;
+ private String countryDownloadName;
+ private boolean hideUserName;
+
+ private String userId;
+
+ LiveUpdatesPurchaseTask(Activity activity, String email, String userName,
+ String countryDownloadName, boolean hideUserName) {
+ this.activity = new WeakReference<>(activity);
+
+ this.email = email;
+ this.userName = userName;
+ this.countryDownloadName = countryDownloadName;
+ this.hideUserName = hideUserName;
}
- logDebug("Launching purchase flow for full version");
- if (mHelper != null) {
+ @Override
+ protected String doInBackground(Void... params) {
+ userId = ctx.getSettings().BILLING_USER_ID.get();
try {
- mHelper.launchPurchaseFlow(activity,
- SKU_FULL_VERSION_PRICE, RC_REQUEST, mPurchaseFinishedListener);
+ Map parameters = new HashMap<>();
+ parameters.put("visibleName", hideUserName ? "" : userName);
+ parameters.put("preferredCountry", countryDownloadName);
+ parameters.put("email", email);
+ if (Algorithms.isEmpty(userId)) {
+ parameters.put("status", "new");
+ }
+
+ return AndroidNetworkUtils.sendRequest(ctx,
+ "http://download.osmand.net/subscription/register.php",
+ parameters, "Requesting userId...", true, true);
+
} catch (Exception e) {
- complain("Cannot launch full version purchase!");
- logError("purchaseFullVersion Error", e);
- if (stopAfterResult) {
- stop();
- }
+ logError("sendRequest Error", e);
+ return null;
}
}
- }
- public void purchaseDepthContours(final Activity activity) {
- if (mHelper == null) {
- //complain("In-app hepler is not initialized!");
- notifyError("In-app hepler is not initialized!");
- if (stopAfterResult) {
- stop();
- }
- return;
- }
-
- logDebug("Launching purchase flow for sea depth contours");
- if (mHelper != null) {
- try {
- mHelper.launchPurchaseFlow(activity,
- SKU_DEPTH_CONTOURS, RC_REQUEST, mPurchaseFinishedListener);
- } catch (Exception e) {
- complain("Cannot launch depth contours purchase!");
- logError("purchaseDepthContours Error", e);
- if (stopAfterResult) {
- stop();
- }
- }
- }
- }
-
- public void purchaseLiveUpdates(final Activity activity, final String email, final String userName,
- final String countryDownloadName, final boolean hideUserName) {
- try {
- if (mHelper == null || !mHelper.subscriptionsSupported()) {
- complain("Subscriptions not supported on your device yet. Sorry!");
- notifyError("Subscriptions not supported on your device yet. Sorry!");
- if (stopAfterResult) {
- stop();
- }
+ @Override
+ protected void onPostExecute(String response) {
+ logDebug("Response=" + response);
+ if (response == null) {
+ complain("Cannot retrieve userId from server.");
+ notifyDismissProgress(InAppPurchaseTaskType.PURCHASE_LIVE_UPDATES);
+ notifyError(InAppPurchaseTaskType.PURCHASE_LIVE_UPDATES, "Cannot retrieve userId from server.");
+ stop(true);
return;
- }
- } catch (Exception e) {
- logError("purchaseLiveUpdates Error", e);
- if (stopAfterResult) {
- stop();
- }
- return;
- }
- notifyShowProgress();
-
- new AsyncTask() {
-
- private String userId;
-
- @Override
- protected String doInBackground(Void... params) {
- userId = ctx.getSettings().BILLING_USER_ID.get();
+ } else {
try {
- Map parameters = new HashMap<>();
- parameters.put("visibleName", hideUserName ? "" : userName);
- parameters.put("preferredCountry", countryDownloadName);
- parameters.put("email", email);
- if (Algorithms.isEmpty(userId)) {
- parameters.put("status", "new");
- }
-
- return AndroidNetworkUtils.sendRequest(ctx,
- "http://download.osmand.net/subscription/register.php",
- parameters, "Requesting userId...", true, true);
-
- } catch (Exception e) {
- logError("sendRequest Error", e);
- return null;
+ JSONObject obj = new JSONObject(response);
+ userId = obj.getString("userid");
+ ctx.getSettings().BILLING_USER_ID.set(userId);
+ token = obj.getString("token");
+ ctx.getSettings().BILLING_USER_TOKEN.set(token);
+ logDebug("UserId=" + userId);
+ } catch (JSONException e) {
+ String message = "JSON parsing error: "
+ + (e.getMessage() == null ? "unknown" : e.getMessage());
+ complain(message);
+ notifyDismissProgress(InAppPurchaseTaskType.PURCHASE_LIVE_UPDATES);
+ notifyError(InAppPurchaseTaskType.PURCHASE_LIVE_UPDATES, message);
+ stop(true);
}
}
- @Override
- protected void onPostExecute(String response) {
- logDebug("Response=" + response);
- if (response == null) {
- complain("Cannot retrieve userId from server.");
- notifyDismissProgress();
- notifyError("Cannot retrieve userId from server.");
- if (stopAfterResult) {
- stop();
- }
- return;
-
- } else {
- try {
- JSONObject obj = new JSONObject(response);
- userId = obj.getString("userid");
- ctx.getSettings().BILLING_USER_ID.set(userId);
- token = obj.getString("token");
- ctx.getSettings().BILLING_USER_TOKEN.set(token);
- logDebug("UserId=" + userId);
- } catch (JSONException e) {
- String message = "JSON parsing error: "
- + (e.getMessage() == null ? "unknown" : e.getMessage());
- complain(message);
- notifyDismissProgress();
- notifyError(message);
- if (stopAfterResult) {
- stop();
- }
- }
- }
-
- notifyDismissProgress();
- if (!Algorithms.isEmpty(userId)) {
- logDebug("Launching purchase flow for live updates subscription for userId=" + userId);
- String payload = userId + " " + token;
- if (mHelper != null) {
+ notifyDismissProgress(InAppPurchaseTaskType.PURCHASE_LIVE_UPDATES);
+ if (!Algorithms.isEmpty(userId)) {
+ logDebug("Launching purchase flow for live updates subscription for userId=" + userId);
+ final String payload = userId + " " + token;
+ exec(InAppPurchaseTaskType.PURCHASE_LIVE_UPDATES, new InAppRunnable() {
+ @Override
+ public boolean run(InAppPurchaseHelper helper) {
try {
- mHelper.launchPurchaseFlow(activity,
- SKU_LIVE_UPDATES, IabHelper.ITEM_TYPE_SUBS,
- RC_REQUEST, mPurchaseFinishedListener, payload);
+ Activity a = activity.get();
+ if (a != null) {
+ mHelper.launchPurchaseFlow(a,
+ SKU_LIVE_UPDATES, IabHelper.ITEM_TYPE_SUBS,
+ RC_REQUEST, mPurchaseFinishedListener, payload);
+ return false;
+ } else {
+ stop(true);
+ }
} catch (Exception e) {
logError("launchPurchaseFlow Error", e);
- if (stopAfterResult) {
- stop();
- }
+ stop(true);
}
+ return true;
}
- } else {
- notifyError("Empty userId");
- if (stopAfterResult) {
- stop();
- }
- }
+ });
+ } else {
+ notifyError(InAppPurchaseTaskType.PURCHASE_LIVE_UPDATES,"Empty userId");
+ stop(true);
}
- }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void) null);
+ }
}
public boolean onActivityResultHandled(int requestCode, int resultCode, Intent data) {
@@ -590,15 +543,16 @@ public class InAppHelper {
logDebug("Purchase finished: " + result + ", purchase: " + purchase);
// if we were disposed of in the meantime, quit.
- if (mHelper == null) return;
+ if (mHelper == null) {
+ stop(true);
+ return;
+ }
if (result.isFailure()) {
complain("Error purchasing: " + result);
- notifyDismissProgress();
- notifyError("Error purchasing: " + result);
- if (stopAfterResult) {
- stop();
- }
+ notifyDismissProgress(activeTask);
+ notifyError(activeTask, "Error purchasing: " + result);
+ stop(true);
return;
}
@@ -611,58 +565,61 @@ public class InAppHelper {
@Override
public void onResult(String result) {
showToast(ctx.getString(R.string.osm_live_thanks));
- mSubscribedToLiveUpdates = true;
ctx.getSettings().LIVE_UPDATES_PURCHASED.set(true);
- notifyDismissProgress();
+ notifyDismissProgress(InAppPurchaseTaskType.PURCHASE_LIVE_UPDATES);
notifyItemPurchased(SKU_LIVE_UPDATES);
- if (stopAfterResult) {
- stop();
- }
+ stop(true);
}
});
- }
- if (purchase.getSku().equals(SKU_FULL_VERSION_PRICE)) {
+
+ } else if (purchase.getSku().equals(SKU_FULL_VERSION_PRICE)) {
// bought full version
logDebug("Full version purchased.");
showToast(ctx.getString(R.string.full_version_thanks));
- mFullVersionPurchased = true;
ctx.getSettings().FULL_VERSION_PURCHASED.set(true);
- notifyDismissProgress();
+ notifyDismissProgress(InAppPurchaseTaskType.PURCHASE_FULL_VERSION);
notifyItemPurchased(SKU_FULL_VERSION_PRICE);
- if (stopAfterResult) {
- stop();
- }
- }
- if (purchase.getSku().equals(SKU_DEPTH_CONTOURS)) {
+ stop(true);
+
+ } else if (purchase.getSku().equals(SKU_DEPTH_CONTOURS)) {
// bought sea depth contours
logDebug("Sea depth contours purchased.");
showToast(ctx.getString(R.string.sea_depth_thanks));
- mDepthContoursPurchased = true;
ctx.getSettings().DEPTH_CONTOURS_PURCHASED.set(true);
ctx.getSettings().getCustomRenderBooleanProperty("depthContours").set(true);
- notifyDismissProgress();
+ notifyDismissProgress(InAppPurchaseTaskType.PURCHASE_DEPTH_CONTOURS);
notifyItemPurchased(SKU_DEPTH_CONTOURS);
- if (stopAfterResult) {
- stop();
- }
+ stop(true);
+
+ } else {
+ notifyDismissProgress(activeTask);
+ stop(true);
}
}
};
// Do not forget call stop() when helper is not needed anymore
public void stop() {
+ stop(false);
+ }
+
+ private void stop(boolean taskDone) {
logDebug("Destroying helper.");
if (mHelper != null) {
- if (!inventoryRequesting) {
- stopRequested = false;
+ if (taskDone) {
+ processingTask = false;
+ }
+ if (!processingTask) {
+ activeTask = null;
mHelper.dispose();
mHelper = null;
- } else {
- stopRequested = true;
}
+ } else {
+ processingTask = false;
+ activeTask = null;
}
}
@@ -739,46 +696,46 @@ public class InAppHelper {
}
}
- private void notifyError(String message) {
- for (InAppListener l : listeners) {
- l.onError(message);
+ private void notifyError(InAppPurchaseTaskType taskType, String message) {
+ for (InAppPurchaseListener l : listeners) {
+ l.onError(taskType, message);
}
}
private void notifyGetItems() {
- for (InAppListener l : listeners) {
+ for (InAppPurchaseListener l : listeners) {
l.onGetItems();
}
}
private void notifyItemPurchased(String sku) {
- for (InAppListener l : listeners) {
+ for (InAppPurchaseListener l : listeners) {
l.onItemPurchased(sku);
}
}
- private void notifyShowProgress() {
- for (InAppListener l : listeners) {
- l.showProgress();
+ private void notifyShowProgress(InAppPurchaseTaskType taskType) {
+ for (InAppPurchaseListener l : listeners) {
+ l.showProgress(taskType);
}
}
- private void notifyDismissProgress() {
- for (InAppListener l : listeners) {
- l.dismissProgress();
+ private void notifyDismissProgress(InAppPurchaseTaskType taskType) {
+ for (InAppPurchaseListener l : listeners) {
+ l.dismissProgress(taskType);
}
}
- public void addListener(InAppListener listener) {
+ public void addListener(InAppPurchaseListener listener) {
this.listeners.add(listener);
}
- public void removeListener(InAppListener listener) {
+ public void removeListener(InAppPurchaseListener listener) {
this.listeners.remove(listener);
}
private void complain(String message) {
- logError("**** InAppHelper Error: " + message);
+ logError("**** InAppPurchaseHelper Error: " + message);
showToast(message);
}
@@ -787,7 +744,9 @@ public class InAppHelper {
}
private void logDebug(String msg) {
- if (mDebugLog) Log.d(TAG, msg);
+ if (mDebugLog) {
+ Log.d(TAG, msg);
+ }
}
private void logError(String msg) {
diff --git a/OsmAnd/src/net/osmand/plus/liveupdates/LiveUpdatesFragment.java b/OsmAnd/src/net/osmand/plus/liveupdates/LiveUpdatesFragment.java
index 17ee435b7b..e736c96a44 100644
--- a/OsmAnd/src/net/osmand/plus/liveupdates/LiveUpdatesFragment.java
+++ b/OsmAnd/src/net/osmand/plus/liveupdates/LiveUpdatesFragment.java
@@ -10,10 +10,10 @@ import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.AsyncTask;
-import android.os.Build;
import android.os.Bundle;
import android.support.annotation.DrawableRes;
import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
import android.support.v4.app.FragmentManager;
import android.support.v4.view.MenuItemCompat;
import android.support.v7.app.ActionBar;
@@ -45,10 +45,12 @@ import net.osmand.plus.Version;
import net.osmand.plus.activities.LocalIndexHelper;
import net.osmand.plus.activities.LocalIndexInfo;
import net.osmand.plus.activities.OsmandBaseExpandableListAdapter;
+import net.osmand.plus.activities.OsmandInAppPurchaseActivity;
import net.osmand.plus.base.BaseOsmAndFragment;
import net.osmand.plus.download.ui.AbstractLoadLocalIndexTask;
-import net.osmand.plus.inapp.InAppHelper;
-import net.osmand.plus.inapp.InAppHelper.InAppListener;
+import net.osmand.plus.inapp.InAppPurchaseHelper;
+import net.osmand.plus.inapp.InAppPurchaseHelper.InAppPurchaseListener;
+import net.osmand.plus.inapp.InAppPurchaseHelper.InAppPurchaseTaskType;
import net.osmand.plus.resources.IncrementalChangesManager;
import net.osmand.util.Algorithms;
@@ -73,7 +75,7 @@ import static net.osmand.plus.liveupdates.LiveUpdatesHelper.preferenceUpdateFreq
import static net.osmand.plus.liveupdates.LiveUpdatesHelper.runLiveUpdate;
import static net.osmand.plus.liveupdates.LiveUpdatesHelper.setAlarmForPendingIntent;
-public class LiveUpdatesFragment extends BaseOsmAndFragment implements InAppListener {
+public class LiveUpdatesFragment extends BaseOsmAndFragment implements InAppPurchaseListener {
public static final int TITLE = R.string.live_updates;
private static final int SUBSCRIPTION_SETTINGS = 5;
public static final Comparator LOCAL_INDEX_INFO_COMPARATOR = new Comparator() {
@@ -90,10 +92,11 @@ public class LiveUpdatesFragment extends BaseOsmAndFragment implements InAppList
private ProgressBar progressBar;
private boolean processing;
- public InAppHelper getInAppHelper() {
+ @Nullable
+ public InAppPurchaseHelper getInAppPurchaseHelper() {
Activity activity = getActivity();
- if (activity instanceof OsmLiveActivity) {
- return ((OsmLiveActivity) activity).getInAppHelper();
+ if (activity instanceof OsmandInAppPurchaseActivity) {
+ return ((OsmandInAppPurchaseActivity) activity).getPurchaseHelper();
} else {
return null;
}
@@ -121,7 +124,8 @@ public class LiveUpdatesFragment extends BaseOsmAndFragment implements InAppList
listView.setOnChildClickListener(new ExpandableListView.OnChildClickListener() {
@Override
public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) {
- if (!processing && InAppHelper.isSubscribedToLiveUpdates()) {
+ InAppPurchaseHelper purchaseHelper = getInAppPurchaseHelper();
+ if (!processing && purchaseHelper != null && purchaseHelper.isSubscribedToLiveUpdates()) {
final FragmentManager fragmentManager = getChildFragmentManager();
LiveUpdatesSettingsDialogFragment
.createInstance(adapter.getChild(groupPosition, childPosition).getFileName())
@@ -143,7 +147,8 @@ public class LiveUpdatesFragment extends BaseOsmAndFragment implements InAppList
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView> parent, View view, int position, long id) {
- if (position == 0 && !processing && InAppHelper.isSubscribedToLiveUpdates()) {
+ InAppPurchaseHelper purchaseHelper = getInAppPurchaseHelper();
+ if (position == 0 && !processing && purchaseHelper != null && purchaseHelper.isSubscribedToLiveUpdates()) {
SubscriptionFragment subscriptionFragment = new SubscriptionFragment();
subscriptionFragment.setEditMode(true);
subscriptionFragment.show(getChildFragmentManager(), SubscriptionFragment.TAG);
@@ -207,17 +212,17 @@ public class LiveUpdatesFragment extends BaseOsmAndFragment implements InAppList
@Override
public void onResume() {
super.onResume();
- InAppHelper helper = getInAppHelper();
- if (helper != null) {
- enableProgress();
- helper.addListener(this);
- helper.start(false);
+ InAppPurchaseHelper purchaseHelper = getInAppPurchaseHelper();
+ if (purchaseHelper != null) {
+ if (purchaseHelper.getActiveTask() == InAppPurchaseTaskType.REQUEST_INVENTORY) {
+ enableProgress();
+ }
+ purchaseHelper.addListener(this);
}
if (((OsmLiveActivity) getActivity()).shouldOpenSubscription()) {
SubscriptionFragment subscriptionFragment = new SubscriptionFragment();
subscriptionFragment.show(getChildFragmentManager(), SubscriptionFragment.TAG);
}
-
}
@Override
@@ -227,11 +232,11 @@ public class LiveUpdatesFragment extends BaseOsmAndFragment implements InAppList
}
@Override
- public void onDestroy() {
- super.onDestroy();
- InAppHelper helper = getInAppHelper();
- if (helper != null) {
- helper.removeListener(this);
+ public void onPause() {
+ super.onPause();
+ InAppPurchaseHelper purchaseHelper = getInAppPurchaseHelper();
+ if (purchaseHelper != null) {
+ purchaseHelper.removeListener(this);
}
}
@@ -383,7 +388,8 @@ public class LiveUpdatesFragment extends BaseOsmAndFragment implements InAppList
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked) {
- if (InAppHelper.isSubscribedToLiveUpdates()) {
+ InAppPurchaseHelper purchaseHelper = getInAppPurchaseHelper();
+ if (purchaseHelper != null && purchaseHelper.isSubscribedToLiveUpdates()) {
switchOnLiveUpdates(settings);
} else {
liveUpdatesSwitch.setChecked(false);
@@ -578,7 +584,8 @@ public class LiveUpdatesFragment extends BaseOsmAndFragment implements InAppList
descriptionTextView.setText(context.getString(R.string.last_map_change, lastCheckString));
}
- if (!fragment.isProcessing() && InAppHelper.isSubscribedToLiveUpdates()) {
+ InAppPurchaseHelper purchaseHelper = fragment.getInAppPurchaseHelper();
+ if (!fragment.isProcessing() && purchaseHelper != null && purchaseHelper.isSubscribedToLiveUpdates()) {
final View.OnClickListener clickListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
@@ -673,14 +680,14 @@ public class LiveUpdatesFragment extends BaseOsmAndFragment implements InAppList
}
@Override
- public void onError(String error) {
+ public void onError(InAppPurchaseTaskType taskType, String error) {
disableProgress();
}
@Override
public void onGetItems() {
- getSettings().LIVE_UPDATES_PURCHASED.set(InAppHelper.isSubscribedToLiveUpdates());
- if (!InAppHelper.isSubscribedToLiveUpdates()) {
+ InAppPurchaseHelper purchaseHelper = getInAppPurchaseHelper();
+ if (purchaseHelper != null && !purchaseHelper.isSubscribedToLiveUpdates()) {
getSettings().IS_LIVE_UPDATES_ON.set(false);
adapter.enableLiveUpdates(false);
}
@@ -689,18 +696,19 @@ public class LiveUpdatesFragment extends BaseOsmAndFragment implements InAppList
@Override
public void onItemPurchased(String sku) {
- if (InAppHelper.getSkuLiveUpdates().equals(sku)) {
+ InAppPurchaseHelper purchaseHelper = getInAppPurchaseHelper();
+ if (purchaseHelper != null && purchaseHelper.getSkuLiveUpdates().equals(sku)) {
updateSubscriptionHeader();
}
}
@Override
- public void showProgress() {
+ public void showProgress(InAppPurchaseTaskType taskType) {
enableProgress();
}
@Override
- public void dismissProgress() {
+ public void dismissProgress(InAppPurchaseTaskType taskType) {
disableProgress();
}
}
diff --git a/OsmAnd/src/net/osmand/plus/liveupdates/OsmLiveActivity.java b/OsmAnd/src/net/osmand/plus/liveupdates/OsmLiveActivity.java
index 28f8e874b4..575967477e 100644
--- a/OsmAnd/src/net/osmand/plus/liveupdates/OsmLiveActivity.java
+++ b/OsmAnd/src/net/osmand/plus/liveupdates/OsmLiveActivity.java
@@ -15,10 +15,8 @@ import android.view.MenuItem;
import net.osmand.AndroidNetworkUtils;
import net.osmand.PlatformUtil;
import net.osmand.plus.R;
-import net.osmand.plus.Version;
import net.osmand.plus.download.AbstractDownloadActivity;
-import net.osmand.plus.download.DownloadIndexesThread;
-import net.osmand.plus.inapp.InAppHelper;
+import net.osmand.plus.download.DownloadIndexesThread.DownloadEvents;
import org.apache.commons.logging.Log;
@@ -28,32 +26,21 @@ import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;
-public class OsmLiveActivity extends AbstractDownloadActivity implements DownloadIndexesThread.DownloadEvents {
+public class OsmLiveActivity extends AbstractDownloadActivity implements DownloadEvents {
private final static Log LOG = PlatformUtil.getLog(OsmLiveActivity.class);
public final static String OPEN_SUBSCRIPTION_INTENT_PARAM = "open_subscription_intent_param";
+
private LiveUpdatesFragmentPagerAdapter pagerAdapter;
- private InAppHelper inAppHelper;
private boolean openSubscription;
private GetLastUpdateDateTask getLastUpdateDateTask;
private static final String URL = "https://osmand.net/api/osmlive_status";
- public InAppHelper getInAppHelper() {
- return inAppHelper;
- }
-
@Override
protected void onCreate(Bundle savedInstanceState) {
getMyApplication().applyTheme(this);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_livie_updates);
- if (Version.isGooglePlayEnabled(getMyApplication())) {
- inAppHelper = new InAppHelper(getMyApplication(), false);
- }
- if (Version.isDeveloperVersion(getMyApplication())) {
- inAppHelper = null;
- }
-
Intent intent = getIntent();
if (intent != null && intent.getExtras() != null) {
openSubscription = intent.getExtras().getBoolean(OPEN_SUBSCRIPTION_INTENT_PARAM, false);
@@ -82,17 +69,6 @@ public class OsmLiveActivity extends AbstractDownloadActivity implements Downloa
return super.onOptionsItemSelected(item);
}
- @Override
- protected void onActivityResult(int requestCode, int resultCode, Intent data) {
- // Pass on the activity result to the helper for handling
- if (inAppHelper == null || !inAppHelper.onActivityResultHandled(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);
- }
- }
-
@Override
protected void onPause() {
super.onPause();
@@ -102,17 +78,17 @@ public class OsmLiveActivity extends AbstractDownloadActivity implements Downloa
@Override
protected void onDestroy() {
super.onDestroy();
- if (inAppHelper != null) {
- inAppHelper.stop();
- }
if (getLastUpdateDateTask != null) {
getLastUpdateDateTask.cancel(true);
}
}
+ public boolean isInAppPurchaseAllowed() {
+ return true;
+ }
+
@Override
public void newDownloadIndexes() {
-
}
@Override
diff --git a/OsmAnd/src/net/osmand/plus/liveupdates/SubscriptionFragment.java b/OsmAnd/src/net/osmand/plus/liveupdates/SubscriptionFragment.java
index ca04348bf1..b372196fd6 100644
--- a/OsmAnd/src/net/osmand/plus/liveupdates/SubscriptionFragment.java
+++ b/OsmAnd/src/net/osmand/plus/liveupdates/SubscriptionFragment.java
@@ -3,6 +3,8 @@ package net.osmand.plus.liveupdates;
import android.app.Activity;
import android.app.ProgressDialog;
import android.os.Bundle;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v7.widget.AppCompatCheckBox;
import android.view.LayoutInflater;
@@ -22,9 +24,11 @@ import net.osmand.AndroidUtils;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.OsmandSettings;
import net.osmand.plus.R;
+import net.osmand.plus.activities.OsmandInAppPurchaseActivity;
import net.osmand.plus.base.BaseOsmAndDialogFragment;
-import net.osmand.plus.inapp.InAppHelper;
-import net.osmand.plus.inapp.InAppHelper.InAppListener;
+import net.osmand.plus.inapp.InAppPurchaseHelper;
+import net.osmand.plus.inapp.InAppPurchaseHelper.InAppPurchaseListener;
+import net.osmand.plus.inapp.InAppPurchaseHelper.InAppPurchaseTaskType;
import net.osmand.plus.liveupdates.CountrySelectionFragment.CountryItem;
import net.osmand.plus.liveupdates.CountrySelectionFragment.OnFragmentInteractionListener;
import net.osmand.util.Algorithms;
@@ -35,7 +39,7 @@ import org.json.JSONObject;
import java.util.HashMap;
import java.util.Map;
-public class SubscriptionFragment extends BaseOsmAndDialogFragment implements InAppListener, OnFragmentInteractionListener {
+public class SubscriptionFragment extends BaseOsmAndDialogFragment implements InAppPurchaseListener, OnFragmentInteractionListener {
public static final String TAG = "SubscriptionFragment";
private static final String EDIT_MODE_ID = "edit_mode_id";
@@ -59,10 +63,11 @@ public class SubscriptionFragment extends BaseOsmAndDialogFragment implements In
this.editMode = editMode;
}
- public InAppHelper getInAppHelper() {
+ @Nullable
+ public InAppPurchaseHelper getInAppPurchaseHelper() {
Activity activity = getActivity();
- if (activity instanceof OsmLiveActivity) {
- return ((OsmLiveActivity) activity).getInAppHelper();
+ if (activity instanceof OsmandInAppPurchaseActivity) {
+ return ((OsmandInAppPurchaseActivity) activity).getPurchaseHelper();
} else {
return null;
}
@@ -103,14 +108,9 @@ public class SubscriptionFragment extends BaseOsmAndDialogFragment implements In
}
@Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
- InAppHelper helper = getInAppHelper();
- if (helper != null) {
- helper.addListener(this);
- }
-
String userName = settings.BILLING_USER_NAME.get();
String email = settings.BILLING_USER_EMAIL.get();
String countryDownloadName = settings.BILLING_USER_COUNTRY_DOWNLOAD_NAME.get();
@@ -214,8 +214,8 @@ public class SubscriptionFragment extends BaseOsmAndDialogFragment implements In
saveChangesButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
- InAppHelper helper = getInAppHelper();
- if (helper != null && applySettings(userNameEdit.getText().toString().trim(),
+ InAppPurchaseHelper purchaseHelper = getInAppPurchaseHelper();
+ if (purchaseHelper != null && applySettings(userNameEdit.getText().toString().trim(),
emailEdit.getText().toString().trim(), hideUserNameCheckbox.isChecked())) {
final Map parameters = new HashMap<>();
@@ -224,16 +224,16 @@ public class SubscriptionFragment extends BaseOsmAndDialogFragment implements In
parameters.put("email", settings.BILLING_USER_EMAIL.get());
parameters.put("cemail", prevEmail);
parameters.put("userid", settings.BILLING_USER_ID.get());
- parameters.put("token", helper.getToken());
+ parameters.put("token", purchaseHelper.getToken());
- showProgress();
+ showProgress(null);
AndroidNetworkUtils.sendRequestAsync(getMyApplication(),
"http://download.osmand.net/subscription/update.php",
parameters, "Sending data...", true, true, new AndroidNetworkUtils.OnRequestResultListener() {
@Override
public void onResult(String result) {
- dismissProgress();
+ dismissProgress(null);
OsmandApplication app = getMyApplication();
if (result != null) {
try {
@@ -283,12 +283,12 @@ public class SubscriptionFragment extends BaseOsmAndDialogFragment implements In
subscribeButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
- InAppHelper helper = getInAppHelper();
- if (helper != null) {
+ InAppPurchaseHelper purchaseHelper = getInAppPurchaseHelper();
+ if (purchaseHelper != null) {
if (applySettings(userNameEdit.getText().toString().trim(),
emailEdit.getText().toString().trim(), hideUserNameCheckbox.isChecked())) {
- helper.purchaseLiveUpdates(getActivity(),
+ purchaseHelper.purchaseLiveUpdates(getActivity(),
settings.BILLING_USER_EMAIL.get(),
settings.BILLING_USER_NAME.get(),
settings.BILLING_USER_COUNTRY_DOWNLOAD_NAME.get(),
@@ -308,13 +308,27 @@ public class SubscriptionFragment extends BaseOsmAndDialogFragment implements In
return view;
}
+ @Override
+ public void onResume() {
+ super.onResume();
+ InAppPurchaseHelper purchaseHelper = getInAppPurchaseHelper();
+ if (purchaseHelper != null) {
+ purchaseHelper.addListener(this);
+ }
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ InAppPurchaseHelper purchaseHelper = getInAppPurchaseHelper();
+ if (purchaseHelper != null) {
+ purchaseHelper.removeListener(this);
+ }
+ }
+
@Override
public void onDestroy() {
super.onDestroy();
- InAppHelper helper = getInAppHelper();
- if (helper != null) {
- helper.removeListener(this);
- }
if (dlg != null && dlg.isShowing()) {
dlg.hide();
}
@@ -350,7 +364,7 @@ public class SubscriptionFragment extends BaseOsmAndDialogFragment implements In
}
@Override
- public void onError(String error) {
+ public void onError(InAppPurchaseTaskType taskType, String error) {
}
@Override
@@ -365,7 +379,7 @@ public class SubscriptionFragment extends BaseOsmAndDialogFragment implements In
}
@Override
- public void showProgress() {
+ public void showProgress(InAppPurchaseTaskType taskType) {
if (dlg != null) {
dlg.dismiss();
}
@@ -377,7 +391,7 @@ public class SubscriptionFragment extends BaseOsmAndDialogFragment implements In
}
@Override
- public void dismissProgress() {
+ public void dismissProgress(InAppPurchaseTaskType taskType) {
if (dlg != null) {
dlg.dismiss();
dlg = null;
@@ -402,8 +416,9 @@ public class SubscriptionFragment extends BaseOsmAndDialogFragment implements In
}
if (view != null) {
TextView priceTextView = (TextView) view.findViewById(R.id.priceTextView);
- if (InAppHelper.getLiveUpdatesPrice() != null) {
- priceTextView.setText(InAppHelper.getLiveUpdatesPrice());
+ InAppPurchaseHelper purchaseHelper = getInAppPurchaseHelper();
+ if (purchaseHelper.getLiveUpdatesPrice() != null) {
+ priceTextView.setText(purchaseHelper.getLiveUpdatesPrice());
}
}
}
From b539069fed2e6b6344c6210ab22cd9cde018e84b Mon Sep 17 00:00:00 2001
From: Dmitriy Prodchenko
Date: Tue, 24 Apr 2018 18:54:28 +0300
Subject: [PATCH 37/38] Add icon for Sea Depth in-app purchase
---
.../drawable-xxhdpi/img_logo_38dp_sea_depth.png | Bin 0 -> 9150 bytes
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 OsmAnd/res/drawable-xxhdpi/img_logo_38dp_sea_depth.png
diff --git a/OsmAnd/res/drawable-xxhdpi/img_logo_38dp_sea_depth.png b/OsmAnd/res/drawable-xxhdpi/img_logo_38dp_sea_depth.png
new file mode 100644
index 0000000000000000000000000000000000000000..0d1aea1b6e6f100dd58421f33004ad69c3badfda
GIT binary patch
literal 9150
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