/* * Copyright (C) 2015 Federico Iosue (federico.iosue@gmail.com) * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package it.feio.android.omninotes.utils; import android.content.Context; import android.location.*; import android.os.Bundle; import android.text.TextUtils; import android.util.Log; import io.nlopez.smartlocation.SmartLocation; import io.nlopez.smartlocation.location.config.LocationParams; import io.nlopez.smartlocation.rx.ObservableFactory; import it.feio.android.omninotes.BuildConfig; import it.feio.android.omninotes.OmniNotes; import it.feio.android.omninotes.helpers.GeoCodeProviderFactory; import it.feio.android.omninotes.models.listeners.OnGeoUtilResultListener; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import rx.Observable; import rx.Subscriber; import java.io.IOException; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import java.net.URLEncoder; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Locale; import java.util.concurrent.TimeUnit; import java.util.regex.Matcher; import java.util.regex.Pattern; public class GeocodeHelper implements LocationListener { private static final String LOG_TAG = Constants.TAG; private static final String PLACES_API_BASE = "https://maps.googleapis.com/maps/api/place"; private static final String TYPE_AUTOCOMPLETE = "/autocomplete"; private static final String OUT_JSON = "/json"; private static GeocodeHelper instance; private static LocationManager locationManager; private GeocodeHelper() { instance = this; locationManager = (LocationManager) OmniNotes.getAppContext().getSystemService(Context.LOCATION_SERVICE); } @Override public void onLocationChanged(Location newLocation) { } @Override public void onStatusChanged(String provider, int status, Bundle extras) { } @Override public void onProviderEnabled(String provider) { } @Override public void onProviderDisabled(String provider) { } public static void getLocation(OnGeoUtilResultListener onGeoUtilResultListener) { SmartLocation.LocationControl bod = SmartLocation.with(OmniNotes.getAppContext()) .location(GeoCodeProviderFactory.getProvider(OmniNotes.getAppContext())) .config(LocationParams.NAVIGATION).oneFix(); Observable<Location> locations = ObservableFactory.from(bod).timeout(2, TimeUnit.SECONDS); locations.subscribe(new Subscriber<Location>() { @Override public void onNext(Location location) { onGeoUtilResultListener.onLocationRetrieved(location); unsubscribe(); } @Override public void onCompleted() { } @Override public void onError(Throwable e) { onGeoUtilResultListener.onLocationUnavailable(); unsubscribe(); } }); } public static void stop() { SmartLocation.with(OmniNotes.getAppContext()).location().stop(); if (Geocoder.isPresent()) { SmartLocation.with(OmniNotes.getAppContext()).geocoding().stop(); } } static String getAddressFromCoordinates(Context mContext, double latitude, double longitude) throws IOException { String addressString = ""; Geocoder geocoder = new Geocoder(mContext, Locale.getDefault()); List<Address> addresses = geocoder.getFromLocation(latitude, longitude, 1); if (addresses.size() > 0) { Address address = addresses.get(0); if (address != null) { addressString = address.getThoroughfare() + ", " + address.getLocality(); } } return addressString; } public static void getAddressFromCoordinates(Location location, final OnGeoUtilResultListener onGeoUtilResultListener) { if (!Geocoder.isPresent()) { onGeoUtilResultListener.onAddressResolved(""); } else { SmartLocation.with(OmniNotes.getAppContext()).geocoding().reverse(location, (location1, list) -> { String address = list.size() > 0 ? list.get(0).getAddressLine(0) : null; onGeoUtilResultListener.onAddressResolved(address); }); } } public static double[] getCoordinatesFromAddress(Context mContext, String address) throws IOException { double[] result = new double[2]; Geocoder geocoder = new Geocoder(mContext, Locale.getDefault()); List<Address> addresses = geocoder.getFromLocationName(address, 1); if (addresses.size() > 0) { double latitude = addresses.get(0).getLatitude(); double longitude = addresses.get(0).getLongitude(); result[0] = latitude; result[1] = longitude; } return result; } public static void getCoordinatesFromAddress(String address, final OnGeoUtilResultListener listener) { SmartLocation.with(OmniNotes.getAppContext()).geocoding().direct(address, (name, results) -> { if (results.size() > 0) { listener.onCoordinatesResolved(results.get(0).getLocation(), address); } }); } public static List<String> autocomplete(String input) { String MAPS_API_KEY = BuildConfig.MAPS_API_KEY; if (TextUtils.isEmpty(MAPS_API_KEY)) { return Collections.emptyList(); } ArrayList<String> resultList = null; HttpURLConnection conn = null; InputStreamReader in = null; StringBuilder jsonResults = new StringBuilder(); try { URL url = new URL(PLACES_API_BASE + TYPE_AUTOCOMPLETE + OUT_JSON + "?key=" + MAPS_API_KEY + "&input=" + URLEncoder.encode(input, "utf8")); conn = (HttpURLConnection) url.openConnection(); in = new InputStreamReader(conn.getInputStream()); // Load the results into a StringBuilder int read; char[] buff = new char[1024]; while ((read = in.read(buff)) != -1) { jsonResults.append(buff, 0, read); } } catch (MalformedURLException e) { Log.e(Constants.TAG, "Error processing Places API URL"); return null; } catch (IOException e) { Log.e(Constants.TAG, "Error connecting to Places API"); return null; } finally { if (conn != null) { conn.disconnect(); } if (in != null) { try { in.close(); } catch (IOException e) { Log.e(Constants.TAG, "Error closing address autocompletion InputStream"); } } } try { // Create a JSON object hierarchy from the results JSONObject jsonObj = new JSONObject(jsonResults.toString()); JSONArray predsJsonArray = jsonObj.getJSONArray("predictions"); // Extract the Place descriptions from the results resultList = new ArrayList<>(predsJsonArray.length()); for (int i = 0; i < predsJsonArray.length(); i++) { resultList.add(predsJsonArray.getJSONObject(i).getString("description")); } } catch (JSONException e) { Log.e(Constants.TAG, "Cannot process JSON results", e); } return resultList; } public static boolean areCoordinates(String string) { Pattern p = Pattern.compile("^[-+]?([1-8]?\\d(\\.\\d+)?|90(\\.0+)?),\\s*[-+]?(180(\\.0+)?|((1[0-7]\\d)|" + "([1-9]?\\d))(\\.\\d+)?)$"); Matcher m = p.matcher(string); return m.matches(); } }