diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 067ca175c..031320e6a 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -96,6 +96,7 @@ android { resValue("string", "google_key", tasks_google_key_debug ?: "") resValue("string", "tasks_caldav_url", tasks_caldav_url ?: "https://caldav.tasks.org") resValue("string", "tasks_nominatim_url", tasks_caldav_url ?: "https://nominatim.tasks.org") + resValue("string", "tasks_places_url", tasks_caldav_url ?: "https://places.tasks.org") isTestCoverageEnabled = project.hasProperty("coverage") } getByName("release") { @@ -215,7 +216,6 @@ dependencies { googleplayImplementation("com.google.firebase:firebase-config-ktx:${Versions.remote_config}") googleplayImplementation("com.google.android.gms:play-services-location:17.1.0") googleplayImplementation("com.google.android.gms:play-services-maps:17.0.0") - googleplayImplementation("com.google.android.libraries.places:places:2.4.0") googleplayImplementation("com.android.billingclient:billing:1.2.2") androidTestImplementation("com.google.dagger:hilt-android-testing:${Versions.hilt}") diff --git a/app/src/generic/java/org/tasks/injection/LocationModule.kt b/app/src/generic/java/org/tasks/injection/LocationModule.kt index fab0662b1..86766fb87 100644 --- a/app/src/generic/java/org/tasks/injection/LocationModule.kt +++ b/app/src/generic/java/org/tasks/injection/LocationModule.kt @@ -5,20 +5,16 @@ import dagger.Module import dagger.Provides import dagger.hilt.InstallIn import dagger.hilt.android.components.ActivityComponent -import dagger.hilt.android.components.ViewModelComponent import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.android.scopes.ActivityScoped -import dagger.hilt.android.scopes.ViewModelScoped -import org.tasks.location.* +import org.tasks.location.AndroidLocationProvider +import org.tasks.location.LocationProvider +import org.tasks.location.MapFragment +import org.tasks.location.OsmMapFragment @Module -@InstallIn(ActivityComponent::class, ViewModelComponent::class) +@InstallIn(ActivityComponent::class) class LocationModule { - @Provides - @ViewModelScoped - fun getPlaceSearchProvider(mapboxSearchProvider: PlaceSearchMapbox): PlaceSearch = - mapboxSearchProvider - @Provides @ActivityScoped fun getLocationProvider(provider: AndroidLocationProvider): LocationProvider = provider diff --git a/app/src/googleplay/java/org/tasks/injection/LocationModule.kt b/app/src/googleplay/java/org/tasks/injection/LocationModule.kt index 9ae25cd1a..c3efa3d02 100644 --- a/app/src/googleplay/java/org/tasks/injection/LocationModule.kt +++ b/app/src/googleplay/java/org/tasks/injection/LocationModule.kt @@ -5,37 +5,15 @@ import dagger.Module import dagger.Provides import dagger.hilt.InstallIn import dagger.hilt.android.components.ActivityComponent -import dagger.hilt.android.components.ViewModelComponent import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.android.scopes.ActivityScoped -import dagger.hilt.android.scopes.ViewModelScoped import org.tasks.R -import org.tasks.billing.Inventory -import org.tasks.gtasks.PlayServices import org.tasks.location.* import org.tasks.preferences.Preferences @Module -@InstallIn(ActivityComponent::class, ViewModelComponent::class) +@InstallIn(ActivityComponent::class) internal class LocationModule { - @Provides - @ViewModelScoped - fun getPlaceSearchProvider( - @ApplicationContext context: Context, - preferences: Preferences, - playServices: PlayServices, - inventory: Inventory, - mapboxSearchProvider: MapboxSearchProvider - ): PlaceSearchProvider { - return if (preferences.useGooglePlaces() - && playServices.isPlayServicesAvailable - && inventory.hasPro) { - PlaceSearchGoogle(context) - } else { - mapboxSearchProvider - } - } - @Provides @ActivityScoped fun getLocationProvider(@ApplicationContext context: Context): LocationProvider = diff --git a/app/src/googleplay/java/org/tasks/location/PlaceSearchGoogle.kt b/app/src/googleplay/java/org/tasks/location/PlaceSearchGoogle.kt deleted file mode 100644 index 17f65cdac..000000000 --- a/app/src/googleplay/java/org/tasks/location/PlaceSearchGoogle.kt +++ /dev/null @@ -1,128 +0,0 @@ -package org.tasks.location - -import android.content.Context -import android.os.Bundle -import com.google.android.gms.maps.model.LatLng -import com.google.android.gms.maps.model.LatLngBounds -import com.google.android.libraries.places.api.Places -import com.google.android.libraries.places.api.model.AutocompletePrediction -import com.google.android.libraries.places.api.model.AutocompleteSessionToken -import com.google.android.libraries.places.api.model.Place.Field -import com.google.android.libraries.places.api.model.RectangularBounds -import com.google.android.libraries.places.api.net.* -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.withContext -import org.tasks.R -import org.tasks.data.Place -import org.tasks.data.Place.Companion.newPlace -import kotlin.coroutines.suspendCoroutine - -class PlaceSearchGoogle(private val context: Context) : PlaceSearch { - private var token: AutocompleteSessionToken? = null - private var placesClient: PlacesClient? = null - - override fun restoreState(savedInstanceState: Bundle?) { - token = savedInstanceState?.getParcelable(EXTRA_SESSION_TOKEN) - } - - override fun saveState(outState: Bundle) { - outState.putParcelable(EXTRA_SESSION_TOKEN, token) - } - - override fun getAttributionRes(dark: Boolean): Int { - return if (dark) R.drawable.places_powered_by_google_dark else R.drawable.places_powered_by_google_light - } - - override suspend fun search(query: String, bias: MapPosition?): List = - withContext(Dispatchers.IO) { - suspendCoroutine { cont -> - if (!Places.isInitialized()) { - Places.initialize(context, context.getString(R.string.google_key)) - } - if (placesClient == null) { - placesClient = Places.createClient(context) - } - if (token == null) { - token = AutocompleteSessionToken.newInstance() - } - val request = FindAutocompletePredictionsRequest.builder().setSessionToken(token).setQuery(query) - if (bias != null) { - request.locationBias = - RectangularBounds.newInstance( - LatLngBounds.builder() - .include(LatLng(bias.latitude, bias.longitude)) - .build()) - } - placesClient!! - .findAutocompletePredictions(request.build()) - .addOnSuccessListener { response: FindAutocompletePredictionsResponse -> - val places = toSearchResults(response.autocompletePredictions) - cont.resumeWith(Result.success(places)) - } - .addOnFailureListener { e: Exception -> - cont.resumeWith(Result.failure(e)) - } - } - } - - override suspend fun fetch(placeSearchResult: PlaceSearchResult): Place = - withContext(Dispatchers.IO) { - suspendCoroutine { cont -> - placesClient!! - .fetchPlace( - FetchPlaceRequest.builder( - placeSearchResult.id, - listOf( - Field.ID, - Field.LAT_LNG, - Field.ADDRESS, - Field.WEBSITE_URI, - Field.NAME, - Field.PHONE_NUMBER)) - .setSessionToken(token) - .build()) - .addOnSuccessListener { result: FetchPlaceResponse -> - cont.resumeWith(Result.success(toPlace(result))) - } - .addOnFailureListener { e: Exception -> - cont.resumeWith(Result.failure(e)) - } - } - } - - - private fun toSearchResults(predictions: List): List { - return predictions.map { - PlaceSearchResult( - it.placeId, - it.getPrimaryText(null).toString(), - it.getSecondaryText(null).toString()) - } - } - - private fun toPlace(fetchPlaceResponse: FetchPlaceResponse): Place { - val place = fetchPlaceResponse.place - val result = newPlace() - result.name = place.name - val address: CharSequence? = place.address - if (address != null) { - result.address = place.address - } - val phoneNumber: CharSequence? = place.phoneNumber - if (phoneNumber != null) { - result.phone = phoneNumber.toString() - } - val uri = place.websiteUri - if (uri != null) { - result.url = uri.toString() - } - val latLng = place.latLng - result.latitude = latLng!!.latitude - result.longitude = latLng.longitude - return result - } - - companion object { - private const val EXTRA_SESSION_TOKEN = "extra_session_token" - } -} \ No newline at end of file diff --git a/app/src/main/java/org/tasks/billing/PurchaseDialog.kt b/app/src/main/java/org/tasks/billing/PurchaseDialog.kt index 4c0345252..1fe924b00 100644 --- a/app/src/main/java/org/tasks/billing/PurchaseDialog.kt +++ b/app/src/main/java/org/tasks/billing/PurchaseDialog.kt @@ -140,6 +140,7 @@ _${getString(R.string.account_not_included)}_ #### ${getString(R.string.tasks_org_account)} * ${getString(R.string.tasks_org_description)} * [${getString(R.string.upgrade_third_party_apps)}](${getString(R.string.url_app_passwords)}) +* ${getString(R.string.upgrade_google_places)} * [${getString(R.string.upgrade_coming_soon)}](${getString(R.string.help_url_sync)}) """ } @@ -155,7 +156,6 @@ _${getString(R.string.account_not_included)}_ --- #### ${getString(R.string.upgrade_additional_features)} * ${getString(R.string.upgrade_themes)} -* ${getString(R.string.upgrade_google_places)} * [${getString(R.string.upgrade_tasker)}](${getString(R.string.url_tasker)}) --- * ${getString(R.string.upgrade_free_trial)} diff --git a/app/src/main/java/org/tasks/http/HttpClientFactory.kt b/app/src/main/java/org/tasks/http/HttpClientFactory.kt index c2c81a3d6..823e610b8 100644 --- a/app/src/main/java/org/tasks/http/HttpClientFactory.kt +++ b/app/src/main/java/org/tasks/http/HttpClientFactory.kt @@ -2,6 +2,7 @@ package org.tasks.http import android.content.Context import at.bitfire.cert4android.CustomCertManager +import at.bitfire.dav4jvm.BasicDigestAuthHandler import dagger.hilt.android.qualifiers.ApplicationContext import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext @@ -9,6 +10,7 @@ import okhttp3.OkHttpClient import okhttp3.internal.tls.OkHostnameVerifier import org.tasks.DebugNetworkInterceptor import org.tasks.preferences.Preferences +import org.tasks.security.KeyStoreEncryption import javax.inject.Inject import javax.net.ssl.SSLContext @@ -16,16 +18,30 @@ class HttpClientFactory @Inject constructor( @ApplicationContext private val context: Context, private val preferences: Preferences, private val interceptor: DebugNetworkInterceptor, + private val encryption: KeyStoreEncryption, ) { suspend fun newCertManager() = withContext(Dispatchers.Default) { CustomCertManager(context) } - suspend fun newBuilder(foreground: Boolean = false): OkHttpClient.Builder = - newBuilder(newCertManager(), foreground) + suspend fun newBuilder( + foreground: Boolean = false, + username: String? = null, + encryptedPassword: String? = null + ): OkHttpClient.Builder = newBuilder( + newCertManager(), + foreground = foreground, + username = username, + password = encryptedPassword?.let { encryption.decrypt(it) } + ) - fun newBuilder(customCertManager: CustomCertManager, foreground: Boolean = false): OkHttpClient.Builder { + fun newBuilder( + customCertManager: CustomCertManager, + foreground: Boolean = false, + username: String? = null, + password: String? = null + ): OkHttpClient.Builder { customCertManager.appInForeground = foreground val hostnameVerifier = customCertManager.hostnameVerifier(OkHostnameVerifier) val sslContext = SSLContext.getInstance("TLS") @@ -37,6 +53,11 @@ class HttpClientFactory @Inject constructor( if (preferences.isFlipperEnabled) { interceptor.apply(builder) } + if (!username.isNullOrBlank() && !password.isNullOrBlank()) { + val auth = BasicDigestAuthHandler(null, username, password) + builder.addNetworkInterceptor(auth) + builder.authenticator(auth) + } return builder } } \ No newline at end of file diff --git a/app/src/main/java/org/tasks/injection/ViewModelModule.kt b/app/src/main/java/org/tasks/injection/ViewModelModule.kt new file mode 100644 index 000000000..3b4bfa68f --- /dev/null +++ b/app/src/main/java/org/tasks/injection/ViewModelModule.kt @@ -0,0 +1,24 @@ +package org.tasks.injection + +import dagger.Lazy +import dagger.Module +import dagger.Provides +import dagger.hilt.InstallIn +import dagger.hilt.android.components.ViewModelComponent +import dagger.hilt.android.scopes.ViewModelScoped +import org.tasks.billing.Inventory +import org.tasks.location.PlaceSearch +import org.tasks.location.PlaceSearchGoogle +import org.tasks.location.PlaceSearchMapbox + +@Module +@InstallIn(ViewModelComponent::class) +class ViewModelModule { + @Provides + @ViewModelScoped + fun getPlaceSearchProvider( + inventory: Inventory, + google: Lazy, + mapbox: Lazy + ): PlaceSearch = if (inventory.hasTasksSubscription) google.get() else mapbox.get() +} \ No newline at end of file diff --git a/app/src/main/java/org/tasks/location/GeocoderNominatim.kt b/app/src/main/java/org/tasks/location/GeocoderNominatim.kt index 7b9f3f328..b30d5bd12 100644 --- a/app/src/main/java/org/tasks/location/GeocoderNominatim.kt +++ b/app/src/main/java/org/tasks/location/GeocoderNominatim.kt @@ -23,7 +23,7 @@ class GeocoderNominatim @Inject constructor( override suspend fun reverseGeocode(mapPosition: MapPosition): Place? = withContext(Dispatchers.IO) { - val client = httpClientFactory.newBuilder(true).build() + val client = httpClientFactory.newBuilder(foreground = true).build() val url = "$url/reverse?format=geocodejson&lat=${mapPosition.latitude}&lon=${mapPosition.longitude}" val response = client.newCall( Request.Builder().get().url(url).addHeader(USER_AGENT, UA_VALUE).build() diff --git a/app/src/main/java/org/tasks/location/LocationPickerActivity.kt b/app/src/main/java/org/tasks/location/LocationPickerActivity.kt index 526f2b0c7..f112d75e4 100644 --- a/app/src/main/java/org/tasks/location/LocationPickerActivity.kt +++ b/app/src/main/java/org/tasks/location/LocationPickerActivity.kt @@ -303,7 +303,7 @@ class LocationPickerActivity : InjectingAppCompatActivity(), Toolbar.OnMenuItemC searchSubject .debounce(SEARCH_DEBOUNCE_TIMEOUT.toLong(), TimeUnit.MILLISECONDS) .observeOn(AndroidSchedulers.mainThread()) - .subscribe { query: String? -> viewModel.query(query, mapPosition) }) + .subscribe { query: String? -> viewModel.query(query, map.mapPosition) }) } override fun onDestroy() { diff --git a/app/src/main/java/org/tasks/location/PlaceSearchGoogle.kt b/app/src/main/java/org/tasks/location/PlaceSearchGoogle.kt new file mode 100644 index 000000000..83d76ea20 --- /dev/null +++ b/app/src/main/java/org/tasks/location/PlaceSearchGoogle.kt @@ -0,0 +1,146 @@ +package org.tasks.location + +import android.content.Context +import android.os.Bundle +import com.google.gson.JsonObject +import com.google.gson.JsonParser +import dagger.hilt.android.qualifiers.ApplicationContext +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext +import okhttp3.Request +import org.tasks.R +import org.tasks.data.CaldavAccount.Companion.TYPE_TASKS +import org.tasks.data.CaldavDao +import org.tasks.data.Place +import org.tasks.data.Place.Companion.newPlace +import org.tasks.http.HttpClientFactory +import org.tasks.http.HttpException +import timber.log.Timber +import java.util.* +import javax.inject.Inject + +class PlaceSearchGoogle @Inject constructor( + @ApplicationContext private val context: Context, + private val httpClientFactory: HttpClientFactory, + private val caldavDao: CaldavDao +) : PlaceSearch { + private val url = context.getString(R.string.tasks_places_url) + private var token: String? = null + + override fun restoreState(savedInstanceState: Bundle?) { + token = savedInstanceState?.getParcelable(EXTRA_SESSION_TOKEN) + } + + override fun saveState(outState: Bundle) { + outState.putString(EXTRA_SESSION_TOKEN, token) + } + + override fun getAttributionRes(dark: Boolean) = if (dark) { + R.drawable.powered_by_google_on_non_white + } else { + R.drawable.powered_by_google_on_white + } + + override suspend fun search(query: String, bias: MapPosition?): List { + if (token == null) { + token = UUID.randomUUID().toString() + } + val proximity = bias?.let { + "&location=${bias.latitude},${bias.longitude}&radius=25000" + } + val jsonObject = execute( + "${this.url}/maps/api/place/queryautocomplete/json?input=$query&sessiontoken=$token$proximity" + ) + return toSearchResults(jsonObject) + } + + override suspend fun fetch(placeSearchResult: PlaceSearchResult): Place { + val jsonObject = execute( + "${this.url}/maps/api/place/details/json?place_id=${placeSearchResult.id}&fields=$FIELDS&sessiontoken=$token" + ) + return toPlace(jsonObject) + } + + private suspend fun execute(url: String): JsonObject = withContext(Dispatchers.IO) { + Timber.d(url) + val account = caldavDao.getAccounts(TYPE_TASKS).firstOrNull() + ?: throw IllegalStateException( + context.getString(R.string.tasks_org_account_required) + ) + val client = httpClientFactory + .newBuilder( + foreground = true, + username = account.username, + encryptedPassword = account.password + ) + .build() + val response = client.newCall(Request.Builder().get().url(url).build()).execute() + if (response.isSuccessful) { + response.body?.string()?.toJson()?.apply { checkResult(this) } + ?: throw IllegalStateException("Request failed") + } else { + throw HttpException(response.code, response.message) + } + } + + companion object { + private const val EXTRA_SESSION_TOKEN = "extra_session_token" + private val FIELDS = + listOf( + "place_id", + "geometry/location", + "formatted_address", + "website", + "name", + "international_phone_number" + ).joinToString(",") + + internal fun String.toJson(): JsonObject = JsonParser.parseString(this).asJsonObject + + private fun checkResult(json: JsonObject) { + val status = json.get("status").asString + when { + status == "OK" -> return + json.has("error_message") -> + throw IllegalStateException(json.get("error_message").asString) + else -> + throw IllegalStateException(status) + } + } + + internal fun toSearchResults(json: JsonObject): List = + json.get("predictions") + .asJsonArray + .map { it.asJsonObject } + .filter { it.has("place_id") } + .map { toSearchEntry(it) } + + private fun toSearchEntry(json: JsonObject): PlaceSearchResult { + val place = json.get("structured_formatting").asJsonObject + return PlaceSearchResult( + json.get("place_id").asString, + place.get("main_text").asString, + place.get("secondary_text").asString + ) + } + + internal fun toPlace(json: JsonObject): Place { + val result = json.get("result").asJsonObject + val location = result.get("geometry").asJsonObject.get("location").asJsonObject + return newPlace().apply { + name = result.get("name").asString + address = result.getString("formatted_address") + phone = result.getString("international_phone_number") + url = result.getString("website") + latitude = location.get("lat").asDouble + longitude = location.get("lng").asDouble + } + } + + private fun JsonObject.getString(field: String): String? = if (has(field)) { + get(field).asString + } else { + null + } + } +} \ No newline at end of file diff --git a/app/src/main/java/org/tasks/preferences/Preferences.kt b/app/src/main/java/org/tasks/preferences/Preferences.kt index 3340cae52..e93796452 100644 --- a/app/src/main/java/org/tasks/preferences/Preferences.kt +++ b/app/src/main/java/org/tasks/preferences/Preferences.kt @@ -423,8 +423,6 @@ class Preferences @JvmOverloads constructor( syncFlags.forEach { setBoolean(it, value) } } - fun useGooglePlaces(): Boolean = getIntegerFromString(R.string.p_place_provider, 0) == 1 - fun getPrefs(c: Class): Map { val result: MutableMap = HashMap() val entries: Iterable> = prefs.all.entries.filter { e: Map.Entry -> c.isInstance(e.value) } diff --git a/app/src/main/java/org/tasks/preferences/fragments/LocationPreferences.kt b/app/src/main/java/org/tasks/preferences/fragments/LocationPreferences.kt index 539d6d028..1570ac9f2 100644 --- a/app/src/main/java/org/tasks/preferences/fragments/LocationPreferences.kt +++ b/app/src/main/java/org/tasks/preferences/fragments/LocationPreferences.kt @@ -35,16 +35,10 @@ class LocationPreferences : InjectingPreferenceFragment() { override suspend fun setupPreferences(savedInstanceState: Bundle?) { if (IS_GOOGLE_PLAY) { - findPreference(R.string.p_place_provider) - .setOnPreferenceChangeListener(this::onPlaceSearchChanged) findPreference(R.string.p_geofence_service) .setOnPreferenceChangeListener(this::onGeofenceServiceChanged) } else { - disable( - R.string.p_map_tiles, - R.string.p_place_provider, - R.string.p_geofence_service - ) + disable(R.string.p_map_tiles, R.string.p_geofence_service) } } @@ -71,21 +65,6 @@ class LocationPreferences : InjectingPreferenceFragment() { findPreference(R.string.p_geofence_service).isEnabled = hasPermissions && IS_GOOGLE_PLAY } - private fun onPlaceSearchChanged(preference: Preference, newValue: Any): Boolean = - if (newValue.toString().toIntOrNull() ?: 0 == 1) { - if (!playServices.refreshAndCheck()) { - playServices.resolve(activity) - false - } else if (!inventory.hasPro) { - toaster.longToast(R.string.requires_pro_subscription) - false - } else { - true - } - } else { - true - } - private fun onGeofenceServiceChanged(preference: Preference, newValue: Any): Boolean = if (newValue.toString().toIntOrNull() ?: 0 == 1) { if (!playServices.refreshAndCheck()) { diff --git a/app/src/main/res/drawable-hdpi/powered_by_google_on_non_white.png b/app/src/main/res/drawable-hdpi/powered_by_google_on_non_white.png new file mode 100644 index 000000000..4ea940251 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/powered_by_google_on_non_white.png differ diff --git a/app/src/main/res/drawable-hdpi/powered_by_google_on_white.png b/app/src/main/res/drawable-hdpi/powered_by_google_on_white.png new file mode 100644 index 000000000..00be8478b Binary files /dev/null and b/app/src/main/res/drawable-hdpi/powered_by_google_on_white.png differ diff --git a/app/src/main/res/drawable-ldpi/powered_by_google_on_non_white.png b/app/src/main/res/drawable-ldpi/powered_by_google_on_non_white.png new file mode 100644 index 000000000..55888f914 Binary files /dev/null and b/app/src/main/res/drawable-ldpi/powered_by_google_on_non_white.png differ diff --git a/app/src/main/res/drawable-ldpi/powered_by_google_on_white.png b/app/src/main/res/drawable-ldpi/powered_by_google_on_white.png new file mode 100644 index 000000000..f5ae53520 Binary files /dev/null and b/app/src/main/res/drawable-ldpi/powered_by_google_on_white.png differ diff --git a/app/src/main/res/drawable-mdpi/powered_by_google_on_non_white.png b/app/src/main/res/drawable-mdpi/powered_by_google_on_non_white.png new file mode 100644 index 000000000..abe091388 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/powered_by_google_on_non_white.png differ diff --git a/app/src/main/res/drawable-mdpi/powered_by_google_on_white.png b/app/src/main/res/drawable-mdpi/powered_by_google_on_white.png new file mode 100644 index 000000000..43a153527 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/powered_by_google_on_white.png differ diff --git a/app/src/main/res/drawable-xhdpi/powered_by_google_on_non_white.png b/app/src/main/res/drawable-xhdpi/powered_by_google_on_non_white.png new file mode 100644 index 000000000..0245b1f25 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/powered_by_google_on_non_white.png differ diff --git a/app/src/main/res/drawable-xhdpi/powered_by_google_on_white.png b/app/src/main/res/drawable-xhdpi/powered_by_google_on_white.png new file mode 100644 index 000000000..4676cb59b Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/powered_by_google_on_white.png differ diff --git a/app/src/main/res/drawable-xxhdpi/powered_by_google_on_non_white.png b/app/src/main/res/drawable-xxhdpi/powered_by_google_on_non_white.png new file mode 100644 index 000000000..3d290aa37 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/powered_by_google_on_non_white.png differ diff --git a/app/src/main/res/drawable-xxhdpi/powered_by_google_on_white.png b/app/src/main/res/drawable-xxhdpi/powered_by_google_on_white.png new file mode 100644 index 000000000..64b2cab5a Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/powered_by_google_on_white.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/powered_by_google_on_non_white.png b/app/src/main/res/drawable-xxxhdpi/powered_by_google_on_non_white.png new file mode 100644 index 000000000..bc8b476ac Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/powered_by_google_on_non_white.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/powered_by_google_on_white.png b/app/src/main/res/drawable-xxxhdpi/powered_by_google_on_white.png new file mode 100644 index 000000000..74ba4b4ef Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/powered_by_google_on_white.png differ diff --git a/app/src/main/res/values-ar/strings.xml b/app/src/main/res/values-ar/strings.xml index c2ccb23e1..c4165c5e0 100644 --- a/app/src/main/res/values-ar/strings.xml +++ b/app/src/main/res/values-ar/strings.xml @@ -188,7 +188,6 @@ توليد الإخطارات ادمج عدة إشعارات في شعار واحد انقر هنا إذا كنت تواجه مشاكل في الإشعارات - مزود الخرائط الموقع إظهار التعليقات في شاشة تحرير المهمة الضغط على زر الرجوع يحفظ المهمة diff --git a/app/src/main/res/values-bg-rBG/strings.xml b/app/src/main/res/values-bg-rBG/strings.xml index e0bc3c3fa..2ef7d2d5e 100644 --- a/app/src/main/res/values-bg-rBG/strings.xml +++ b/app/src/main/res/values-bg-rBG/strings.xml @@ -438,7 +438,6 @@ Изберете местоположение Избери това местоположение Или избери местоположение - Намери доставчик Липсващи разрешения Необходими са разрешения за местоположение, за да откриете текущото ви местоположение Отворете картата diff --git a/app/src/main/res/values-cs/strings.xml b/app/src/main/res/values-cs/strings.xml index 885bdec12..454212143 100644 --- a/app/src/main/res/values-cs/strings.xml +++ b/app/src/main/res/values-cs/strings.xml @@ -464,7 +464,6 @@ Dle systému každý %1$s %2$s Nebo vyberte místo - Poskytovatel vyhledávání Chybí oprávnění Oprávnění k přístupu k poloze je nutné pro zjištění Vaší aktuální polohy Otevřít mapu diff --git a/app/src/main/res/values-da/strings.xml b/app/src/main/res/values-da/strings.xml index aee0dadd0..bdb156194 100644 --- a/app/src/main/res/values-da/strings.xml +++ b/app/src/main/res/values-da/strings.xml @@ -211,7 +211,6 @@ Åbn kort Placeringstilladelse kræves for at finde din nuværende placering Manglende tilladelser - Søgeudbyder Eller vælg et sted Vælg dette sted Vælg sted diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 9c4f9dc07..d39b8ec81 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -435,7 +435,6 @@ Ort auswählen Diesen Ort auswählen Oder Ort auswählen - Suchanbieter Fehlende Berechtigungen Standortberechtigung wird zur Ermittlung des aktuellen Standortes benötigt Karte öffnen diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index f83567758..ad063fd40 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -438,7 +438,6 @@ Escoger ubicación Seleccionar esta ubicación O elija una ubicación - Proveedor de búsquedas Permisos ausentes Son necesarios permisos de ubicación para encontrar tu ubicación actual Abrir mapa diff --git a/app/src/main/res/values-eu/strings.xml b/app/src/main/res/values-eu/strings.xml index 0f23eba17..a534f8b54 100644 --- a/app/src/main/res/values-eu/strings.xml +++ b/app/src/main/res/values-eu/strings.xml @@ -444,7 +444,6 @@ Hautatu kokaleku bat Hautatu kokaleku hau Edo hautatu kokaleku bat - Bilatu hornitzailea Baimenak falta dira Kokapen baimena behar da zure uneko kokalekua aurkitzeko Ireki mapa diff --git a/app/src/main/res/values-fi/strings.xml b/app/src/main/res/values-fi/strings.xml index a9a9c7f2d..973adeba8 100644 --- a/app/src/main/res/values-fi/strings.xml +++ b/app/src/main/res/values-fi/strings.xml @@ -441,7 +441,6 @@ Avaa kartta Sijaintioikeudet tarvitaan nykysijainnin paikannukseen Oikeuksia puuttuu - Hauntarjoaja Tai valitse muu sijainti Valitse tämä sijainti Valitse sijainti diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 1fb0e8a40..ac621fd07 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -420,7 +420,6 @@ Choisir une localisation Sélectionner cette localisation Ou choisir une localisation - Moteurs de recherche Permissions manquantes La permission de la localisation est nécessaire pour trouver votre localisation actuelle Ouvrir la carte diff --git a/app/src/main/res/values-hu/strings.xml b/app/src/main/res/values-hu/strings.xml index af3cda2b2..3ce39d436 100644 --- a/app/src/main/res/values-hu/strings.xml +++ b/app/src/main/res/values-hu/strings.xml @@ -439,7 +439,6 @@ Hely kiválasztása Hely kiválasztása Vagy másik hely keresése - Keresési szolgáltató Hiányzó jogosultságok A jelenlegi pozíció meghatározásához helymeghatározási jogosultság szükséges Térkép megnyitása diff --git a/app/src/main/res/values-id/strings.xml b/app/src/main/res/values-id/strings.xml index 0913cd05c..f397cc58d 100644 --- a/app/src/main/res/values-id/strings.xml +++ b/app/src/main/res/values-id/strings.xml @@ -368,7 +368,6 @@ Pilih sebuah lokasi Pilih lokasi ini Atau pilih sebuah lokasi - Penyedia pencarian Izin akses lokasi diperlukan untuk mencari lokasi Anda saat ini Buka peta Pilih lokasi baru diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index 6ac7a95ac..286c34031 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -439,7 +439,6 @@ Scegli una posizione Seleziona questa posizione O scegli una posizione - Seleziona fornitore Permessi mancanti Per trovare la tua posizione sono richiesti i permessi di localizzazione Apri mappa diff --git a/app/src/main/res/values-iw/strings.xml b/app/src/main/res/values-iw/strings.xml index 1ad9c8c93..72885c6a0 100644 --- a/app/src/main/res/values-iw/strings.xml +++ b/app/src/main/res/values-iw/strings.xml @@ -473,7 +473,6 @@ בחרו מיקום בחרו את המיקום הזה או בחרו מיקום - ספק חיפוש חסרות הרשאות הרשאות מיקום נדרשות על מנת למצוא את מיקומך הנוכחי פתיחת מפה diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml index 60949bd7d..5e9f64544 100644 --- a/app/src/main/res/values-ja/strings.xml +++ b/app/src/main/res/values-ja/strings.xml @@ -436,7 +436,6 @@ 場所を選択 この場所を選択 または場所を選ぶ - プロバイダーを検索 アクセス許可がありません 現在の場所を見つけるには位置のアクセス許可が必要です 地図を開く diff --git a/app/src/main/res/values-ko/strings.xml b/app/src/main/res/values-ko/strings.xml index 3c93b6169..df1ab515f 100644 --- a/app/src/main/res/values-ko/strings.xml +++ b/app/src/main/res/values-ko/strings.xml @@ -441,7 +441,6 @@ 위치 선택 현위치 선택 위치 고르기 - 검색 제공업체 권한 누락 기기의 현재 위치를 확인하려면 위치 권한이 필요합니다 지도 열기 diff --git a/app/src/main/res/values-lt/strings.xml b/app/src/main/res/values-lt/strings.xml index 623fa3372..e64b4eb1c 100644 --- a/app/src/main/res/values-lt/strings.xml +++ b/app/src/main/res/values-lt/strings.xml @@ -435,7 +435,6 @@ Pasirinkti vietą Pasirinkti šią vietą Arba pasirinkti vietą - Paieškos tiekėjas Dingę leidimai Vietos leidimai reikalingi surasti jūsų esamą vietą Atidaryti žemėlapį diff --git a/app/src/main/res/values-nb/strings.xml b/app/src/main/res/values-nb/strings.xml index 7166a11f1..1d45630b5 100644 --- a/app/src/main/res/values-nb/strings.xml +++ b/app/src/main/res/values-nb/strings.xml @@ -444,7 +444,6 @@ Velg et sted Velg dette stedet Eller velg et sted - Søketilbyder Manglende tilganger Plasseringstilganger trengs for å finne ditt nåværende sted Åpne kart diff --git a/app/src/main/res/values-nl/strings.xml b/app/src/main/res/values-nl/strings.xml index b16beda60..eaaaf4fd5 100644 --- a/app/src/main/res/values-nl/strings.xml +++ b/app/src/main/res/values-nl/strings.xml @@ -428,7 +428,6 @@ Kies een locatie Selecteer deze locatie Of kies een locatie - Zoek aanbieder Missende rechten Locatie rechten zijn nodig om je huidige locatie te vinden Open kaart diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml index 609a40088..87b2ba32e 100644 --- a/app/src/main/res/values-pl/strings.xml +++ b/app/src/main/res/values-pl/strings.xml @@ -448,7 +448,6 @@ Wybierz lokalizację Ustaw wybraną lokalizację Lub wybierz lokalizację - Silnik wyszukiwania Brakujące uprawnienia Uprawnienia lokalizacji są wymagane do ustalenia twojej aktualnej lokalizacji Otwórz mapę diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index 96a0330f7..39e069764 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -436,7 +436,6 @@ Escolher uma localização Selecionar essa localização Ou escolha uma localização - Provedor de pesquisa Permissões faltando Permissão de Localização é necessária para encontrar sua localização atual Abrir mapa diff --git a/app/src/main/res/values-pt/strings.xml b/app/src/main/res/values-pt/strings.xml index 06299250d..de12a4d13 100644 --- a/app/src/main/res/values-pt/strings.xml +++ b/app/src/main/res/values-pt/strings.xml @@ -399,7 +399,6 @@ Abrir mapa Permissão de localização é necessária para encontrar a sua localização atual Permissões faltando - Provedor de pesquisa Ou escolha uma localização Selecione esta localização Escolher uma localização diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 7c1149504..6720fa186 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -455,7 +455,6 @@ Выбрать местоположение Выбрать это местоположение Или выбрать местоположение - Поставщик системы поиска Отсутствующие разрешения Версия %s Google Tasks diff --git a/app/src/main/res/values-sk/strings.xml b/app/src/main/res/values-sk/strings.xml index e3d769663..1e92f41ba 100644 --- a/app/src/main/res/values-sk/strings.xml +++ b/app/src/main/res/values-sk/strings.xml @@ -435,7 +435,6 @@ Vybrať polohu Vybrať túto polohu Alebo vybrať polohu ručne - Vyhľadávanie poskytuje Chýbajúce oprávnenia Pre učenie súčasnej polohy sú potrebné povolenia Otvoriť mapu diff --git a/app/src/main/res/values-sv/strings.xml b/app/src/main/res/values-sv/strings.xml index 0acc44b16..80e1e8d8d 100644 --- a/app/src/main/res/values-sv/strings.xml +++ b/app/src/main/res/values-sv/strings.xml @@ -439,7 +439,6 @@ Välj en plats Välj den här platsen Eller Välj en plats - Sökleverantör Saknar behörigheter Plats behörigheter behövs för att hitta din aktuella plats Öppna karta diff --git a/app/src/main/res/values-ta/strings.xml b/app/src/main/res/values-ta/strings.xml index c4e10c23b..115e3ebd6 100644 --- a/app/src/main/res/values-ta/strings.xml +++ b/app/src/main/res/values-ta/strings.xml @@ -273,7 +273,6 @@ வரைபடத்தைத் திறக்கவும் உங்கள் தற்போதைய இருப்பிடத்தைக் கண்டுபிடிக்க இருப்பிட அனுமதிகள் தேவை அனுமதிகள் இல்லை - தேடல் வழங்குநர் அல்லது இருப்பிடத்தைத் தேர்வுசெய்க இந்த இருப்பிடத்தைத் தேர்ந்தெடுக்கவும் இருப்பிடத்தைத் தேர்வுசெய்க diff --git a/app/src/main/res/values-tr/strings.xml b/app/src/main/res/values-tr/strings.xml index d021cf971..3189c2f44 100644 --- a/app/src/main/res/values-tr/strings.xml +++ b/app/src/main/res/values-tr/strings.xml @@ -441,7 +441,6 @@ Konum seç Bu konumu seç Ya da konum seç - Arama sağlayıcı Eksik izinler Geçerli konumunuzu bulmak için konum izinleri gereklidir Haritayı aç diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml index e74935da4..1844655c5 100644 --- a/app/src/main/res/values-uk/strings.xml +++ b/app/src/main/res/values-uk/strings.xml @@ -457,7 +457,6 @@ Обрати місце Обрати це місце Або вказати інше місце - Знайти провайдера Відсутні дозволи Щоб визначити ваше місцезнаходження необхідний дозвіл на перегляд місцезнаходження Відкрити карту diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index 5d6a8fd30..ca695d7f9 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -434,7 +434,6 @@ 选择一个位置 选中这个位置 或选择一个位置 - 搜索引擎供应商 缺少权限 需要位置权限来发现您当前位置 打开地图 diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index d083cabb0..27c14921d 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -444,7 +444,6 @@ 開啟地圖 需要位置權限以找到您現在的位置 缺少權限 - 搜尋提供者 或選擇一個地點 選擇此地點 選擇一個地點 diff --git a/app/src/main/res/values/arrays.xml b/app/src/main/res/values/arrays.xml index f5d25522b..947822b4d 100644 --- a/app/src/main/res/values/arrays.xml +++ b/app/src/main/res/values/arrays.xml @@ -292,16 +292,6 @@ 2 - - @string/mapbox - @string/map_search_google_places - - - - 0 - 1 - - @string/google_play_location_service @string/android_location_services diff --git a/app/src/main/res/values/keys.xml b/app/src/main/res/values/keys.xml index 7bb963d15..f3ab2e8a9 100644 --- a/app/src/main/res/values/keys.xml +++ b/app/src/main/res/values/keys.xml @@ -396,12 +396,10 @@ linkify_task_list linkify_task_edit Mapbox - Google Places Nominatim Google Maps OpenStreetMap Android - place_provider_v2 location_based_reminders geofence_service preference_screen diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 3f1a5f557..bfb277341 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -523,7 +523,6 @@ File %1$s contained %2$s.\n\n Choose a location Select this location Or choose a location - Search provider Missing permissions This app collects location data to enable location-based reminders even when the app is closed or not in use. Location permissions are needed to find your current location diff --git a/app/src/main/res/xml/preferences_location.xml b/app/src/main/res/xml/preferences_location.xml index b2f258bca..b4b11c9e5 100644 --- a/app/src/main/res/xml/preferences_location.xml +++ b/app/src/main/res/xml/preferences_location.xml @@ -54,14 +54,6 @@ android:entryValues="@array/reverse_geocoder_values" android:summary="%s"/> - - \ No newline at end of file diff --git a/app/src/release/res/values/keys.xml b/app/src/release/res/values/keys.xml index fa04b6d97..f77ddd2ef 100644 --- a/app/src/release/res/values/keys.xml +++ b/app/src/release/res/values/keys.xml @@ -3,4 +3,5 @@ Tasks https://caldav.tasks.org https://nominatim.tasks.org + https://places.tasks.org \ No newline at end of file diff --git a/app/src/test/java/org/tasks/location/PlaceSearchGoogleTest.kt b/app/src/test/java/org/tasks/location/PlaceSearchGoogleTest.kt new file mode 100644 index 000000000..b36f786b7 --- /dev/null +++ b/app/src/test/java/org/tasks/location/PlaceSearchGoogleTest.kt @@ -0,0 +1,49 @@ +package org.tasks.location + +import org.junit.Assert.assertEquals +import org.junit.Test +import org.tasks.TestUtilities.readFile +import org.tasks.location.PlaceSearchGoogle.Companion.toJson +import org.tasks.location.PlaceSearchGoogle.Companion.toPlace +import org.tasks.location.PlaceSearchGoogle.Companion.toSearchResults + +class PlaceSearchGoogleTest { + @Test + fun placeSearchWithMultipleResults() { + val results = toSearchResults(readFile("google_places/search.json").toJson()) + + assertEquals( + listOf( + "ChIJfQQVCCMzjoARce0POzONI8I", + "ChIJQXqgXsiAj4ARqtl6U4GD-Cw", + "ChIJCWNdVNgr3YAR4pLlOt8CfEk", + "ChIJhTEH6lev3IARDMKC_pGF6nI" + ), + results.map { it.id } + ) + } + + @Test + fun validatePlace() { + val result = toSearchResults(readFile("google_places/search.json").toJson())[2] + + assertEquals("ChIJCWNdVNgr3YAR4pLlOt8CfEk", result.id) + assertEquals("Portillo's Hot Dogs", result.name) + assertEquals("La Palma Avenue, Buena Park, CA, USA", result.address) + } + + @Test + fun fetchPlace() { + val result = toPlace(readFile("google_places/fetch.json").toJson()) + + assertEquals("Magic Kingdom Park", result.name) + assertEquals("1180 Seven Seas Drive, Lake Buena Vista, FL 32836, USA", result.address) + assertEquals(28.417663, result.latitude, 0.0) + assertEquals(-81.581212, result.longitude, 0.0) + assertEquals("+1 407-939-5277", result.phone) + assertEquals( + "https://disneyworld.disney.go.com/destinations/magic-kingdom/?CMP=OKC-80007944_GM_WDW_destination_magickingdompark_NA", + result.url + ) + } +} \ No newline at end of file diff --git a/app/src/test/resources/google_places/fetch.json b/app/src/test/resources/google_places/fetch.json new file mode 100644 index 000000000..ef1aa08c4 --- /dev/null +++ b/app/src/test/resources/google_places/fetch.json @@ -0,0 +1,17 @@ +{ + "html_attributions": [], + "result": { + "formatted_address": "1180 Seven Seas Drive, Lake Buena Vista, FL 32836, USA", + "geometry": { + "location": { + "lat": 28.417663, + "lng": -81.581212 + } + }, + "international_phone_number": "+1 407-939-5277", + "name": "Magic Kingdom Park", + "place_id": "ChIJgUulalN-3YgRGoTaWM2LawY", + "website": "https://disneyworld.disney.go.com/destinations/magic-kingdom/?CMP=OKC-80007944_GM_WDW_destination_magickingdompark_NA" + }, + "status": "OK" +} \ No newline at end of file diff --git a/app/src/test/resources/google_places/search.json b/app/src/test/resources/google_places/search.json new file mode 100644 index 000000000..774d37ca2 --- /dev/null +++ b/app/src/test/resources/google_places/search.json @@ -0,0 +1,225 @@ +{ + "predictions": [ + { + "description": "portillo's hot dogs", + "matched_substrings": [ + { + "length": 19, + "offset": 0 + } + ], + "structured_formatting": { + "main_text": "portillo's hot dogs", + "main_text_matched_substrings": [ + { + "length": 19, + "offset": 0 + } + ] + }, + "terms": [ + { + "offset": 0, + "value": "portillo's hot dogs" + } + ] + }, + { + "description": "Portillo Diesel, Leo Avenue, San Jose, CA, USA", + "matched_substrings": [ + { + "length": 15, + "offset": 0 + } + ], + "place_id": "ChIJfQQVCCMzjoARce0POzONI8I", + "reference": "ChIJfQQVCCMzjoARce0POzONI8I", + "structured_formatting": { + "main_text": "Portillo Diesel", + "main_text_matched_substrings": [ + { + "length": 15, + "offset": 0 + } + ], + "secondary_text": "Leo Avenue, San Jose, CA, USA" + }, + "terms": [ + { + "offset": 0, + "value": "Portillo Diesel" + }, + { + "offset": 17, + "value": "Leo Avenue" + }, + { + "offset": 29, + "value": "San Jose" + }, + { + "offset": 39, + "value": "CA" + }, + { + "offset": 43, + "value": "USA" + } + ], + "types": [ + "car_repair", + "point_of_interest", + "establishment" + ] + }, + { + "description": "Portillo's Trucking, Franklin Street, Oakland, CA, USA", + "matched_substrings": [ + { + "length": 19, + "offset": 0 + } + ], + "place_id": "ChIJQXqgXsiAj4ARqtl6U4GD-Cw", + "reference": "ChIJQXqgXsiAj4ARqtl6U4GD-Cw", + "structured_formatting": { + "main_text": "Portillo's Trucking", + "main_text_matched_substrings": [ + { + "length": 19, + "offset": 0 + } + ], + "secondary_text": "Franklin Street, Oakland, CA, USA" + }, + "terms": [ + { + "offset": 0, + "value": "Portillo's Trucking" + }, + { + "offset": 21, + "value": "Franklin Street" + }, + { + "offset": 38, + "value": "Oakland" + }, + { + "offset": 47, + "value": "CA" + }, + { + "offset": 51, + "value": "USA" + } + ], + "types": [ + "moving_company", + "point_of_interest", + "establishment" + ] + }, + { + "description": "Portillo's Hot Dogs, La Palma Avenue, Buena Park, CA, USA", + "matched_substrings": [ + { + "length": 19, + "offset": 0 + } + ], + "place_id": "ChIJCWNdVNgr3YAR4pLlOt8CfEk", + "reference": "ChIJCWNdVNgr3YAR4pLlOt8CfEk", + "structured_formatting": { + "main_text": "Portillo's Hot Dogs", + "main_text_matched_substrings": [ + { + "length": 19, + "offset": 0 + } + ], + "secondary_text": "La Palma Avenue, Buena Park, CA, USA" + }, + "terms": [ + { + "offset": 0, + "value": "Portillo's Hot Dogs" + }, + { + "offset": 21, + "value": "La Palma Avenue" + }, + { + "offset": 38, + "value": "Buena Park" + }, + { + "offset": 50, + "value": "CA" + }, + { + "offset": 54, + "value": "USA" + } + ], + "types": [ + "meal_takeaway", + "restaurant", + "food", + "point_of_interest", + "establishment" + ] + }, + { + "description": "Portillo's Hot Dogs, Day Street, Moreno Valley, CA, USA", + "matched_substrings": [ + { + "length": 19, + "offset": 0 + } + ], + "place_id": "ChIJhTEH6lev3IARDMKC_pGF6nI", + "reference": "ChIJhTEH6lev3IARDMKC_pGF6nI", + "structured_formatting": { + "main_text": "Portillo's Hot Dogs", + "main_text_matched_substrings": [ + { + "length": 19, + "offset": 0 + } + ], + "secondary_text": "Day Street, Moreno Valley, CA, USA" + }, + "terms": [ + { + "offset": 0, + "value": "Portillo's Hot Dogs" + }, + { + "offset": 21, + "value": "Day Street" + }, + { + "offset": 33, + "value": "Moreno Valley" + }, + { + "offset": 48, + "value": "CA" + }, + { + "offset": 52, + "value": "USA" + } + ], + "types": [ + "meal_takeaway", + "restaurant", + "food", + "point_of_interest", + "establishment" + ] + } + ], + "status": "OK" +} \ No newline at end of file diff --git a/deps_googleplay.txt b/deps_googleplay.txt index 5a6f17f94..4e884b4ae 100644 --- a/deps_googleplay.txt +++ b/deps_googleplay.txt @@ -186,8 +186,32 @@ +| +--- androidx.fragment:fragment:1.0.0 -> 1.2.5 (*) +| +--- com.google.android.gms:play-services-base:17.0.0 -> 17.3.0 (*) +| \--- com.google.android.gms:play-services-basement:17.0.0 -> 17.3.0 (*) -++--- com.google.android.libraries.places:places:2.4.0 -+| +--- androidx.appcompat:appcompat:1.0.0 -> 1.2.0 +++--- com.android.billingclient:billing:1.2.2 +++--- com.gitlab.bitfireAT:dav4jvm:2.1.1 ++| +--- org.jetbrains.kotlin:kotlin-stdlib:1.3.72 -> 1.4.30 (*) ++| \--- org.apache.commons:commons-lang3:3.9 +++--- com.gitlab.abaker:ical4android:0e928b567c ++| +--- org.mnode.ical4j:ical4j:3.0.21 ++| | +--- org.slf4j:slf4j-api:1.7.25 -> 1.7.30 ++| | +--- commons-codec:commons-codec:1.11 ++| | +--- org.apache.commons:commons-lang3:3.8.1 -> 3.9 ++| | \--- org.apache.commons:commons-collections4:4.1 ++| +--- org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.4.21 (*) ++| +--- com.sun.mail:android-mail:1.6.5 ++| | \--- com.sun.mail:android-activation:1.6.5 ++| +--- commons-io:commons-io:2.6 ++| +--- org.slf4j:slf4j-jdk14:1.7.30 ++| | \--- org.slf4j:slf4j-api:1.7.30 ++| \--- androidx.core:core-ktx:1.3.2 ++| +--- org.jetbrains.kotlin:kotlin-stdlib:1.3.71 -> 1.4.30 (*) ++| +--- androidx.annotation:annotation:1.1.0 ++| \--- androidx.core:core:1.3.2 (*) +++--- com.gitlab.bitfireAT:cert4android:26a91a729f ++| +--- androidx.databinding:databinding-common:4.1.1 -> 4.1.2 ++| +--- androidx.databinding:databinding-runtime:4.1.1 -> 4.1.2 (*) ++| +--- androidx.databinding:databinding-adapters:4.1.1 -> 4.1.2 (*) ++| +--- org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.4.21 (*) ++| +--- androidx.appcompat:appcompat:1.2.0 +| | +--- androidx.annotation:annotation:1.1.0 +| | +--- androidx.core:core:1.3.0 -> 1.3.2 (*) +| | +--- androidx.cursoradapter:cursoradapter:1.0.0 @@ -213,8 +237,7 @@ +| | \--- androidx.collection:collection:1.0.0 -> 1.1.0 (*) +| +--- androidx.cardview:cardview:1.0.0 +| | \--- androidx.annotation:annotation:1.0.0 -> 1.1.0 -+| +--- androidx.fragment:fragment:1.1.0 -> 1.2.5 (*) -+| +--- androidx.lifecycle:lifecycle-extensions:2.1.0 -> 2.2.0 ++| +--- androidx.lifecycle:lifecycle-extensions:2.2.0 +| | +--- androidx.lifecycle:lifecycle-runtime:2.2.0 (*) +| | +--- androidx.arch.core:core-common:2.1.0 (*) +| | +--- androidx.arch.core:core-runtime:2.1.0 (*) @@ -226,50 +249,6 @@ +| | +--- androidx.lifecycle:lifecycle-service:2.2.0 +| | | \--- androidx.lifecycle:lifecycle-runtime:2.2.0 (*) +| | \--- androidx.lifecycle:lifecycle-viewmodel:2.2.0 (*) -+| +--- androidx.recyclerview:recyclerview:1.0.0 -> 1.1.0 -+| | +--- androidx.annotation:annotation:1.1.0 -+| | +--- androidx.core:core:1.1.0 -> 1.3.2 (*) -+| | +--- androidx.customview:customview:1.0.0 (*) -+| | \--- androidx.collection:collection:1.0.0 -> 1.1.0 (*) -+| +--- com.android.volley:volley:1.1.1 -+| +--- com.google.android.datatransport:transport-api:2.2.0 -> 2.2.1 (*) -+| +--- com.google.android.datatransport:transport-backend-cct:2.3.0 -> 2.3.3 (*) -+| +--- com.google.android.datatransport:transport-runtime:2.2.3 -> 2.2.5 (*) -+| +--- com.google.android.gms:play-services-base:17.2.1 -> 17.3.0 (*) -+| +--- com.google.android.gms:play-services-basement:17.0.0 -> 17.3.0 (*) -+| +--- com.google.android.gms:play-services-location:17.0.0 -> 17.1.0 (*) -+| +--- com.google.android.gms:play-services-maps:17.0.0 (*) -+| +--- com.google.android.gms:play-services-tasks:17.0.0 -> 17.1.0 (*) -+| +--- com.google.auto.value:auto-value-annotations:1.6.2 -> 1.7.4 -+| \--- com.google.code.gson:gson:2.8.5 -> 2.8.6 -++--- com.android.billingclient:billing:1.2.2 -++--- com.gitlab.bitfireAT:dav4jvm:2.1.1 -+| +--- org.jetbrains.kotlin:kotlin-stdlib:1.3.72 -> 1.4.30 (*) -+| \--- org.apache.commons:commons-lang3:3.9 -++--- com.gitlab.abaker:ical4android:0e928b567c -+| +--- org.mnode.ical4j:ical4j:3.0.21 -+| | +--- org.slf4j:slf4j-api:1.7.25 -> 1.7.30 -+| | +--- commons-codec:commons-codec:1.11 -+| | +--- org.apache.commons:commons-lang3:3.8.1 -> 3.9 -+| | \--- org.apache.commons:commons-collections4:4.1 -+| +--- org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.4.21 (*) -+| +--- com.sun.mail:android-mail:1.6.5 -+| | \--- com.sun.mail:android-activation:1.6.5 -+| +--- commons-io:commons-io:2.6 -+| +--- org.slf4j:slf4j-jdk14:1.7.30 -+| | \--- org.slf4j:slf4j-api:1.7.30 -+| \--- androidx.core:core-ktx:1.3.2 -+| +--- org.jetbrains.kotlin:kotlin-stdlib:1.3.71 -> 1.4.30 (*) -+| +--- androidx.annotation:annotation:1.1.0 -+| \--- androidx.core:core:1.3.2 (*) -++--- com.gitlab.bitfireAT:cert4android:26a91a729f -+| +--- androidx.databinding:databinding-common:4.1.1 -> 4.1.2 -+| +--- androidx.databinding:databinding-runtime:4.1.1 -> 4.1.2 (*) -+| +--- androidx.databinding:databinding-adapters:4.1.1 -> 4.1.2 (*) -+| +--- org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.4.21 (*) -+| +--- androidx.appcompat:appcompat:1.2.0 (*) -+| +--- androidx.cardview:cardview:1.0.0 (*) -+| +--- androidx.lifecycle:lifecycle-extensions:2.2.0 (*) +| +--- androidx.lifecycle:lifecycle-livedata-ktx:2.2.0 +| | +--- org.jetbrains.kotlin:kotlin-stdlib:1.3.50 -> 1.4.30 (*) +| | +--- org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.0 -> 1.4.1 @@ -307,7 +286,11 @@ +| | +--- androidx.annotation:annotation-experimental:1.0.0 +| | +--- androidx.fragment:fragment:1.0.0 -> 1.2.5 (*) +| | +--- androidx.lifecycle:lifecycle-runtime:2.0.0 -> 2.2.0 (*) -+| | +--- androidx.recyclerview:recyclerview:1.0.0 -> 1.1.0 (*) ++| | +--- androidx.recyclerview:recyclerview:1.0.0 -> 1.1.0 ++| | | +--- androidx.annotation:annotation:1.1.0 ++| | | +--- androidx.core:core:1.1.0 -> 1.3.2 (*) ++| | | +--- androidx.customview:customview:1.0.0 (*) ++| | | \--- androidx.collection:collection:1.0.0 -> 1.1.0 (*) +| | +--- androidx.transition:transition:1.2.0 +| | | +--- androidx.annotation:annotation:1.1.0 +| | | +--- androidx.core:core:1.0.1 -> 1.3.2 (*)