يوضّح هذا الدليل التغييرات بين مكتبة التوافق الخاصة بخدمة Places والإصدار الجديد المستقل من Places SDK لنظام التشغيل Android. إذا كنت تستخدم مكتبة التوافق مع Places بدلاً من نقل البيانات إلى الإصدار الجديد المستقل من "حزمة تطوير البرامج (SDK) الخاصة بـ Places" لنظام التشغيل Android، يوضّح لك هذا الدليل كيفية تعديل مشاريعك لاستخدام الإصدار الجديد من "حزمة تطوير البرامج (SDK) الخاصة بـ Places" لنظام التشغيل Android.
الطريقة الوحيدة للاستفادة من الميزات وإصلاح الأخطاء في الإصدارات الأحدث من الإصدار 2.6.0 من Places SDK for Android هي استخدام Places SDK for Android. تنصح Google بالتحديث من مكتبة التوافق إلى الإصدار الجديد من Places SDK for Android في أقرب وقت ممكن.
الخطأ: 9005 PLACES_API_RATE_LIMIT_EXCEEDED
ما التغييرات التي أُجريت؟
في ما يلي المجالات الرئيسية للتغيير:
- يتم توزيع الإصدار الجديد من Places SDK for Android كمكتبة عميل ثابتة. قبل كانون الثاني (يناير) 2019، كانت حزمة تطوير البرامج Places SDK for Android متاحة من خلال "خدمات Google Play". ومنذ ذلك الحين، تم توفير مكتبة توافق مع Places لتسهيل عملية الانتقال إلى حزمة Places SDK الجديدة لنظام التشغيل Android.
- تتوفّر طُرق جديدة تمامًا.
- تتوفّر الآن أقنعة الحقول للطُرق التي تعرض تفاصيل الأماكن. يمكنك استخدام أقنعة الحقول لتحديد أنواع بيانات الأماكن التي تريد عرضها.
- تم تحسين رموز الحالة المستخدَمة للإبلاغ عن الأخطاء.
- تتيح ميزة الإكمال التلقائي الآن استخدام رموز الجلسات.
- لم يعُد "أداة اختيار المكان" متوفّرًا.
لمحة عن مكتبة توافق Places
في يناير 2019، ومع طرح الإصدار 1.0 من حزمة تطوير البرامج (SDK) المستقلة للأماكن لنظام التشغيل Android، قدّمت Google مكتبة توافق للمساعدة في عملية نقل البيانات من الإصدار المتوقّف نهائيًا من حزمة تطوير البرامج (SDK) للأماكن لنظام التشغيل Android في "خدمات Google Play" (com.google.android.gms:play-services-places
).
تم توفير مكتبة التوافق هذه بشكل مؤقت لإعادة توجيه طلبات البيانات من واجهة برمجة التطبيقات (API) المخصّصة لإصدار "خدمات Google Play" وترجمتها إلى الإصدار الجديد المستقل، وذلك إلى أن يتمكّن المطوّرون من نقل الرمز البرمجي الخاص بهم لاستخدام الأسماء الجديدة في حزمة SDK المستقلة. بالنسبة إلى كل إصدار من حزمة تطوير البرامج Places SDK لنظام التشغيل Android تم إطلاقه من الإصدار 1.0 إلى الإصدار 2.6.0، تم إطلاق إصدار مطابق من مكتبة التوافق الخاصة بـ Places لتوفير وظائف مكافئة.
إيقاف مكتبة Places المتوافقة نهائيًا
تم إيقاف جميع إصدارات مكتبة التوافق الخاصة بحزمة تطوير البرامج (SDK) لنظام التشغيل Android من "أماكن Google" نهائيًا اعتبارًا من 31 آذار (مارس) 2022. الإصدار 2.6.0 هو آخر إصدار من مكتبة توافق "الأماكن". الطريقة الوحيدة للوصول إلى الميزات وإصلاح الأخطاء في الإصدارات الأحدث من 2.6.0 من Places SDK for Android هي استخدام Places SDK for Android.
تنصحك Google بالانتقال إلى Places SDK لنظام التشغيل Android للوصول إلى الميزات الجديدة وإصلاحات الأخطاء المهمة للإصدارات الأحدث من الإصدار 2.6.0. إذا كنت تستخدم حاليًا مكتبة التوافق، اتّبِع الخطوات الواردة أدناه في قسم تثبيت حزمة تطوير البرامج (SDK) للأماكن في Android لنقل البيانات إلى حزمة تطوير البرامج (SDK) للأماكن في Android.
تثبيت مكتبة البرامج
يتم توزيع الإصدار الجديد من Places SDK for Android كمكتبة عميل ثابتة.
استخدِم Maven لإضافة حزمة تطوير البرامج (SDK) الخاصة بـ Places API لنظام التشغيل Android إلى مشروعك في "استوديو Android" باتّباع الخطوات التالية:
إذا كنت تستخدم حاليًا مكتبة توافق Places:
استبدِل السطر التالي في القسم
dependencies
:implementation 'com.google.android.libraries.places:places-compat:X.Y.Z'
استخدِم السطر التالي للتبديل إلى Places SDK for Android:
implementation("com.google.android.libraries.places:places:4.3.1")
إذا كنت تستخدم حاليًا إصدار "خدمات Play" من Places SDK for Android:
استبدِل السطر التالي في القسم
dependencies
:implementation 'com.google.android.gms:play-services-places:X.Y.Z'
استخدِم السطر التالي للتبديل إلى Places SDK for Android:
implementation("com.google.android.libraries.places:places:4.3.1")
مزامنة مشروع Gradle
اضبط
minSdkVersion
لمشروع تطبيقك على 23 أو مستوى أعلى.تعديل مواد العرض "Powered by 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
أنشئ تطبيقك. إذا ظهرت لك أي أخطاء في الإنشاء بسبب عملية التحويل إلى Places SDK for 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);
رموز الحالة
تم تغيير رمز الحالة الخاص بأخطاء الحدّ الأقصى لعدد الطلبات في الثانية. يتم الآن عرض أخطاء الحدّ الأقصى لعدد الطلبات في الثانية من خلال PlaceStatusCodes.OVER_QUERY_LIMIT
. لم تعُد هناك حدود لعدد الطلبات في اليوم.
تمت إضافة رموز الحالة التالية:
REQUEST_DENIED
: تم رفض الطلب. وتشمل الأسباب المحتملة ما يلي:- لم يتم تقديم مفتاح واجهة برمجة التطبيقات.
- تم تقديم مفتاح واجهة برمجة تطبيقات غير صالح.
- لم يتم تفعيل Places API في Cloud Console.
- تم تقديم مفتاح واجهة برمجة تطبيقات مع قيود مفتاح غير صحيحة.
INVALID_REQUEST
: الطلب غير صالح بسبب وسيط مفقود أو غير صالح.
NOT_FOUND
: لم يتم العثور على أي نتيجة للطلب المقدَّم.
طُرق جديدة
يتضمّن الإصدار الجديد من Places SDK for Android طرقًا جديدة تمامًا تم تصميمها لتحقيق التناسق. تلتزم جميع الطرق الجديدة بما يلي:
- لم تعُد نقاط النهاية تستخدم الفعل
get
. - تتشارك عناصر الطلب والاستجابة الاسم نفسه مع طريقة العميل المقابلة.
- تتضمّن عناصر الطلب الآن أدوات إنشاء، ويتم تمرير المَعلمات المطلوبة كمَعلمات لأداة إنشاء الطلب.
- لم يعُد يتم استخدام المخازن المؤقتة.
يعرض هذا القسم الطرق الجديدة ويوضّح كيفية عملها.
استرداد مكان باستخدام المعرّف
استخدِم fetchPlace()
للحصول على تفاصيل حول مكان معيّن. تعمل الدالة fetchPlace()
بشكل مشابه للدالة
getPlaceById()
.
اتّبِع الخطوات التالية لجلب مكان:
اتّصِل بالدالة
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();
اتّصِل بالرقم
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()
.
اتّبِع الخطوات التالية لجلب صور الأماكن:
حدِّد موعدًا لإجراء مكالمة مع
fetchPlace()
. يُرجى التأكّد من تضمين الحقلPHOTO_METADATAS
في طلبك:List<Place.Field> fields = Arrays.asList(Place.Field.PHOTO_METADATAS);
الحصول على عنصر Place (يستخدم هذا المثال
fetchPlace()
، ولكن يمكنك أيضًا استخدامfindCurrentPlace()
):FetchPlaceRequest placeRequest = FetchPlaceRequest.builder(placeId, fields).build();
أضِف
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()
للعثور على الموقع الجغرافي الحالي لجهاز المستخدم. تعرض هذه الطريقة قائمة بعناصر PlaceLikelihood
تشير إلى الأماكن التي من المرجّح أن يكون جهاز المستخدم فيها.findCurrentPlace()
تعمل findCurrentPlace()
بشكل مشابه لـ getCurrentPlace()
.
اتّبِع الخطوات التالية للحصول على الموقع الجغرافي الحالي لجهاز المستخدم:
تأكَّد من أنّ تطبيقك يطلب الحصول على إذنَي
ACCESS_FINE_LOCATION
وACCESS_WIFI_STATE
. يجب أن يمنح المستخدم الإذن بالوصول إلى الموقع الجغرافي الحالي لجهازه. اطّلِع على طلب أذونات التطبيق للحصول على التفاصيل.أنشئ
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();
استدعِ الدالة 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
لإضافة جزء من ميزة الإكمال التلقائي، اتّبِع الخطوات التالية:
أضِف جزءًا إلى تنسيق 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" />
لإضافة أداة الإكمال التلقائي إلى النشاط، اتّبِع الخطوات التالية:
- ابدأ
Places
، مع تمرير سياق التطبيق ومفتاح واجهة برمجة التطبيقات. - ابدأ عملية إعداد
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); } });
- ابدأ
استخدام هدف لتشغيل نشاط الإكمال التلقائي
- إعداد
Places
، مع تمرير سياق التطبيق ومفتاح واجهة برمجة التطبيقات - استخدِم
Autocomplete.IntentBuilder
لإنشاء هدف، مع تمرير الوضع المطلوبPlaceAutocomplete
(ملء الشاشة أو التراكب). يجب أن يستدعي الغرضstartActivityForResult
، مع تمرير رمز طلب يحدّد الغرض. - يمكنك إلغاء الدالة
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) الجديدة مع أداة اختيار الأماكن.