/*
* This is the source code of Telegram for Android v. 3.x.x
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*
* Copyright Nikolai Kudashov, 2013-2017.
*/
package org.telegram.ui.Adapters;
import android.location.Location;
import android.os.AsyncTask;
import org.json.JSONArray;
import org.json.JSONObject;
import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.BuildVars;
import org.telegram.messenger.FileLog;
import org.telegram.tgnet.ConnectionsManager;
import org.telegram.tgnet.TLRPC;
import org.telegram.ui.Components.RecyclerListView;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Locale;
import java.util.Timer;
import java.util.TimerTask;
public abstract class BaseLocationAdapter extends RecyclerListView.SelectionAdapter {
public interface BaseLocationAdapterDelegate {
void didLoadedSearchResult(ArrayList<TLRPC.TL_messageMediaVenue> places);
}
protected boolean searching;
protected ArrayList<TLRPC.TL_messageMediaVenue> places = new ArrayList<>();
protected ArrayList<String> iconUrls = new ArrayList<>();
private Location lastSearchLocation;
private BaseLocationAdapterDelegate delegate;
private Timer searchTimer;
private AsyncTask<Void, Void, JSONObject> currentTask;
public void destroy() {
if (currentTask != null) {
currentTask.cancel(true);
currentTask = null;
}
}
public void setDelegate(BaseLocationAdapterDelegate delegate) {
this.delegate = delegate;
}
public void searchDelayed(final String query, final Location coordinate) {
if (query == null || query.length() == 0) {
places.clear();
notifyDataSetChanged();
} else {
try {
if (searchTimer != null) {
searchTimer.cancel();
}
} catch (Exception e) {
FileLog.e(e);
}
searchTimer = new Timer();
searchTimer.schedule(new TimerTask() {
@Override
public void run() {
try {
searchTimer.cancel();
searchTimer = null;
} catch (Exception e) {
FileLog.e(e);
}
AndroidUtilities.runOnUIThread(new Runnable() {
@Override
public void run() {
lastSearchLocation = null;
searchGooglePlacesWithQuery(query, coordinate);
}
});
}
}, 200, 500);
}
}
public void searchGooglePlacesWithQuery(final String query, final Location coordinate) {
if (lastSearchLocation != null && coordinate.distanceTo(lastSearchLocation) < 200) {
return;
}
lastSearchLocation = coordinate;
if (searching) {
searching = false;
if (currentTask != null) {
currentTask.cancel(true);
currentTask = null;
}
}
try {
searching = true;
final String url = String.format(Locale.US, "https://api.foursquare.com/v2/venues/search/?v=%s&locale=en&limit=25&client_id=%s&client_secret=%s&ll=%s%s", BuildVars.FOURSQUARE_API_VERSION, BuildVars.FOURSQUARE_API_ID, BuildVars.FOURSQUARE_API_KEY, String.format(Locale.US, "%f,%f", coordinate.getLatitude(), coordinate.getLongitude()), query != null && query.length() > 0 ? "&query=" + URLEncoder.encode(query, "UTF-8") : "");
/*
GOOGLE MAPS
JSONArray result = response.getJSONArray("results");
for (int a = 0; a < result.length(); a++) {
try {
JSONObject object = result.getJSONObject(a);
JSONObject location = object.getJSONObject("geometry").getJSONObject("location");
TLRPC.TL_messageMediaVenue venue = new TLRPC.TL_messageMediaVenue();
venue.geo = new TLRPC.TL_geoPoint();
venue.geo.lat = location.getDouble("lat");
venue.geo._long = location.getDouble("lng");
if (object.has("vicinity")) {
venue.address = object.getString("vicinity").trim();
} else {
venue.address = String.format(Locale.US, "%f,%f", venue.geo.lat, venue.geo._long);
}
if (object.has("name")) {
venue.title = object.getString("name").trim();
}
venue.venue_id = object.getString("place_id");
venue.provider = "google";
places.add(venue);
} catch (Exception e) {
FileLog.e(e);
}
}
*/
currentTask = new AsyncTask<Void, Void, JSONObject>() {
private boolean canRetry = true;
private String downloadUrlContent(String url) {
boolean canRetry = true;
InputStream httpConnectionStream = null;
boolean done = false;
StringBuilder result = null;
URLConnection httpConnection = null;
try {
URL downloadUrl = new URL(url);
httpConnection = downloadUrl.openConnection();
httpConnection.addRequestProperty("User-Agent", "Mozilla/5.0 (X11; Linux x86_64; rv:10.0) Gecko/20150101 Firefox/47.0 (Chrome)");
httpConnection.addRequestProperty("Accept-Language", "en-us,en;q=0.5");
httpConnection.addRequestProperty("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
httpConnection.addRequestProperty("Accept-Charset", "ISO-8859-1,utf-8;q=0.7,*;q=0.7");
httpConnection.setConnectTimeout(5000);
httpConnection.setReadTimeout(5000);
if (httpConnection instanceof HttpURLConnection) {
HttpURLConnection httpURLConnection = (HttpURLConnection) httpConnection;
httpURLConnection.setInstanceFollowRedirects(true);
int status = httpURLConnection.getResponseCode();
if (status == HttpURLConnection.HTTP_MOVED_TEMP || status == HttpURLConnection.HTTP_MOVED_PERM || status == HttpURLConnection.HTTP_SEE_OTHER) {
String newUrl = httpURLConnection.getHeaderField("Location");
String cookies = httpURLConnection.getHeaderField("Set-Cookie");
downloadUrl = new URL(newUrl);
httpConnection = downloadUrl.openConnection();
httpConnection.setRequestProperty("Cookie", cookies);
httpConnection.addRequestProperty("User-Agent", "Mozilla/5.0 (X11; Linux x86_64; rv:10.0) Gecko/20150101 Firefox/47.0 (Chrome)");
httpConnection.addRequestProperty("Accept-Language", "en-us,en;q=0.5");
httpConnection.addRequestProperty("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
httpConnection.addRequestProperty("Accept-Charset", "ISO-8859-1,utf-8;q=0.7,*;q=0.7");
}
}
httpConnection.connect();
httpConnectionStream = httpConnection.getInputStream();
} catch (Throwable e) {
if (e instanceof SocketTimeoutException) {
if (ConnectionsManager.isNetworkOnline()) {
canRetry = false;
}
} else if (e instanceof UnknownHostException) {
canRetry = false;
} else if (e instanceof SocketException) {
if (e.getMessage() != null && e.getMessage().contains("ECONNRESET")) {
canRetry = false;
}
} else if (e instanceof FileNotFoundException) {
canRetry = false;
}
FileLog.e(e);
}
if (canRetry) {
try {
if (httpConnection != null && httpConnection instanceof HttpURLConnection) {
int code = ((HttpURLConnection) httpConnection).getResponseCode();
if (code != HttpURLConnection.HTTP_OK && code != HttpURLConnection.HTTP_ACCEPTED && code != HttpURLConnection.HTTP_NOT_MODIFIED) {
//canRetry = false;
}
}
} catch (Exception e) {
FileLog.e(e);
}
if (httpConnectionStream != null) {
try {
byte[] data = new byte[1024 * 32];
while (true) {
if (isCancelled()) {
break;
}
try {
int read = httpConnectionStream.read(data);
if (read > 0) {
if (result == null) {
result = new StringBuilder();
}
result.append(new String(data, 0, read, "UTF-8"));
} else if (read == -1) {
done = true;
break;
} else {
break;
}
} catch (Exception e) {
FileLog.e(e);
break;
}
}
} catch (Throwable e) {
FileLog.e(e);
}
}
try {
if (httpConnectionStream != null) {
httpConnectionStream.close();
}
} catch (Throwable e) {
FileLog.e(e);
}
}
return done ? result.toString() : null;
}
protected JSONObject doInBackground(Void... voids) {
String code = downloadUrlContent(url);
if (isCancelled()) {
return null;
}
try {
return new JSONObject(code);
} catch (Exception e) {
FileLog.e(e);
}
return null;
}
@Override
protected void onPostExecute(JSONObject response) {
if (response != null) {
try {
places.clear();
iconUrls.clear();
JSONArray result = response.getJSONObject("response").getJSONArray("venues");
for (int a = 0; a < result.length(); a++) {
try {
JSONObject object = result.getJSONObject(a);
String iconUrl = null;
if (object.has("categories")) {
JSONArray categories = object.getJSONArray("categories");
if (categories.length() > 0) {
JSONObject category = categories.getJSONObject(0);
if (category.has("icon")) {
JSONObject icon = category.getJSONObject("icon");
iconUrl = String.format(Locale.US, "%s64%s", icon.getString("prefix"), icon.getString("suffix"));
}
}
}
iconUrls.add(iconUrl);
JSONObject location = object.getJSONObject("location");
TLRPC.TL_messageMediaVenue venue = new TLRPC.TL_messageMediaVenue();
venue.geo = new TLRPC.TL_geoPoint();
venue.geo.lat = location.getDouble("lat");
venue.geo._long = location.getDouble("lng");
if (location.has("address")) {
venue.address = location.getString("address");
} else if (location.has("city")) {
venue.address = location.getString("city");
} else if (location.has("state")) {
venue.address = location.getString("state");
} else if (location.has("country")) {
venue.address = location.getString("country");
} else {
venue.address = String.format(Locale.US, "%f,%f", venue.geo.lat, venue.geo._long);
}
if (object.has("name")) {
venue.title = object.getString("name");
}
venue.venue_id = object.getString("id");
venue.provider = "foursquare";
places.add(venue);
} catch (Exception e) {
FileLog.e(e);
}
}
} catch (Exception e) {
FileLog.e(e);
}
searching = false;
notifyDataSetChanged();
if (delegate != null) {
delegate.didLoadedSearchResult(places);
}
} else {
searching = false;
notifyDataSetChanged();
if (delegate != null) {
delegate.didLoadedSearchResult(places);
}
}
}
};
currentTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, null, null, null);
} catch (Exception e) {
FileLog.e(e);
searching = false;
if (delegate != null) {
delegate.didLoadedSearchResult(places);
}
}
notifyDataSetChanged();
}
}