複数の目的地のルートを確認する

このガイドでは、Navigation SDK for Android を使用して、アプリ内で複数の目的地(ウェイポイント)までのルートを作成する方法について説明します。

概要

  1. 次のように Navigation SDK をアプリに統合します。 (プロジェクトを設定するを参照)
  2. アプリに SupportNavigationFragment または NavigationView を追加します。この UI 要素により、インタラクティブな地図とターンバイターン ナビゲーションの UI がアクティビティに追加されます。
  3. NavigationApi クラスを使用して SDK を初期化します。
  4. Navigator を定義して、ターンバイターン方式のナビゲーションを制御します。

    • setDestinations() を使用してデスティネーションを追加します。
    • startGuidance() でナビを開始します。
    • getSimulator() を使用すると、アプリのテスト、デバッグ、デモのために、ルート上の車両の進行状況をシミュレートできます。
  5. アプリをビルドして実行します。

コードの確認

ナビゲーション フラグメントを追加する

SupportNavigationFragment は、インタラクティブな地図やターンバイターンの経路案内など、ナビゲーションの視覚的な出力を表示する UI コンポーネントです。フラグメントは、次のように XML レイアウト ファイルで宣言できます。

<?xml version="1.0" encoding="utf-8"?>
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
    android:name="com.google.android.libraries.navigation.SupportNavigationFragment"
    android:id="@+id/navigation_fragment"
    android:layout_width="match_parent"
    android:layout_height="match_parent"/>

別の方法として、フラグメントをプログラマティックに作成することもできます。詳しくは、 Android のドキュメントをご覧ください。 FragmentActivity.getSupportFragmentManager()

フラグメントの代わりに、UI コンポーネントを NavigationView として使用することもできます。ほとんどの場合、NavigationView を直接操作するのではなく、NavigationView のラッパーである SupportNavigationFragment を使用することをおすすめします。詳細については、次をご覧ください: ナビゲーション マップ操作のベスト プラクティス

位置情報の利用許可をリクエストする

デバイスの位置を特定するには、アプリで位置情報の利用許可をリクエストする必要があります。

このチュートリアルでは、高精度位置情報の利用許可をリクエストするためのコードを提供します。詳しくは、Android の権限に関するガイドをご覧ください。

  1. Android で権限を <manifest> 要素の子として追加する manifest:

    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.example.navsdkmultidestination">
        <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    </manifest>
    
  2. アプリで実行時の権限をリクエストして、ユーザーが位置情報の利用許可を許可または拒否できるようにします。次のコードは、 ユーザーが精度の高い位置情報の利用許可を付与しました。許可していない場合は、パーミッションをリクエストします。

    if (ContextCompat.checkSelfPermission(this.getApplicationContext(),
            android.Manifest.permission.ACCESS_FINE_LOCATION)
                == PackageManager.PERMISSION_GRANTED) {
        mLocationPermissionGranted = true;
    } else {
        ActivityCompat.requestPermissions(this,
                new String[] { android.Manifest.permission.ACCESS_FINE_LOCATION },
                PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION);
    }
    
    if (!mLocationPermissionGranted) {
        displayMessage("Error loading Navigation SDK: "
                + "The user has not granted location permission.", DISPLAY_BOTH);
        return;
    }
    
  3. onRequestPermissionsResult() コールバックをオーバーライドして、 必要があります。

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String permissions[],
                                           @NonNull int[] grantResults) {
        mLocationPermissionGranted = false;
        switch (requestCode) {
            case PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION: {
                // If request is canceled, the result arrays are empty.
                if (grantResults.length > 0
                        && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    mLocationPermissionGranted = true;
                }
            }
        }
    }
    

Navigation SDK を初期化してルートを設定する

NavigationApi クラスは、アプリが Google ナビゲーションを使用できるようにする初期化ロジックを提供します。Navigator クラスにより、ナビゲーションの構成や開始/停止を制御できます。 取り組みます。

  1. 画面とログにメッセージを表示するヘルパー メソッドを作成します。

    private void displayMessage(String errorMessage, String displayMedium) {
        if (displayMedium.equals(DISPLAY_BOTH) || displayMedium.equals(DISPLAY_TOAST)) {
            Toast.makeText(this, errorMessage, Toast.LENGTH_LONG).show();
        }
    
        if (displayMedium.equals(DISPLAY_BOTH) || displayMedium.equals(DISPLAY_LOG)) {
            Log.d(TAG, errorMessage);
        }
    }
    
  2. Navigation SDK を初期化して、 ナビゲータの起動時にナビゲーションを開始する onNavigatorReady() コールバック ready:

    NavigationApi.getNavigator(this, new NavigationApi.NavigatorListener() {
                /**
                 * Sets up the navigation UI when the navigator is ready for use.
                 */
                @Override
                public void onNavigatorReady(Navigator navigator) {
                    displayMessage("Navigator ready.", DISPLAY_BOTH);
                    mNavigator = navigator;
                    mNavFragment = (SupportNavigationFragment) getFragmentManager()
                            .findFragmentById(R.id.navigation_fragment);
    
                    // Set the camera to follow the device location with 'TILTED' driving view.
                    mNavFragment.getCamera().followMyLocation(Camera.Perspective.TILTED);
    
                    // Navigate to the specified places.
                    navigateToPlaces();
                }
    
                /**
                 * Handles errors from the Navigation SDK.
                 * @param errorCode The error code returned by the navigator.
                 */
                @Override
                public void onError(@NavigationApi.ErrorCode int errorCode) {
                    switch (errorCode) {
                        case NavigationApi.ErrorCode.NOT_AUTHORIZED:
                            displayMessage("Error loading Navigation SDK: Your API key is "
                                    + "invalid or not authorized to use the Navigation SDK.",
                                    DISPLAY_BOTH);
                            break;
                        case NavigationApi.ErrorCode.TERMS_NOT_ACCEPTED:
                            displayMessage("Error loading Navigation SDK: User did not accept "
                                    + "the Navigation Terms of Use.", DISPLAY_BOTH);
                            break;
                        case NavigationApi.ErrorCode.NETWORK_ERROR:
                            displayMessage("Error loading Navigation SDK: Network error.",
                                    DISPLAY_BOTH);
                            break;
                        case NavigationApi.ErrorCode.LOCATION_PERMISSION_MISSING:
                            displayMessage("Error loading Navigation SDK: Location permission "
                                    + "is missing.", DISPLAY_BOTH);
                            break;
                        default:
                            displayMessage("Error loading Navigation SDK: " + errorCode,
                                    DISPLAY_BOTH);
                    }
                }
            });
    
  3. 特定の場所から Waypoint オブジェクトを作成するメソッドを追加します。 ID と役職です。

    private void createWaypoint(String placeId, String title) {
        try {
            mWaypoints.add(
              Waypoint.builder()
                     .setPlaceIdString(placeId)
                     .setTitle(title)
                     .build()
            );
        } catch (Waypoint.UnsupportedPlaceIdException e) {
            displayMessage("Error starting navigation: Place ID is not supported: " + placeId,
                    DISPLAY_BOTH);
        }
    }
    
  4. 各ウェイポイントまでの計算された移動時間と距離を表示するメソッドを追加します。

    private void displayTimesAndDistances() {
        List<TimeAndDistance> timesAndDistances = mNavigator.getTimeAndDistanceList();
        int leg = 1;
        String message = "You're on your way!";
        for (TimeAndDistance timeAndDistance : timesAndDistances) {
            message = message + "\nRoute leg: " + leg++
                    + ": Travel time (seconds): " + timeAndDistance.getSeconds()
                    + ". Distance (meters): " + timeAndDistance.getMeters();
        }
        displayMessage(message, DISPLAY_BOTH);
    }
    
  5. このルートのすべてのウェイポイントを設定します。(エラー メッセージが返される場合があります) ナビゲータがルートをプロットできないプレイス ID を使用している場合このチュートリアルのサンプルアプリでは、オーストラリアのウェイポイントにプレイス ID を使用しています。メモを見る 別のプレイス ID の取得については、下記をご覧ください)。ルートの計算が完了すると、SupportNavigationFragment に、地図上にルートを表すポリラインと、各ウェイポイントにマーカーが表示されます。

    private void navigateToPlaces() {
    
        // Set up a waypoint for each place that we want to go to.
        createWaypoint("ChIJq6qq6jauEmsRJAf7FjrKnXI", "Sydney Star");
        createWaypoint("ChIJ3S-JXmauEmsRUcIaWtf4MzE", "Sydney Opera House");
        createWaypoint("ChIJLwgLFGmuEmsRzpDhHQuyyoU", "Sydney Conservatorium of Music");
    
        // If this journey is already in progress, no need to restart navigation.
        // This can happen when the user rotates the device, or sends the app to the background.
        if (mSavedInstanceState != null
                && mSavedInstanceState.containsKey(KEY_JOURNEY_IN_PROGRESS)
                && mSavedInstanceState.getInt(KEY_JOURNEY_IN_PROGRESS) == 1) {
            return;
        }
    
        // Create a future to await the result of the asynchronous navigator task.
        ListenableResultFuture<Navigator.RouteStatus> pendingRoute =
                mNavigator.setDestinations(mWaypoints);
    
        // Define the action to perform when the SDK has determined the route.
        pendingRoute.setOnResultListener(
                new ListenableResultFuture.OnResultListener<Navigator.RouteStatus>() {
                    @Override
                    public void onResult(Navigator.RouteStatus code) {
                        switch (code) {
                            case OK:
                                mJourneyInProgress = true;
                                // Hide the toolbar to maximize the navigation UI.
                                if (getActionBar() != null) {
                                    getActionBar().hide();
                                }
    
                                // Register some listeners for navigation events.
                                registerNavigationListeners();
    
                                // Display the time and distance to each waypoint.
                                displayTimesAndDistances();
    
                                // 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.getSimulator().simulateLocationsAlongExistingRoute(
                                            new SimulationOptions().speedMultiplier(5));
                                }
    
                                // Start turn-by-turn guidance along the current route.
                                mNavigator.startGuidance();
                                break;
                            // Handle error conditions returned by the navigator.
                            case NO_ROUTE_FOUND:
                                displayMessage("Error starting navigation: No route found.",
                                        DISPLAY_BOTH);
                                break;
                            case NETWORK_ERROR:
                                displayMessage("Error starting navigation: Network error.",
                                        DISPLAY_BOTH);
                                break;
                            case ROUTE_CANCELED:
                                displayMessage("Error starting navigation: Route canceled.",
                                        DISPLAY_BOTH);
                                break;
                            default:
                                displayMessage("Error starting navigation: "
                                        + String.valueOf(code), DISPLAY_BOTH);
                        }
                    }
                });
    }
    

アプリをビルドして実行する

  1. Android デバイスをコンピュータに接続します。手順に沿って、Android デバイスでデベロッパー オプションを有効にし、デバイスを検出するようにシステムを設定します(または、Android Virtual Device(AVD)Manager を使用して仮想デバイスを設定することもできます。エミュレータを指定する際は、必ず次の要素を含むイメージを選択してください。 説明します)。
  2. Android Studio で [Run] メニュー オプション(またはプレイボタン アイコン)をクリックします。表示される指示に沿ってデバイスを選択します。

ユーザー エクスペリエンスを向上させるためのヒント

  • ナビゲーションを利用できるようになるには、ユーザーが Google ナビゲーションの利用規約に同意する必要があります。この同意が必要となるのは 1 回のみです。デフォルトでは、ナビゲータが初めて呼び出されたときに、SDK から承認を求めるメッセージが表示されます。必要に応じて、ナビゲーションの利用規約ダイアログを表示することもできます アプリの UX フローの初期段階(登録時やログイン時など)に、 showTermsAndConditionsDialog()
  • 以下を使用すると、ナビゲーションの品質と ETA の精度が大幅に向上します 緯度と経度ではなく、プレイス ID を使用して地点を初期化します。 あります。
  • このサンプルでは、特定の場所 ID からウェイポイントを取得します。プレイス ID を取得する方法は他にもあります。