Amazon Location Service で Android 用 Tangram ES を使用する - Amazon Location Service

翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。

Amazon Location Service で Android 用 Tangram ES を使用する

Tangram ES は、OpenGL ES を使用してベクトルデータから 2D および 3D マップをレンダリングする C++ ライブラリです。Tangram のネイティブ版です。

Tilezen スキーマで動作するように構築されたTangram スタイルは、HERE のマップを使用する場合には Amazon Location とほぼ互換性があります。具体的には次のとおりです。

  • 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 マップリソースとのみ互換性があります。

アプリケーションの構築:初期化

アプリケーションを初期化するには:

  1. [空のアクティビティ] テンプレートから新しい Android Studio プロジェクトを作成します。

  2. プロジェクト言語に [Kotlin] が選択されていることを確認します。

  3. [Minimum SDK of API 16: Android 4.1 (Jelly Bean)] 以降を選択してください。

  4. [プロジェクト構造]を開き、[ファイル]、[プロジェクト構造...] に移動します。[依存関係] セクションを選択します。

  5. [<All Modules>] を選択したら、[+] ボタンを選択して[新しいライブラリ依存関係]を追加します。

  6. [AWS Android SDK] バージョンは、2.19.1 以降を追加します。例:com.amazonaws:aws-android-sdk-core:2.19.1

  7. [Tangram] バージョンは、0.13.0 以降を追加します。例: com.mapzen.tangram:tangram:0.13.0

    注記

    [Tangram] の検索:com.mapzen.tangram:tangram:0.13.0 は、「見つかりません」というメッセージを表示しますが、[OK] を選択すると追加できます。

アプリケーションの構築:設定

アプリケーションにリソースと AWS リージョンをを設定するには:

  1. app/src/main/res/values/configuration.xml を作成します。

  2. リソースの名前と ID、および 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 を追加してください。

これにより、マップの初期中心点も設定されます。

注記

使用する各データプロバイダーのワードマークまたはテキストアトリビューションを、アプリケーションまたはドキュメントに記載する必要があります。アトリビューション文字列は、スタイル記述子のレスポンスのsources.esri.attributionsources.here.attributionsource.grabmaptiles.attribution キーに含まれています。

Tangram はこれらのリソースをリクエストせず、HERE のマップとのみ互換性があるため、「© 2020 HERE」を使用してください。Amazon Location リソースをデータプロバイダーと併用する場合は、サービスの利用規約を必ずお読みください。

<?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>

アプリケーションの構築:リクエスト変換

SigV4Interceptor リクエストをインターセプトし、署名バージョン 4 を使用して署名する AWS という名前のクラスを作成します。この情報は、メインアクティビティの作成時にマップリソースの取得に使用される 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 をインスタンス化します。

  • 署名バージョン 4をインターセプターとして登録します。

  • マップスタイルを指定してマップを構成し、タイルの URL をオーバーライドして、適切なアトリビューションを表示します。

また、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