From 5c5833ee8f763fe21fc61aad3b3748fd0d673c66 Mon Sep 17 00:00:00 2001 From: Alex Baker Date: Fri, 12 Feb 2021 09:47:05 -0600 Subject: [PATCH] Convert Geocoders to Kotlin --- .../java/org/tasks/injection/FlavorModule.kt | 15 +++++ .../java/org/tasks/injection/FlavorModule.kt | 15 +++++ .../org/tasks/injection/ApplicationModule.kt | 5 -- .../org/tasks/location/AndroidGeocoder.java | 50 ---------------- .../org/tasks/location/AndroidGeocoder.kt | 43 ++++++++++++++ .../java/org/tasks/location/Geocoder.java | 8 --- .../main/java/org/tasks/location/Geocoder.kt | 7 +++ .../tasks/location/LocationPickerActivity.kt | 15 ++--- .../org/tasks/location/MapboxGeocoder.java | 58 ------------------- .../java/org/tasks/location/MapboxGeocoder.kt | 48 +++++++++++++++ 10 files changed, 134 insertions(+), 130 deletions(-) create mode 100644 app/src/generic/java/org/tasks/injection/FlavorModule.kt create mode 100644 app/src/googleplay/java/org/tasks/injection/FlavorModule.kt delete mode 100644 app/src/main/java/org/tasks/location/AndroidGeocoder.java create mode 100644 app/src/main/java/org/tasks/location/AndroidGeocoder.kt delete mode 100644 app/src/main/java/org/tasks/location/Geocoder.java create mode 100644 app/src/main/java/org/tasks/location/Geocoder.kt delete mode 100644 app/src/main/java/org/tasks/location/MapboxGeocoder.java create mode 100644 app/src/main/java/org/tasks/location/MapboxGeocoder.kt diff --git a/app/src/generic/java/org/tasks/injection/FlavorModule.kt b/app/src/generic/java/org/tasks/injection/FlavorModule.kt new file mode 100644 index 000000000..a574560ca --- /dev/null +++ b/app/src/generic/java/org/tasks/injection/FlavorModule.kt @@ -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 +} \ No newline at end of file diff --git a/app/src/googleplay/java/org/tasks/injection/FlavorModule.kt b/app/src/googleplay/java/org/tasks/injection/FlavorModule.kt new file mode 100644 index 000000000..a574560ca --- /dev/null +++ b/app/src/googleplay/java/org/tasks/injection/FlavorModule.kt @@ -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 +} \ No newline at end of file diff --git a/app/src/main/java/org/tasks/injection/ApplicationModule.kt b/app/src/main/java/org/tasks/injection/ApplicationModule.kt index 99978a538..e48d589d0 100644 --- a/app/src/main/java/org/tasks/injection/ApplicationModule.kt +++ b/app/src/main/java/org/tasks/injection/ApplicationModule.kt @@ -13,8 +13,6 @@ import org.tasks.billing.BillingClientImpl import org.tasks.billing.Inventory import org.tasks.data.* import org.tasks.locale.Locale -import org.tasks.location.Geocoder -import org.tasks.location.MapboxGeocoder import org.tasks.notifications.NotificationDao import javax.inject.Singleton @@ -96,7 +94,4 @@ class ApplicationModule { @Provides fun getBillingClient(@ApplicationContext context: Context, inventory: Inventory, firebase: Firebase): BillingClient = BillingClientImpl(context, inventory, firebase) - - @Provides - fun getGeocoder(@ApplicationContext context: Context): Geocoder = MapboxGeocoder(context) } \ No newline at end of file diff --git a/app/src/main/java/org/tasks/location/AndroidGeocoder.java b/app/src/main/java/org/tasks/location/AndroidGeocoder.java deleted file mode 100644 index 739a323a8..000000000 --- a/app/src/main/java/org/tasks/location/AndroidGeocoder.java +++ /dev/null @@ -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
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; - } -} diff --git a/app/src/main/java/org/tasks/location/AndroidGeocoder.kt b/app/src/main/java/org/tasks/location/AndroidGeocoder.kt new file mode 100644 index 000000000..97b424661 --- /dev/null +++ b/app/src/main/java/org/tasks/location/AndroidGeocoder.kt @@ -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 + } +} \ No newline at end of file diff --git a/app/src/main/java/org/tasks/location/Geocoder.java b/app/src/main/java/org/tasks/location/Geocoder.java deleted file mode 100644 index dd612936b..000000000 --- a/app/src/main/java/org/tasks/location/Geocoder.java +++ /dev/null @@ -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; -} diff --git a/app/src/main/java/org/tasks/location/Geocoder.kt b/app/src/main/java/org/tasks/location/Geocoder.kt new file mode 100644 index 000000000..e0b11d319 --- /dev/null +++ b/app/src/main/java/org/tasks/location/Geocoder.kt @@ -0,0 +1,7 @@ +package org.tasks.location + +import org.tasks.data.Place + +interface Geocoder { + suspend fun reverseGeocode(mapPosition: MapPosition): Place +} \ No newline at end of file diff --git a/app/src/main/java/org/tasks/location/LocationPickerActivity.kt b/app/src/main/java/org/tasks/location/LocationPickerActivity.kt index f09eb9ed0..812fd9136 100644 --- a/app/src/main/java/org/tasks/location/LocationPickerActivity.kt +++ b/app/src/main/java/org/tasks/location/LocationPickerActivity.kt @@ -25,10 +25,8 @@ import com.google.android.material.appbar.AppBarLayout.OnOffsetChangedListener import com.google.android.material.appbar.CollapsingToolbarLayout import com.todoroo.andlib.utility.AndroidUtilities import dagger.hilt.android.AndroidEntryPoint -import io.reactivex.Single import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.disposables.CompositeDisposable -import io.reactivex.schedulers.Schedulers import io.reactivex.subjects.PublishSubject import kotlinx.coroutines.launch import org.tasks.Event @@ -231,14 +229,13 @@ class LocationPickerActivity : InjectingAppCompatActivity(), Toolbar.OnMenuItemC @OnClick(R.id.select_this_location) fun selectLocation() { + val mapPosition = map.mapPosition ?: return loadingIndicator.visibility = View.VISIBLE - val mapPosition = map.mapPosition - disposables!!.add( - Single.fromCallable { geocoder.reverseGeocode(mapPosition) } - .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - .doFinally { loadingIndicator.visibility = View.GONE } - .subscribe({ place: Place? -> returnPlace(place) }) { e: Throwable -> toaster.longToast(e.message) }) + lifecycleScope.launch { + val place = geocoder.reverseGeocode(mapPosition) + loadingIndicator.visibility = View.GONE + returnPlace(place) + } } @OnClick(R.id.search) diff --git a/app/src/main/java/org/tasks/location/MapboxGeocoder.java b/app/src/main/java/org/tasks/location/MapboxGeocoder.java deleted file mode 100644 index 95d2ddd4d..000000000 --- a/app/src/main/java/org/tasks/location/MapboxGeocoder.java +++ /dev/null @@ -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 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 features = body.features(); - if (features.size() > 0) { - return newPlace(features.get(0)); - } - } else { - Timber.e(response.errorBody().string()); - } - return newPlace(mapPosition); - } -} diff --git a/app/src/main/java/org/tasks/location/MapboxGeocoder.kt b/app/src/main/java/org/tasks/location/MapboxGeocoder.kt new file mode 100644 index 000000000..ead9856eb --- /dev/null +++ b/app/src/main/java/org/tasks/location/MapboxGeocoder.kt @@ -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 + } + } +} \ No newline at end of file