مهاجرت به سرویس گیرنده SDK مکان‌های جدید

این راهنما تغییرات بین کتابخانه سازگاری Places و نسخه مستقل جدید Places SDK برای Android را توضیح می دهد. اگر به جای مهاجرت به نسخه مستقل جدید Places SDK برای Android از کتابخانه سازگاری Places استفاده کرده اید، این راهنما به شما نشان می دهد چگونه پروژه های خود را برای استفاده از نسخه جدید 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 در دسترس قرار گرفت. از آن زمان، یک کتابخانه سازگاری Places برای سهولت انتقال به Places SDK جدید برای Android ارائه شد.
  • روش های کاملاً جدیدی وجود دارد.
  • اکنون ماسک‌های فیلد برای روش‌هایی پشتیبانی می‌شوند که جزئیات مکان را برمی‌گردانند. می‌توانید از ماسک‌های فیلد برای تعیین نوع داده‌های مکان استفاده کنید.
  • کدهای وضعیت مورد استفاده برای گزارش خطاها بهبود یافته است.
  • اکنون تکمیل خودکار از نشانه‌های جلسه پشتیبانی می‌کند.
  • انتخاب مکان دیگر در دسترس نیست .

درباره کتابخانه سازگاری Places

در ژانویه 2019 با انتشار نسخه 1.0 از Places SDK مستقل برای Android، Google یک کتابخانه سازگاری برای کمک به انتقال از نسخه از کارافتاده خدمات Google Play Places SDK برای Android ( com.google.android.gms:play-services-places ارائه کرد. com.google.android.gms:play-services-places ).

این کتابخانه سازگاری به طور موقت برای هدایت و ترجمه تماس‌های API با هدف نسخه خدمات Google Play به نسخه مستقل جدید ارائه شده است تا زمانی که توسعه‌دهندگان بتوانند کد خود را برای استفاده از نام‌های جدید در 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 توصیه می‌کند برای دسترسی به ویژگی‌های جدید و رفع اشکالات مهم برای نسخه‌های بالاتر از نسخه 2.6.0، به Places SDK برای Android مهاجرت کنید. اگر در حال حاضر از کتابخانه سازگاری استفاده می کنید، مراحل زیر را در قسمت Install the Places SDK for Android دنبال کنید تا به Places SDK for 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 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. اپلیکیشن خود را بسازید اگر به دلیل تبدیل خود به 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 نامعتبر ارائه شده است.
    • API Places در کنسول Cloud فعال نشده است.
    • یک کلید API با محدودیت های کلیدی نادرست ارائه شده است.
  • INVALID_REQUEST - درخواست نامعتبر است به دلیل وجود آرگومان موجود یا نامعتبر.

  • NOT_FOUND - هیچ نتیجه ای برای درخواست داده شده یافت نشد.

روش های جدید

نسخه جدید Places SDK برای اندروید روش‌های کاملاً جدیدی را معرفی می‌کند که برای سازگاری طراحی شده‌اند. همه روش های جدید از موارد زیر پیروی می کنند:

  • نقاط پایانی دیگر از فعل 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. برای مدیریت FetchPlaceResponse با addOnSuccessListener() تماس بگیرید. یک نتیجه 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.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);

برای فهرستی از فیلدهایی که می‌توانید در یک فیلد ماسک استفاده کنید، به فیلدهای داده مکان (جدید) مراجعه کنید.

درباره مکان‌های SKU داده‌های مکان‌ها بیشتر بخوانید.

به‌روزرسانی‌های انتخاب‌کننده مکان و تکمیل خودکار

این بخش تغییرات ویجت های Places (انتخاب مکان و تکمیل خودکار) را توضیح می دهد.

تکمیل خودکار برنامه ای

تغییرات زیر برای تکمیل خودکار انجام شد:

  • PlaceAutocomplete به Autocomplete تغییر نام داد.
    • PlaceAutocomplete.getPlace به Autocomplete.getPlaceFromIntent تغییر نام داد.
    • PlaceAutocomplete.getStatus به Autocomplete.getStatusFromIntent تغییر نام داد.
  • نام PlaceAutocomplete.RESULT_ERROR به AutocompleteActivity.RESULT_ERROR تغییر نام داده شد (بررسی خطا برای قطعه تکمیل خودکار تغییر نکرده است).

انتخاب کننده مکان

Place Picker در 29 ژانویه 2019 منسوخ شد. در 29 ژوئیه 2019 خاموش شد و دیگر در دسترس نیست. ادامه استفاده منجر به پیام خطا می شود. SDK جدید از Place Picker پشتیبانی نمی‌کند.

تکمیل خودکار ویجت ها

ویجت های تکمیل خودکار به روز شده اند:

  • پیشوند 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);
        }
    });
    

از یک قصد برای راه اندازی فعالیت تکمیل خودکار استفاده کنید

  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.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.
            }
        }
    }

Place Picker دیگر در دسترس نیست

Place Picker در 29 ژانویه 2019 منسوخ شد. در 29 ژوئیه 2019 خاموش شد و دیگر در دسترس نیست. ادامه استفاده منجر به پیام خطا می شود. SDK جدید از Place Picker پشتیبانی نمی‌کند.