Di chuyển trong tuyến đường đa điểm đến

Hãy làm theo hướng dẫn này để vẽ một tuyến đường trong ứng dụng đến nhiều đích đến. còn được gọi là điểm tham chiếu, bằng cách sử dụng SDK điều hướng cho Android.

Tổng quan

  1. Tích hợp SDK điều hướng vào ứng dụng của bạn, như được mô tả trong Thiết lập dự án.
  2. Thêm SupportNavigationFragment hoặc NavigationView cho ứng dụng của bạn. Thành phần này trên giao diện người dùng sẽ thêm bản đồ tương tác và giao diện người dùng điều hướng từng chặng vào hoạt động của bạn.
  3. Sử dụng lớp NavigationApi để khởi chạy SDK.
  4. Xác định Navigator để điều khiển đường đi từng chặng:

    • Thêm đích đến bằng cách sử dụng setDestinations().
    • Bắt đầu đi theo chỉ dẫn bằng startGuidance().
    • Sử dụng getSimulator() để mô phỏng tiến trình của xe dọc theo tuyến đường để kiểm tra, gỡ lỗi và minh hoạ .
  5. Tạo bản dựng và chạy ứng dụng của bạn.

Xem mã

Thêm mảnh điều hướng

SupportNavigationFragment là thành phần giao diện người dùng hiển thị kết quả chỉ đường trực quan, bao gồm bản đồ tương tác và từng chặng đường đi. Bạn có thể khai báo mảnh trong tệp bố cục XML như minh hoạ dưới đây:

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

Ngoài ra, bạn có thể tạo mảnh theo phương thức lập trình, như mô tả trong tài liệu Android, sử dụng FragmentActivity.getSupportFragmentManager().

Bên cạnh một mảnh, thành phần giao diện người dùng cũng có sẵn dưới dạng một NavigationView. Xin lưu ý thông tin ở đầu nội dung mô tả về lớp, đặc biệt là về yêu cầu chuyển tiếp vòng đời .

Yêu cầu cấp quyền vị trí

Ứng dụng của bạn phải yêu cầu quyền truy cập thông tin vị trí để xác định vị trí của thiết bị.

Hướng dẫn này cung cấp mã bạn cần để yêu cầu quyền truy cập thông tin vị trí chính xác. Để biết thêm thông tin, hãy xem hướng dẫn về Các quyền trên Android.

  1. Thêm quyền này ở dạng phần tử con của phần tử <manifest> trong thiết bị Android tệp kê khai:

    <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. Yêu cầu quyền khi bắt đầu chạy trong ứng dụng của bạn, để người dùng có cơ hội để cho phép hoặc từ chối cấp quyền truy cập thông tin vị trí. Mã sau đây kiểm tra xem người dùng đã cấp quyền truy cập thông tin vị trí chính xác. Nếu không, ứng dụng sẽ yêu cầu quyền:

    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. Ghi đè lệnh gọi lại onRequestPermissionsResult() để xử lý kết quả của yêu cầu quyền:

    @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;
                }
            }
        }
    }
    

Khởi chạy SDK điều hướng và định cấu hình một hành trình

Lớp NavigationApi cung cấp logic khởi động cho phép ứng dụng của bạn sử dụng tính năng điều hướng của Google. Navigator lớp cung cấp khả năng kiểm soát việc định cấu hình và bắt đầu/dừng điều hướng hành trình.

  1. Tạo một phương thức trợ giúp để hiển thị thông báo trên màn hình và trong nhật ký.

    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. Khởi chạy SDK điều hướng và ghi đè Lệnh gọi lại onNavigatorReady() để bắt đầu điều hướng khi trình điều hướng được sẵn sàng:

    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. Thêm phương thức để tạo đối tượng Waypoint từ một địa điểm nhất định Mã nhận dạng và chức danh.

    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. Thêm một phương thức để hiển thị thời gian di chuyển và khoảng cách đã tính cho mỗi điểm tham chiếu.

    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. Thiết lập tất cả các điểm tham chiếu cho hành trình này. (Xin lưu ý rằng bạn có thể gặp lỗi nếu bạn sử dụng mã địa điểm mà trình điều hướng không thể vẽ một tuyến đường. Mẫu trong hướng dẫn này sử dụng ID địa điểm cho điểm tham chiếu ở Úc. Xem ghi chú bên dưới về cách nhận các mã địa điểm khác nhau.) Sau khi tính toán thì SupportNavigationFragment sẽ hiển thị hình nhiều đường thể hiện tuyến đường trên bản đồ, với một điểm đánh dấu tại mỗi điểm tham chiếu.

    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);
                        }
                    }
                });
    }
    

Tạo và chạy ứng dụng

  1. Kết nối thiết bị Android với máy tính. Làm theo hướng dẫn bật tuỳ chọn cho nhà phát triển trên thiết bị Android thiết bị và định cấu hình hệ thống của bạn để phát hiện thiết bị. (Ngoài ra, bạn có thể sử dụng Trình quản lý thiết bị Android ảo (AVD) để định cấu hình máy ảo thiết bị. Khi chọn một trình mô phỏng, hãy nhớ chọn hình ảnh có chứa các API của Google.)
  2. Trong Android Studio, hãy nhấp vào tuỳ chọn trình đơn Run (Chạy) (hoặc biểu tượng nút phát). Chọn một thiết bị khi được nhắc.

Gợi ý để cải thiện trải nghiệm người dùng

  • Người dùng phải chấp nhận Điều khoản dịch vụ của Google Navigation trước điều hướng sẽ khả dụng. Bạn chỉ phải chấp nhận một lần. Theo theo mặc định, SDK sẽ nhắc chấp nhận vào lần đầu tiên trình điều hướng đã gọi. Nếu muốn, bạn có thể kích hoạt hộp thoại Điều khoản dịch vụ điều hướng tại thời điểm đầu trong luồng trải nghiệm người dùng của ứng dụng, chẳng hạn như trong khi đăng ký hoặc đăng nhập, sử dụng showTermsAndConditionsDialog().
  • Chất lượng điều hướng và độ chính xác của giờ đến dự kiến được cải thiện đáng kể nếu bạn sử dụng mã địa điểm để khởi tạo một điểm tham chiếu, thay vì vĩ độ/kinh độ đích.
  • Mẫu này lấy điểm tham chiếu từ một địa điểm cụ thể Mã nhận dạng. Sau đây là một số cách khác để lấy mã địa điểm: