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

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

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

מה השתנה?

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

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

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

בינואר 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, פורסמה גרסה תואמת של ספריית התאימות של מקומות Google כדי לספק פונקציונליות מקבילה.

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

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

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

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

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

בעזרת Maven תוכלו להוסיף את Places SDK ל-Android לפרויקט ב-Android Studio:

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

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

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

      באמצעות השורה הזו, למעבר אל Places SDK עבור Android:

          implementation 'com.google.android.libraries.places:places:3.3.0'

  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:3.3.0'

  3. צריך לסנכרן את פרויקט Gradle.

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

  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 כלשהן בעקבות ההמרה ל-Place 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);

קודי סטטוס

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

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

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

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

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

שיטות חדשות

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

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

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

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

באמצעות 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.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() מחזירה רשימה של PlaceLikelihood שמציין את המקומות שבהם יש את הסיכוי הגבוה ביותר להימצא במכשיר של המשתמש. 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.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.Field ב-FetchPlaceRequest, כמו בדוגמה הבאה:

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

אפשר להשתמש באחד או יותר מהשדות הבאים:

  • Place.Field.ADDRESS
  • Place.Field.ID
  • Place.Field.LAT_LNG
  • Place.Field.NAME
  • Place.Field.OPENING_HOURS
  • Place.Field.PHONE_NUMBER
  • Place.Field.PHOTO_METADATAS
  • Place.Field.PLUS_CODE
  • Place.Field.PRICE_LEVEL
  • Place.Field.RATING
  • Place.Field.TYPES
  • Place.Field.USER_RATINGS_TOTAL
  • Place.Field.VIEWPORT
  • Place.Field.WEBSITE_URI

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

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

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

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

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

  • השם של 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.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, ולהעביר קוד בקשה שמזהה את הכוונה שלכם.
  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.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 החדשה אינה תומכת בבוחר המקומות.