Merge remote-tracking branch 'origin/master'

This commit is contained in:
Weblate 2016-01-26 22:11:36 +01:00
commit a7fa8b4315
11 changed files with 432 additions and 470 deletions

View file

@ -30,6 +30,14 @@
<string name="osm_live_subscription">OSM Live subscription</string> <string name="osm_live_subscription">OSM Live subscription</string>
<string name="osm_live_subscribe_btn">Subscribe</string> <string name="osm_live_subscribe_btn">Subscribe</string>
<string name="osm_live_default_price">€1,49</string> <string name="osm_live_default_price">€1,49</string>
<string name="osm_live_email_desc">We need it to provide you information about contributions</string>
<string name="osm_live_user_public_name">Public Name</string>
<string name="osm_live_hide_user_name">Don\'t show my name in reports</string>
<string name="osm_live_support_region">Support region</string>
<string name="osm_live_month_cost">Month cost</string>
<string name="osm_live_month_cost_desc">Monthly payment</string>
<string name="osm_live_active">Active</string>
<string name="osm_live_not_active">Inactive</string>
<string name="osm_live_header">This subscription enables hourly updates for all maps around the world. <string name="osm_live_header">This subscription enables hourly updates for all maps around the world.
Major part of the income goes back to OSM community and is paid out per each OSM contribution. Major part of the income goes back to OSM community and is paid out per each OSM contribution.

View file

@ -99,13 +99,15 @@
app:typeface="@string/font_roboto_regular"/> app:typeface="@string/font_roboto_regular"/>
<net.osmand.plus.widgets.TextViewEx <net.osmand.plus.widgets.TextViewEx
android:id="@+id/statusTextView"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginBottom="4dp" android:layout_marginBottom="4dp"
android:layout_marginLeft="16dp" android:layout_marginLeft="16dp"
android:layout_marginRight="16dp" android:layout_marginRight="16dp"
android:layout_marginTop="4dp" android:layout_marginTop="4dp"
android:text="Active" android:gravity="right"
android:text="@string/osm_live_active"
android:textColor="?android:attr/textColorPrimary" android:textColor="?android:attr/textColorPrimary"
android:textSize="@dimen/default_desc_text_size" android:textSize="@dimen/default_desc_text_size"
app:textAllCapsCompat="true" app:textAllCapsCompat="true"
@ -129,18 +131,20 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginLeft="16dp" android:layout_marginLeft="16dp"
android:layout_marginRight="16dp" android:layout_marginRight="16dp"
android:text="Support country" android:text="@string/osm_live_support_region"
android:textColor="?android:attr/textColorPrimary" android:textColor="?android:attr/textColorPrimary"
android:textSize="@dimen/default_desc_text_size" android:textSize="@dimen/default_desc_text_size"
app:typeface="@string/font_roboto_regular"/> app:typeface="@string/font_roboto_regular"/>
<net.osmand.plus.widgets.TextViewEx <net.osmand.plus.widgets.TextViewEx
android:id="@+id/regionTextView"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginBottom="4dp" android:layout_marginBottom="4dp"
android:layout_marginLeft="16dp" android:layout_marginLeft="16dp"
android:layout_marginRight="16dp" android:layout_marginRight="16dp"
android:layout_marginTop="4dp" android:layout_marginTop="4dp"
android:gravity="right"
android:text="World" android:text="World"
android:textColor="?android:attr/textColorPrimary" android:textColor="?android:attr/textColorPrimary"
android:textSize="@dimen/default_desc_text_size" android:textSize="@dimen/default_desc_text_size"
@ -165,18 +169,20 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginLeft="16dp" android:layout_marginLeft="16dp"
android:layout_marginRight="16dp" android:layout_marginRight="16dp"
android:text="Email" android:text="@string/shared_string_email_address"
android:textColor="?android:attr/textColorPrimary" android:textColor="?android:attr/textColorPrimary"
android:textSize="@dimen/default_desc_text_size" android:textSize="@dimen/default_desc_text_size"
app:typeface="@string/font_roboto_regular"/> app:typeface="@string/font_roboto_regular"/>
<net.osmand.plus.widgets.TextViewEx <net.osmand.plus.widgets.TextViewEx
android:id="@+id/emailTextView"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginBottom="4dp" android:layout_marginBottom="4dp"
android:layout_marginLeft="16dp" android:layout_marginLeft="16dp"
android:layout_marginRight="16dp" android:layout_marginRight="16dp"
android:layout_marginTop="4dp" android:layout_marginTop="4dp"
android:gravity="right"
android:text="my@email.com" android:text="my@email.com"
android:textColor="?android:attr/textColorPrimary" android:textColor="?android:attr/textColorPrimary"
android:textSize="@dimen/default_desc_text_size" android:textSize="@dimen/default_desc_text_size"
@ -201,18 +207,20 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginLeft="16dp" android:layout_marginLeft="16dp"
android:layout_marginRight="16dp" android:layout_marginRight="16dp"
android:text="Visible Name" android:text="@string/osm_live_user_public_name"
android:textColor="?android:attr/textColorPrimary" android:textColor="?android:attr/textColorPrimary"
android:textSize="@dimen/default_desc_text_size" android:textSize="@dimen/default_desc_text_size"
app:typeface="@string/font_roboto_regular"/> app:typeface="@string/font_roboto_regular"/>
<net.osmand.plus.widgets.TextViewEx <net.osmand.plus.widgets.TextViewEx
android:id="@+id/userNameTextView"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginBottom="4dp" android:layout_marginBottom="4dp"
android:layout_marginLeft="16dp" android:layout_marginLeft="16dp"
android:layout_marginRight="16dp" android:layout_marginRight="16dp"
android:layout_marginTop="4dp" android:layout_marginTop="4dp"
android:gravity="right"
android:text="None" android:text="None"
android:textColor="?android:attr/textColorPrimary" android:textColor="?android:attr/textColorPrimary"
android:textSize="@dimen/default_desc_text_size" android:textSize="@dimen/default_desc_text_size"
@ -220,44 +228,6 @@
</LinearLayout> </LinearLayout>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="?attr/dashboard_divider"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:minHeight="44dp">
<net.osmand.plus.widgets.TextViewEx
android:layout_width="120dp"
android:layout_height="wrap_content"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:text="Last pay"
android:textColor="?android:attr/textColorPrimary"
android:textSize="@dimen/default_desc_text_size"
app:typeface="@string/font_roboto_regular"/>
<net.osmand.plus.widgets.TextViewEx
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="4dp"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:layout_marginTop="4dp"
android:text="25 Nov 2015"
android:textColor="?android:attr/textColorPrimary"
android:textSize="@dimen/default_desc_text_size"
app:typeface="@string/font_roboto_medium"/>
</LinearLayout>
</LinearLayout> </LinearLayout>
</LinearLayout> </LinearLayout>

View file

@ -24,7 +24,7 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginLeft="16dp" android:layout_marginLeft="16dp"
android:text="Subscription form" android:text="@string/osm_live_subscription"
android:textColor="@color/color_white" android:textColor="@color/color_white"
android:textSize="@dimen/default_list_text_size_large" android:textSize="@dimen/default_list_text_size_large"
android:textStyle="bold" android:textStyle="bold"
@ -63,7 +63,7 @@
android:layout_gravity="center_vertical" android:layout_gravity="center_vertical"
android:layout_marginLeft="16dp" android:layout_marginLeft="16dp"
android:layout_marginRight="16dp" android:layout_marginRight="16dp"
android:hint="E-mail address" android:hint="@string/shared_string_email_address"
android:inputType="textEmailAddress"/> android:inputType="textEmailAddress"/>
</LinearLayout> </LinearLayout>
@ -74,7 +74,7 @@
android:layout_gravity="center_vertical" android:layout_gravity="center_vertical"
android:layout_marginLeft="72dp" android:layout_marginLeft="72dp"
android:layout_marginRight="16dp" android:layout_marginRight="16dp"
android:text="We need it to provide you information about contributions" android:text="@string/osm_live_email_desc"
android:textColor="?android:attr/textColorSecondary"/> android:textColor="?android:attr/textColorSecondary"/>
@ -103,20 +103,21 @@
android:layout_gravity="center_vertical" android:layout_gravity="center_vertical"
android:layout_marginLeft="16dp" android:layout_marginLeft="16dp"
android:layout_marginRight="16dp" android:layout_marginRight="16dp"
android:hint="Public Name" android:hint="@string/osm_live_user_public_name"
android:inputType="text"/> android:inputType="text"/>
</LinearLayout> </LinearLayout>
<CheckBox <CheckBox
android:id="@+id/hideUserNameCheckbox"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginBottom="12dp" android:layout_marginBottom="12dp"
android:layout_marginLeft="72dp" android:layout_marginLeft="72dp"
android:layout_marginRight="16dp" android:layout_marginRight="16dp"
android:layout_marginTop="8dp" android:layout_marginTop="8dp"
android:text="Don't show my name in reports" android:text="@string/osm_live_hide_user_name"
android:textColor="?android:attr/textColorPrimary"/> android:textColor="?android:attr/textColorPrimary"/>
<LinearLayout <LinearLayout
@ -149,7 +150,7 @@
android:layout_marginTop="4dp" android:layout_marginTop="4dp"
android:drawableRight="@drawable/ic_action_arrow_drop_down" android:drawableRight="@drawable/ic_action_arrow_drop_down"
android:editable="false" android:editable="false"
android:hint="Support region"/> android:hint="@string/osm_live_support_region"/>
</LinearLayout> </LinearLayout>
@ -174,22 +175,21 @@
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="1" android:layout_weight="1"
android:text="Month cost" android:text="@string/osm_live_month_cost"
android:textColor="?android:attr/textColorPrimary" android:textColor="?android:attr/textColorPrimary"
android:textSize="@dimen/default_list_text_size_large" android:textSize="@dimen/default_list_text_size_large"
android:textStyle="bold" android:textStyle="bold"/>
app:typeface="@string/font_roboto_regular"/>
<net.osmand.plus.widgets.TextViewEx <net.osmand.plus.widgets.TextViewEx
android:id="@+id/priceTextView" android:id="@+id/priceTextView"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginLeft="16dp"
android:gravity="right" android:gravity="right"
android:text="@string/osm_live_default_price" android:text="@string/osm_live_default_price"
android:textColor="?attr/color_dialog_buttons" android:textColor="?attr/color_dialog_buttons"
android:textSize="@dimen/default_list_text_size_large" android:textSize="@dimen/default_list_text_size_large"
android:textStyle="bold" android:textStyle="bold"/>
app:typeface="@string/font_roboto_regular"/>
</LinearLayout> </LinearLayout>
@ -198,10 +198,9 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginLeft="16dp" android:layout_marginLeft="16dp"
android:layout_marginRight="16dp" android:layout_marginRight="16dp"
android:text="Monthly payment" android:text="@string/osm_live_month_cost_desc"
android:textColor="?android:attr/textColorSecondary" android:textColor="?android:attr/textColorSecondary"
android:textSize="@dimen/default_desc_text_size" android:textSize="@dimen/default_desc_text_size"/>
app:typeface="@string/font_roboto_regular"/>
<View <View
android:layout_width="match_parent" android:layout_width="match_parent"
@ -223,7 +222,7 @@
android:background="?attr/selectableItemBackground" android:background="?attr/selectableItemBackground"
android:paddingLeft="10dp" android:paddingLeft="10dp"
android:paddingRight="10dp" android:paddingRight="10dp"
android:text="Subscribe" android:text="@string/osm_live_subscribe_btn"
android:textColor="?attr/color_dialog_buttons"/> android:textColor="?attr/color_dialog_buttons"/>
</LinearLayout> </LinearLayout>

View file

@ -9,6 +9,7 @@
3. All your modified/created strings are in the top of the file (to make easier find what\'s translated). 3. All your modified/created strings are in the top of the file (to make easier find what\'s translated).
PLEASE: Have a look at http://code.google.com/p/osmand/wiki/UIConsistency, it may really improve your and our work :-) Thx - Hardy PLEASE: Have a look at http://code.google.com/p/osmand/wiki/UIConsistency, it may really improve your and our work :-) Thx - Hardy
--> -->
<string name="shared_string_email_address">E-mail address</string>
<string name="rendering_attr_hideUnderground_name">Hide underground objects</string> <string name="rendering_attr_hideUnderground_name">Hide underground objects</string>
<string name="data_is_not_available">Data is not available</string> <string name="data_is_not_available">Data is not available</string>
<string name="shared_string_remove">Remove</string> <string name="shared_string_remove">Remove</string>

View file

@ -815,6 +815,8 @@ public class OsmandSettings {
public final OsmandPreference<String> BILLING_USER_NAME = new StringPreference("billing_user_name", "").makeGlobal(); public final OsmandPreference<String> BILLING_USER_NAME = new StringPreference("billing_user_name", "").makeGlobal();
public final OsmandPreference<String> BILLING_USER_EMAIL = new StringPreference("billing_user_email", "").makeGlobal(); public final OsmandPreference<String> BILLING_USER_EMAIL = new StringPreference("billing_user_email", "").makeGlobal();
public final OsmandPreference<String> BILLING_USER_COUNTRY = new StringPreference("billing_user_country", "").makeGlobal(); public final OsmandPreference<String> BILLING_USER_COUNTRY = new StringPreference("billing_user_country", "").makeGlobal();
public final OsmandPreference<String> BILLING_USER_COUNTRY_DOWNLOAD_NAME = new StringPreference("billing_user_country_download_name", "").makeGlobal();
public final OsmandPreference<Boolean> BILLING_HIDE_USER_NAME = new BooleanPreference("billing_hide_user_name", false).makeGlobal();
public final OsmandPreference<Boolean> BILLING_PURCHASE_TOKEN_SENT = new BooleanPreference("billing_purchase_token_sent", false).makeGlobal(); public final OsmandPreference<Boolean> BILLING_PURCHASE_TOKEN_SENT = new BooleanPreference("billing_purchase_token_sent", false).makeGlobal();
// this value string is synchronized with settings_pref.xml preference name // this value string is synchronized with settings_pref.xml preference name

View file

@ -19,16 +19,20 @@ import net.osmand.util.Algorithms;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
import java.io.BufferedOutputStream;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection; import java.net.HttpURLConnection;
import java.net.MalformedURLException; import java.net.MalformedURLException;
import java.net.URLEncoder; import java.net.URLEncoder;
import java.text.MessageFormat; import java.text.MessageFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map;
public class InAppHelper { public class InAppHelper {
// Debug tag, for logging // Debug tag, for logging
@ -58,10 +62,13 @@ public class InAppHelper {
public interface InAppCallbacks { public interface InAppCallbacks {
void onError(String error); void onError(String error);
void onGetItems(); void onGetItems();
void onItemPurchased(String sku); void onItemPurchased(String sku);
void showProgress(); void showProgress();
void dismissProgress(); void dismissProgress();
} }
@ -80,8 +87,8 @@ public class InAppHelper {
public void start(final boolean stopAfterResult) { public void start(final boolean stopAfterResult) {
this.stopAfterResult = stopAfterResult; this.stopAfterResult = stopAfterResult;
/* base64EncodedPublicKey should be YOUR APPLICATION'S PUBLIC KEY /* base64EncodedPublicKey should be YOUR APPLICATION'S PUBLIC KEY
* (that you got from the Google Play developer console). This is not your * (that you got from the Google Play developer console). This is not your
* developer public key, it's the *app-specific* public key. * developer public key, it's the *app-specific* public key.
* *
* Instead of just storing the entire literal string here embedded in the * Instead of just storing the entire literal string here embedded in the
@ -159,15 +166,14 @@ public class InAppHelper {
Log.d(TAG, "Query inventory was successful."); Log.d(TAG, "Query inventory was successful.");
/* /*
* Check for items we own. Notice that for each purchase, we check * Check for items we own. Notice that for each purchase, we check
* the developer payload to see if it's correct! See * the developer payload to see if it's correct! See
* verifyDeveloperPayload(). * verifyDeveloperPayload().
*/ */
// Do we have the live updates? // Do we have the live updates?
Purchase liveUpdatesPurchase = inventory.getPurchase(SKU_LIVE_UPDATES); Purchase liveUpdatesPurchase = inventory.getPurchase(SKU_LIVE_UPDATES);
mSubscribedToLiveUpdates = (liveUpdatesPurchase != null && mSubscribedToLiveUpdates = (liveUpdatesPurchase != null);
verifyDeveloperPayload(liveUpdatesPurchase));
Log.d(TAG, "User " + (mSubscribedToLiveUpdates ? "HAS" : "DOES NOT HAVE") Log.d(TAG, "User " + (mSubscribedToLiveUpdates ? "HAS" : "DOES NOT HAVE")
+ " live updates purchased."); + " live updates purchased.");
@ -193,7 +199,7 @@ public class InAppHelper {
}; };
public void purchaseLiveUpdates(final Activity activity, final String email, final String userName, public void purchaseLiveUpdates(final Activity activity, final String email, final String userName,
final String country) { final String countryDownloadName) {
if (!mHelper.subscriptionsSupported()) { if (!mHelper.subscriptionsSupported()) {
complain("Subscriptions not supported on your device yet. Sorry!"); complain("Subscriptions not supported on your device yet. Sorry!");
if (callbacks != null) { if (callbacks != null) {
@ -218,12 +224,17 @@ public class InAppHelper {
userId = ctx.getSettings().BILLING_USER_ID.get(); userId = ctx.getSettings().BILLING_USER_ID.get();
if (Algorithms.isEmpty(userId)) { if (Algorithms.isEmpty(userId)) {
try { try {
return sendRequest("http://download.osmand.net/subscription/register?email=" + URLEncoder.encode(email, "UTF-8") Map<String, String> parameters = new HashMap<>();
+ "&visibleName=" + URLEncoder.encode(userName, "UTF-8") parameters.put("visibleName", userName);
+ "&preferredCountry=" + URLEncoder.encode(country, "UTF-8") parameters.put("preferredCountry", countryDownloadName);
+ (Algorithms.isEmpty(userId) ? "&status=new" : ""), parameters.put("email", email);
"POST", "Requesting userId..."); parameters.put("status", "new");
return sendRequest("http://download.osmand.net/subscription/register.php",
parameters, "Requesting userId...");
} catch (Exception e) { } catch (Exception e) {
Log.e(TAG, "sendRequest Error", e);
return null; return null;
} }
} else { } else {
@ -236,6 +247,7 @@ public class InAppHelper {
if (Algorithms.isEmpty(userId)) { if (Algorithms.isEmpty(userId)) {
Log.d(TAG, "Response=" + response); Log.d(TAG, "Response=" + response);
if (response == null) { if (response == null) {
complain("Cannot retrieve userId from server.");
if (callbacks != null) { if (callbacks != null) {
callbacks.dismissProgress(); callbacks.dismissProgress();
callbacks.onError("Cannot retrieve userId from server."); callbacks.onError("Cannot retrieve userId from server.");
@ -252,10 +264,12 @@ public class InAppHelper {
ctx.getSettings().BILLING_USER_ID.set(userId); ctx.getSettings().BILLING_USER_ID.set(userId);
Log.d(TAG, "UserId=" + userId); Log.d(TAG, "UserId=" + userId);
} catch (JSONException e) { } catch (JSONException e) {
String message = "JSON parsing error: "
+ (e.getMessage() == null ? "unknown" : e.getMessage());
complain(message);
if (callbacks != null) { if (callbacks != null) {
callbacks.dismissProgress(); callbacks.dismissProgress();
callbacks.onError("JSON parsing error: " callbacks.onError(message);
+ (e.getMessage() == null ? "unknown" : e.getMessage()));
} }
if (stopAfterResult) { if (stopAfterResult) {
stop(); stop();
@ -304,36 +318,6 @@ public class InAppHelper {
} }
} }
/** Verifies the developer payload of a purchase. */
private boolean verifyDeveloperPayload(Purchase p) {
String payload = p.getDeveloperPayload();
/*
* TODO: verify that the developer payload of the purchase is correct. It will be
* the same one that you sent when initiating the purchase.
*
* WARNING: Locally generating a random string when starting a purchase and
* verifying it here might seem like a good approach, but this will fail in the
* case where the user purchases an item on one device and then uses your app on
* a different device, because on the other device you will not have access to the
* random string you originally generated.
*
* So a good developer payload has these characteristics:
*
* 1. If two different users purchase an item, the payload is different between them,
* so that one user's purchase can't be replayed to another user.
*
* 2. The payload must be such that you can verify it even when the app wasn't the
* one who initiated the purchase flow (so that items purchased by the user on
* one device work on other devices owned by the user).
*
* Using your own server to store and verify developer payloads across app
* installations is recommended.
*/
return true;
}
// Callback for when a purchase is finished // Callback for when a purchase is finished
private IabHelper.OnIabPurchaseFinishedListener mPurchaseFinishedListener = new IabHelper.OnIabPurchaseFinishedListener() { private IabHelper.OnIabPurchaseFinishedListener mPurchaseFinishedListener = new IabHelper.OnIabPurchaseFinishedListener() {
public void onIabPurchaseFinished(IabResult result, Purchase purchase) { public void onIabPurchaseFinished(IabResult result, Purchase purchase) {
@ -353,17 +337,6 @@ public class InAppHelper {
} }
return; return;
} }
if (!verifyDeveloperPayload(purchase)) {
complain("Error purchasing. Authenticity verification failed.");
if (callbacks != null) {
callbacks.dismissProgress();
callbacks.onError("Error purchasing. Authenticity verification failed.");
}
if (stopAfterResult) {
stop();
}
return;
}
Log.d(TAG, "Purchase successful."); Log.d(TAG, "Purchase successful.");
@ -398,11 +371,14 @@ public class InAppHelper {
String userId = ctx.getSettings().BILLING_USER_ID.get(); String userId = ctx.getSettings().BILLING_USER_ID.get();
String email = ctx.getSettings().BILLING_USER_EMAIL.get(); String email = ctx.getSettings().BILLING_USER_EMAIL.get();
try { try {
sendRequestAsync("http://download.osmand.net/subscription/purchased?userid=" + URLEncoder.encode(userId, "UTF-8") Map<String, String> parameters = new HashMap<>();
+ "&sku=" + URLEncoder.encode(SKU_LIVE_UPDATES, "UTF-8") parameters.put("userId", userId);
+ "&purchaseToken=" + URLEncoder.encode(token, "UTF-8") parameters.put("sku", SKU_LIVE_UPDATES);
+ "&email=" + URLEncoder.encode(email, "UTF-8"), parameters.put("purchaseToken", token);
"POST", "Sending purchase info...", new OnRequestResultListener() { parameters.put("email", email);
sendRequestAsync("http://download.osmand.net/subscription/purchased.php",
parameters, "Sending purchase info...", new OnRequestResultListener() {
@Override @Override
public void onResult(String result) { public void onResult(String result) {
if (result != null && result.trim().toLowerCase().equals("ok")) { if (result != null && result.trim().toLowerCase().equals("ok")) {
@ -411,6 +387,7 @@ public class InAppHelper {
} }
}); });
} catch (Exception e) { } catch (Exception e) {
Log.e(TAG, "sendToken Error", e);
} }
} }
@ -423,33 +400,63 @@ public class InAppHelper {
ctx.showToastMessage(message); ctx.showToastMessage(message);
} }
private String sendRequest(String url, String requestMethod, String userOperation) { private String sendRequest(String url, Map<String, String> parameters, String userOperation) {
Log.d(TAG, "Sending request " + url); //$NON-NLS-1$ Log.d(TAG, "Sending request " + url); //$NON-NLS-1$
HttpURLConnection connection = null;
try { try {
HttpURLConnection connection = NetworkUtils.getHttpURLConnection(url); connection = NetworkUtils.getHttpURLConnection(url);
connection.setRequestProperty("Accept-Charset", "UTF-8");
connection.setRequestProperty("User-Agent", Version.getFullVersion(ctx));
connection.setConnectTimeout(15000); connection.setConnectTimeout(15000);
connection.setRequestMethod(requestMethod);
connection.setRequestProperty("User-Agent", Version.getFullVersion(ctx)); //$NON-NLS-1$ if (parameters != null && parameters.size() > 0) {
StringBuilder responseBody = new StringBuilder(); StringBuilder sb = new StringBuilder();
connection.connect(); for (Map.Entry<String, String> entry : parameters.entrySet()) {
if (sb.length() > 0) {
sb.append("&");
}
sb.append(entry.getKey()).append("=").append(URLEncoder.encode(entry.getValue(), "UTF-8"));
}
String params = sb.toString();
connection.setDoInput(true);
connection.setDoOutput(true);
connection.setUseCaches(false);
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8");
connection.setRequestProperty("Content-Length", String.valueOf(params.getBytes("UTF-8").length));
connection.setFixedLengthStreamingMode(params.getBytes("UTF-8").length);
OutputStream output = new BufferedOutputStream(connection.getOutputStream());
output.write(params.getBytes("UTF-8"));
output.flush();
output.close();
} else {
connection.setRequestMethod("GET");
connection.connect();
}
if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) { if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) {
String msg = userOperation String msg = userOperation
+ " " + ctx.getString(R.string.failed_op) + " : " + connection.getResponseMessage(); //$NON-NLS-1$//$NON-NLS-2$ + " " + ctx.getString(R.string.failed_op) + " : " + connection.getResponseMessage();
Log.e(TAG, msg); Log.e(TAG, msg);
showToast(msg); showToast(msg);
} else { } else {
Log.d(TAG, "Response : " + connection.getResponseMessage()); //$NON-NLS-1$ Log.d(TAG, "Response : " + connection.getResponseMessage());
// populate return fields. // populate return fields.
StringBuilder responseBody = new StringBuilder();
responseBody.setLength(0); responseBody.setLength(0);
InputStream i = connection.getInputStream(); InputStream i = connection.getInputStream();
if (i != null) { if (i != null) {
BufferedReader in = new BufferedReader(new InputStreamReader(i, "UTF-8"), 256); //$NON-NLS-1$ BufferedReader in = new BufferedReader(new InputStreamReader(i, "UTF-8"), 256);
String s; String s;
boolean f = true; boolean f = true;
while ((s = in.readLine()) != null) { while ((s = in.readLine()) != null) {
if (!f) { if (!f) {
responseBody.append("\n"); //$NON-NLS-1$ responseBody.append("\n");
} else { } else {
f = false; f = false;
} }
@ -459,37 +466,42 @@ public class InAppHelper {
in.close(); in.close();
i.close(); i.close();
} catch (Exception e) { } catch (Exception e) {
Log.e(TAG, "sendRequest", e);
} }
} }
return responseBody.toString(); return responseBody.toString();
} }
connection.disconnect();
} catch (NullPointerException e) { } catch (NullPointerException e) {
// that's tricky case why NPE is thrown to fix that problem httpClient could be used // that's tricky case why NPE is thrown to fix that problem httpClient could be used
String msg = ctx.getString(R.string.auth_failed); String msg = ctx.getString(R.string.auth_failed);
Log.e(TAG, msg, e); Log.e(TAG, msg, e);
showToast(msg); showToast(msg);
} catch (MalformedURLException e) { } catch (MalformedURLException e) {
Log.e(TAG, userOperation + " " + ctx.getString(R.string.failed_op), e); //$NON-NLS-1$ Log.e(TAG, userOperation + " " + ctx.getString(R.string.failed_op), e);
showToast(MessageFormat.format(ctx.getResources().getString(R.string.shared_string_action_template) showToast(MessageFormat.format(ctx.getResources().getString(R.string.shared_string_action_template)
+ ": " + ctx.getResources().getString(R.string.shared_string_unexpected_error), userOperation)); + ": " + ctx.getResources().getString(R.string.shared_string_unexpected_error), userOperation));
} catch (IOException e) { } catch (IOException e) {
Log.e(TAG, userOperation + " " + ctx.getString(R.string.failed_op), e); //$NON-NLS-1$ Log.e(TAG, userOperation + " " + ctx.getString(R.string.failed_op), e);
showToast(MessageFormat.format(ctx.getResources().getString(R.string.shared_string_action_template) showToast(MessageFormat.format(ctx.getResources().getString(R.string.shared_string_action_template)
+ ": " + ctx.getResources().getString(R.string.shared_string_io_error), userOperation)); + ": " + ctx.getResources().getString(R.string.shared_string_io_error), userOperation));
} finally {
if (connection != null) {
connection.disconnect();
}
} }
return null; return null;
} }
private void sendRequestAsync(final String url, final String requestMethod, final String userOperation, final OnRequestResultListener listener) { private void sendRequestAsync(final String url, final Map<String, String> parameters, final String userOperation, final OnRequestResultListener listener) {
new AsyncTask<Void, Void, String>() { new AsyncTask<Void, Void, String>() {
@Override @Override
protected String doInBackground(Void... params) { protected String doInBackground(Void... params) {
try { try {
return sendRequest(url, requestMethod, userOperation); return sendRequest(url, parameters, userOperation);
} catch (Exception e) { } catch (Exception e) {
return null; return null;
} }

View file

@ -0,0 +1,229 @@
package net.osmand.plus.liveupdates;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.support.annotation.DrawableRes;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.ListView;
import android.widget.TextView;
import net.osmand.map.WorldRegion;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
import net.osmand.plus.base.BaseOsmAndDialogFragment;
import net.osmand.util.Algorithms;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class CountrySelectionFragment extends BaseOsmAndDialogFragment {
private List<CountryItem> countryItems = new ArrayList<>();
private OnFragmentInteractionListener mListener;
public List<CountryItem> getCountryItems() {
return countryItems;
}
public CountryItem getCountryItem(String downloadName) {
if (!Algorithms.isEmpty(downloadName)) {
for (CountryItem item : countryItems) {
if (downloadName.equals(item.downloadName)) {
return item;
}
}
}
return null;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
if (countryItems.size() == 0) {
initCountries(getMyApplication());
}
View view = inflater.inflate(R.layout.fragment_search_list, container, false);
ListView listView = (ListView) view.findViewById(android.R.id.list);
final ArrayAdapter<CountryItem> adapter = new ListAdapter(getListItemIcon());
if (countryItems.size() > 0) {
adapter.addAll(countryItems);
}
listView.setAdapter(adapter);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
mListener.onSearchResult(adapter.getItem(position));
dismiss();
}
});
final EditText searchEditText = (EditText) view.findViewById(R.id.searchEditText);
searchEditText.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable s) {
adapter.getFilter().filter(s);
}
});
ImageButton clearButton = (ImageButton) view.findViewById(R.id.clearButton);
setThemedDrawable(clearButton, R.drawable.ic_action_remove_dark);
clearButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
dismiss();
}
});
return view;
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof OnFragmentInteractionListener) {
mListener = (OnFragmentInteractionListener) context;
} else if (getParentFragment() instanceof OnFragmentInteractionListener) {
mListener = (OnFragmentInteractionListener) getParentFragment();
} else {
throw new RuntimeException(context.toString()
+ " must implement OnFragmentInteractionListener");
}
}
@DrawableRes
protected int getListItemIcon() {
return R.drawable.ic_map;
}
@Override
public void onDetach() {
super.onDetach();
mListener = null;
}
public interface OnFragmentInteractionListener {
void onSearchResult(CountryItem name);
}
public void initCountries(OsmandApplication app) {
final WorldRegion root = app.getRegions().getWorldRegion();
ArrayList<WorldRegion> groups = new ArrayList<>();
groups.add(root);
processGroup(root, groups);
Collections.sort(groups, new Comparator<WorldRegion>() {
@Override
public int compare(WorldRegion lhs, WorldRegion rhs) {
if (lhs == root) {
return -1;
}
if (rhs == root) {
return 1;
}
return getHumanReadableName(lhs).compareTo(getHumanReadableName(rhs));
}
});
for (WorldRegion group : groups) {
String name = getHumanReadableName(group);
countryItems.add(new CountryItem(name, group.getRegionDownloadName()));
}
}
private static void processGroup(WorldRegion group,
List<WorldRegion> nameList) {
if (group.isRegionMapDownload()) {
nameList.add(group);
}
if (group.getSubregions() != null) {
for (WorldRegion g : group.getSubregions()) {
processGroup(g, nameList);
}
}
}
private static String getHumanReadableName(WorldRegion group) {
String name;
if (group.getLevel() > 2 || (group.getLevel() == 2
&& group.getSuperregion().getRegionId().equals(WorldRegion.RUSSIA_REGION_ID))) {
WorldRegion parent = group.getSuperregion();
WorldRegion parentsParent = group.getSuperregion().getSuperregion();
if (group.getLevel() == 3) {
if (parentsParent.getRegionId().equals(WorldRegion.RUSSIA_REGION_ID)) {
name = parentsParent.getLocaleName() + " " + group.getLocaleName();
} else if (!parent.getRegionId().equals(WorldRegion.UNITED_KINGDOM_REGION_ID)) {
name = parent.getLocaleName() + " " + group.getLocaleName();
} else {
name = group.getLocaleName();
}
} else {
name = parent.getLocaleName() + " " + group.getLocaleName();
}
} else {
name = group.getLocaleName();
}
if (name == null) {
name = "";
}
return name;
}
public static class CountryItem {
private String localName;
private String downloadName;
public CountryItem(String localName, String downloadName) {
this.localName = localName;
this.downloadName = downloadName;
}
public String getLocalName() {
return localName;
}
public String getDownloadName() {
return downloadName;
}
@Override
public String toString() {
return localName;
}
}
private class ListAdapter extends ArrayAdapter<CountryItem> {
private final Drawable drawableLeft;
public ListAdapter(@DrawableRes int drawableLeftId) {
super(getMyActivity(), android.R.layout.simple_list_item_1);
this.drawableLeft = drawableLeftId == -1 ? null : getContentIcon(drawableLeftId);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
CountryItem item = getItem(position);
TextView view = (TextView) super.getView(position, convertView, parent);
view.setText(item.localName);
view.setCompoundDrawablesWithIntrinsicBounds(drawableLeft, null, null, null);
view.setCompoundDrawablePadding(getResources().getDimensionPixelSize(R.dimen.list_content_padding));
return view;
}
}
}

View file

@ -22,6 +22,7 @@ import android.widget.ImageButton;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.TextView; import android.widget.TextView;
import net.osmand.map.WorldRegion;
import net.osmand.plus.OsmandApplication; import net.osmand.plus.OsmandApplication;
import net.osmand.plus.OsmandSettings; import net.osmand.plus.OsmandSettings;
import net.osmand.plus.R; import net.osmand.plus.R;
@ -106,6 +107,29 @@ public class LiveUpdatesFragment extends BaseOsmAndFragment {
} }
}); });
if (InAppHelper.isSubscribedToLiveUpdates()) { if (InAppHelper.isSubscribedToLiveUpdates()) {
TextView statusTextView = (TextView) subscriptionHeader.findViewById(R.id.statusTextView);
TextView regionNameTextView = (TextView) subscriptionHeader.findViewById(R.id.regionTextView);
TextView emailTextView = (TextView) subscriptionHeader.findViewById(R.id.emailTextView);
TextView userNameTextView = (TextView) subscriptionHeader.findViewById(R.id.userNameTextView);
if (InAppHelper.isSubscribedToLiveUpdates()) {
statusTextView.setText(getString(R.string.osm_live_active));
} else {
statusTextView.setText(getString(R.string.osm_live_not_active));
}
OsmandSettings settings = getMyApplication().getSettings();
String countryName = settings.BILLING_USER_COUNTRY.get();
if (Algorithms.isEmpty(countryName)) {
WorldRegion world = getMyApplication().getRegions().getWorldRegion();
countryName = world.getLocaleName();
}
regionNameTextView.setText(countryName);
emailTextView.setText(settings.BILLING_USER_EMAIL.get());
userNameTextView.setText(settings.BILLING_USER_NAME.get());
subscriptionBanner.setVisibility(View.GONE); subscriptionBanner.setVisibility(View.GONE);
subscriptionInfo.setVisibility(View.VISIBLE); subscriptionInfo.setVisibility(View.VISIBLE);
} else { } else {

View file

@ -22,23 +22,19 @@ import com.google.gson.Gson;
import com.google.gson.JsonSyntaxException; import com.google.gson.JsonSyntaxException;
import net.osmand.PlatformUtil; import net.osmand.PlatformUtil;
import net.osmand.map.WorldRegion;
import net.osmand.osm.io.NetworkUtils; import net.osmand.osm.io.NetworkUtils;
import net.osmand.plus.R; import net.osmand.plus.R;
import net.osmand.plus.base.BaseOsmAndFragment; import net.osmand.plus.base.BaseOsmAndFragment;
import net.osmand.plus.liveupdates.CountrySelectionFragment.CountryItem;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Calendar; import java.util.Calendar;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Locale; import java.util.Locale;
public class ReportsFragment extends BaseOsmAndFragment implements SearchSelectionFragment.OnFragmentInteractionListener { public class ReportsFragment extends BaseOsmAndFragment implements CountrySelectionFragment.OnFragmentInteractionListener {
public static final String TITLE = "Report"; public static final String TITLE = "Report";
public static final String TOTAL_CHANGES_BY_MONTH_URL_PATTERN = "http://download.osmand.net/" + public static final String TOTAL_CHANGES_BY_MONTH_URL_PATTERN = "http://download.osmand.net/" +
"reports/query_report.php?report=total_changes_by_month&month=%s&region=%s"; "reports/query_report.php?report=total_changes_by_month&month=%s&region=%s";
@ -50,11 +46,9 @@ public class ReportsFragment extends BaseOsmAndFragment implements SearchSelecti
private Spinner montReportsSpinner; private Spinner montReportsSpinner;
private MonthsForReportsAdapter monthsForReportsAdapter; private MonthsForReportsAdapter monthsForReportsAdapter;
CountrySearchSelectionFragment searchSelectionFragment = new CountrySearchSelectionFragment(); private CountrySelectionFragment countrySelectionFragment = new CountrySelectionFragment();
private TextView countryNameTextView; private TextView countryNameTextView;
private CountryItem selectedCountryItem;
HashMap<String, String> queryRegionNames = new HashMap<>();
ArrayList<String> regionNames = new ArrayList<>();
private ImageView numberOfContributorsIcon; private ImageView numberOfContributorsIcon;
private ImageView numberOfEditsIcon; private ImageView numberOfEditsIcon;
@ -69,7 +63,6 @@ public class ReportsFragment extends BaseOsmAndFragment implements SearchSelecti
@Override @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) { Bundle savedInstanceState) {
initCountries();
View view = inflater.inflate(R.layout.fragment_reports, container, false); View view = inflater.inflate(R.layout.fragment_reports, container, false);
montReportsSpinner = (Spinner) view.findViewById(R.id.montReportsSpinner); montReportsSpinner = (Spinner) view.findViewById(R.id.montReportsSpinner);
monthsForReportsAdapter = new MonthsForReportsAdapter(getActivity()); monthsForReportsAdapter = new MonthsForReportsAdapter(getActivity());
@ -79,15 +72,15 @@ public class ReportsFragment extends BaseOsmAndFragment implements SearchSelecti
regionReportsButton.setOnClickListener(new View.OnClickListener() { regionReportsButton.setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(View v) { public void onClick(View v) {
SearchSelectionFragment countrySearchSelectionFragment = countrySelectionFragment.show(getChildFragmentManager(), "CountriesSearchSelectionFragment");
searchSelectionFragment;
countrySearchSelectionFragment
.show(getChildFragmentManager(), "CountriesSearchSelectionFragment");
} }
}); });
countrySelectionFragment.initCountries(getMyApplication());
selectedCountryItem = countrySelectionFragment.getCountryItems().get(0);
countryNameTextView = (TextView) regionReportsButton.findViewById(android.R.id.text1); countryNameTextView = (TextView) regionReportsButton.findViewById(android.R.id.text1);
countryNameTextView.setText(regionNames.get(0)); countryNameTextView.setText(selectedCountryItem.getLocalName());
setThemedDrawable(view, R.id.calendarImageView, R.drawable.ic_action_data); setThemedDrawable(view, R.id.calendarImageView, R.drawable.ic_action_data);
setThemedDrawable(view, R.id.regionIconImageView, R.drawable.ic_world_globe_dark); setThemedDrawable(view, R.id.regionIconImageView, R.drawable.ic_world_globe_dark);
@ -127,7 +120,7 @@ public class ReportsFragment extends BaseOsmAndFragment implements SearchSelecti
public void requestAndUpdateUi() { public void requestAndUpdateUi() {
int monthItemPosition = montReportsSpinner.getSelectedItemPosition(); int monthItemPosition = montReportsSpinner.getSelectedItemPosition();
String monthUrlString = monthsForReportsAdapter.getQueryString(monthItemPosition); String monthUrlString = monthsForReportsAdapter.getQueryString(monthItemPosition);
String countryUrlString = queryRegionNames.get(countryNameTextView.getText().toString()); String countryUrlString = selectedCountryItem.getDownloadName();
tryUpdateData(monthUrlString, countryUrlString); tryUpdateData(monthUrlString, countryUrlString);
} }
@ -171,79 +164,12 @@ public class ReportsFragment extends BaseOsmAndFragment implements SearchSelecti
} }
@Override @Override
public void onSearchResult(String name) { public void onSearchResult(CountryItem item) {
countryNameTextView.setText(name); selectedCountryItem = item;
countryNameTextView.setText(item.getLocalName());
requestAndUpdateUi(); requestAndUpdateUi();
} }
private void initCountries() {
final WorldRegion root = getMyApplication().getRegions().getWorldRegion();
ArrayList<WorldRegion> groups = new ArrayList<>();
groups.add(root);
processGroup(root, groups, getActivity());
Collections.sort(groups, new Comparator<WorldRegion>() {
@Override
public int compare(WorldRegion lhs, WorldRegion rhs) {
if (lhs == root) {
return -1;
}
if (rhs == root) {
return 1;
}
return getHumanReadableName(lhs).compareTo(getHumanReadableName(rhs));
}
});
for (WorldRegion group : groups) {
String name = getHumanReadableName(group);
regionNames.add(name);
queryRegionNames.put(name, group == root ? "" : group.getRegionDownloadName());
}
}
private static String getHumanReadableName(WorldRegion group) {
String name;
if (group.getLevel() > 2 || (group.getLevel() == 2
&& group.getSuperregion().getRegionId().equals(WorldRegion.RUSSIA_REGION_ID))) {
WorldRegion parent = group.getSuperregion();
WorldRegion parentsParent = group.getSuperregion().getSuperregion();
if (group.getLevel() == 3) {
if (parentsParent.getRegionId().equals(WorldRegion.RUSSIA_REGION_ID)) {
name = parentsParent.getLocaleName() + " " + group.getLocaleName();
} else if (!parent.getRegionId().equals(WorldRegion.UNITED_KINGDOM_REGION_ID)) {
name = parent.getLocaleName() + " " + group.getLocaleName();
} else {
name = group.getLocaleName();
}
} else {
name = parent.getLocaleName() + " " + group.getLocaleName();
}
} else {
name = group.getLocaleName();
}
if (name == null) {
name = "";
}
return name;
}
public String getQueryString(int position) {
return queryRegionNames.get(position);
}
private static void processGroup(WorldRegion group,
List<WorldRegion> nameList,
Context context) {
if (group.isRegionMapDownload()) {
nameList.add(group);
}
if (group.getSubregions() != null) {
for (WorldRegion g : group.getSubregions()) {
processGroup(g, nameList, context);
}
}
}
private static class MonthsForReportsAdapter extends ArrayAdapter<String> { private static class MonthsForReportsAdapter extends ArrayAdapter<String> {
private static final SimpleDateFormat queryFormat = new SimpleDateFormat("yyyy-MM", Locale.US); private static final SimpleDateFormat queryFormat = new SimpleDateFormat("yyyy-MM", Locale.US);
@SuppressLint("SimpleDateFormat") @SuppressLint("SimpleDateFormat")
@ -325,18 +251,6 @@ public class ReportsFragment extends BaseOsmAndFragment implements SearchSelecti
} }
} }
public static class CountrySearchSelectionFragment extends SearchSelectionFragment {
@Override
protected ArrayList<String> getList() {
return ((ReportsFragment) getParentFragment()).regionNames;
}
@Override
protected int getListItemIcon() {
return R.drawable.ic_map;
}
}
private void enableProgress() { private void enableProgress() {
numberOfContributorsIcon.setImageDrawable(getPaintedContentIcon(R.drawable.ic_group, inactiveColor)); numberOfContributorsIcon.setImageDrawable(getPaintedContentIcon(R.drawable.ic_group, inactiveColor));
numberOfEditsIcon.setImageDrawable(getPaintedContentIcon(R.drawable.ic_map, inactiveColor)); numberOfEditsIcon.setImageDrawable(getPaintedContentIcon(R.drawable.ic_map, inactiveColor));

View file

@ -1,126 +0,0 @@
package net.osmand.plus.liveupdates;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.support.annotation.DrawableRes;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.ListView;
import android.widget.TextView;
import net.osmand.plus.R;
import net.osmand.plus.base.BaseOsmAndDialogFragment;
import java.util.ArrayList;
public abstract class SearchSelectionFragment extends BaseOsmAndDialogFragment {
private OnFragmentInteractionListener mListener;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_search_list, container, false);
ListView listView = (ListView) view.findViewById(android.R.id.list);
final ArrayAdapter<String> adapter = new ListAdapter(getActivity(), getListItemIcon());
if (getArray() != null) {
adapter.addAll(getArray());
} else if (getList() != null) {
adapter.addAll(getList());
} else {
throw new RuntimeException("Either getArray() or getList() must return non null value.");
}
listView.setAdapter(adapter);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
mListener.onSearchResult(adapter.getItem(position));
dismiss();
}
});
final EditText searchEditText = (EditText) view.findViewById(R.id.searchEditText);
searchEditText.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable s) {
adapter.getFilter().filter(s);
}
});
ImageButton clearButton = (ImageButton) view.findViewById(R.id.clearButton);
setThemedDrawable(clearButton, R.drawable.ic_action_remove_dark);
clearButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
dismiss();
}
});
return view;
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof OnFragmentInteractionListener) {
mListener = (OnFragmentInteractionListener) context;
} else if (getParentFragment() instanceof OnFragmentInteractionListener) {
mListener = (OnFragmentInteractionListener) getParentFragment();
} else {
throw new RuntimeException(context.toString()
+ " must implement OnFragmentInteractionListener");
}
}
protected String[] getArray() {
return null;
}
protected ArrayList<String> getList() {
return null;
}
@DrawableRes
protected int getListItemIcon() {
return -1;
}
@Override
public void onDetach() {
super.onDetach();
mListener = null;
}
public interface OnFragmentInteractionListener {
void onSearchResult(String name);
}
private class ListAdapter extends ArrayAdapter<String> {
private final Drawable drawableLeft;
public ListAdapter(Context context, @DrawableRes int drawableLeftId) {
super(getMyActivity(), android.R.layout.simple_list_item_1);
this.drawableLeft = drawableLeftId == -1 ? null : getContentIcon(drawableLeftId);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
TextView view = (TextView) super.getView(position, convertView, parent);
view.setCompoundDrawablesWithIntrinsicBounds(drawableLeft, null, null, null);
view.setCompoundDrawablePadding(getResources().getDimensionPixelSize(R.dimen.list_content_padding));
return view;
}
}
}

View file

@ -2,7 +2,6 @@ package net.osmand.plus.liveupdates;
import android.app.Activity; import android.app.Activity;
import android.app.ProgressDialog; import android.app.ProgressDialog;
import android.content.Context;
import android.os.Bundle; import android.os.Bundle;
import android.support.v4.app.Fragment; import android.support.v4.app.Fragment;
import android.view.LayoutInflater; import android.view.LayoutInflater;
@ -10,27 +9,23 @@ import android.view.MotionEvent;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.Button; import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText; import android.widget.EditText;
import android.widget.ImageButton; import android.widget.ImageButton;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.TextView; import android.widget.TextView;
import net.osmand.AndroidUtils; import net.osmand.AndroidUtils;
import net.osmand.map.WorldRegion;
import net.osmand.plus.OsmandSettings; import net.osmand.plus.OsmandSettings;
import net.osmand.plus.R; import net.osmand.plus.R;
import net.osmand.plus.base.BaseOsmAndDialogFragment; import net.osmand.plus.base.BaseOsmAndDialogFragment;
import net.osmand.plus.inapp.InAppHelper; import net.osmand.plus.inapp.InAppHelper;
import net.osmand.plus.inapp.InAppHelper.InAppCallbacks; import net.osmand.plus.inapp.InAppHelper.InAppCallbacks;
import net.osmand.plus.liveupdates.SearchSelectionFragment.OnFragmentInteractionListener; import net.osmand.plus.liveupdates.CountrySelectionFragment.CountryItem;
import net.osmand.plus.liveupdates.CountrySelectionFragment.OnFragmentInteractionListener;
import net.osmand.util.Algorithms; import net.osmand.util.Algorithms;
import java.util.ArrayList; public class SubscriptionFragment extends BaseOsmAndDialogFragment implements InAppCallbacks, OnFragmentInteractionListener {
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class SubscriptionFragment extends BaseOsmAndDialogFragment implements InAppCallbacks, OnFragmentInteractionListener{
public static final String TAG = "SubscriptionFragment"; public static final String TAG = "SubscriptionFragment";
@ -40,11 +35,9 @@ public class SubscriptionFragment extends BaseOsmAndDialogFragment implements In
private String userName; private String userName;
private String email; private String email;
private String country; private CountryItem selectedCountryItem;
ArrayList<String> regionNames = new ArrayList<>(); private CountrySelectionFragment countrySelectionFragment = new CountrySelectionFragment();
private CountrySearchSelectionFragment searchSelectionFragment
= new CountrySearchSelectionFragment();
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
@ -73,8 +66,6 @@ public class SubscriptionFragment extends BaseOsmAndDialogFragment implements In
} }
}); });
initCountries();
userName = settings.BILLING_USER_NAME.get(); userName = settings.BILLING_USER_NAME.get();
final EditText userNameEdit = (EditText) view.findViewById(R.id.userNameEdit); final EditText userNameEdit = (EditText) view.findViewById(R.id.userNameEdit);
if (!Algorithms.isEmpty(userName)) { if (!Algorithms.isEmpty(userName)) {
@ -87,52 +78,62 @@ public class SubscriptionFragment extends BaseOsmAndDialogFragment implements In
emailEdit.setText(email); emailEdit.setText(email);
} }
country = settings.BILLING_USER_COUNTRY.get(); countrySelectionFragment.initCountries(getMyApplication());
String countryDownloadName = settings.BILLING_USER_COUNTRY_DOWNLOAD_NAME.get();
if (Algorithms.isEmpty(countryDownloadName)) {
selectedCountryItem = countrySelectionFragment.getCountryItems().get(0);
} else {
selectedCountryItem = countrySelectionFragment.getCountryItem(countryDownloadName);
}
final EditText selectCountryEdit = (EditText) view.findViewById(R.id.selectCountryEdit); final EditText selectCountryEdit = (EditText) view.findViewById(R.id.selectCountryEdit);
if (!Algorithms.isEmpty(country)) { if (selectedCountryItem != null) {
selectCountryEdit.setText(country); selectCountryEdit.setText(selectedCountryItem.getLocalName());
} }
selectCountryEdit.setOnTouchListener(new View.OnTouchListener() { selectCountryEdit.setOnTouchListener(new View.OnTouchListener() {
@Override @Override
public boolean onTouch(View v, MotionEvent event) { public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_UP) { if (event.getAction() == MotionEvent.ACTION_UP) {
SearchSelectionFragment countrySearchSelectionFragment = CountrySelectionFragment countryCountrySelectionFragment =
searchSelectionFragment; countrySelectionFragment;
countrySearchSelectionFragment countryCountrySelectionFragment
.show(getChildFragmentManager(), "CountriesSearchSelectionFragment"); .show(getChildFragmentManager(), "CountriesSearchSelectionFragment");
} }
return false; return false;
} }
}); });
updatePrice(); updatePrice(view);
Button subscribeButton = (Button) view.findViewById(R.id.subscribeButton); final Button subscribeButton = (Button) view.findViewById(R.id.subscribeButton);
final CheckBox hideUserNameCheckbox = (CheckBox) view.findViewById(R.id.hideUserNameCheckbox);
boolean hideUserName = settings.BILLING_HIDE_USER_NAME.get();
hideUserNameCheckbox.setChecked(hideUserName);
subscribeButton.setOnClickListener(new View.OnClickListener() { subscribeButton.setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(View v) { public void onClick(View v) {
if (inAppHelper != null) { if (inAppHelper != null) {
userName = userNameEdit.getText().toString().trim(); userName = userNameEdit.getText().toString().trim();
email = emailEdit.getText().toString().trim(); email = emailEdit.getText().toString().trim();
country = selectCountryEdit.getText().toString().trim(); String countryName = selectedCountryItem != null ? selectedCountryItem.getLocalName() : "";
String countryDownloadName = selectedCountryItem != null ? selectedCountryItem.getDownloadName() : "";
if (Algorithms.isEmpty(userName)) {
getMyApplication().showToastMessage("Please enter visible name");
return;
}
if (Algorithms.isEmpty(email) || !AndroidUtils.isValidEmail(email)) { if (Algorithms.isEmpty(email) || !AndroidUtils.isValidEmail(email)) {
getMyApplication().showToastMessage("Please enter valid E-mail address"); getMyApplication().showToastMessage("Please enter valid E-mail address");
return; return;
} }
if (Algorithms.isEmpty(userName) && !hideUserNameCheckbox.isChecked()) {
getMyApplication().showToastMessage("Please enter Public Name");
return;
}
settings.BILLING_USER_NAME.set(userName); settings.BILLING_USER_NAME.set(userName);
settings.BILLING_USER_EMAIL.set(email); settings.BILLING_USER_EMAIL.set(email);
settings.BILLING_USER_COUNTRY.set(country); settings.BILLING_USER_COUNTRY.set(countryName);
settings.BILLING_USER_COUNTRY_DOWNLOAD_NAME.set(countryDownloadName);
settings.BILLING_HIDE_USER_NAME.set(hideUserNameCheckbox.isChecked());
final WorldRegion world = getMyApplication().getRegions().getWorldRegion(); inAppHelper.purchaseLiveUpdates(getActivity(), email, userName, countryDownloadName);
String countryParam = country.equals(world.getLocaleName()) ? "" : country;
inAppHelper.purchaseLiveUpdates(getActivity(), email, userName, countryParam);
} }
} }
}); });
@ -165,7 +166,7 @@ public class SubscriptionFragment extends BaseOsmAndDialogFragment implements In
@Override @Override
public void onGetItems() { public void onGetItems() {
updatePrice(); updatePrice(getView());
} }
@Override @Override
@ -201,18 +202,21 @@ public class SubscriptionFragment extends BaseOsmAndDialogFragment implements In
} }
@Override @Override
public void onSearchResult(String name) { public void onSearchResult(CountryItem item) {
selectedCountryItem = item;
View view = getView(); View view = getView();
if (view != null) { if (view != null) {
EditText selectCountryEdit = (EditText) view.findViewById(R.id.selectCountryEdit); EditText selectCountryEdit = (EditText) view.findViewById(R.id.selectCountryEdit);
if (selectCountryEdit != null) { if (selectCountryEdit != null) {
selectCountryEdit.setText(name); selectCountryEdit.setText(item.getLocalName());
} }
} }
} }
private void updatePrice() { private void updatePrice(View view) {
View view = getView(); if (view == null) {
view = getView();
}
if (view != null) { if (view != null) {
TextView priceTextView = (TextView) view.findViewById(R.id.priceTextView); TextView priceTextView = (TextView) view.findViewById(R.id.priceTextView);
if (InAppHelper.getLiveUpdatesPrice() != null) { if (InAppHelper.getLiveUpdatesPrice() != null) {
@ -220,79 +224,4 @@ public class SubscriptionFragment extends BaseOsmAndDialogFragment implements In
} }
} }
} }
private void initCountries() {
final WorldRegion root = getMyApplication().getRegions().getWorldRegion();
ArrayList<WorldRegion> groups = new ArrayList<>();
groups.add(root);
processGroup(root, groups, getActivity());
Collections.sort(groups, new Comparator<WorldRegion>() {
@Override
public int compare(WorldRegion lhs, WorldRegion rhs) {
if (lhs == root) {
return -1;
}
if (rhs == root) {
return 1;
}
return getHumanReadableName(lhs).compareTo(getHumanReadableName(rhs));
}
});
for (WorldRegion group : groups) {
String name = getHumanReadableName(group);
regionNames.add(name);
}
}
private static void processGroup(WorldRegion group,
List<WorldRegion> nameList,
Context context) {
if (group.isRegionMapDownload()) {
nameList.add(group);
}
if (group.getSubregions() != null) {
for (WorldRegion g : group.getSubregions()) {
processGroup(g, nameList, context);
}
}
}
private static String getHumanReadableName(WorldRegion group) {
String name;
if (group.getLevel() > 2 || (group.getLevel() == 2
&& group.getSuperregion().getRegionId().equals(WorldRegion.RUSSIA_REGION_ID))) {
WorldRegion parent = group.getSuperregion();
WorldRegion parentsParent = group.getSuperregion().getSuperregion();
if (group.getLevel() == 3) {
if (parentsParent.getRegionId().equals(WorldRegion.RUSSIA_REGION_ID)) {
name = parentsParent.getLocaleName() + " " + group.getLocaleName();
} else if (!parent.getRegionId().equals(WorldRegion.UNITED_KINGDOM_REGION_ID)) {
name = parent.getLocaleName() + " " + group.getLocaleName();
} else {
name = group.getLocaleName();
}
} else {
name = parent.getLocaleName() + " " + group.getLocaleName();
}
} else {
name = group.getLocaleName();
}
if (name == null) {
name = "";
}
return name;
}
public static class CountrySearchSelectionFragment extends SearchSelectionFragment {
@Override
protected ArrayList<String> getList() {
return ((SubscriptionFragment) getParentFragment()).regionNames;
}
@Override
protected int getListItemIcon() {
return R.drawable.ic_map;
}
}
} }