コンテンツにスキップ

チュートリアル

このチュートリアルでは、MapConductor Android SDK を使って、地図を表示し、マーカーや図形を追加し、ユーザーインタラクションを処理する方法を学びます。

このチュートリアルで学べること

Section titled “このチュートリアルで学べること”
  • MapConductor SDK のインストールと初期設定
  • 地図を表示する方法
  • マーカー、円、ポリラインなどの追加方法
  • ユーザーのタップやクリックイベントの処理
  • カメラ位置の制御
  • 地図SDKの切り替え方法
  • Android Studio がインストールされていること
  • Jetpack Compose の基本的な知識
  • Kotlin の基礎知識

ステップ1: プロジェクトのセットアップ

Section titled “ステップ1: プロジェクトのセットアップ”

モジュールレベルの build.gradle.kts または build.gradle に MapConductor の依存関係を追加します。

dependencies {
val mapconductorVersion = "1.1.3"
// BOM を利用してバージョンを統一
implementation(platform("com.mapconductor:mapconductor-bom:$mapconductorVersion"))
// コアモジュール(必須)
implementation("com.mapconductor:core")
// Google Maps を使う場合
implementation("com.mapconductor:for-googlemaps")
// または Mapbox を使う場合
// implementation("com.mapconductor:for-mapbox")
// または HERE Maps を使う場合
// implementation("com.mapconductor:for-here")
// または ArcGIS を使う場合
// implementation("com.mapconductor:for-arcgis")
// または MapLibre を使う場合
// implementation("com.mapconductor:for-maplibre")
}

build.gradle.kts または build.gradle に以下の設定を追加します。

plugin {
id("org.jetbrains.kotlin.plugin.compose:1.9.25")
id("org.jetbrains.kotlin.android:1.9.25")
}
android {
compileSdk = 35
defaultConfig {
minSdk = 26
targetSdk = 35
}
buildFeatures {
compose = true
}
composeOptions {
kotlinCompilerExtensionVersion =
project.property("1.9.25").toString()
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
kotlinOptions {
jvmTarget = "17"
}
}

重要: MapConductor は既存の地図 SDK の上に統一 API レイヤーを提供するライブラリです。そのため、MapConductor を利用する前に、各地図 SDK を個別にセットアップする必要があります。

各地図SDKは、それぞれ API キー、パーミッション、設定などの準備が必要です。

ステップ2: シンプルな地図の表示

Section titled “ステップ2: シンプルな地図の表示”

まずは、最もシンプルな地図を表示してみましょう。 これで、東京を中心とした地図が表示されます。

import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import com.mapconductor.core.GeoPoint
import com.mapconductor.core.MapCameraPosition
import com.mapconductor.googlemaps.GoogleMapView
import com.mapconductor.googlemaps.rememberGoogleMapViewState
@Composable
fun MyFirstMap(modifier: Modifier = Modifier) {
// 東京の座標
val tokyo = GeoPoint.fromLatLong(35.6812, 139.7671)
// 初期カメラ位置
val initialCamera = MapCameraPosition(
position = tokyo,
zoom = 12
)
// 状態管理
val mapViewState = rememberGoogleMapViewState(
cameraPosition = initialCamera
)
// 地図表示
GoogleMapView(
modifier = modifier,
state = mapViewState
)
}

実行結果 Note: デモを見やすくするために、地図のデザインをデフォルトから変更しています

これで、東京を中心とした地図が表示されます。

ステップ3: マーカーを追加する

Section titled “ステップ3: マーカーを追加する”

地図上にマーカーを表示してみましょう。

import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import com.mapconductor.core.*
import com.mapconductor.googlemaps.GoogleMapView
import com.mapconductor.googlemaps.rememberGoogleMapViewState
@Composable
fun MapWithMarkers(modifier: Modifier = Modifier) {
// 座標
val marker1 = GeoPoint.fromLatLong(35.6586, 139.7454)
val marker2 = GeoPoint.fromLatLong(35.7101, 139.8107)
// 初期位置
val initialCamera = MapCameraPosition(
position = GeoPoint.fromLatLong(35.6586, 139.7454),
zoom = 11
)
val mapViewState = rememberGoogleMapViewState(
cameraPosition = initialCamera
)
val onMarkerClick: (MarkerState) -> Unit = { markerState ->
println("マーカークリック時の処理${markerState.extra}")
}
GoogleMapView(
modifier = modifier.fillMaxSize(),
state = mapViewState
) {
// マーカーの追加
Marker(
position = marker1,
icon = DefaultIcon(label = "Tokyo Tower"),
extra = "marker1",
onClick = onMarkerClick
)
Marker(
position = marker2,
icon = DefaultIcon(label = "Sky Tree"),
extra = "marker2",
onClick = onMarkerClick
)
}
}

実行結果 Note: デモを見やすくするために、地図のデザインをデフォルトから変更しています

マーカーをさらにカスタマイズすることもできます。

Marker(
position = GeoPoint.fromLatLong(35.6586, 139.7454),
icon = DefaultIcon(
label = "TT",
backgroundColor = Color.Red,
textColor = Color.White
),
extra = "tokyo_tower",
anchor = Offset(0.5f, 1.0f) // アンカー情報
)

ステップ4: 円とポリラインを追加する

Section titled “ステップ4: 円とポリラインを追加する”

マーカーの周りに円を描画してみましょう。

import androidx.compose.ui.graphics.Color
GoogleMapView(
modifier = modifier.fillMaxSize(),
state = mapViewState
) {
// マーカー
Marker(
position = GeoPoint.fromLatLong(35.6586, 139.7454),
icon = DefaultIcon(label = "TT"),
extra = "tokyo_tower"
)
// 円を描画
Circle(
center = GeoPoint.fromLatLong(35.6586, 139.7454),
radiusMeters = 1000, // 半径(メートル)
strokeColor = Color.Blue,
strokeWidth = 3.dp, // 線幅(dp)
fillColor = Color.Blue.copy(alpha = 0.2f)
)
}

実行結果 Note: デモを見やすくするために、地図のデザインをデフォルトから変更しています

2つのポイントを線で結んでみましょう。

GoogleMapView(
modifier = modifier.fillMaxSize(),
state = mapViewState
) {
// マーカー
Marker(position = GeoPoint.fromLatLong(35.6586, 139.7454), icon = DefaultIcon(label = "TT"))
Marker(position = GeoPoint.fromLatLong(35.7101, 139.8107), icon = DefaultIcon(label = "ST"))
// 線を描画
Polyline(
points = listOf(
GeoPoint.fromLatLong(35.6586, 139.7454),
GeoPoint.fromLatLong(35.7101, 139.8107)
),
strokeColor = Color.Red,
strokeWidth = 5.dp
)
}

実行結果 Note: デモを見やすくするために、地図のデザインをデフォルトから変更しています

ステップ5: ユーザーインタラクションを処理する

Section titled “ステップ5: ユーザーインタラクションを処理する”

ユーザーが地図をタップしたときの処理を追加できます。

import androidx.compose.runtime.*
@Composable
fun InteractiveMap(modifier: Modifier = Modifier) {
var clickedPosition by remember { mutableStateOf<GeoPointInterface?>(null) }
val initialCamera = MapCameraPosition(
position = GeoPoint.fromLatLong(35.6812, 139.7671),
zoom = 12
)
val mapViewState = rememberGoogleMapViewState(
cameraPosition = initialCamera
)
GoogleMapView(
modifier = modifier.fillMaxSize(),
state = mapViewState,
onMapClick = { geoPoint ->
// 地図をクリック
clickedPosition = geoPoint
println("クリック位置${geoPoint.latitude}, ${geoPoint.longitude}")
}
) {
// マーカーを表示
clickedPosition?.let { position ->
Marker(
position = position,
icon = DefaultIcon(label = "!"),
extra = "clicked_marker"
)
}
}
}

Note: デモを見やすくするために、地図のデザインをデフォルトから変更しています

5-2. マーカーのクリックイベント

Section titled “5-2. マーカーのクリックイベント”
val marker1 = GeoPoint.fromLatLong(35.6586, 139.7454)
val marker2 = GeoPoint.fromLatLong(35.7101, 139.8107)
GoogleMapView(
modifier = modifier.fillMaxSize(),
state = mapViewState
) {
Marker(
position = marker1,
icon = DefaultIcon(label = "TT"),
extra = "marker1",
onClick = { markerState ->
// マーカークリック時の処理
markerState.animate(MarkerAnimation.Drop)
}
)
Marker(
position = marker2,
icon = DefaultIcon(label = "ST"),
extra = "marker2",
onClick = { markerState ->
// マーカークリック時の処理
markerState.animate(MarkerAnimation.Bounce)
}
)
}

Note: デモを見やすくするために、地図のデザインをデフォルトから変更しています

6-1. ボタンで特定の位置に移動する

Section titled “6-1. ボタンで特定の位置に移動する”
import androidx.compose.foundation.layout.*
import androidx.compose.material3.Button
import androidx.compose.material3.Text
import androidx.compose.runtime.rememberCoroutineScope
import kotlinx.coroutines.launch
@Composable
fun MapWithCameraControl(modifier: Modifier = Modifier) {
val marker1 = GeoPoint.fromLatLong(35.6586, 139.7454)
val marker2 = GeoPoint.fromLatLong(35.7101, 139.8107)
val mapViewState = rememberGoogleMapViewState(
cameraPosition = MapCameraPosition(
position = marker1,
zoom = 12.0
)
)
val scope = rememberCoroutineScope()
Column(modifier = modifier.fillMaxSize()) {
// ボタン
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceEvenly
) {
Button(onClick = {
scope.launch {
mapViewState.moveCameraTo(
MapCameraPosition(
position = marker1,
zoom = 15
),
durationMillis = 1000
)
}
}) {
Text("Tokyo Tower")
}
Button(onClick = {
scope.launch {
mapViewState.moveCameraTo(
MapCameraPosition(
position = marker2,
zoom = 15
),
durationMillis = 1000
)
}
}) {
Text("Sky Tree")
}
}
// 地図
GoogleMapView(
modifier = Modifier.fillMaxSize(),
state = mapViewState
) {
Marker(position = marker1, icon = DefaultIcon(label = "TT"))
Marker(position = marker2, icon = DefaultIcon(label = "ST"))
}
}
}

6-2. カメラの移動イベントを監視する

Section titled “6-2. カメラの移動イベントを監視する”
GoogleMapView(
modifier = modifier.fillMaxSize(),
state = mapViewState,
onCameraMoveStart = {
println("カメラの移動が開始されました")
},
onCameraMove = { cameraPosition ->
println("カメラ位置: ${cameraPosition.position.latitude}, ${cameraPosition.position.longitude}")
},
onCameraMoveEnd = {
println("カメラの移動が終了しました")
}
) {
// マーカーなど
}

ステップ7: 地図SDKを切り替える

Section titled “ステップ7: 地図SDKを切り替える”

MapConductor の最大の利点は、わずかな変更で地図SDKを切り替えられることです。

Google Maps から Mapbox への切り替え

Section titled “Google Maps から Mapbox への切り替え”
import com.mapconductor.googlemaps.GoogleMapView
import com.mapconductor.googlemaps.rememberGoogleMapViewState
@Composable
fun MyMap() {
val mapViewState = rememberGoogleMapViewState(
cameraPosition = initialCamera
)
GoogleMapView(
state = mapViewState
) {
// マーカーやその他のコンポーネント
}
}

マーカーや円、ポリラインなどのコンポーネントは、まったく同じコードで動作します。

地図SDKMapViewStateInterfaceMapView
Google MapsrememberGoogleMapViewStateGoogleMapView
MapboxrememberMapboxViewStateMapboxMapView
HERE MapsrememberHereMapViewStateHereMapView
ArcGISrememberArcGISMapViewStateArcGISMapView
MapLibrerememberMapLibreViewStateMapLibreMapView

これまで学んだことをまとめた、完全なサンプルコードです。

import androidx.compose.foundation.layout.*
import androidx.compose.material3.Button
import androidx.compose.material3.Text
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
import com.mapconductor.core.*
import com.mapconductor.googlemaps.GoogleMapView
import com.mapconductor.googlemaps.rememberGoogleMapViewState
import kotlinx.coroutines.launch
@Composable
fun CompleteSample(modifier: Modifier = Modifier) {
val context = LocalContext.current
// 位置情報
val marker1 = GeoPoint.fromLatLong(35.6586, 139.7454)
val marker2 = GeoPoint.fromLatLong(35.7101, 139.8107)
// クリックされた位置を保存
var clickedPosition by remember { mutableStateOf<GeoPointInterface?>(null) }
val initialCamera = MapCameraPosition(
position = GeoPoint.fromLatLong(35.6812, 139.7671),
zoom = 12.0
)
val mapViewState = rememberGoogleMapViewState(
cameraPosition = initialCamera
)
val scope = rememberCoroutineScope()
val onMarkerClick: (MarkerState) -> Unit = { markerState ->
Toast
.makeText(
context,
"clicked: ${markerState.extra}",
Toast.LENGTH_SHORT,
)
.show()
}
Column(modifier = modifier.fillMaxSize()) {
// コントロールボタン
Row(
modifier = Modifier
.fillMaxWidth()
.padding(8.dp),
horizontalArrangement = Arrangement.SpaceEvenly
) {
Button(onClick = {
scope.launch {
mapViewState.moveCameraTo(
MapCameraPosition(position = marker1, zoom = 15.0),
durationMillis = 1000
)
}
}) {
Text("TT")
}
Button(onClick = {
scope.launch {
mapViewState.moveCameraTo(
MapCameraPosition(position = marker2, zoom = 15.0),
durationMillis = 1000
)
}
}) {
Text("ST")
}
}
// 地図
GoogleMapView(
modifier = Modifier.fillMaxSize(),
state = mapViewState,
onMapClick = { geoPoint ->
clickedPosition = geoPoint
}
) {
// マーカー
Marker(
position = marker1,
icon = DefaultIcon(
label = "TT",
fillColor = Color.Red,
),
extra = "marker1",
onClick = onMarkerClick
)
Marker(
position = marker2,
icon = DefaultIcon(
label = "ST",
fillColor = Color.Blue
),
extra = "marker2",
onClick = onMarkerClick
)
// クリックされた位置のマーカー
clickedPosition?.let { position ->
Marker(
position = position,
icon = DefaultIcon(
label = "!",
fillColor = Color.Green
),
extra = "clicked",
onClick = onMarkerClick
)
}
// 円
Circle(
center = marker1,
radiusMeters = 1000,
strokeColor = Color.Red,
fillColor = Color.Red.copy(alpha = 0.2f)
)
Circle(
center = marker2,
radiusMeters = 1000,
strokeColor = Color.Blue,
fillColor = Color.Blue.copy(alpha = 0.2f)
)
// ポリライン
Polyline(
points = listOf(marker1, marker2),
strokeColor = Color.Magenta,
strokeWidth = 3.dp
)
}
}
}

このチュートリアルで、MapConductor SDK の基本的な使い方を学びました。

さらに詳しく学びたい場合は、以下のドキュメントを参照してください:

  • API キーが正しく設定されているか確認してください
  • インターネット接続を確認してください
  • 必要な権限が AndroidManifest.xml に追加されているか確認してください
  • minSdk が 26 以上に設定されているか確認してください
  • Kotlin と Compose のバージョンが互換性があるか確認してください
  • 依存関係が正しく追加されているか確認してください
  • MarkerState.onClick が正しく設定されているか確認してください
  • マーカーに extra プロパティが設定されているか確認してください