Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Improved place parser #778

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,12 @@ import com.google.android.gms.maps.model.LatLng
import com.google.android.gms.maps.model.MapStyleOptions
import com.google.android.gms.maps.model.Marker
import com.google.android.gms.maps.model.MarkerOptions
import com.google.android.libraries.places.api.model.AddressComponents
import com.google.android.libraries.places.api.model.Place
import com.google.android.libraries.places.api.model.PlaceTypes
import com.google.android.libraries.places.widget.Autocomplete
import com.google.android.libraries.places.widget.model.AutocompleteActivityMode
import com.google.maps.android.SphericalUtil.computeDistanceBetween
import java.util.*

/**
* Activity for using Place Autocomplete to assist filling out an address form.
Expand Down Expand Up @@ -197,38 +197,19 @@ class AutocompleteAddressActivity : AppCompatActivity(R.layout.autocomplete_addr

private fun fillInAddress(place: Place) {
val components = place.addressComponents
val address1 = StringBuilder()
val postcode = StringBuilder()

// Get each component of the address from the place details,
// and then fill-in the corresponding field on the form.
// Possible AddressComponent types are documented at https://goo.gle/32SJPM1
if (components != null) {
for (component in components.asList()) {
when (component.types[0]) {
"street_number" -> {
address1.insert(0, component.name)
}
"route" -> {
address1.append(" ")
address1.append(component.shortName)
}
"postal_code" -> {
postcode.insert(0, component.name)
}
"postal_code_suffix" -> {
postcode.append("-").append(component.name)
}
"locality" -> binding.autocompleteCity.setText(component.name)
"administrative_area_level_1" -> {
binding.autocompleteState.setText(component.shortName)
}
"country" -> binding.autocompleteCountry.setText(component.name)
}
with (components.toAddress()) {
binding.autocompleteAddress1.setText(streetAddress)
binding.autocompletePostal.setText(fullPostalCode)
binding.autocompleteCity.setText(locality)
binding.autocompleteState.setText(adminArea)
binding.autocompleteCountry.setText(country)
}
}
binding.autocompleteAddress1.setText(address1.toString())
binding.autocompletePostal.setText(postcode.toString())

// After filling the form with address components from the Autocomplete
// prediction, set cursor focus on the second address line to encourage
Expand Down Expand Up @@ -335,4 +316,55 @@ class AutocompleteAddressActivity : AppCompatActivity(R.layout.autocomplete_addr
private val TAG = AutocompleteAddressActivity::class.java.simpleName
private const val MAP_FRAGMENT_TAG = "MAP"
}
}

/**
* Data class representing a postal address.
*
* @property streetNumber The street number of the address.
* @property locality The locality or neighborhood of the address.
* @property route The street name or route of the address.
* @property postCode The primary part of the postal code.
* @property postCodeSuffix The optional suffix or extension of the postal code.
* @property adminArea The administrative area, such as state, province, or region.
* @property country The country of the address.
*/
private data class Address(
val streetNumber: String,
val locality: String,
val route: String,
val postCode: String,
val postCodeSuffix: String,
val adminArea: String,
val country: String
) {
val fullPostalCode: String
get() = listOf(postCode, postCodeSuffix).filter { it.isNotBlank() }.joinToString("-")
val streetAddress: String
get() = listOf(streetNumber, route).filter { it.isNotBlank() }.joinToString(" ")
}

/**
* Converts an [AddressComponents] object to an [Address] object.
*
* This function iterates through the address components, creating a map where the key is the component type
* (e.g., "street_number", "route") and the value is the component name. It then uses this map to populate
* the fields of an [Address] object.
*
* If a specific address component type is not found in the [AddressComponents], the corresponding field in
* the [Address] object will be set to an empty string.
*
* @return An [Address] object representing the address information extracted from the [AddressComponents].
*/
private fun AddressComponents.toAddress(): Address {
val addressMap = this.asList().associate { it.types[0] to it.name }
return Address(
streetNumber = addressMap["street_number"] ?: "",
route = addressMap["route"] ?: "",
postCode = addressMap["postal_code"] ?: "",
postCodeSuffix = addressMap["postal_code_suffix"] ?: "",
locality = addressMap["locality"] ?: "",
adminArea = addressMap["administrative_area_level_1"] ?: "",
country = addressMap["country"] ?: ""
)
}