Geocodificación inversa en Android

La geocodificación inversa es un proceso utilizado para convertir coordenadas (latitud y longitud) en direcciones legibles por humanos. Esto no es exactamente lo contrario de Geocodificación. En Geocodificación, el Lugar está asociado a un nombre y coordenadas fijas. Estas coordenadas son de naturaleza doble. Un cambio insignificante en estas coordenadas aún puede referirse al mismo lugar, pero nunca obtendremos el nombre del lugar ya que está asociado solo con esas coordenadas fijas. Por lo tanto, definitivamente obtendremos la dirección completa en la geocodificación inversa, pero el nombre del lugar no está garantizado. A través de este artículo, le mostraremos un ejemplo de cómo realizar una geocodificación inversa en Android. Pero antes de continuar, consulte los siguientes artículos:

  1. Google Cloud Platform: creación de cuentas y proyectos de Google Cloud Console
  2. Generación de claves API para usar cualquier API de Google
  3. ¿Cómo ocultar la API y las claves secretas en Android Studio?
  4. ¿Cómo implementar la barra de autocompletado de lugares de Google en Android?
  5. ¿Cómo implementar la función de botón de ubicación actual en Google Maps en Android?

Estructura del proyecto

Para la codificación geográfica inversa, necesitaremos la latitud y la longitud en el tipo de datos Doble. Así que implementaremos un mapa de Google y consideraremos su centro como nuestra latitud y longitud principal. Podemos obtener fácilmente las coordenadas del centro usando la posición de la cámara (consulte el código principal). Siempre que se arrastre el Mapa, el centro cambiará y provocará un cambio en la latitud y la longitud. Una vez que el Mapa está inactivo, es decir, deja de arrastrarse o moverse, el algoritmo de geocodificación inversa considerará las coordenadas del centro y las procesará para obtener una dirección completa. Esto se publicará instantáneamente en una vista de texto. Esto confirmará que la geocodificación inversa funciona bien en el código. Siga los pasos a continuación para crear este proyecto.

¿Qué vamos a construir en este artículo? 

Paso 1: crea un nuevo proyecto en Android Studio

Para crear un nuevo proyecto en Android Studio, consulte Cómo crear/iniciar un nuevo proyecto en Android Studio . Demostramos la aplicación en Kotlin, así que asegúrese de seleccionar Kotlin como idioma principal al crear un nuevo proyecto.

Paso 2: Obtenga y oculte la clave API

  1. Nuestra aplicación utiliza la API de lugares de Google, por lo que necesitamos obtener la clave de la API de lugares de Google. Para obtener una clave de API, consulte Generación de claves de API para usar cualquier API de Google .
  2. Ocultar una clave API es esencial y para hacerlo, consulte ¿Cómo ocultar API y claves secretas en Android Studio? .

Paso 3: Agrega estas dependencias

Esta dependencia será necesaria para la geocodificación inversa.

Kotlin

dependencies {
    implementation 'com.google.android.libraries.places:places:2.4.0'
}

Paso 4: agregar un fragmento de mapa, un marcador de ubicación personalizado y una vista de texto en el archivo de diseño (actividad_principal.xml)

XML

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">
  
    <!--Map Fragment-->
    <fragment xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/map"
        tools:context=".MapsActivity"
        android:name="com.google.android.gms.maps.SupportMapFragment" />
  
    <!--This layout overlays the Map Fragment 
        which matches parent width and height-->
    <!--We want to display our TextView over 
        the Map with good aesthetics-->
    <LinearLayout
        android:layout_margin="20sp"
        android:id="@+id/ll1"
        android:layout_width="match_parent"
        android:layout_height="100sp"
        android:background="@drawable/shape"
        android:layout_alignBottom="@id/map"
        android:orientation="horizontal">
  
          <!--TextView for displaying Lat and
             Lng along with Address-->
        <TextView
            android:id="@+id/tv"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_margin="10sp"
            />
  
    </LinearLayout>
  
      <!--This is only for reference to the center 
        of the screen, can be any element-->
      <!--We have set fixed this element at the parent
         center, which is the actual centre of the screen-->
    <Button
        android:id="@+id/centerReferencePoint"
        android:layout_width="0sp"
        android:layout_height="0sp"
        android:layout_centerInParent="true"/>
  
      <!--This image is the Marker-->
    <ImageView
        android:id="@+id/marker"
        android:layout_width="30sp"
        android:layout_height="40sp"
        android:src="@drawable/marker"
        android:layout_centerInParent="true"
        android:layout_above="@id/centerReferencePoint"
        />
  
</RelativeLayout>

Marcador:

Descargamos esta imagen en formato PNG de Internet. No tiene color de fondo y puede denominarse imagen transparente. Una vez descargado, puede copiarlo directamente desde donde esté almacenado, abrir Android Studio y pegarlo en la carpeta dibujable presente en la carpeta res. Mientras hacía esto, lo renombramos como «marcador» que puede encontrar en los atributos de ImageView en el archivo activity_main.xml .

Archivo Shape.xml (Fondo del diseño lineal en activity_main.xml)

Hemos establecido un fondo blanco y un radio de esquina con algún valor. Esto es para que el diseño se vea mejor.

XML

<shape
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle"   >
  
    <solid
        android:color="#ffffff" >
    </solid>
  
    <corners
        android:radius="11dp"   >
    </corners>
  
</shape>

Vista previa de Shape.xml

Vista previa de activity_main.xml:

vista previa de activity_main.xml

Paso 5: Trabajando en el backend (MainActivity.kt)

Tomamos las coordenadas del lugar presente en el centro de la pantalla y las convertimos en direcciones de texto. Una vez que se arrastra la pantalla, las coordenadas del centro cambian y la dirección cambia respectivamente. Los cambios tienen lugar una vez que la pantalla está inactiva y no está en movimiento y es por eso que implementamos nuestro algoritmo de codificación geográfica inversa en setOnCamera Idle Listener. El siguiente código es bastante fácil de entender. Hemos proporcionado algunos comentarios para ayudarlo a comprender mejor.

Kotlin

package org.geeksforgeeks.reversegeocoding
  
import android.content.pm.ApplicationInfo
import android.content.pm.PackageManager
import android.location.Address
import android.location.Geocoder
import android.os.Bundle
import android.widget.TextView
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import com.google.android.gms.maps.CameraUpdateFactory
import com.google.android.gms.maps.GoogleMap
import com.google.android.gms.maps.GoogleMap.OnCameraIdleListener
import com.google.android.gms.maps.OnMapReadyCallback
import com.google.android.gms.maps.SupportMapFragment
import com.google.android.gms.maps.model.LatLng
import com.google.android.libraries.places.api.Places
import java.io.IOException
import java.util.*
  
  
class MainActivity : AppCompatActivity(), OnMapReadyCallback {
  
    private lateinit var mMap: GoogleMap
  
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
  
        // Fetching API_KEY which we wrapped
        val ai: ApplicationInfo = applicationContext.packageManager.getApplicationInfo(applicationContext.packageName, PackageManager.GET_META_DATA)
        val value = ai.metaData["com.google.android.geo.API_KEY"]
        val apiKey = value.toString()
  
        // Initializing the Places API
          // with the help of our API_KEY
        if (!Places.isInitialized()) {
            Places.initialize(applicationContext, apiKey)
        }
  
        // Initializing map
        val mapFragment = supportFragmentManager.findFragmentById(R.id.map) as SupportMapFragment
        mapFragment.getMapAsync(this)
  
    }
  
    override fun onMapReady(p0: GoogleMap) {
        
        mMap = p0
        
          // These are GeeksforGeeks Noida Office Coordinates.
        val india = LatLng(28.5021359, 77.4054901)
        mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(india,17F))
  
        mMap.setOnCameraIdleListener {
            val lat = mMap.cameraPosition.target.latitude
            val lng = mMap.cameraPosition.target.longitude
            val addressTV = findViewById<TextView>(R.id.tv)
  
            // Initializing Geocoder
            val mGeocoder = Geocoder(applicationContext, Locale.getDefault())
            var addressString= ""
  
              // Reverse-Geocoding starts
            try {
                val addressList: List<Address> = mGeocoder.getFromLocation(lat, lng, 1)
  
                // use your lat, long value here
                if (addressList != null && addressList.isNotEmpty()) {
                    val address = addressList[0]
                    val sb = StringBuilder()
                    for (i in 0 until address.maxAddressLineIndex) {
                        sb.append(address.getAddressLine(i)).append("\n")
                    }
  
                    // Various Parameters of an Address are appended
                      // to generate a complete Address
                    if (address.premises != null)
                        sb.append(address.premises).append(", ")
                          
                    sb.append(address.subAdminArea).append("\n")
                    sb.append(address.locality).append(", ")
                    sb.append(address.adminArea).append(", ")
                    sb.append(address.countryName).append(", ")
                    sb.append(address.postalCode)
                      
                    // StringBuilder sb is converted into a string
                     // and this value is assigned to the 
                    // initially declared addressString string.
                    addressString = sb.toString()
                }
            } catch (e: IOException) {
                Toast.makeText(applicationContext,"Unable connect to Geocoder",Toast.LENGTH_LONG).show()
            }
              
            // Finally, the address string is posted in the textView with LatLng.
            addressTV.text = "Lat: $lat \nLng: $lng \nAddress: $addressString"
        }
    }
}

Producción:

Observe, la dirección cambia con un cambio en los valores de latitud y longitud. Los valores de latitud y longitud cambian cuando el usuario arrastra la pantalla, ya que el centro sigue cambiando.

Publicación traducida automáticamente

Artículo escrito por aashaypawar y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *