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

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

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

מה השתנה?

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

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

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

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

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

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

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

Google ממליצה לעבור ל-Places SDK ל-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: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 בגלל ההמרה ל-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. אין יותר הגבלות על מספר הבקשות לשעה.

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

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

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

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

שיטות חדשות

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

  • בנקודות קצה כבר לא נעשה שימוש בפעולה get.
  • אובייקטי הבקשה והתגובה חולקים את אותו שם כמו שיטת הלקוח המתאימה.
  • אובייקטים של בקשות כוללים עכשיו בוני מודלים (builders). הפרמטרים הנדרשים מועברים כפרמטרים של ה-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.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() מחזירה רשימה של ערכים של 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.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.Field ב-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 (בורר המקומות והשלמה אוטומטית).

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

בוצעו השינויים הבאים בautocomplete:

  • השם של 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 כדי ליצור כוונה, ומעבירים את המצב הרצוי של PlaceAutocomplete (מסך מלא או שכבת-על). הכוונה צריכה לקרוא ל-startActivityForResult ולהעביר קוד בקשה שמזהה את הכוונה.
  3. משנים את קריאת החזרה (callback) של onActivityResult כדי לקבל את המקום שנבחר.

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

    /**
     * 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 החדש לא תומך בבורר המקומות.