Amazon Location Service에서 AndroidSDK용 MapLibre 네이티브 사용 - Amazon Location Service

기계 번역으로 제공되는 번역입니다. 제공된 번역과 원본 영어의 내용이 상충하는 경우에는 영어 버전이 우선합니다.

Amazon Location Service에서 AndroidSDK용 MapLibre 네이티브 사용

MapLibre 네이티브SDK를 사용하여 대화형 맵을 Android 애플리케이션에 임베드합니다.

AndroidSDK용 MapLibre 네이티브는 Mapbox 네이티브 를 기반으로 하는 라이브러리이며 Amazon Location Service Maps 에서 제공하는 스타일 및 타일과 호환됩니다API. MapLibre Native SDK for Android를 통합하여 대화형 맵 뷰를 확장 가능하고 사용자 지정 가능한 벡터 맵과 Android 애플리케이션에 포함할 수 있습니다.

이 자습서에서는 AndroidSDK용 MapLibre Native를 Amazon Location과 통합하는 방법을 설명합니다. 이 자습서의 샘플 애플리케이션은 의 Amazon Location Service 샘플 리포지토리의 일부로 사용할 수 있습니다GitHub.

애플리케이션 빌드: 초기화

애플리케이션을 초기화하려면:

  1. 빈 활동 템플릿에서 새 Android 스튜디오 프로젝트를 만듭니다.

  2. 프로젝트 언어로 Kotlin이 선택되었는지 확인합니다.

  3. Android API 4.0(아이스크림 샌드위치) 이상SDK에서 최소 14개를 선택합니다.

  4. 프로젝트 구조를 연 다음 파일 > 프로젝트 구조...로 이동하여 종속성 섹션을 선택합니다.

  5. <All Modules>를 선택한 상태에서 + 버튼을 선택하여 새 라이브러리 종속성을 추가합니다.

  6. AWS Android SDK 버전 2.20.0 이상을 추가합니다. 예: com.amazonaws:aws-android-sdk-core:2.20.0

  7. MapLibre AndroidSDK용 Native 버전 9.4.0 이상을 추가합니다. 예: org.maplibre.gl:android-sdk:9.4.0

  8. build.gradle 파일의 프로젝트 수준에서 다음 maven 리포지토리를 추가하여 Android용 패키지에 MapLibre 액세스합니다.

    allprojects { repositories { // Retain your existing repositories google() jcenter() // Declare the repositories for MapLibre mavenCentral() } }

애플리케이션 빌드: 구성

리소스 및 AWS 리전으로 애플리케이션을 구성하려면:

<?xml version="1.0" encoding="utf-8"?> <resources> <string name="identityPoolId">us-east-1:54f2ba88-9390-498d-aaa5-0d97fb7ca3bd</string> <string name="mapName">ExampleMap</string> <string name="awsRegion">us-east-1</string> </resources>

애플리케이션 빌드: 활동 레이아웃

편집 app/src/main/res/layout/activity_main.xml:

  • 맵을 렌더링하는 MapView를 추가합니다. 이렇게 하면 맵의 초기 중심점도 설정됩니다.

  • 속성을 표시하는 TextView를 추가합니다.

<?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.mapbox.mapboxsdk.maps.MapView android:id="@+id/mapView" android:layout_width="match_parent" android:layout_height="match_parent" app:mapbox_cameraTargetLat="49.2819" app:mapbox_cameraTargetLng="-123.1187" app:mapbox_cameraZoom="12" app:mapbox_uiAttribution="false" app:mapbox_uiLogo="false" /> <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>
참고

애플리케이션 또는 문서에서 사용하는 각 데이터 공급자에 대한 워드마크 또는 텍스트 속성을 제공해야 합니다. 속성 문자열은 sources.esri.attribution, sources.here.attribution, source.grabmaptiles.attribution 키의 스타일 설명자 응답에 포함됩니다. 데이터 공급자와 함께 Amazon Location 리소스를 사용할 때는 서비스 이용 약관을 반드시 읽어보세요.

애플리케이션 빌드: 변환 요청

AWS 요청을 가로채기 SigV4Interceptor 위해 라는 클래스를 생성하고 서명 버전 4를 사용하여 서명합니다. 이는 기본 활동이 생성될 때 맵 리소스를 가져오는 데 사용되는 HTTP 클라이언트에 등록됩니다.

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() } } }

애플리케이션 빌드: 기본 활동

기본 활동은 사용자에게 표시될 보기를 초기화하는 역할을 담당합니다. 여기에는 다음이 포함됩니다.

  • Amazon Cognito CredentialsProvider 인스턴트화.

  • Signature Version 4 인터셉터 등록.

  • 맵 스타일 설명자를 가리키고 적절한 속성을 표시하여 맵을 구성합니다.

MainActivity는 또한 맵 보기에 수명 주기 이벤트를 전달하여 호출 사이에도 활성 뷰포트를 유지할 수 있도록 합니다.

package aws.location.demo.maplibre 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.mapbox.mapboxsdk.Mapbox import com.mapbox.mapboxsdk.maps.MapView import com.mapbox.mapboxsdk.maps.Style import com.mapbox.mapboxsdk.module.http.HttpRequestUtil import okhttp3.OkHttpClient private const val SERVICE_NAME = "geo" class MainActivity : AppCompatActivity() { private var mapView: MapView? = null override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // configuration val identityPoolId = getString(R.string.identityPoolId) val region = getString(R.string.awsRegion) val mapName = getString(R.string.mapName) // Credential initialization val credentialProvider = CognitoCachingCredentialsProvider( applicationContext, identityPoolId, Regions.fromName(identityPoolId.split(":").first()) ) // initialize MapLibre Mapbox.getInstance(this, null) HttpRequestUtil.setOkHttpClient( OkHttpClient.Builder() .addInterceptor(SigV4Interceptor(credentialProvider, SERVICE_NAME)) .build() ) // initialize the view setContentView(R.layout.activity_main) // initialize the map view mapView = findViewById(R.id.mapView) mapView?.onCreate(savedInstanceState) mapView?.getMapAsync { map -> map.setStyle( Style.Builder() .fromUri("https://maps.geo.${region}.amazonaws.com/maps/v0/maps/${mapName}/style-descriptor") ) { style -> findViewById<TextView>(R.id.attributionView).text = style.sources.first()?.attribution } } } override fun onStart() { super.onStart() mapView?.onStart() } override fun onResume() { super.onResume() mapView?.onResume() } override fun onPause() { super.onPause() mapView?.onPause() } override fun onStop() { super.onStop() mapView?.onStop() } override fun onSaveInstanceState(outState: Bundle) { super.onSaveInstanceState(outState) mapView?.onSaveInstanceState(outState) } override fun onLowMemory() { super.onLowMemory() mapView?.onLowMemory() } override fun onDestroy() { super.onDestroy() mapView?.onDestroy() } }

이 애플리케이션을 실행하면 선택한 스타일로 전체 화면 맵이 표시됩니다. 이 샘플은 의 Amazon Location Service 샘플 리포지토리의 일부로 사용할 수 있습니다GitHub.