この Codelab について
1. 始める前に
この Codelab では、Google Maps Platform Navigation SDK を使用して、事前に設定された目的地にナビゲートするシンプルな Android アプリを作成する方法について説明します。
完成したアプリの外観は次のようになります。
前提条件
- Kotlin による Android アプリ開発の基本的な知識
- 地図、位置情報、座標など、Google Maps SDK の基本コンセプトをある程度理解している。
学習内容
- Navigation SDK を使用して目的地に移動するシンプルな Android アプリを作成する方法。
- リモートの Google Maven リポジトリから Navigation SDK を統合する方法
- Navigation SDK のエンドユーザー規約で位置情報の利用許可とユーザーの同意を管理する方法
- SDK を初期化する方法
- 目的地を設定してナビゲーション ガイダンスを開始する方法。
必要なもの
- Android Studio の最新の安定版がインストールされている。この Codelab は Android Studio Jellyfish を使用して作成されています。別のバージョンを使用している場合、インターフェースとコンポーネントの外観とレイアウトが異なる場合があります。
- 課金が有効になっている Google アカウントとプロジェクト。
- USB デバッグを有効にした開発者モードの Android デバイス、または Android エミュレータ。どちらを選択する場合でも、Navigation SDK の最小要件を満たす必要があります。
2. セットアップする
課金を有効にした Google Cloud Platform アカウントとプロジェクトをまだ作成していない場合は、Google Maps Platform スタートガイドの手順に沿って Google Cloud プロジェクトを設定してください(https://developers.google.com/maps/gmp-get-started)。
コンソールで Google Cloud プロジェクトを選択します。
Cloud Console で、プロジェクトのプルダウン メニューをクリックし、この Codelab に使用するプロジェクトを選択します。
プロジェクトで Navigation SDK を有効にする
Google Cloud Marketplace で、この Codelab に必要な Google Maps Platform API と SDK を有効にします。
Google Cloud コンソールで、[API とサービス] > [ライブラリ] に移動し、「Navigation SDK」を検索します。
検索結果が 1 つ表示されます。
Navigation SDK の結果をクリックして、プロダクトの詳細ページを開きます。[有効にする] ボタンをクリックして、プロジェクトで SDK を有効にします。
Google Maps SDK for Android でもこのプロセスを繰り返します。
API キーを作成する
Cloud Console の [認証情報] ページで API キーを生成します。Google Maps Platform スタートガイドのクイックスタート セクションのステップ 3 の手順に沿って操作します。Google Maps Platform へのすべてのリクエストで API キーが必要になります。
3. サンプル プロジェクト ファイルを取得する
このセクションでは、この Codelab の GitHub リポジトリからファイルのクローンを作成して、基本的な空の Android Studio プロジェクトをセットアップする方法について説明します。GitHub リポジトリには、Codelab コードの前後のバージョンが含まれています。この Codelab は、空のプロジェクト テンプレートを使用して開始し、最終的に作成した状態にします。行き詰まった場合は、リポジトリ内の完成したプロジェクトを参照できます。
この GitHub リポジトリのクローンを作成して、この Codelab のコードを取得します。
git clone https://github.com/googlemaps-samples/codelab-navigation-101-android-kotlin.git
git がインストールされていない場合は、次のボタンをクリックしてコードを取得します。
できるだけ早く開始できるように、リポジトリの Starter
フォルダには、この Codelab の学習に役立つスターター コードが含まれています。スターター プロジェクトは、基本的なアプリ UI とビルド構成を提供しますが、Navigation SDK は追加されていません。また、Solution
プロジェクトも完成しているので、いつでもここで作業を進めたり、進捗状況を確認したりできます。
Android Studio でクローン リポジトリを開く
リポジトリのクローンをローカルに作成したら、Android Studio を使用して、既存のプロジェクトとして Starter
フォルダを開きます。
- [Welcome to Android Studio] ダイアログで、[Open] ボタンをクリックします。
- クローン リポジトリを保存したフォルダに移動し、最上位の「
codelab-navigation-101-android-kotlin
」内のStarter
フォルダを選択します。フォルダに配置されます。 - プロジェクトがビルドされ、実行されることを確認します。
仮想デバイスを追加するか、ハードウェア デバイスを接続する
Android デバイスをパソコンに接続するには、Android Studio のハードウェア デバイス上でのアプリの実行の手順に沿って操作します。または、Android Virtual Device(AVD)Manager を使用して仮想デバイスを設定することもできます。エミュレータを指定する際は、Google API を含むイメージを選択する必要があります。
Android Studio で [Run] メニュー オプションまたはプレイボタン アイコンをクリックします。表示される指示に沿ってデバイスを選択します。
4. アプリに Navigation SDK を追加する
Navigation SDK ライブラリと API キーをプロジェクトに追加する
アプリに Navigation SDK ライブラリを追加するには、アプリレベル の build.gradle.kts
を変更して Google Maven リポジトリから Navigation SDK を取得し、バージョン番号を設定する必要があります。
Navigation SDK のバージョン番号を格納する変数をビルド構成で作成します。
アプリで使用する Navigation SDK のバージョンの値を格納する変数をアプリレベルの build.gradle.kts
でセットアップします。これにより、後で最新バージョンに簡単に変更できます。
最新のバージョン番号については、Navigation SDK リリースノートをご覧ください。
val navSdkVersion by extra("6.0.0")
[ファイル] > [ファイル] にあるダイアログを使用して、この変数や他の変数の値を変更することもできます。プロジェクト構造 >変数:
ビルド構成に依存関係を追加する
次に、アプリレベルの build.gradle.kts.
の依存関係ブロックに次の API 依存関係を追加します。使用されるバージョンは、アプリレベルの build.gradle.kts
で設定した ${navSdkVersion}
の値になります。
dependencies {
// Include the Google Navigation SDK.
api("com.google.android.libraries.navigation:navigation:${navSdkVersion}")
...
API キーを追加する
Secrets Gradle プラグインを使用して API キーを管理する
アプリで API キーを安全に管理するには、Secrets Gradle プラグインを使用することをおすすめします。このプラグインは、最上位の build.gradle.kts
ファイルの依存関係として初期プロジェクト テンプレートに追加されています。
// Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins {
id("com.google.android.libraries.mapsplatform.secrets-gradle-plugin") version "2.0.1" apply false
//... other plugin definitions here
}
最上位レベルのディレクトリで secrets.properties
ファイルを開き、YOUR_API_KEY
を API キーに置き換えます。secrets.properties
はバージョン管理システムにチェックインされないため、このファイルにキーを保存します。
MAPS_API_KEY=YOUR_API_KEY
このトピックについて詳しくは、Navigation SDK ドキュメントのアプリに API キーを追加するをご覧ください。
local.defaults.properties の内容を確認する
また、空のプロジェクトの最上位ディレクトリ(secrets.properties
ファイルと同じフォルダ)に local.defaults.properties
ファイルが含まれます。開いて、次のコードを確認します。
MAPS_API_KEY=DEFAULT_API_KEY
これは、secrets.properties
がプロジェクトに追加されていない場合に MAPS_API_KEY
プロパティのバックアップ値を提供し、ビルドが失敗しないようにするために存在します。このファイルを編集する必要はありません。MAPS_API_KEY
の secrets.properties
定義が見つからない場合、デフォルト値により、API キーエラーでアプリの実行がランタイムで停止します。
Android マニフェストで指定した API キーが使用されていることを確認する
app/src/main/AndroidManifest.xml を開きます。MAPS_API_KEY
プロパティは、アプリケーションの API キーの設定に使用されています。
<meta-data
android:name="com.google.android.geo.API_KEY"
android:value="${MAPS_API_KEY}" />
アプリレベルの build.gradle.kts
ファイルを開き、secrets
プロパティを見つけます。
プラグインの propertiesFileName
設定は secrets.properties
に設定し、defaultPropertiesFileName
は local.defaults.properties
に設定する必要があります。
secrets {
// Optionally specify a different file name containing your secrets.
// The plugin defaults to "local.properties"
propertiesFileName = "secrets.properties"
// A properties file containing default secret values. This file can be
// checked in version control.
defaultPropertiesFileName = "local.defaults.properties"
}
すべてのファイルを保存して、プロジェクトを Gradle と同期します。
5. アプリの権限を設定し、基本的な UI を追加する
正確な位置情報の利用許可をリクエストする
Navigation SDK は GPS 信号に依存して機能するため、アプリは正確な位置情報へのアクセスを許可するようユーザーに求める必要があります。正確な位置情報にアクセスする権限を、AndroidManifest.xml の <manifest>
要素の子要素として追加します。
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" >
<uses-permission
android:name="android.permission.ACCESS_FINE_LOCATION"
/>
</manifest>
Android の位置情報へのアクセス権について詳しくは、Android デベロッパー向けドキュメントの位置情報へのアクセス権をリクエストするをご覧ください。
Android 14 デバイスでアプリを実行するには、正確な位置情報へのアクセス権限と同じ場所に次の uses-permission
タグを追加して、フォアグラウンド サービスの位置情報の利用許可をリクエストします。
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_LOCATION" />
基本的な UI を使用して起動アクティビティを追加する
アプリの実行時に、起動時に実行されるコードが必要になります。このコードは、ユーザーが位置情報へのアクセスを許可しているかどうかを確認し、考えられるシナリオごとに処理し、まだ許可されていない場合は権限をリクエストします。そのためには、アプリに基本的なユーザー インターフェースを追加します。この Codelab では、Android Studio で新しい空のビュー アクティビティを作成するときに作成される UI を使用します。これを変更して、ナビゲーション UI のアクティビティにコードを追加する前に、位置情報の利用許可チェックを実行します。
コードエディタで MainActivity.kt
ファイルを開き、コードを確認します。基本的な UI が表示されます。
実行時に位置情報へのアクセス権限をリクエストする
アプリは、Navigation SDK を初期化する前に、正確な位置情報にアクセスするリクエストをトリガーする必要があります。
アプリの起動時にこのチェックが行われるようにするには、アクティビティのオーバーライドされた onCreate()
メソッドの MainActivity
クラスにコードを追加します。
ユーザーが精度の高い位置情報の利用許可を付与しているかどうかは、次のコードで確認できます。許可されていない場合は、権限をリクエストします。このコードを onCreate()
メソッド内に追加します。
val permissions =
if (VERSION.SDK_INT >= VERSION_CODES.TIRAMISU) {
arrayOf(permission.ACCESS_FINE_LOCATION, permission.POST_NOTIFICATIONS)
} else {
arrayOf(permission.ACCESS_FINE_LOCATION)
}
if (permissions.any { !checkPermissionGranted(it) }) {
if (permissions.any { shouldShowRequestPermissionRationale(it) }) {
// Display a dialogue explaining the required permissions.
}
val permissionsLauncher =
registerForActivityResult(
RequestMultiplePermissions(),
{ permissionResults ->
if (permissionResults.getOrDefault(permission.ACCESS_FINE_LOCATION, false)) {
onLocationPermissionGranted()
} else {
finish()
}
},
)
permissionsLauncher.launch(permissions)
} else {
android.os.Handler(Looper.getMainLooper()).postDelayed({ onLocationPermissionGranted() }, SPLASH_SCREEN_DELAY_MILLIS)
}
}
private fun checkPermissionGranted(permissionToCheck: String): Boolean =
ContextCompat.checkSelfPermission(this, permissionToCheck) == PackageManager.PERMISSION_GRANTED
MainActivity
クラスに onLocationPermissionGranted
という新しい関数を追加します。この関数は、ユーザーが位置情報の共有を許可した場合の結果を処理します。次の手順では、新しいナビゲーション アクティビティを起動するコードをここに追加します。
private fun onLocationPermissionGranted() {
//code to initialize Navigation SDK will go here
}
プロジェクトをビルドします。ビルドエラーがある場合は、エラーを見つけて修正します。
新しい仮想デバイスでプロジェクトを実行します。アプリがインストールされて起動すると、権限リクエスト ダイアログが表示されます。
6. ナビゲーション ユーザー インターフェースを追加する
ナビゲーション UI を追加するには、SupportNavigationFragment
または NavigationView
の 2 つの方法があります。
わかりやすくするために、この Codelab では NavigationView
を使用します。
レイアウトを編集する
res/layout/activity_main.xml
を編集して、NavigationView のレイアウトを追加します。
- ファイルを開き、コードビューに切り替えます。
- ファイルの内容全体を、次の例のように
RelativeLayout
内のNavigationView
の新しいレイアウトに置き換えます。アプリにナビゲーション ビューを追加するだけなので、シンプルなレイアウトで対処します。 - NavigationView に ID「
@+id/navigation_view
」を指定します。
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.libraries.navigation.NavigationView
android:id="@+id/navigation_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
</RelativeLayout>
ナビゲーション アクティビティを設定する
Android Studio のエディタで MainActivity.kt ファイルを開きます。
アプリでナビゲーション エクスペリエンスが正しく機能するように、基本的なセットアップ コードを追加します。MainActivity.kt ファイルに次の変更を加えます。
MainActivity
クラスで変数を宣言してNavigationView
を参照します。
private lateinit var navView: NavigationView
onCreate()
メソッドにコードを追加して、NavigationView
への参照を取得します。
navView = findViewById(R.id.navigation_view)
navView.onCreate(savedInstanceState)
- ナビゲーション ガイダンス中に画面がオンのままになるように、
onCreate()
メソッドにコードを追加します。
// Ensure the screen stays on during nav.
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
ViewCompat.setOnApplyWindowInsetsListener
を呼び出すコードを編集して、NavigationView
の ID を参照します。
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.navigation_view)) { v, insets ->
val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
insets
}
showToast()
メソッドをクラスに追加して、ユーザーにフィードバックを表示します。
private fun showToast(errorMessage: String) {
Toast.makeText(this@MainActivity, errorMessage, Toast.LENGTH_LONG).show()
}
7. Navigation SDK を初期化する
基本的な Navigation アクティビティのセットアップが完了したので、Navigation SDK を初期化することができます。そのために、MainActivity.kt ファイルに次のコードを追加します。
/** Starts the Navigation API, capturing a reference when ready. */
@SuppressLint("MissingPermission")
private fun initializeNavigationApi() {
NavigationApi.getNavigator(
this,
object : NavigatorListener {
override fun onNavigatorReady(navigator: Navigator) {
// store a reference to the Navigator object
mNavigator = navigator
// code to start guidance will go here
}
override fun onError(@NavigationApi.ErrorCode errorCode: Int) {
when (errorCode) {
NavigationApi.ErrorCode.NOT_AUTHORIZED -> {
// Note: If this message is displayed, you may need to check that
// your API_KEY is specified correctly in AndroidManifest.xml
// and is been enabled to access the Navigation API
showToast(
"Error loading Navigation API: Your API key is " +
"invalid or not authorized to use Navigation."
)
}
NavigationApi.ErrorCode.TERMS_NOT_ACCEPTED -> {
showToast(
"Error loading Navigation API: User did not " +
"accept the Navigation Terms of Use."
)
}
else -> showToast("Error loading Navigation API: $errorCode")
}
}
},
)
}
このコードは、initializeNavigationApi()
という名前の新しいメソッドを作成します。このメソッドは、NavigationApi.getNavigator()
を呼び出して Navigator
オブジェクトへの参照を取得し、コールバックを処理する NavigatorListener
を実装します。
Navigation API が初期化されると、NavigationListener.onNavigatorReady
メソッドが呼び出され、Navigator
オブジェクトがパラメータとして渡されます。上記のコードは、前に宣言した mNavigator
変数を、このメソッドに渡された初期化された Navigator
オブジェクトで更新します。
最後に、onLocationPermissionGranted
メソッドから initializeNavigationApi
メソッドの呼び出しを追加します。
private fun onLocationPermissionGranted() {
initializeNavigationApi()
}
8. 重要なナビゲーション イベントのリスナーを追加する
ユーザーがガイダンスに従うと、Navigation SDK によってイベントが起動され、ユーザーがルートを変更したときや目的地に到着したときなど、ルート上の主要な状態の変化をアプリに通知できます。MainActivity.kt ファイルに、以下のイベントを処理するリスナーを追加します。
MainActivity
クラス内で、イベント リスナー オブジェクトを参照する 2 つの変数を宣言します。
private var arrivalListener: Navigator.ArrivalListener? = null
private var routeChangedListener: Navigator.RouteChangedListener? = null
- ナビゲータの初期化時にリスナーを設定する
registerNavigationListeners()
メソッドを追加しました。このメソッドは、Arrival イベントが発生したときにNavigator.clearDestinations()
を呼び出してNavigationView
をリセットします。
/**
* Registers a number of example event listeners that show an on screen message when certain
* navigation events occur (e.g. the driver's route changes or the destination is reached).
*/
private fun registerNavigationListeners() {
withNavigatorAsync {
arrivalListener =
Navigator.ArrivalListener { // Show an onscreen message
showToast("User has arrived at the destination!")
mNavigator?.clearDestinations()
}
mNavigator?.addArrivalListener(arrivalListener)
routeChangedListener =
Navigator.RouteChangedListener { // Show an onscreen message when the route changes
showToast("onRouteChanged: the driver's route changed")
}
mNavigator?.addRouteChangedListener(routeChangedListener)
}
}
initializeNavigationApi
メソッドのonNavigatorReady
コールバック コードからregisterNavigationListeners()
の呼び出しを追加します。
override fun onNavigatorReady(navigator: Navigator) {
// store a reference to the Navigator object
mNavigator = navigator
//listen for events en route
registerNavigationListeners()
}
- ユーザー インターフェースを構成します。ナビゲーション ユーザー インターフェースのさまざまな要素は、ガイダンスの実行中に制御できます。重要なカスタマイズのひとつがカメラの位置です。次のように、
onNavigatorReady
で返されるnavigator
オブジェクトのsetTaskRemovedBehaviour
メソッドの呼び出しを追加します。アプリがスワイプされると、ガイダンスと通知が終了します。
// Disables the guidance notifications and shuts down the app and background service
// when the user dismisses/swipes away the app from Android's recent tasks.
navigator.setTaskRemovedBehavior(Navigator.TaskRemovedBehavior.QUIT_SERVICE)
GoogleMap.followMyLocation
の呼び出しを追加してCameraPerspective
を指定します。GoogleMap
には、次のようにNavigatorView.getMapAsync()
メソッドを介してアクセスします。
navView.getMapAsync {
googleMap ->
googleMap.followMyLocation(GoogleMap.CameraPerspective.TILTED)
}
- アプリのライフサイクル全体でナビゲーションがスムーズに機能するようにするには、
MainActivity
クラスに次のメソッドを実装します。
override fun onSaveInstanceState(savedInstanceState: Bundle) {
super.onSaveInstanceState(savedInstanceState)
navView.onSaveInstanceState(savedInstanceState)
}
override fun onTrimMemory(level: Int) {
super.onTrimMemory(level)
navView.onTrimMemory(level)
}
override fun onStart() {
super.onStart()
navView.onStart()
}
override fun onResume() {
super.onResume()
navView.onResume()
}
override fun onPause() {
navView.onPause()
super.onPause()
}
override fun onConfigurationChanged(configuration: Configuration) {
super.onConfigurationChanged(configuration)
navView.onConfigurationChanged(configuration)
}
override fun onStop() {
navView.onStop()
super.onStop()
}
override fun onDestroy() {
navView.onDestroy()
withNavigatorAsync {
// Unregister event listeners to avoid memory leaks.
if (arrivalListener != null) {
navigator.removeArrivalListener(arrivalListener)
}
if (routeChangedListener != null) {
navigator.removeRouteChangedListener(routeChangedListener)
}
navigator.simulator?.unsetUserLocation()
navigator.cleanup()
}
super.onDestroy()
}
9. 宛先を設定する
これで、目的地を設定してナビゲーション ガイダンスを開始する準備が整いました。MainActivity.kt ファイルに次の変更を加えます。
- ナビゲーション デスティネーションを設定し、
placeId
パラメータを受け入れる新しいnavigateToPlace()
メソッドを追加します。
/**
* Requests directions from the user's current location to a specific place (provided by the
* Place ID).
*/
private fun navigateToPlace(placeId: String) {
}
navigateToPlace()
メソッドで、Waypoint.builder()
メソッドを使用して、メソッドに渡されたプレイス ID からWaypoint
を作成します。プレイス ID が正確な住所に解決されない場合にスローされるUnsupportedPlaceIdException
を処理します。
val waypoint: Waypoint? =
// Set a destination by using a Place ID (the recommended method)
try {
Waypoint.builder().setPlaceIdString(placeId).build()
} catch (e: Waypoint.UnsupportedPlaceIdException) {
showToast("Place ID was unsupported.")
return
}
- 次のコードを
navigateToPlace()
メソッドに追加して、Waypoint を使用してデスティネーションを設定します。
val pendingRoute = mNavigator?.setDestination(waypoint)
// Set an action to perform when a route is determined to the destination
pendingRoute?.setOnResultListener { code ->
when (code) {
RouteStatus.OK -> {
// Code to start guidance will go here
}
RouteStatus.ROUTE_CANCELED -> showToast("Route guidance canceled.")
RouteStatus.NO_ROUTE_FOUND,
RouteStatus.NETWORK_ERROR ->
// TODO: Add logic to handle when a route could not be determined
showToast("Error starting guidance: $code")
else -> showToast("Error starting guidance: $code")
}
}
Navigator
オブジェクトには、さまざまなパラメータを取ることができる setDestinations()
メソッドがあります。最も基本的な方法は、Waypoint
を指定することです。デフォルトの移動手段は DRIVING
で、4 輪車に適しています。setDestinations()
メソッドは、RouteStatus
オブジェクトを含む ListenableResultFuture
オブジェクトを返します。RouteStatus
は、宛先へのルートが見つかっているかどうかを示し、見つからない場合はさまざまなエラー状態を処理できます。
- ナビゲーションのユーザー エクスペリエンスを向上させるために、さらに設定を変更します。
// Hide the toolbar to maximize the navigation UI
supportActionBar?.hide()
// Enable voice audio guidance (through the device speaker)
mNavigator?.setAudioGuidance(Navigator.AudioGuidance.VOICE_ALERTS_AND_GUIDANCE)
// Simulate vehicle progress along the route (for demo/debug builds)
if (BuildConfig.DEBUG) {
mNavigator?.simulator?.simulateLocationsAlongExistingRoute(
SimulationOptions().speedMultiplier(5f)
)
}
主な変更点は次のとおりです。
- アクションバーを非表示にしてナビゲーション UI のスペースを最大化する。
- 音声案内を有効にして、アラートやナビゲーションの指示を読み上げます。
- 速度の乗数を指定して、デバッグ用のシミュレータを設定する。
- 目的地として使用するプレイス ID を見つけます。理想的には、ユーザーの位置情報からそれほど離れていない場所に設定します。Google Maps Platform の Place ID Finder ユーティリティを使用するか、Places API 呼び出しでプレイス ID を取得します。
ナビゲーションをシミュレートする場合は、ユーザーの位置情報をコードで設定するか、接続されたデバイスから取得できます。この Codelab では、英国のロンドンの場所をシミュレートすることを前提としています。
- 開始位置とプレイス ID を格納するコンパニオン オブジェクトを
MainActivity
クラスに追加します。この Codelab では、ロンドンの出発地とトラファルガー広場のプレイス ID を使用します。
companion object{
const val TRAFALGAR_SQUARE ="ChIJH-tBOc4EdkgRJ8aJ8P1CUxo" //London, UK
val startLocation = LatLng(51.345678, -0.1234456)
}
initializeNavigationApi
メソッド内のonNavigatorReady
コールバックからnavigateToPlace()
メソッドの呼び出しを追加し、デバッグモードで実行され、ユーザーの位置情報を設定するロジックのブランチを追加します。
// Disables the guidance notifications and shuts down the app and background service
// when the user dismisses/swipes away the app from Android's recent tasks.
navigator.setTaskRemovedBehavior(Navigator.TaskRemovedBehavior.QUIT_SERVICE)
mNavigator = navigator
if (BuildConfig.DEBUG) {
mNavigator?.simulator?.setUserLocation(MainActivity.startLocation)
}
//listen for events en route
registerNavigationListeners()
navView.getMapAsync {
googleMap ->
googleMap.followMyLocation(GoogleMap.CameraPerspective.TILTED)
}
//navigate to a destination
navigateToPlace(MainActivity.TRAFALGAR_SQUARE)
10. コードをビルドして実行する
アプリを初めて実行する際は、アプリに位置情報の利用を許可し、Navigation SDK の利用規約に同意する必要があります。
注: アプリを実行すると setDestinations() メソッドが呼び出されますが、最初の 1,000 か所の目的地が使用されると料金が発生します。詳しくは、使用量と請求額をご覧ください。
場所の設定
デフォルトでは、コードで位置情報を設定するか、エミュレータのプロパティ ダイアログを使用して位置情報を設定しない限り、エミュレートされたデバイスの位置情報はカリフォルニア州マウンテンビューの Google キャンパスに設定されます。
その場合、設定した場所 ID へのルートがアプリで見つからないことがあります(デフォルトでは、オーストラリアのシドニー オペラハウスです)。これは、showToast()
メソッドによって「ルートが見つかりませんでした」というメッセージが表示されることで示されます。
開始位置をハードコードする
コード内で別の場所を設定するには、MainActivity.kt の navigateToPlace()
メソッドで、mNavigator.startGuidance()
の呼び出しの前に次の行を追加します。
mNavigator?.simulator?.setUserLocation(startLocation)
任意のデフォルトの場所でエミュレータを起動する
デバイス エミュレータで別の位置情報を設定するには、エミュレータがまだ実行されていない場合は起動し、ツールチップ「拡張コントロール」が表示されているその他アイコンをクリックします。表示されるダイアログには、[地域] のメニュー オプションがあります。
たとえば、シドニー オペラハウスの場所 ID を目的地として使用する場合は、オーストラリアのシドニーにある場所を選択します。たとえば、「ボンダイビーチ」を検索し、候補を選択して、ダイアログの右下にある [場所を保存] をクリックします。[ポイントを保存] をクリックして、保存済みのリストに場所を追加し、後で使用することもできます。
別の Place ID を目的地として設定する場合は、シミュレートするルートが現実的なルートになるように、近くの場所を選択します。また、デバッグが容易になるように、長すぎないようにします。
アプリを再起動すると、デスティネーションに移動するはずです。
12. さらに改善する
アプリ開発をさらに進めたい場合は、次のトピックを参考にしてください。
- その他のナビゲーション イベントをリッスンする。ドライバーがルートを変更した場合や、到着したときにメッセージを表示するコードを追加します。
- ナビゲーション インターフェースをカスタマイズする。
- さらに大きな問題に挑戦したい場合は、ユーザーが目的地を設定できるように Places API の Place Picker コントロールを追加してみましょう。ヒント: GitHub の Navigation SDK のデモアプリにサンプル実装が用意されています。
- Github の Navigation SDK デモアプリで使用されているアプローチを採用して、Navigator オブジェクトと GoogleMap オブジェクトを非同期で呼び出す際の問題を回避します。より複雑なアプリのシナリオでは、コードを実行してもこれらのオブジェクトの初期化が完了していないことがあります。ヒント: 非常に迅速に実装するには、MainActivity.kt ファイルの最後に InitializedNavScope クラスを追加します。