يوضح هذا الدليل التغييرات بين مكتبة التوافق في الأماكن والإصدار المستقل الجديد من الأماكن SDK لنظام التشغيل Android. إذا كنت تستخدم مكتبة التوافق مع الأماكن بدلاً من الترحيل إلى الإصدار المستقل الجديد من حزمة تطوير برامج الأماكن لـ Android، فسيوضح لك هذا الدليل كيفية تحديث مشاريعك لاستخدام الإصدار الجديد من الأماكن SDK لنظام التشغيل Android.
إن الطريقة الوحيدة للدخول إلى الميزات وإصلاحات الأخطاء في حزمة تطوير البرامج (SDK) للأماكن لنظام التشغيل Android أعلى من الإصدار 2.6.0 تتمثل في استخدام حزمة SDK للأماكن في Android. توصي Google بالتحديث من مكتبة التوافق إلى الإصدار الجديد من الأماكن SDK لنظام التشغيل Android في أقرب وقت ممكن.
ما التغييرات التي أُجريت؟
في ما يلي النواحي الرئيسية للتغيير:
- يتم توزيع الإصدار الجديد من الأماكن SDK لنظام التشغيل Android كمكتبة عميل ثابتة. قبل كانون الثاني (يناير) 2019، تم توفير الأماكن المخصصة لـ Android من خلال خدمات Google Play. ومنذ ذلك الحين، تم توفير مكتبة التوافق في الأماكن لتيسير النقل إلى الإصدار الجديد من الأماكن في Android.
- هناك طرق جديدة تمامًا.
- أصبحت أقنعة الحقول معتمدة الآن للطرق التي تعرض تفاصيل المكان. يمكنك استخدام أقنعة الحقول لتحديد أنواع بيانات الأماكن المطلوب عرضها.
- تم تحسين رموز الحالة المُستخدَمة للإبلاغ عن الأخطاء.
- يدعم الإكمال التلقائي الآن الرموز المميزة للجلسة.
- لم يعد منتقي الأماكن متاحًا.
حول مكتبة توافق الأماكن
في كانون الثاني (يناير) 2019 مع طرح الإصدار 1.0 من حزمة SDK للأماكن المستقلة لنظام التشغيل Android،
قدّمت Google مكتبة توافق للمساعدة في عملية الترحيل
من إصدار خدمات Google Play الذي تم إيقاف العمل به من تطبيق SDK لأماكن Google لأجهزة Android
(com.google.android.gms:play-services-places
).
تم توفير مكتبة التوافق مؤقتًا لإعادة توجيه استدعاءات واجهة برمجة التطبيقات الموجّهة إلى إصدار خدمات Google Play إلى الإصدار المستقل الجديد وترجمتها إلى أن يتمكن مطوّرو البرامج من نقل الرموز الخاصة بهم لاستخدام الأسماء الجديدة في حزمة تطوير البرامج (SDK) المستقلة. بالنسبة إلى كل إصدار من SDK للأماكن لأجهزة Android والذي تم طرحه من الإصدار 1.0 إلى الإصدار 2.6.0، تم طرح إصدار مقابل من مكتبة التوافق في الأماكن لتوفير وظائف مكافئة.
تجميد وإيقاف مكتبة التوافق في الأماكن
سيتم إيقاف جميع إصدارات مكتبة التوافق لحزمة تطوير البرامج (SDK) لخدمة الأماكن من Android اعتبارًا من 31 آذار (مارس) 2022. الإصدار 2.6.0 هو الإصدار الأخير من مكتبة التوافق مع الأماكن. إن الطريقة الوحيدة للدخول إلى الميزات وإصلاحات الأخطاء في حزمة SDK للأماكن التي تعمل بنظام التشغيل Android أعلى من الإصدار 2.6.0 تتمثل في استخدام حزمة SDK للأماكن في Android.
توصي Google بالترحيل إلى الأماكن SDK لـ Android للوصول إلى الميزات الجديدة وإصلاحات الأخطاء الحرجة للإصدارات الأحدث من الإصدار 2.6.0. إذا كنت تستخدم مكتبة التوافق حاليًا، فاتبع الخطوات أدناه في قسم تثبيت حزمة SDK للأماكن في Android للترحيل إلى الأماكن SDK لـ Android.
تثبيت مكتبة البرامج
يتم توزيع الإصدار الجديد من تطبيق الأماكن لـ Android كمكتبة عميل ثابتة.
استخدم Maven لإضافة تطبيق SDK لأماكن Android إلى مشروع Android Studio:
إذا كنت تستخدم حاليًا مكتبة توافق الأماكن:
استبدل السطر التالي في قسم
dependencies
:implementation 'com.google.android.libraries.places:places-compat:X.Y.Z'
باستخدام هذا السطر للتبديل إلى الأماكن SDK لنظام التشغيل Android:
implementation 'com.google.android.libraries.places:places:3.0.0'
إذا كنت تستخدم حاليًا إصدار "خدمات Play" من حِزمة تطوير البرامج (SDK) الخاصة بتطبيق "الأماكن" لنظام التشغيل Android:
استبدل السطر التالي في قسم
dependencies
:implementation 'com.google.android.gms:play-services-places:X.Y.Z'
باستخدام هذا السطر للتبديل إلى الأماكن SDK لنظام التشغيل Android:
implementation 'com.google.android.libraries.places:places:3.0.0'
مزامنة مشروع Gradle.
اضبط
minSdkVersion
لمشروع التطبيق على 16 أو أعلى.تحديث مواد العرض "المدعومة من 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
أنشئ تطبيقك. وإذا كنت ترى أي أخطاء في الإصدار بسبب التحويل إلى حزمة SDK لأماكن Google، فراجع الأقسام أدناه للحصول على معلومات حول حل هذه الأخطاء.
تهيئة عميل SDK للأماكن الجديد
ابدأ في تهيئة عميل 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
— تم رفض الطلب. وتشمل الأسباب المحتملة ما يلي:- لم يتم تقديم مفتاح واجهة برمجة التطبيقات.
- تم تقديم مفتاح واجهة برمجة تطبيقات غير صالح.
- لم يتم تفعيل واجهة برمجة تطبيقات الأماكن في Cloud Console.
- تم تقديم مفتاح واجهة برمجة تطبيقات مع قيود مفتاح غير صحيحة.
INVALID_REQUEST
— الطلب غير صالح بسبب وسيطة مفقودة أو غير صالحة.NOT_FOUND
— لم يتم العثور على أي نتائج للطلب المعني.
طرق جديدة
يقدم الإصدار الجديد من الأماكن SDK لنظام التشغيل 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.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);
الحصول على كائن مكان (هذا المثال يستخدم
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()
للعثور على الموقع الجغرافي الحالي لجهاز المستخدم. تعرض findCurrentPlace()
قائمة بـ PlaceLikelihood
تشير إلى الأماكن التي يُرجح وجود جهاز المستخدم فيها. 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.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.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
لإضافة جزء إكمال تلقائي، اتّبع الخطوات التالية:
أضف جزءًا إلى تنسيق 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.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.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) الجديدة مع منتقي الأماكن.