מעבר ללקוח SDK חדש של 'מקומות'

מפתחים באזור הכלכלי האירופי (EEA)

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

הדרך היחידה לגשת לתכונות ולתיקוני באגים ב-Places SDK ל-Android בגרסה 2.6.0 ומעלה היא להשתמש ב-Places SDK ל-Android. ‫Google ממליצה לעדכן מהספרייה לתאימות לגרסה החדשה של Places SDK for Android בהקדם האפשרי.

שגיאה: 9005 PLACES_API_RATE_LIMIT_EXCEEDED

מה השתנה?

אלה האזורים העיקריים שבהם בוצעו שינויים:

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

מידע על ספריית התאימות של Places

בינואר 2019, עם השקת גרסה 1.0 של Places SDK עצמאי ל-Android,‏ Google סיפקה ספריית תאימות כדי לעזור במיגרציה מגרסת Google Play Services של Places SDK ל-Android (‏com.google.android.gms:play-services-places) שהוצאה משימוש.

ספריית התאימות הזו סופקה באופן זמני כדי להפנות מחדש ולתרגם קריאות ל-API שמיועדות לגרסה של Google Play Services לגרסה החדשה העצמאית, עד שמפתחים יוכלו להעביר את הקוד שלהם לשימוש בשמות החדשים ב-SDK העצמאי. לכל גרסה של Places SDK ל-Android שפורסמה מגרסה 1.0 עד גרסה 2.6.0, פורסמה גרסה תואמת של ספריית התאימות של Places כדי לספק פונקציונליות שוות ערך.

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

כל הגרסאות של ספריית התאימות ל-Places SDK ל-Android הוצאו משימוש ב-31 במרץ 2022. גרסה 2.6.0 היא הגרסה האחרונה של ספריית התאימות של Places. הדרך היחידה לגשת לתכונות ולתיקוני באגים ב-Places SDK ל-Android מעל גרסה 2.6.0 היא להשתמש ב-Places SDK ל-Android.

‫Google ממליצה לעבור אל Places SDK for Android כדי לקבל גישה לתכונות חדשות ולתיקוני באגים קריטיים בגרסאות מעל גרסה 2.6.0. אם אתם משתמשים כרגע בספריית התאימות, אתם יכולים לפעול לפי השלבים שבקטע התקנת Places SDK ל-Android כדי לעבור ל-Places SDK ל-Android.

התקנת ספריית הלקוח

הגרסה החדשה של Places SDK ל-Android מופצת כספריית לקוח סטטית.

משתמשים ב-Maven כדי להוסיף את Places SDK ל-Android לפרויקט Android Studio:

  1. אם אתם משתמשים כרגע בספריית התאימות של Places:

    1. מחליפים את השורה הבאה בקטע dependencies:

          implementation 'com.google.android.libraries.places:places-compat:X.Y.Z'

      כדי לעבור ל-Places SDK ל-Android, מוסיפים את השורה הבאה:

          implementation("com.google.android.libraries.places:places:4.3.1")

  2. אם אתם משתמשים כרגע בגרסת Play Services של Places SDK ל-Android:

    1. מחליפים את השורה הבאה בקטע dependencies:

          implementation 'com.google.android.gms:play-services-places:X.Y.Z'

      כדי לעבור ל-Places SDK ל-Android, מוסיפים את השורה הבאה:

          implementation("com.google.android.libraries.places:places:4.3.1")

  3. מסנכרנים את פרויקט Gradle.

  4. מגדירים את minSdkVersion של פרויקט האפליקציה ל-23 ומעלה.

  5. עדכון הנכסים הדיגיטליים עם הכיתוב 'מופעל על ידי Google':

    @drawable/powered_by_google_light // OLD
    @drawable/places_powered_by_google_light // NEW
    @drawable/powered_by_google_dark // OLD
    @drawable/places_powered_by_google_dark // NEW
  6. מבצעים build לאפליקציה. אם מופיעות שגיאות build בגלל המעבר ל-Places SDK ל-Android, אפשר לעיין בקטעים הבאים כדי לקבל מידע על פתרון השגיאות האלה.

אתחול של לקוח חדש של Places SDK

מפעילים את הלקוח החדש של Places SDK כמו בדוגמה הבאה:

// Add an import statement for the client library.
import com.google.android.libraries.places.api.Places;

...

// Initialize Places.
Places.initialize(getApplicationContext(), apiKey);

// Create a new Places client instance.
PlacesClient placesClient = Places.createClient(this);

קודי סטטוס

קוד הסטטוס של שגיאות שקשורות למגבלת השאילתות לשנייה השתנה. שגיאות שקשורות למגבלת השאילתות לשנייה מוחזרות עכשיו דרך PlaceStatusCodes.OVER_QUERY_LIMIT. אין יותר הגבלות על מספר השאילתות לדקה.

נוספו קודי הסטטוס הבאים:

  • REQUEST_DENIED — הבקשה נדחתה. הסיבות האפשריות לכך:

    • לא סופק מפתח API.
    • סופק מפתח API לא תקין.
    • לא הפעלתם את Places API במסוף Cloud.
    • סופק מפתח API עם הגבלות שגויות.
  • INVALID_REQUEST – הבקשה לא תקינה בגלל ארגומנט חסר או לא תקין.

  • NOT_FOUND – לא נמצאה תוצאה לבקשה שצוינה.

שיטות חדשות

בגרסה החדשה של Places SDK ל-Android מוצגות שיטות חדשות לגמרי, שנועדו לשמור על עקביות. כל השיטות החדשות עומדות בדרישות הבאות:

  • נקודות הקצה כבר לא משתמשות בפועל get.
  • לאובייקטים של הבקשה והתגובה יש את אותו שם כמו לשיטת הלקוח המתאימה.
  • לאובייקטים של בקשות יש עכשיו בנאים. הפרמטרים הנדרשים מועברים כפרמטרים של בנאי הבקשות.
  • המאגרים כבר לא בשימוש.

בקטע הזה נציג את השיטות החדשות ונסביר איך הן פועלות.

אחזור מקום לפי מזהה

אפשר להשתמש ב-fetchPlace() כדי לקבל פרטים על מקום מסוים. הפונקציה fetchPlace() פועלת באופן דומה ל-getPlaceById().

כדי לאחזר מקום, פועלים לפי השלבים הבאים:

  1. קוראים לפונקציה fetchPlace() ומעבירים אליה אובייקט FetchPlaceRequest שמציין מזהה מקום ורשימה של שדות שמציינים את נתוני המקום שיוחזרו.

    // Define a Place ID.
    String placeId = "INSERT_PLACE_ID_HERE";
    
    // Specify the fields to return.
    List<Place.Field> placeFields = Arrays.asList(Place.Field.ID, Place.Field.DISPLAY_NAME);
    
    // Construct a request object, passing the place ID and fields array.
    FetchPlaceRequest request = FetchPlaceRequest.builder(placeId, placeFields)
            .build();
    
    
  2. אפשר להתקשר אל addOnSuccessListener() כדי לטפל ב-FetchPlaceResponse. מוחזרת תוצאה אחת (Place).

    // Add a listener to handle the response.
    placesClient.fetchPlace(request).addOnSuccessListener((response) -> {
      Place place = response.getPlace();
      Log.i(TAG, "Place found: " + place.getName());
    }).addOnFailureListener((exception) -> {
        if (exception instanceof ApiException) {
            ApiException apiException = (ApiException) exception;
            int statusCode = apiException.getStatusCode();
            // Handle error with given status code.
            Log.e(TAG, "Place not found: " + exception.getMessage());
        }
    });
    

שליפת תמונה של מקום

משתמשים ב-fetchPhoto() כדי לקבל תמונה של מקום. ‫fetchPhoto() מחזירה תמונות של מקום. הפישוט של התבנית לבקשת תמונה עכשיו אפשר לשלוח בקשה ל-PhotoMetadata ישירות מאובייקט Place, ולא צריך לשלוח בקשה נפרדת. הרוחב או הגובה המקסימליים של התמונות הם 1,600 פיקסלים. הפונקציה fetchPhoto() דומה לפונקציה getPhoto().

כדי לאחזר תמונות של מקומות:

  1. מתקשרים אל fetchPlace(). חשוב לכלול את השדה PHOTO_METADATAS בבקשה:

    List<Place.Field> fields = Arrays.asList(Place.Field.PHOTO_METADATAS);
    
  2. אחזור אובייקט Place (בדוגמה הזו נעשה שימוש ב-fetchPlace(), אבל אפשר להשתמש גם ב-findCurrentPlace()):

    FetchPlaceRequest placeRequest = FetchPlaceRequest.builder(placeId, fields).build();
    
  3. מוסיפים OnSuccessListener כדי לקבל את המטא-נתונים של התמונה מתוך Place שמתקבל ב-FetchPlaceResponse, ואז משתמשים במטא-נתונים של התמונה שמתקבלים כדי לקבל מפת סיביות וטקסט שיוך:

    placesClient.fetchPlace(placeRequest).addOnSuccessListener((response) -> {
        Place place = response.getPlace();
    
        // Get the photo metadata.
        PhotoMetadata photoMetadata = place.getPhotoMetadatas().get(0);
    
        // Get the attribution text.
        String attributions = photoMetadata.getAttributions();
    
        // Create a FetchPhotoRequest.
        FetchPhotoRequest photoRequest = FetchPhotoRequest.builder(photoMetadata)
                .setMaxWidth(500) // Optional.
                .setMaxHeight(300) // Optional.
                .build();
        placesClient.fetchPhoto(photoRequest).addOnSuccessListener((fetchPhotoResponse) -> {
            Bitmap bitmap = fetchPhotoResponse.getBitmap();
            imageView.setImageBitmap(bitmap);
        }).addOnFailureListener((exception) -> {
            if (exception instanceof ApiException) {
                ApiException apiException = (ApiException) exception;
                int statusCode = apiException.getStatusCode();
                // Handle error with given status code.
                Log.e(TAG, "Place not found: " + exception.getMessage());
            }
        });
    });
    

חיפוש מקום מהמיקום של המשתמש

אפשר להשתמש ב-findCurrentPlace() כדי למצוא את המיקום הנוכחי של המכשיר של המשתמש. findCurrentPlace() מחזירה רשימה של PlaceLikelihoods שמציינים מקומות שבהם סביר להניח שהמכשיר של המשתמש נמצא. הפונקציה findCurrentPlace() דומה לפונקציה getCurrentPlace().

כדי לקבל את המיקום הנוכחי של המכשיר של המשתמש:

  1. מוודאים שהאפליקציה מבקשת את ההרשאות ACCESS_FINE_LOCATION ו-ACCESS_WIFI_STATE. המשתמש צריך לתת הרשאה לגישה למיקום הנוכחי של המכשיר. פרטים נוספים זמינים במאמר בנושא בקשת הרשאות לאפליקציה.

  2. יוצרים FindCurrentPlaceRequest, כולל רשימה של סוגי נתוני מקומות להחזרה.

      // Use fields to define the data types to return.
      List<Place.Field> placeFields = Arrays.asList(Place.Field.DISPLAY_NAME);
    
      // Use the builder to create a FindCurrentPlaceRequest.
      FindCurrentPlaceRequest request =
              FindCurrentPlaceRequest.builder(placeFields).build();
    
  3. קוראים לפונקציה findCurrentPlace ומטפלים בתגובה, ובודקים קודם אם המשתמש העניק הרשאה להשתמש במיקום המכשיר שלו.

      // Call findCurrentPlace and handle the response (first check that the user has granted permission).
      if (ContextCompat.checkSelfPermission(this, ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
          placesClient.findCurrentPlace(request).addOnSuccessListener(((response) -> {
              for (PlaceLikelihood placeLikelihood : response.getPlaceLikelihoods()) {
                  Log.i(TAG, String.format("Place '%s' has likelihood: %f",
                          placeLikelihood.getPlace().getName(),
                          placeLikelihood.getLikelihood()));
                  textView.append(String.format("Place '%s' has likelihood: %f\n",
                          placeLikelihood.getPlace().getName(),
                          placeLikelihood.getLikelihood()));
              }
          })).addOnFailureListener((exception) -> {
              if (exception instanceof ApiException) {
                  ApiException apiException = (ApiException) exception;
                  Log.e(TAG, "Place not found: " + apiException.getStatusCode());
              }
          });
      } else {
          // A local method to request required permissions;
          // See https://developer.android.com/training/permissions/requesting
          getLocationPermission();
      }
    

איך מוצאים הצעות להשלמת החיפוש

משתמשים ב-findAutocompletePredictions() כדי להחזיר תחזיות לגבי מקומות בתגובה לשאילתות חיפוש של משתמשים. הפונקציה findAutocompletePredictions() דומה לפונקציה getAutocompletePredictions().

בדוגמה הבאה מוצגת קריאה ל-findAutocompletePredictions():

// Create a new token for the autocomplete session. Pass this to FindAutocompletePredictionsRequest,
// and once again when the user makes a selection (for example when calling fetchPlace()).
AutocompleteSessionToken token = AutocompleteSessionToken.newInstance();
// Create a RectangularBounds object.
RectangularBounds bounds = RectangularBounds.newInstance(
  new LatLng(-33.880490, 151.184363),
  new LatLng(-33.858754, 151.229596));
// Use the builder to create a FindAutocompletePredictionsRequest.
FindAutocompletePredictionsRequest request = FindAutocompletePredictionsRequest.builder()
// Call either setLocationBias() OR setLocationRestriction().
   .setLocationBias(bounds)
   //.setLocationRestriction(bounds)
   .setCountry("au")
   .setTypesFilter(Arrays.asList(PlaceTypes.ADDRESS))
   .setSessionToken(token)
   .setQuery(query)
   .build();

placesClient.findAutocompletePredictions(request).addOnSuccessListener((response) -> {
   for (AutocompletePrediction prediction : response.getAutocompletePredictions()) {
       Log.i(TAG, prediction.getPlaceId());
       Log.i(TAG, prediction.getPrimaryText(null).toString());
   }
}).addOnFailureListener((exception) -> {
   if (exception instanceof ApiException) {
       ApiException apiException = (ApiException) exception;
       Log.e(TAG, "Place not found: " + apiException.getStatusCode());
   }
});

טוקנים של סשנים

אסימוני סשן מקבצים את שלבי השאילתה והבחירה של חיפוש משתמש לסשן נפרד למטרות חיוב. מומלץ להשתמש באסימוני סשן לכל הסשנים של השלמה אוטומטית. הסשן מתחיל כשהמשתמש מתחיל להקליד שאילתה, ומסתיים כשהוא בוחר מקום. כל ביקור באתר יכול לכלול כמה שאילתות, ואחריהן בחירה של מקום אחד. אחרי סיום הסשן, האסימון כבר לא תקף. האפליקציה צריכה ליצור אסימון חדש לכל סשן.

מסיכות שדות

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

כדי לציין אילו סוגי נתונים להחזיר, מעבירים מערך של Place.Fields ב-FetchPlaceRequest, כמו בדוגמה הבאה:

// Include address, ID, and phone number.
List<Place.Field> placeFields = Arrays.asList(Place.Field.FORMATTED_ADDRESS,
                                              Place.Field.ID,
                                              Place.Field.INTERNATIONAL_PHONE_NUMBER);

רשימת השדות שאפשר להשתמש בהם במסכת שדות מופיעה במאמר הצבת שדות נתונים (חדש) .

מידע נוסף על מק"טים של נתוני מקומות

עדכונים בבורר המקומות ובהשלמה האוטומטית

בקטע הזה מוסברים השינויים בווידג'טים של Places (הכלי לבחירת מקום וההשלמה האוטומטית).

השלמה אוטומטית פרוגרמטית

בוצעו השינויים הבאים בהשלמה אוטומטית:

  • השם של PlaceAutocomplete השתנה לAutocomplete.
    • השם של PlaceAutocomplete.getPlace השתנה לAutocomplete.getPlaceFromIntent.
    • השם של PlaceAutocomplete.getStatus השתנה לAutocomplete.getStatusFromIntent.
  • השם של PlaceAutocomplete.RESULT_ERROR השתנה ל-AutocompleteActivity.RESULT_ERROR (הטיפול בשגיאות בקטע של ההשלמה האוטומטית לא השתנה).

הכלי לבחירת מקומות

הכלי לבחירת מקומות הוצא משימוש ב-29 בינואר 2019. היא הושבתה ב-29 ביולי 2019, והיא כבר לא זמינה. אם תמשיכו להשתמש בגרסה הזו, תוצג לכם הודעת שגיאה. ערכת ה-SDK החדשה לא תומכת בכלי לבחירת מקומות.

ווידג'טים של השלמה אוטומטית

הווידג'טים של ההשלמה האוטומטית עודכנו:

  • הקידומת Place הוסרה מכל הכיתות.
  • הוספנו תמיכה בטוקנים של סשנים. הווידג'ט מנהל את האסימונים באופן אוטומטי ברקע.
  • נוספה תמיכה במסכות שדות, שמאפשרות לכם לבחור אילו סוגים של נתוני מקומות יוחזרו אחרי שהמשתמש יבחר.

בקטעים הבאים מוסבר איך להוסיף ווידג'ט להשלמה אוטומטית לפרויקט.

הטמעת AutocompleteFragment

כדי להוסיף קטע של השלמה אוטומטית, פועלים לפי השלבים הבאים:

  1. מוסיפים קטע לפריסת ה-XML של הפעילות, כמו בדוגמה הבאה.

    <fragment
      android:id="@+id/autocomplete_fragment"
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:name=
    "com.google.android.libraries.places.widget.AutocompleteSupportFragment"
      />
    
  2. כדי להוסיף את הווידג'ט של ההשלמה האוטומטית לפעילות:

    • מאתחלים את Places, מעבירים את הקשר של האפליקציה ואת מפתח ה-API.
    • מאתחלים את AutocompleteSupportFragment.
    • מתקשרים אל setPlaceFields() כדי לציין את סוגי נתוני המקומות שרוצים לקבל.
    • מוסיפים PlaceSelectionListener כדי לבצע פעולה כלשהי עם התוצאה, וגם כדי לטפל בשגיאות שעלולות להתרחש.

    בדוגמה הבאה מוצג הוספה של ווידג'ט להשלמה אוטומטית לפעילות:

    /**
     * Initialize Places. For simplicity, the API key is hard-coded. In a production
     * environment we recommend using a secure mechanism to manage API keys.
     */
    if (!Places.isInitialized()) {
        Places.initialize(getApplicationContext(), "YOUR_API_KEY");
    }
    
    // Initialize the AutocompleteSupportFragment.
    AutocompleteSupportFragment autocompleteFragment = (AutocompleteSupportFragment)
            getSupportFragmentManager().findFragmentById(R.id.autocomplete_fragment);
    
    autocompleteFragment.setPlaceFields(Arrays.asList(Place.Field.ID, Place.Field.DISPLAY_NAME));
    
    autocompleteFragment.setOnPlaceSelectedListener(new PlaceSelectionListener() {
        @Override
        public void onPlaceSelected(Place place) {
            // TODO: Get info about the selected place.
            Log.i(TAG, "Place: " + place.getName() + ", " + place.getId());
        }
    
        @Override
        public void onError(Status status) {
            // TODO: Handle the error.
            Log.i(TAG, "An error occurred: " + status);
        }
    });
    

שימוש ב-Intent להפעלת פעילות ההשלמה האוטומטית

  1. מפעילים את Places, מעבירים את הקשר של האפליקציה ואת מפתח ה-API
  2. משתמשים ב-Autocomplete.IntentBuilder כדי ליצור Intent, ומעבירים את המצב הרצוי (מסך מלא או כיסוי).PlaceAutocomplete ה-Intent צריך לקרוא ל-startActivityForResult ולהעביר קוד בקשה שמזהה את ה-Intent.
  3. מחליפים את פונקציית הקריאה החוזרת onActivityResult כדי לקבל את המקום שנבחר.

בדוגמה הבאה אפשר לראות איך משתמשים ב-Intent כדי להפעיל השלמה אוטומטית, ואז לטפל בתוצאה:

    /**
     * Initialize Places. For simplicity, the API key is hard-coded. In a production
     * environment we recommend using a secure mechanism to manage API keys.
     */
    if (!Places.isInitialized()) {
        Places.initialize(getApplicationContext(), "YOUR_API_KEY");
    }

    ...

    // Set the fields to specify which types of place data to return.
    List<Place.Field> fields = Arrays.asList(Place.Field.ID, Place.Field.DISPLAY_NAME);

    // Start the autocomplete intent.
    Intent intent = new Autocomplete.IntentBuilder(
            AutocompleteActivityMode.FULLSCREEN, fields)
            .build(this);
    startActivityForResult(intent, AUTOCOMPLETE_REQUEST_CODE);

    ...

    /**
     * Override the activity's onActivityResult(), check the request code, and
     * do something with the returned place data (in this example its place name and place ID).
     */
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == AUTOCOMPLETE_REQUEST_CODE) {
            if (resultCode == RESULT_OK) {
                Place place = Autocomplete.getPlaceFromIntent(data);
                Log.i(TAG, "Place: " + place.getName() + ", " + place.getId());
            } else if (resultCode == AutocompleteActivity.RESULT_ERROR) {
                // TODO: Handle the error.
                Status status = Autocomplete.getStatusFromIntent(data);
                Log.i(TAG, status.getStatusMessage());
            } else if (resultCode == RESULT_CANCELED) {
                // The user canceled the operation.
            }
        }
    }

כלי בחירת המקומות כבר לא זמין

הכלי לבחירת מקומות הוצא משימוש ב-29 בינואר 2019. היא הושבתה ב-29 ביולי 2019, והיא כבר לא זמינה. אם תמשיכו להשתמש בגרסה הזו, תוצג לכם הודעת שגיאה. ערכת ה-SDK החדשה לא תומכת בכלי לבחירת מקומות.