replace nominatimClient with copied/pacthes version replacing legacy httpClient with okhttp3

Signed-off-by: Andy Scherzinger <info@andy-scherzinger.de>
This commit is contained in:
Andy Scherzinger 2021-06-11 00:24:21 +02:00
parent ba64d693ef
commit f52d7f29d9
No known key found for this signature in database
GPG Key ID: 6CADC7E3523C308B
4 changed files with 356 additions and 32 deletions

View File

@ -294,8 +294,10 @@ dependencies {
implementation 'com.elyeproj.libraries:loaderviewlibrary:2.0.0' implementation 'com.elyeproj.libraries:loaderviewlibrary:2.0.0'
implementation 'org.osmdroid:osmdroid-android:6.1.10' implementation 'org.osmdroid:osmdroid-android:6.1.10'
//noinspection DuplicatePlatformClasses implementation ('fr.dudie:nominatim-api:3.4', {
implementation 'fr.dudie:nominatim-api:3.4' //noinspection DuplicatePlatformClasses
exclude group: 'org.apache.httpcomponents', module: 'httpclient'
})
testImplementation 'junit:junit:4.13.2' testImplementation 'junit:junit:4.13.2'
testImplementation 'org.mockito:mockito-core:3.11.0' testImplementation 'org.mockito:mockito-core:3.11.0'

View File

@ -46,20 +46,14 @@ import com.nextcloud.talk.controllers.util.viewBinding
import com.nextcloud.talk.databinding.ControllerGeocodingBinding import com.nextcloud.talk.databinding.ControllerGeocodingBinding
import com.nextcloud.talk.utils.bundle.BundleKeys import com.nextcloud.talk.utils.bundle.BundleKeys
import com.nextcloud.talk.utils.database.user.UserUtils import com.nextcloud.talk.utils.database.user.UserUtils
import fr.dudie.nominatim.client.JsonNominatimClient import fr.dudie.nominatim.client.TalkJsonNominatimClient
import fr.dudie.nominatim.model.Address import fr.dudie.nominatim.model.Address
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers.IO import kotlinx.coroutines.Dispatchers.IO
import kotlinx.coroutines.Dispatchers.Main import kotlinx.coroutines.Dispatchers.Main
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import org.apache.http.client.HttpClient import okhttp3.OkHttpClient
import org.apache.http.conn.ClientConnectionManager
import org.apache.http.conn.scheme.Scheme
import org.apache.http.conn.scheme.SchemeRegistry
import org.apache.http.conn.ssl.SSLSocketFactory
import org.apache.http.impl.client.DefaultHttpClient
import org.apache.http.impl.conn.SingleClientConnManager
import org.osmdroid.config.Configuration import org.osmdroid.config.Configuration
import javax.inject.Inject import javax.inject.Inject
@ -78,8 +72,11 @@ class GeocodingController(args: Bundle) :
@Inject @Inject
lateinit var userUtils: UserUtils lateinit var userUtils: UserUtils
@Inject
lateinit var okHttpClient: OkHttpClient
var roomToken: String? var roomToken: String?
var nominatimClient: JsonNominatimClient? = null var nominatimClient: TalkJsonNominatimClient? = null
var searchItem: MenuItem? = null var searchItem: MenuItem? = null
var searchView: SearchView? = null var searchView: SearchView? = null
@ -178,13 +175,9 @@ class GeocodingController(args: Bundle) :
} }
private fun initGeocoder() { private fun initGeocoder() {
val registry = SchemeRegistry()
registry.register(Scheme("https", SSLSocketFactory.getSocketFactory(), HTTPS_PORT))
val connexionManager: ClientConnectionManager = SingleClientConnManager(null, registry)
val httpClient: HttpClient = DefaultHttpClient(connexionManager, null)
val baseUrl = context!!.getString(R.string.osm_geocoder_url) val baseUrl = context!!.getString(R.string.osm_geocoder_url)
val email = context!!.getString(R.string.osm_geocoder_contact) val email = context!!.getString(R.string.osm_geocoder_contact)
nominatimClient = JsonNominatimClient(baseUrl, httpClient, email) nominatimClient = TalkJsonNominatimClient(baseUrl, okHttpClient, email)
} }
private fun searchLocation(): Boolean { private fun searchLocation(): Boolean {
@ -223,6 +216,5 @@ class GeocodingController(args: Bundle) :
companion object { companion object {
private const val TAG = "GeocodingController" private const val TAG = "GeocodingController"
private const val HTTPS_PORT: Int = 443
} }
} }

View File

@ -57,7 +57,7 @@ import com.nextcloud.talk.utils.DisplayUtils
import com.nextcloud.talk.utils.bundle.BundleKeys import com.nextcloud.talk.utils.bundle.BundleKeys
import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_ROOM_TOKEN import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_ROOM_TOKEN
import com.nextcloud.talk.utils.database.user.UserUtils import com.nextcloud.talk.utils.database.user.UserUtils
import fr.dudie.nominatim.client.JsonNominatimClient import fr.dudie.nominatim.client.TalkJsonNominatimClient
import fr.dudie.nominatim.model.Address import fr.dudie.nominatim.model.Address
import io.reactivex.Observer import io.reactivex.Observer
import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.android.schedulers.AndroidSchedulers
@ -67,13 +67,7 @@ import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import org.apache.http.client.HttpClient import okhttp3.OkHttpClient
import org.apache.http.conn.ClientConnectionManager
import org.apache.http.conn.scheme.Scheme
import org.apache.http.conn.scheme.SchemeRegistry
import org.apache.http.conn.ssl.SSLSocketFactory
import org.apache.http.impl.client.DefaultHttpClient
import org.apache.http.impl.conn.SingleClientConnManager
import org.osmdroid.config.Configuration.getInstance import org.osmdroid.config.Configuration.getInstance
import org.osmdroid.events.DelayedMapListener import org.osmdroid.events.DelayedMapListener
import org.osmdroid.events.MapListener import org.osmdroid.events.MapListener
@ -103,7 +97,10 @@ class LocationPickerController(args: Bundle) :
@Inject @Inject
lateinit var userUtils: UserUtils lateinit var userUtils: UserUtils
var nominatimClient: JsonNominatimClient? = null @Inject
lateinit var okHttpClient: OkHttpClient
var nominatimClient: TalkJsonNominatimClient? = null
var roomToken: String? var roomToken: String?
@ -425,13 +422,9 @@ class LocationPickerController(args: Bundle) :
} }
private fun initGeocoder() { private fun initGeocoder() {
val registry = SchemeRegistry()
registry.register(Scheme("https", SSLSocketFactory.getSocketFactory(), HTTPS_PORT))
val connexionManager: ClientConnectionManager = SingleClientConnManager(null, registry)
val httpClient: HttpClient = DefaultHttpClient(connexionManager, null)
val baseUrl = context!!.getString(R.string.osm_geocoder_url) val baseUrl = context!!.getString(R.string.osm_geocoder_url)
val email = context!!.getString(R.string.osm_geocoder_contact) val email = context!!.getString(R.string.osm_geocoder_contact)
nominatimClient = JsonNominatimClient(baseUrl, httpClient, email) nominatimClient = TalkJsonNominatimClient(baseUrl, okHttpClient, email)
} }
private fun searchPlaceNameForCoordinates(lat: Double, lon: Double): Boolean { private fun searchPlaceNameForCoordinates(lat: Double, lon: Double): Boolean {
@ -483,6 +476,5 @@ class LocationPickerController(args: Bundle) :
private const val ZOOM_LEVEL_RECEIVED_RESULT: Double = 14.0 private const val ZOOM_LEVEL_RECEIVED_RESULT: Double = 14.0
private const val ZOOM_LEVEL_DEFAULT: Double = 14.0 private const val ZOOM_LEVEL_DEFAULT: Double = 14.0
private const val GEOCODE_ZERO: Double = 0.0 private const val GEOCODE_ZERO: Double = 0.0
private const val HTTPS_PORT: Int = 443
} }
} }

View File

@ -0,0 +1,338 @@
package fr.dudie.nominatim.client;
/*
* [license]
* Nominatim Java API client
* ~~~~
* Copyright (C) 2010 - 2014 Dudie
* ~~~~
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser 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 Lesser Public License for more details.
*
* You should have received a copy of the GNU General Lesser Public
* License along with this program. If not, see
* <http://www.gnu.org/licenses/lgpl-3.0.html>.
* [/license]
*/
import android.util.Log;
import com.github.filosganga.geogson.gson.GeometryAdapterFactory;
import com.github.filosganga.geogson.jts.JtsAdapterFactory;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import fr.dudie.nominatim.client.request.NominatimLookupRequest;
import fr.dudie.nominatim.client.request.NominatimReverseRequest;
import fr.dudie.nominatim.client.request.NominatimSearchRequest;
import fr.dudie.nominatim.client.request.paramhelper.OsmType;
import fr.dudie.nominatim.gson.ArrayOfAddressElementsDeserializer;
import fr.dudie.nominatim.gson.ArrayOfPolygonPointsDeserializer;
import fr.dudie.nominatim.gson.BoundingBoxDeserializer;
import fr.dudie.nominatim.gson.PolygonPointDeserializer;
import fr.dudie.nominatim.model.Address;
import fr.dudie.nominatim.model.BoundingBox;
import fr.dudie.nominatim.model.Element;
import fr.dudie.nominatim.model.PolygonPoint;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.ResponseBody;
/**
* An implementation of the Nominatim Api Service.
*
* @author Jérémie Huchet
* @author Sunil D S
* @author Andy Scherzinger
*/
public final class TalkJsonNominatimClient implements NominatimClient {
private static final String TAG = "TalkNominationClient";
/**
* The default nominatim base URL.
*/
private static final String DEFAULT_BASE_URL = "https://nominatim.openstreetmap.org/";
/**
* UTF-8 encoding.
*/
public static final String ENCODING_UTF_8 = "UTF-8";
private final OkHttpClient httpClient;
/**
* Gson instance for Nominatim API calls.
*/
private final Gson gson;
/**
* The url to make search queries.
*/
private final String searchUrl;
/**
* The url for reverse geocoding.
*/
private final String reverseUrl;
/**
* The url for address lookup.
*/
private final String lookupUrl;
/**
* The default search options.
*/
private final NominatimOptions defaults;
/**
* Creates the json nominatim client with the default base URL ({@value #DEFAULT_BASE_URL}.
*
* @param httpClient an HTTP client
* @param email an email to add in the HTTP requests parameters to "sign" them
*/
public TalkJsonNominatimClient(final OkHttpClient httpClient, final String email) {
this(DEFAULT_BASE_URL, httpClient, email, new NominatimOptions());
}
/**
* Creates the json nominatim client with the default base URL ({@value #DEFAULT_BASE_URL}.
*
* @param httpClient an HTTP client
* @param email an email to add in the HTTP requests parameters to "sign" them
* @param defaults defaults options, they override null valued requests options
*/
public TalkJsonNominatimClient(final OkHttpClient httpClient, final String email, final NominatimOptions defaults) {
this(DEFAULT_BASE_URL, httpClient, email, defaults);
}
/**
* Creates the json nominatim client.
*
* @param baseUrl the nominatim server url
* @param httpClient an HTTP client
* @param email an email to add in the HTTP requests parameters to "sign" them (see
* https://wiki.openstreetmap.org/wiki/Nominatim_usage_policy)
*/
public TalkJsonNominatimClient(final String baseUrl, final OkHttpClient httpClient, final String email) {
this(baseUrl, httpClient, email, new NominatimOptions());
}
/**
* Creates the json nominatim client.
*
* @param baseUrl the nominatim server url
* @param httpClient an HTTP client
* @param email an email to add in the HTTP requests parameters to "sign" them (see
* https://wiki.openstreetmap.org/wiki/Nominatim_usage_policy)
* @param defaults defaults options, they override null valued requests options
*/
public TalkJsonNominatimClient(final String baseUrl, final OkHttpClient httpClient, final String email, final NominatimOptions defaults) {
String emailEncoded;
try {
emailEncoded = URLEncoder.encode(email, ENCODING_UTF_8);
} catch (UnsupportedEncodingException e) {
emailEncoded = email;
}
this.searchUrl = String.format("%s/search?format=jsonv2&email=%s", baseUrl.replaceAll("/$", ""), emailEncoded);
this.reverseUrl = String.format("%s/reverse?format=jsonv2&email=%s", baseUrl.replaceAll("/$", ""), emailEncoded);
this.lookupUrl = String.format("%s/lookup?format=json&email=%s", baseUrl.replaceAll("/$", ""), emailEncoded);
Log.d(TAG, "API search URL: " + searchUrl);
Log.d(TAG, "API reverse URL: " + reverseUrl);
this.defaults = defaults;
// prepare gson instance
final GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(Element[].class, new ArrayOfAddressElementsDeserializer());
gsonBuilder.registerTypeAdapter(PolygonPoint.class, new PolygonPointDeserializer());
gsonBuilder.registerTypeAdapter(PolygonPoint[].class, new ArrayOfPolygonPointsDeserializer());
gsonBuilder.registerTypeAdapter(BoundingBox.class, new BoundingBoxDeserializer());
gsonBuilder.registerTypeAdapterFactory(new JtsAdapterFactory());
gsonBuilder.registerTypeAdapterFactory(new GeometryAdapterFactory());
gson = gsonBuilder.create();
// prepare httpclient
this.httpClient = httpClient;
}
/**
* {@inheritDoc}
*
* @see fr.dudie.nominatim.client.NominatimClient#search(fr.dudie.nominatim.client.request.NominatimSearchRequest)
*/
@Override
public List<Address> search(final NominatimSearchRequest search) throws IOException {
defaults.mergeTo(search);
final String apiCall = String.format("%s&%s", searchUrl, search.getQueryString());
Log.d(TAG, "search url: " + apiCall);
Request requesthttp = new Request.Builder()
.addHeader("accept", "application/json")
.url(apiCall)
.build();
Response response = httpClient.newCall(requesthttp).execute();
if (response.isSuccessful()) {
ResponseBody responseBody = response.body();
if (responseBody != null) {
return gson.fromJson(responseBody.string(), new TypeToken<List<Address>>() {
}.getType());
}
}
return new ArrayList<>();
}
/**
* {@inheritDoc}
*
* @see fr.dudie.nominatim.client.NominatimClient#getAddress(fr.dudie.nominatim.client.request.NominatimReverseRequest)
*/
@Override
public Address getAddress(final NominatimReverseRequest reverse) throws IOException {
final String apiCall = String.format("%s&%s", reverseUrl, reverse.getQueryString());
Log.d(TAG, "reverse geocoding url: " + apiCall);
Request requesthttp = new Request.Builder()
.addHeader("accept", "application/json")
.url(apiCall)
.build();
Response response = httpClient.newCall(requesthttp).execute();
if (response.isSuccessful()) {
ResponseBody responseBody = response.body();
if (responseBody != null) {
return gson.fromJson(responseBody.string(), Address.class);
}
}
return null;
}
/**
* {@inheritDoc}
*
* @see fr.dudie.nominatim.client.NominatimClient#lookupAddress(fr.dudie.nominatim.client.request.NominatimLookupRequest)
*/
@Override
public List<Address> lookupAddress(final NominatimLookupRequest lookup) throws IOException {
final String apiCall = String.format("%s&%s", lookupUrl, lookup.getQueryString());
Log.d(TAG, "lookup url: " + apiCall);
Request requesthttp = new Request.Builder()
.addHeader("accept", "application/json")
.url(apiCall)
.build();
Response response = httpClient.newCall(requesthttp).execute();
if (response.isSuccessful()) {
ResponseBody responseBody = response.body();
if (responseBody != null) {
return gson.fromJson(responseBody.string(), new TypeToken<List<Address>>() {
}.getType());
}
}
return new ArrayList<>();
}
/**
* {@inheritDoc}
*
* @see fr.dudie.nominatim.client.NominatimClient#search(java.lang.String)
*/
@Override
public List<Address> search(final String query) throws IOException {
final NominatimSearchRequest q = new NominatimSearchRequest();
q.setQuery(query);
return this.search(q);
}
/**
* {@inheritDoc}
*
* @see fr.dudie.nominatim.client.NominatimClient#getAddress(double, double)
*/
@Override
public Address getAddress(final double longitude, final double latitude) throws IOException {
final NominatimReverseRequest q = new NominatimReverseRequest();
q.setQuery(longitude, latitude);
return this.getAddress(q);
}
/**
* {@inheritDoc}
*
* @see fr.dudie.nominatim.client.NominatimClient#getAddress(double, double, int)
*/
@Override
public Address getAddress(final double longitude, final double latitude, final int zoom)
throws IOException {
final NominatimReverseRequest q = new NominatimReverseRequest();
q.setQuery(longitude, latitude);
q.setZoom(zoom);
return this.getAddress(q);
}
/**
* {@inheritDoc}
*
* @see fr.dudie.nominatim.client.NominatimClient#getAddress(int, int)
*/
@Override
public Address getAddress(final int longitudeE6, final int latitudeE6) throws IOException {
return this.getAddress((double) (longitudeE6 / 1E6), (double) (latitudeE6 / 1E6));
}
/**
* {@inheritDoc}
*
* @see fr.dudie.nominatim.client.NominatimClient#getAddress(String, long)
*/
@Override
public Address getAddress(final String type, final long id) throws IOException {
final NominatimReverseRequest q = new NominatimReverseRequest();
q.setQuery(OsmType.from(type), id);
return this.getAddress(q);
}
/**
* {@inheritDoc}
*
* @see fr.dudie.nominatim.client.NominatimClient#lookupAddress(java.util.List)
*/
@Override
public List<Address> lookupAddress(final List<String> typeId) throws IOException {
final NominatimLookupRequest q = new NominatimLookupRequest();
q.setQuery(typeId);
return this.lookupAddress(q);
}
}