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

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

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

מה השתנה?

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

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

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

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

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

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

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

Google ממליצה לעבור ל-Places SDK ל-Android כדי לקבל גישה לתכונות חדשות ולתיקוני באגים קריטיים בגרסאות קודמות של גרסה 2.6.0. אם אתם משתמשים בספריית התאימות, עליכם לבצע את השלבים הבאים בקטע Install the 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'

      באמצעות השורה הזו, ניתן לעבור ל-Place 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'

      באמצעות השורה הזו, ניתן לעבור ל-Place 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 בגלל ההמרה ל-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);

קודי סטטוס

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

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

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

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

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

שיטות חדשות

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

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

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

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

בעזרת 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. אין יותר צורך בבקשה נפרדת. רוחב או גובה מקסימלי של תמונות הוא 1600 פיקסלים. הפונקציה 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());
   }
});

אסימוני סשן

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

מסכות שדה

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

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