기계 번역으로 제공되는 번역입니다. 제공된 번역과 원본 영어의 내용이 상충하는 경우에는 영어 버전이 우선합니다.
Amazon Location Service로 Android용 Tangram ES 사용
Tangram ES
Tilezen 스키마
-
Bubble Wrap
– 모든 기능을 갖춘 길 찾기 스타일로, 관심 지점을 표시하는 유용한 아이콘이 포함되어 있습니다. -
Cinnabar
– 클래식한 디자인으로 일반 매핑 애플리케이션에 적합합니다. -
Refill
– Stamen Design의 획기적인 Toner 스타일에서 영감을 받아 데이터 시각화 오버레이를 위해 디자인된 미니멀한 맵 스타일입니다. -
Tron
- 의 시각적 언어로 된 스케일 변환에 대한 탐색입니다TRON. -
Walkabout
– 야외 활동에 초점을 맞춘 스타일로 하이킹이나 야외 활동에 안성맞춤입니다.
이 가이드에서는 Cinnabar라는 Tangram 스타일을 사용하여 Android용 Tangram ES를 Amazon Location과 통합하는 방법을 설명합니다. 이 샘플은 의 Amazon Location Service 샘플 리포지토리의 일부로 사용할 수 있습니다GitHub
다른 Tangram 스타일은 지형 정보를 인코딩하는 래스터 타일을 사용하는 것이 가장 좋지만, Amazon Location에서는 아직 이 기능을 지원하지 않습니다.
중요
다음 튜토리얼의 Tangram 스타일은 VectorHereContrast
스타일로 구성된 Amazon Location 맵 리소스와만 호환됩니다.
애플리케이션 빌드: 초기화
애플리케이션을 초기화하려면:
-
빈 활동 템플릿에서 새 Android 스튜디오 프로젝트를 만듭니다.
-
프로젝트 언어로 Kotlin이 선택되었는지 확인합니다.
-
Android SDK API 4.1(Jelly Bean) 이상에서 최소 16개를 선택합니다.
-
프로젝트 구조를 열어 파일, 프로젝트 구조...를 선택한 다음 종속성 섹션을 선택합니다.
-
<All Modules>를 선택한 상태에서 + 버튼을 선택하여 새 라이브러리 종속성을 추가합니다.
-
AWS Android SDK 버전 2.19.1 이상을 추가합니다. 예:
com.amazonaws:aws-android-sdk-core:2.19.1
-
Tangram 버전 0.13.0 이상을 추가합니다. 예:
com.mapzen.tangram:tangram:0.13.0
.참고
Tangram을 검색하면
com.mapzen.tangram:tangram:0.13.0
이 “not found”라는 메시지를 만들지만 확인을 선택하면 추가할 수 있습니다.
애플리케이션 빌드: 구성
리소스 및 AWS 리전으로 애플리케이션을 구성하려면:
-
app/src/main/res/values/configuration.xml
생성. -
리소스의 이름과 식별자는 물론 리소스가 생성된 AWS 리전도 입력합니다.
<?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>
애플리케이션 빌드: 활동 레이아웃
편집 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.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>
애플리케이션 빌드: 변환 요청
AWS
요청을 가로채는 이름이 SigV4Interceptor
인 클래스를 만들고 Signature Version 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 인터셉터 등록.
-
맵 스타일을 가리키고, 타일을 재정의하고URLs, 적절한 속성을 표시하여 맵을 구성합니다.
MainActivity
은 수명 주기 이벤트를 맵 보기로 전달하는 역할도 합니다.
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() } }
이 애플리케이션을 실행하면 선택한 스타일로 전체 화면 맵이 표시됩니다. 이 샘플은 의 Amazon Location Service 샘플 리포지토리의 일부로 사용할 수 있습니다GitHub