پیمایش مسیر چندمقصدی

این راهنما را دنبال کنید تا بااستفاده از Navigation SDK for Android، مسیری را در برنامه‌تان به چندین مقصد (که نقطه‌مسیر نیز نامیده می‌شود) ترسیم کنید. می‌توانید حداکثر ۲۵ نقطه‌مسیر، ازجمله مقصد نهایی، تنظیم کنید.

نمای کلی

  1. همان‌طور که در راه‌اندازی پروژه شرح داده شده است، Navigation SDK را در برنامه‌تان ادغام کنید.
  2. NavigationFragment یا NavigationView را به برنامه‌تان اضافه کنید. این عنصر میانای کاربر نقشه تعاملی و میانای کاربر ناوبری گام‌به‌گام را به فعالیتتان اضافه می‌کند.
  3. از کلاس NavigationApi برای مقداردهی اولیه کیت توسعه نرم‌افزار استفاده کنید.
  4. Navigator را برای کنترل ناوبری گام‌به‌گام تعریف کنید:

    • بااستفاده از setDestinations مقصد اضافه کنید.
    • شروع ناوبری با startGuidance.
    • از getSimulator برای شبیه‌سازی پیشرفت خودرو درطول مسیر، برای آزمایش، اشکال‌زدایی، و نمایش برنامه‌تان استفاده کنید.
  5. برنامه‌تان را بسازید و اجرا کنید.

دیدن کد

افزودن قطعه پیمایش

NavigationFragment مؤلفه میانای کاربر است که خروجی دیداری ناوبری را نمایش می‌دهد، ازجمله نقشه تعاملی و مسیرهای گام‌به‌گام. می‌توانید قطعه را در فایل چیدمان 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.NavigationFragment"
    android:id="@+id/navigation_fragment"
    android:layout_width="match_parent"
    android:layout_height="match_parent"/>

یا می‌توانید قطعه را به‌صورت برنامه‌نویسی‌شده، همان‌طور که در سند Android شرح داده شده است، بااستفاده از FragmentActivity.getSupportFragmentManager() بسازید.

به‌عنوان جایگزینی برای قطعه، مؤلفه واسط کاربر به‌صورت NavigationView نیز دردسترس است. در اکثر موارد، توصیه می‌کنیم به‌جای تعامل مستقیم با NavigationView، از NavigationFragment که پوششی برای NavigationView است استفاده کنید. برای اطلاعات بیشتر، روال‌های مطلوب تعامل با نقشه ناوبری را ببینید.

درخواست اجازه مکان

برنامه شما باید اجازه مکان را درخواست کند تا بتواند مکان دستگاه را تعیین کند.

این آموزش گام‌به‌گام کدی را که برای درخواست اجازه مکان دقیق نیاز دارید ارائه می‌دهد. برای جزئیات بیشتر، راهنمای اجازه‌های Android را ببینید.

  1. اجازه را به‌عنوان فرزند عنصر <manifest> در مانیفست Android خود اضافه کنید:

        <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. کیت توسعه نرم‌افزار ناوبری را مقداردهی اولیه کنید و فراخوان برگشتی onNavigatorReady را لغو کنید تا وقتی ناوبری آماده شد، ناوبری شروع شود:

        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 = (NavigationFragment) getSupportFragmentManager()
                                .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 از شناسه و عنوان مکان داده‌شده اضافه کنید.

        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. برای این سفر، حداکثر ۲۵ نقطه‌مسیر تنظیم کنید. پس‌از محاسبه مسیرها، NavigationFragment چندخطی‌ای را نمایش می‌دهد که نشان‌دهنده مسیر روی نقشه است و نشانگری در هر نقطه‌مسیر دارد.

        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).
                                    AudioGuidanceSettings audioSettings =
                                            AudioGuidanceSettings.builder()
                                                    .setGuidanceMode(
                                                            AudioGuidanceSettings.GuidanceMode
                                                                    .VOICE_ALERTS_AND_GUIDANCE)
                                                    .build();
                                    mNavigator.setAudioGuidanceSettings(audioSettings);
    
                                    // 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;
                                case ROUTING_TIMEOUT:
                                    displayMessage("Error starting navigation: Routing timed out.",
                                            DISPLAY_BOTH);
                                    break;
                                default:
                                    displayMessage("Error starting navigation: "
                                            + String.valueOf(code), DISPLAY_BOTH);
                            }
                        }
                    });
        }
    

ساختن و اجرای برنامه

  1. دستگاه Android را به رایانه وصل کنید. دستورالعمل‌ها را دنبال کنید تا گزینه‌های توسعه‌دهنده را در دستگاه Android خود فعال کنید و سیستم خود را برای شناسایی دستگاه پیکربندی کنید. (یا می‌توانید از مدیر دستگاه مجازی Android (AVD) برای پیکربندی دستگاه مجازی استفاده کنید. هنگام انتخاب شبیه‌ساز، مطمئن شوید تصویری را انتخاب می‌کنید که شامل Google APIs باشد.)
  2. در Android Studio، روی گزینه منو اجرا (یا نماد دکمه پخش) کلیک کنید. دستگاهی را طبق درخواست انتخاب کنید.

نکاتی برای بهبود تجربه کاربری

  • کاربر باید «شرایط خدمات Google Navigation» را بپذیرد تا ناوبری دردسترس قرار گیرد. این پذیرش فقط یک‌بار لازم است. به‌طور پیش‌فرض، کیت توسعه نرم‌افزار اولین باری که ناوبر فراخوانده می‌شود، درخواست پذیرش می‌کند. اگر ترجیح می‌دهید، می‌توانید کادر گفتگوی «شرایط خدمات ناوبری» را در نقطه‌ای اولیه در جریان تجربه کاربری برنامه‌تان، مثلاً درطول ثبت‌نام یا ورود به سیستم، بااستفاده از showTermsAndConditionsDialog راه‌اندازی کنید.
  • اگر برای مقداردهی اولیه نقطه‌مسیر به‌جای مقصد طول/عرض جغرافیایی از شناسه جا استفاده کنید، کیفیت ناوبری و دقت زمان تخمینی رسیدن به‌طور قابل‌توجهی بهبود می‌یابد.
  • این نمونه نقاط‌مسیر را از شناسه‌های مکان خاصی مشتق می‌کند. روش‌های دیگر برای دریافت شناسه مکان عبارت‌اند از:

  • از یابنده شناسه مکان برای دریافت شناسه مکان برای مکان‌های خاص استفاده کنید.

  • از Geocoding API برای پیدا کردن شناسه مکان برای نشانی داده‌شده استفاده کنید. Geocoding API درصورتی به‌خوبی کار می‌کند که نشانی‌های کامل و بدون ابهامی برای نقطه‌مسیرها داشته باشید. راهنمای روال‌های مطلوب زمین‌کدیابی را ببینید.

  • از جستجوی نوشتار Places API برای پیدا کردن شناسه مکان برای نشانی داده‌شده استفاده کنید. اگر نشانی‌های ناقص یا مبهمی برای نقطه‌مسیرها دارید، Places API به‌خوبی کار می‌کند. راهنمای روال‌های مطلوب زمین‌کدیابی را ببینید.