ניווט במסלול עם יעד אחד

במדריך הזה מוסבר איך להתוות מסלול באפליקציה באמצעות Navigation SDK ל-Android. במדריך הזה אנחנו מניחים שכבר שילבתם את Navigation SDK באפליקציה, כמו שמתואר במאמר הגדרת הפרויקט.

סיכום

  1. מוסיפים רכיב ממשק משתמש לאפליקציה, כקטע ניווט או כתצוגת ניווט. רכיב ממשק המשתמש הזה מוסיף לפעילות שלכם את המפה האינטראקטיבית ואת ממשק המשתמש של הניווט המפורט.
  2. שליחת בקשה להרשאות מיקום. האפליקציה צריכה לבקש הרשאת מיקום כדי לקבוע את מיקום המכשיר.
  3. מאתחלים את ה-SDK באמצעות המחלקה NavigationApi.
  4. מגדירים יעד ושולטים בניווט המפורט באמצעות המחלקה Navigator. התהליך כולל שלושה שלבים:

    • מגדירים יעד באמצעות setDestination().
    • התחלת הניווט באמצעות startGuidance().
    • אפשר להשתמש ב-getSimulator() כדי לדמות את התקדמות הרכב לאורך המסלול, לצורך בדיקה, ניפוי באגים והדגמה של האפליקציה.
  5. יוצרים ומריצים את האפליקציה.

הצגת הקוד

הוספת רכיב ממשק משתמש לאפליקציה

בקטע הזה מוסברות שתי דרכים להוספת המפה האינטראקטיבית וממשק המשתמש להצגת ניווט מפורט. ברוב המקרים, מומלץ להשתמש ב-SupportNavigationFragment, שהוא עטיפה של NavigationView, במקום ליצור אינטראקציה ישירות עם NavigationView. מידע נוסף זמין במאמר בנושא שיטות מומלצות לאינטראקציה עם מפת הניווט .

SupportNavigationFragment הוא רכיב ממשק המשתמש שמציג את הפלט החזותי של הניווט, כולל מפה אינטראקטיבית והוראות ניווט מפורטות. אפשר להצהיר על הפרגמנט בקובץ פריסת ה-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().

במקום להשתמש ב-Fragment, אפשר להשתמש ב-NavigationView כדי להציג רכיב של ממשק משתמש עם מפה לניווט.

שליחת בקשה להרשאת מיקום

בקטע הזה מוסבר איך לבקש הרשאה למיקום מדויק. פרטים נוספים זמינים במדריך בנושא הרשאות ב-Android.

  1. מוסיפים את ההרשאה כצאצא של הרכיב <manifest> במניפסט של Android:

    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.example.navsdksingledestination">
        <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.");
            return;
        }
    
  3. מבטלים את ההגדרה של onRequestPermissionsResult() callback כדי לטפל בתוצאה של בקשת ההרשאה:

        @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. בקטע הזה מוסבר איך להפעיל את הניווט, וגם כמה הגדרות אחרות שאפשר להפעיל באפליקציה:

  1. מפעילים את Navigation SDK ומבטלים את ההגדרה של הקריאה החוזרת onNavigatorReady() כדי להתחיל בניווט כשהניווט מוכן.

  2. אופציונלי. מגדירים את האפליקציה כך שההתראות עם ההנחיות ושירותי הרקע יושבתו כשהמשתמש יסגור את האפליקציה במכשיר שלו. הבחירה הזו תלויה במודל העסקי שלכם. אולי תרצו להשתמש בהתנהגות ברירת המחדל של הניווט, שממשיכה להציג הנחיות לגבי פניות ועדכונים לגבי מיקום גם כשהאפליקציה נסגרת. אם רוצים להפסיק את הניווט ואת עדכוני המיקום כשהמשתמש סוגר את האפליקציה, צריך להשתמש בהגדרה הזו.

  3. אופציונלי. הפעלת הגבלות על כבישים במדינות נתמכות. מגדירים את הספרה האחרונה של לוחית הרישוי. צריך לבצע את הקריאה הזו רק פעם אחת: בקשות עתידיות להוראות הגעה ימשיכו להשתמש בה. השיחה הזו פועלת רק באזורים נתמכים. רשימת המדינות שנתמכות ב-Navigation SDK

        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.");
                        mNavigator = navigator;
                        mNavFragment = (NavigationFragment) getFragmentManager()
                                .findFragmentById(R.id.navigation_fragment);
    
                        // Optional. Disable the guidance notifications and shut down the app
                        // and background service when the user closes the app.
                        // mNavigator.setTaskRemovedBehavior(Navigator.TaskRemovedBehavior.QUIT_SERVICE)
    
                        // Optional. Set the last digit of the car's license plate to get
                        // route restrictions for supported countries.
                        // mNavigator.setLicensePlateRestrictionInfo(getLastDigit(), "BZ");
    
                        // Set the camera to follow the device location with 'TILTED' driving view.
                        mNavFragment.getCamera().followMyLocation(Camera.Perspective.TILTED);
    
                        // Set the travel mode (DRIVING, WALKING, CYCLING, TWO_WHEELER, or TAXI).
                        mRoutingOptions = new RoutingOptions();
                        mRoutingOptions.travelMode(RoutingOptions.TravelMode.DRIVING);
    
                        // Navigate to a place, specified by Place ID.
                        navigateToPlace(SYDNEY_OPERA_HOUSE, mRoutingOptions);
                    }
    
                    /**
                     * 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.");
                                break;
                            case NavigationApi.ErrorCode.TERMS_NOT_ACCEPTED:
                                displayMessage("Error loading Navigation SDK: User did not accept "
                                        + "the Navigation Terms of Use.");
                                break;
                            case NavigationApi.ErrorCode.NETWORK_ERROR:
                                displayMessage("Error loading Navigation SDK: Network error.");
                                break;
                            case NavigationApi.ErrorCode.LOCATION_PERMISSION_MISSING:
                                displayMessage("Error loading Navigation SDK: Location permission "
                                        + "is missing.");
                                break;
                            default:
                                displayMessage("Error loading Navigation SDK: " + errorCode);
                        }
                    }
                });
    

הגדרת יעד

המחלקות Navigator מספקות שליטה בהגדרה, בהתחלה ובהפסקה של מסלול ניווט.

בעזרת הערך של Navigator שהתקבל בקטע הקודם, מגדירים יעד Waypoint למסלול הזה. אחרי חישוב המסלול, הסמל SupportNavigationFragment מציג קו פוליגוני שמייצג את המסלול במפה, וסמן ביעד.

```none
    private void navigateToPlace(String placeId, RoutingOptions travelMode) {
        Waypoint destination;
        try {
            destination = Waypoint.builder().setPlaceIdString(placeId).build();
        } catch (Waypoint.UnsupportedPlaceIdException e) {
            displayMessage("Error starting navigation: Place ID is not supported.");
            return;
        }

        // Create a future to await the result of the asynchronous navigator task.
        ListenableResultFuture<Navigator.RouteStatus> pendingRoute =
                mNavigator.setDestination(destination, travelMode);

        // 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:
                                // Hide the toolbar to maximize the navigation UI.
                                if (getActionBar() != null) {
                                    getActionBar().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.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.");
                                break;
                            case NETWORK_ERROR:
                                displayMessage("Error starting navigation: Network error.");
                                break;
                            case ROUTE_CANCELED:
                                displayMessage("Error starting navigation: Route canceled.");
                                break;
                            default:
                                displayMessage("Error starting navigation: "
                                        + String.valueOf(code));
                        }
                    }
                });
    }
```

איך יוצרים ומריצים את האפליקציה

  1. מחברים מכשיר Android למחשב. פועלים לפי ההוראות של Android Studio בנושא הפעלת אפליקציות במכשיר חומרה. לחלופין, אפשר להגדיר מכשיר וירטואלי באמצעות Android Virtual Device (AVD) Manager. כשבוחרים אמולטור, חשוב לוודא שבוחרים תמונה שכוללת את Google APIs.
  2. ב-Android Studio, לוחצים על האפשרות Run בתפריט או על סמל ההפעלה. בוחרים מכשיר לפי ההנחיות.

הצעות לשיפור חוויית המשתמש

  • המשתמש צריך לאשר את התנאים וההגבלות של Google Navigation כדי שהניווט יהיה זמין. צריך לאשר את התנאים וההגבלות רק פעם אחת. כברירת מחדל, ה-SDK מבקש אישור בפעם הראשונה שמפעילים את הניווט. אם אתם מעדיפים, אתם יכולים להציג את תיבת הדו-שיח של התנאים וההגבלות של הניווט בשלב מוקדם בתהליך חוויית המשתמש של האפליקציה, למשל במהלך ההרשמה או הכניסה, באמצעות TermsAndConditionsCheckOption.
  • כדי לשפר באופן משמעותי את איכות הניווט ואת הדיוק של זמן ההגעה המשוער, כדאי להשתמש במזהי מקומות כדי לאתחל נקודת ציון במקום בקואורדינטות של קו רוחב וקו אורך.
  • בדוגמה הזו, נקודת הציון של היעד נגזרת ממזהה מקום ספציפי של בית האופרה של סידני. אתם יכולים להשתמש בכלי למציאת מזהי מקומות כדי לקבל מזהי מקומות למיקומים ספציפיים אחרים.