Convert Geocoders to Kotlin

pull/1369/head
Alex Baker 4 years ago
parent af9b89fef3
commit 5c5833ee8f

@ -0,0 +1,15 @@
package org.tasks.injection
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import org.tasks.location.Geocoder
import org.tasks.location.MapboxGeocoder
@Module
@InstallIn(SingletonComponent::class)
class FlavorModule {
@Provides
fun getGeocoder(geocoder: MapboxGeocoder): Geocoder = geocoder
}

@ -0,0 +1,15 @@
package org.tasks.injection
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import org.tasks.location.Geocoder
import org.tasks.location.MapboxGeocoder
@Module
@InstallIn(SingletonComponent::class)
class FlavorModule {
@Provides
fun getGeocoder(geocoder: MapboxGeocoder): Geocoder = geocoder
}

@ -13,8 +13,6 @@ import org.tasks.billing.BillingClientImpl
import org.tasks.billing.Inventory import org.tasks.billing.Inventory
import org.tasks.data.* import org.tasks.data.*
import org.tasks.locale.Locale import org.tasks.locale.Locale
import org.tasks.location.Geocoder
import org.tasks.location.MapboxGeocoder
import org.tasks.notifications.NotificationDao import org.tasks.notifications.NotificationDao
import javax.inject.Singleton import javax.inject.Singleton
@ -96,7 +94,4 @@ class ApplicationModule {
@Provides @Provides
fun getBillingClient(@ApplicationContext context: Context, inventory: Inventory, firebase: Firebase): BillingClient fun getBillingClient(@ApplicationContext context: Context, inventory: Inventory, firebase: Firebase): BillingClient
= BillingClientImpl(context, inventory, firebase) = BillingClientImpl(context, inventory, firebase)
@Provides
fun getGeocoder(@ApplicationContext context: Context): Geocoder = MapboxGeocoder(context)
} }

@ -1,50 +0,0 @@
package org.tasks.location;
import static com.todoroo.andlib.utility.AndroidUtilities.assertNotMainThread;
import static org.tasks.data.Place.newPlace;
import android.content.Context;
import android.location.Address;
import java.io.IOException;
import java.util.List;
import org.tasks.data.Place;
@SuppressWarnings("unused")
public class AndroidGeocoder implements Geocoder {
private final Context context;
public AndroidGeocoder(Context context) {
this.context = context;
}
@Override
public Place reverseGeocode(MapPosition mapPosition) throws IOException {
assertNotMainThread();
android.location.Geocoder geocoder = new android.location.Geocoder(context);
List<Address> addresses =
geocoder.getFromLocation(mapPosition.getLatitude(), mapPosition.getLongitude(), 1);
Place place = newPlace(mapPosition);
if (addresses.isEmpty()) {
return place;
}
Address address = addresses.get(0);
if (address.getMaxAddressLineIndex() >= 0) {
place.setName(address.getAddressLine(0));
StringBuilder builder = new StringBuilder(place.getName());
for (int i = 1; i <= address.getMaxAddressLineIndex(); i++) {
builder.append(", ").append(address.getAddressLine(i));
}
place.setAddress(builder.toString());
}
if (address.hasLatitude() && address.hasLongitude()) {
place.setLatitude(address.getLatitude());
place.setLongitude(address.getLongitude());
}
place.setPhone(address.getPhone());
place.setUrl(address.getUrl());
return place;
}
}

@ -0,0 +1,43 @@
package org.tasks.location
import android.content.Context
import dagger.hilt.android.qualifiers.ApplicationContext
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import org.tasks.data.Place
import org.tasks.data.Place.Companion.newPlace
import javax.inject.Inject
@Suppress("unused")
class AndroidGeocoder @Inject constructor(@ApplicationContext context: Context) : Geocoder {
private val geocoder = if (android.location.Geocoder.isPresent()) {
android.location.Geocoder(context)
} else {
null
}
override suspend fun reverseGeocode(mapPosition: MapPosition): Place =
withContext(Dispatchers.IO) {
val addresses = geocoder?.getFromLocation(mapPosition.latitude, mapPosition.longitude, 1) ?: emptyList()
val place = newPlace(mapPosition)
if (addresses.isEmpty()) {
return@withContext place!!
}
val address = addresses[0]
if (address.maxAddressLineIndex >= 0) {
place!!.name = address.getAddressLine(0)
val builder = StringBuilder(place.name)
for (i in 1..address.maxAddressLineIndex) {
builder.append(", ").append(address.getAddressLine(i))
}
place.address = builder.toString()
}
if (address.hasLatitude() && address.hasLongitude()) {
place!!.latitude = address.latitude
place.longitude = address.longitude
}
place!!.phone = address.phone
place.url = address.url
place
}
}

@ -1,8 +0,0 @@
package org.tasks.location;
import java.io.IOException;
import org.tasks.data.Place;
public interface Geocoder {
Place reverseGeocode(MapPosition mapPosition) throws IOException;
}

@ -0,0 +1,7 @@
package org.tasks.location
import org.tasks.data.Place
interface Geocoder {
suspend fun reverseGeocode(mapPosition: MapPosition): Place
}

@ -25,10 +25,8 @@ import com.google.android.material.appbar.AppBarLayout.OnOffsetChangedListener
import com.google.android.material.appbar.CollapsingToolbarLayout import com.google.android.material.appbar.CollapsingToolbarLayout
import com.todoroo.andlib.utility.AndroidUtilities import com.todoroo.andlib.utility.AndroidUtilities
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import io.reactivex.Single
import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.CompositeDisposable import io.reactivex.disposables.CompositeDisposable
import io.reactivex.schedulers.Schedulers
import io.reactivex.subjects.PublishSubject import io.reactivex.subjects.PublishSubject
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import org.tasks.Event import org.tasks.Event
@ -231,14 +229,13 @@ class LocationPickerActivity : InjectingAppCompatActivity(), Toolbar.OnMenuItemC
@OnClick(R.id.select_this_location) @OnClick(R.id.select_this_location)
fun selectLocation() { fun selectLocation() {
val mapPosition = map.mapPosition ?: return
loadingIndicator.visibility = View.VISIBLE loadingIndicator.visibility = View.VISIBLE
val mapPosition = map.mapPosition lifecycleScope.launch {
disposables!!.add( val place = geocoder.reverseGeocode(mapPosition)
Single.fromCallable { geocoder.reverseGeocode(mapPosition) } loadingIndicator.visibility = View.GONE
.subscribeOn(Schedulers.io()) returnPlace(place)
.observeOn(AndroidSchedulers.mainThread()) }
.doFinally { loadingIndicator.visibility = View.GONE }
.subscribe({ place: Place? -> returnPlace(place) }) { e: Throwable -> toaster.longToast(e.message) })
} }
@OnClick(R.id.search) @OnClick(R.id.search)

@ -1,58 +0,0 @@
package org.tasks.location;
import static com.todoroo.andlib.utility.AndroidUtilities.assertNotMainThread;
import static org.tasks.data.Place.newPlace;
import android.content.Context;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonParser;
import com.mapbox.api.geocoding.v5.MapboxGeocoding;
import com.mapbox.api.geocoding.v5.models.CarmenFeature;
import com.mapbox.api.geocoding.v5.models.GeocodingResponse;
import com.mapbox.geojson.Point;
import java.io.IOException;
import java.util.List;
import org.tasks.BuildConfig;
import org.tasks.R;
import org.tasks.data.Place;
import retrofit2.Response;
import timber.log.Timber;
public class MapboxGeocoder implements Geocoder {
private final String token;
public MapboxGeocoder(Context context) {
token = context.getString(R.string.mapbox_key);
}
private static String prettyPrint(String json) {
if (BuildConfig.DEBUG) {
return new GsonBuilder().setPrettyPrinting().create().toJson(new JsonParser().parse(json));
}
return json;
}
@Override
public Place reverseGeocode(MapPosition mapPosition) throws IOException {
assertNotMainThread();
Response<GeocodingResponse> response =
MapboxGeocoding.builder()
.accessToken(token)
.query(Point.fromLngLat(mapPosition.getLongitude(), mapPosition.getLatitude()))
.build()
.executeCall();
GeocodingResponse body = response.body();
if (response.isSuccessful() && body != null) {
Timber.d(prettyPrint(body.toJson()));
List<CarmenFeature> features = body.features();
if (features.size() > 0) {
return newPlace(features.get(0));
}
} else {
Timber.e(response.errorBody().string());
}
return newPlace(mapPosition);
}
}

@ -0,0 +1,48 @@
package org.tasks.location
import android.content.Context
import com.google.gson.GsonBuilder
import com.google.gson.JsonParser
import com.mapbox.api.geocoding.v5.MapboxGeocoding
import com.mapbox.geojson.Point
import dagger.hilt.android.qualifiers.ApplicationContext
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import org.tasks.BuildConfig
import org.tasks.R
import org.tasks.data.Place
import org.tasks.data.Place.Companion.newPlace
import timber.log.Timber
import javax.inject.Inject
class MapboxGeocoder @Inject constructor(@ApplicationContext context: Context) : Geocoder {
private val token: String = context.getString(R.string.mapbox_key)
override suspend fun reverseGeocode(mapPosition: MapPosition): Place =
withContext(Dispatchers.IO) {
val response = MapboxGeocoding.builder()
.accessToken(token)
.query(Point.fromLngLat(mapPosition.longitude, mapPosition.latitude))
.build()
.executeCall()
val body = response.body()
if (response.isSuccessful && body != null) {
Timber.d(prettyPrint(body.toJson()))
val features = body.features()
if (features.size > 0) {
return@withContext newPlace(features[0])
}
} else {
Timber.e(response.errorBody()!!.string())
}
newPlace(mapPosition)!!
}
companion object {
private fun prettyPrint(json: String): String {
return if (BuildConfig.DEBUG) {
GsonBuilder().setPrettyPrinting().create().toJson(JsonParser().parse(json))
} else json
}
}
}
Loading…
Cancel
Save