Uso de Tangram ES para Android con Amazon Location Service - Amazon Location Service

Las traducciones son generadas a través de traducción automática. En caso de conflicto entre la traducción y la version original de inglés, prevalecerá la version en inglés.

Uso de Tangram ES para Android con Amazon Location Service

Tangram ES es una biblioteca de C++ para renderizar mapas 2D y 3D a partir de datos vectoriales utilizando OpenGL ES. Es la contraparte nativa de Tangram.

Los estilos de Tangram diseñados para funcionar con el esquema de Tilezen son en gran medida compatibles con Amazon Location cuando se utilizan mapas de HERE. Entre ellos se incluyen:

  • Bubble Wrap: un estilo de orientación con todas las funciones e íconos útiles para los puntos de interés.

  • Cinnabar: un diseño clásico, ideal para aplicaciones generales de cartografía.

  • Refill: un estilo de mapa minimalista diseñado para superposiciones de visualización de datos, inspirado en el popular estilo de Toner de Stamen Design.

  • Tron: una exploración de las transformaciones de escala en el lenguaje visual de TRON.

  • Walkabout: un estilo centrado en actividades al aire libre que es perfecto para practicar senderismo o salir a pasear.

Esta guía describe cómo integrar Tangram ES para Android con Amazon Location utilizando el estilo Tangram llamado Cinnabar. Este ejemplo está disponible como parte del repositorio de muestras de Amazon Location Service en GitHub.

Mientras que otros estilos de Tangram se acompañan mejor de mosaicos rasterizados, que codifican la información del terreno, esta característica aún no es compatible con Amazon Location.

importante

Los estilos Tangram del siguiente tutorial sólo son compatibles con los recursos de mapa de Amazon Location configurados con el estilo VectorHereContrast.

Creación de la aplicación: inicialización

Para inicializar la aplicación:

  1. Cree un nuevo proyecto de Android Studio a partir de la plantilla Empty Activity.

  2. Asegúrese de que Kotlin esté seleccionado como idioma del proyecto.

  3. Seleccione un SDK mínimo de API 16: Android 4.1 (Jelly Bean) o posterior.

  4. Abra la estructura del proyecto para seleccionar Archivo, Estructura del proyecto... y elija la sección Dependencias.

  5. Con <Todos los módulos> seleccionado, pulse el botón + para agregar una nueva dependencia de biblioteca.

  6. Agregue la versión 2.19.1 o posterior del SDK para Android de AWS. Por ejemplo: com.amazonaws:aws-android-sdk-core:2.19.1

  7. Agregue Tangram, versión 0.13.0 o posterior. Por ejemplo: com.mapzen.tangram:tangram:0.13.0.

    nota

    Si busca Tangram: com.mapzen.tangram:tangram:0.13.0 se generará un mensaje diciendo que “no se encuentra”, pero si selecciona Aceptar, podrá agregarlo.

Creación de la aplicación: configuración

Para configurar la aplicación con los recursos y la región AWS:

  1. Cree app/src/main/res/values/configuration.xml.

  2. Introduzca los nombres e identificadores de sus recursos, así como AWS la Región en la que fueron creados:

<?xml version="1.0" encoding="utf-8"?> <resources> <string name="identityPoolId">us-east-1:54f2ba88-9390-498d-aaa5-0d97fb7ca3bd</string> <string name="mapName">TangramExampleMap</string> <string name="awsRegion">us-east-1</string> <string name="sceneUrl">https://www.nextzen.org/carto/cinnabar-style/9/cinnabar-style.zip</string> <string name="attribution">© 2020 HERE</string> </resources>

Creación de la aplicación: diseño de actividades

Editar app/src/main/res/layout/activity_main.xml:

  • Agregue un MapView, que renderiza el mapa. Esto también establecerá el punto central inicial del mapa.

  • Agrega un TextView, que muestra la atribución.

Esto también establecerá el punto central inicial del mapa.

nota

Debe proporcionar una marca denominativa o una atribución de texto para cada proveedor de datos que utilice, ya sea en su solicitud o en su documentación. Los string de atribución se incluyen en la respuesta del descriptor de estilo, debajo de las claves sources.esri.attribution, sources.here.attribution, y source.grabmaptiles.attribution.

Como Tangram no solicita estos recursos y solo es compatible con los mapas de HERE, use “© 2020 HERE”. Cuando utilice los recursos de Amazon Location con proveedores de datos, asegúrese de leer los términos y condiciones del servicio.

<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout 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"> <com.mapzen.tangram.MapView android:id="@+id/map" android:layout_height="match_parent" android:layout_width="match_parent" /> <TextView android:id="@+id/attributionView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="#80808080" android:padding="5sp" android:textColor="@android:color/black" android:textSize="10sp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" tools:ignore="SmallSp" /> </androidx.constraintlayout.widget.ConstraintLayout>

Creación de la aplicación: solicite la transformación

Cree una clase denominada SigV4Interceptor para interceptar AWS las solicitudes y fírmelas con Signature Version 4. Se registrará en el cliente HTTP utilizado para obtener los recursos del mapa cuando se cree la actividad principal.

package aws.location.demo.okhttp import com.amazonaws.DefaultRequest import com.amazonaws.auth.AWS4Signer import com.amazonaws.auth.AWSCredentialsProvider import com.amazonaws.http.HttpMethodName import com.amazonaws.util.IOUtils import okhttp3.HttpUrl import okhttp3.Interceptor import okhttp3.Request import okhttp3.Response import okio.Buffer import java.io.ByteArrayInputStream import java.net.URI class SigV4Interceptor( private val credentialsProvider: AWSCredentialsProvider, private val serviceName: String ) : Interceptor { override fun intercept(chain: Interceptor.Chain): Response { val originalRequest = chain.request() if (originalRequest.url().host().contains("amazonaws.com")) { val signer = if (originalRequest.url().encodedPath().contains("@")) { // the presence of "@" indicates that it doesn't need to be double URL-encoded AWS4Signer(false) } else { AWS4Signer() } val awsRequest = toAWSRequest(originalRequest, serviceName) signer.setServiceName(serviceName) signer.sign(awsRequest, credentialsProvider.credentials) return chain.proceed(toSignedOkHttpRequest(awsRequest, originalRequest)) } return chain.proceed(originalRequest) } companion object { fun toAWSRequest(request: Request, serviceName: String): DefaultRequest<Any> { // clone the request (AWS-style) so that it can be populated with credentials val dr = DefaultRequest<Any>(serviceName) // copy request info dr.httpMethod = HttpMethodName.valueOf(request.method()) with(request.url()) { dr.resourcePath = uri().path dr.endpoint = URI.create("${scheme()}://${host()}") // copy parameters for (p in queryParameterNames()) { if (p != "") { dr.addParameter(p, queryParameter(p)) } } } // copy headers for (h in request.headers().names()) { dr.addHeader(h, request.header(h)) } // copy the request body val bodyBytes = request.body()?.let { body -> val buffer = Buffer() body.writeTo(buffer) IOUtils.toByteArray(buffer.inputStream()) } dr.content = ByteArrayInputStream(bodyBytes ?: ByteArray(0)) return dr } fun toSignedOkHttpRequest( awsRequest: DefaultRequest<Any>, originalRequest: Request ): Request { // copy signed request back into an OkHttp Request val builder = Request.Builder() // copy headers from the signed request for ((k, v) in awsRequest.headers) { builder.addHeader(k, v) } // start building an HttpUrl val urlBuilder = HttpUrl.Builder() .host(awsRequest.endpoint.host) .scheme(awsRequest.endpoint.scheme) .encodedPath(awsRequest.resourcePath) // copy parameters from the signed request for ((k, v) in awsRequest.parameters) { urlBuilder.addQueryParameter(k, v) } return builder.url(urlBuilder.build()) .method(originalRequest.method(), originalRequest.body()) .build() } } }

Creación de la aplicación: Actividad principal

La actividad principal se encarga de inicializar las vistas que se mostrarán a los usuarios. Esto implica:

  • Creación de una instancia de Amazon Cognito. CredentialsProvider

  • Registro del interceptor de firmas de la versión 4.

  • Configurar el mapa apuntando a un estilo de mapa, anulando las URL de los mosaicos y mostrando la atribución adecuada.

MainActivity también es responsable de reenviar los eventos del ciclo de vida a la vista del mapa.

package aws.location.demo.tangram import android.os.Bundle import android.widget.TextView import androidx.appcompat.app.AppCompatActivity import aws.location.demo.okhttp.SigV4Interceptor import com.amazonaws.auth.CognitoCachingCredentialsProvider import com.amazonaws.regions.Regions import com.mapzen.tangram.* import com.mapzen.tangram.networking.DefaultHttpHandler import com.mapzen.tangram.networking.HttpHandler private const val SERVICE_NAME = "geo" class MainActivity : AppCompatActivity(), MapView.MapReadyCallback { private var mapView: MapView? = null override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) mapView = findViewById(R.id.map) mapView?.getMapAsync(this, getHttpHandler()) findViewById<TextView>(R.id.attributionView).text = getString(R.string.attribution) } override fun onMapReady(mapController: MapController?) { val sceneUpdates = arrayListOf( SceneUpdate( "sources.mapzen.url", "https://maps.geo.${getString(R.string.awsRegion)}.amazonaws.com/maps/v0/maps/${ getString( R.string.mapName ) }/tiles/{z}/{x}/{y}" ) ) mapController?.let { map -> map.updateCameraPosition( CameraUpdateFactory.newLngLatZoom( LngLat(-123.1187, 49.2819), 12F ) ) map.loadSceneFileAsync( getString(R.string.sceneUrl), sceneUpdates ) } } private fun getHttpHandler(): HttpHandler { val builder = DefaultHttpHandler.getClientBuilder() val credentialsProvider = CognitoCachingCredentialsProvider( applicationContext, getString(R.string.identityPoolId), Regions.US_EAST_1 ) return DefaultHttpHandler( builder.addInterceptor( SigV4Interceptor( credentialsProvider, SERVICE_NAME ) ) ) } override fun onResume() { super.onResume() mapView?.onResume() } override fun onPause() { super.onPause() mapView?.onPause() } override fun onLowMemory() { super.onLowMemory() mapView?.onLowMemory() } override fun onDestroy() { super.onDestroy() mapView?.onDestroy() } }

Al ejecutar esta aplicación, se muestra un mapa a pantalla completa con el estilo que elija. Este ejemplo está disponible como parte del repositorio de muestras de Amazon Location Service en GitHub.