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

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

הדרך היחידה לגשת לתכונות ולתיקוני באגים ב-Places SDK ל-Android בגרסה 2.6.0 ואילך היא להשתמש ב-Places SDK ל-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

כל הגרסאות של ספריית התאימות של Places SDK ל-Android הוצאו משימוש ב-31 במרץ 2022. גרסה 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. אם אתם משתמשים כרגע בגרסה של Places SDK ל-Android שמשויכת ל-Play Services:

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

    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 (בורר המקומות והשלמה אוטומטית).

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

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

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