ميزات Android المتقدمة في Kotlin 04.1: خرائط Google لنظام التشغيل Android

1. قبل البدء

يتيح لك إنشاء تطبيقات باستخدام "خرائط Google" إضافة ميزات إلى تطبيقك، مثل صور الأقمار الصناعية وعناصر تحكّم قوية في واجهة المستخدم للخرائط وتتبُّع الموقع الجغرافي وعلامات الموقع الجغرافي. يمكنك إضافة قيمة إلى "خرائط Google" العادية من خلال عرض معلومات من مجموعة البيانات الخاصة بك، مثل مواقع مناطق الصيد أو التسلق المعروفة. يمكنك أيضًا إنشاء ألعاب يستكشف فيها اللاعب العالم المادي، مثل البحث عن الكنز أو حتى ألعاب الواقع المعزّز.

في هذا الدرس، ستنشئ تطبيقًا على "خرائط Google" باسم Wander يعرض خرائط مخصّصة ويُظهر الموقع الجغرافي للمستخدم.

المتطلبات الأساسية

المعرفة بما يلي:

  • كيفية إنشاء تطبيق Android أساسي وتشغيله باستخدام "استوديو Android"
  • كيفية إنشاء الموارد وإدارتها، مثل السلاسل
  • كيفية إعادة تصميم الرمز البرمجي وإعادة تسمية المتغيرات باستخدام "استوديو Android"
  • كيفية استخدام خريطة Google كمستخدم
  • كيفية ضبط أذونات وقت التشغيل

أهداف الدورة التعليمية

  • كيفية الحصول على مفتاح واجهة برمجة تطبيقات من "وحدة تحكّم Google API" وتسجيل المفتاح في تطبيقك
  • كيفية دمج "خريطة Google" في تطبيقك
  • كيفية عرض أنواع مختلفة من الخرائط
  • كيفية تصميم "خريطة Google"
  • كيفية إضافة علامات إلى خريطتك
  • كيفية السماح للمستخدم بوضع علامة على نقطة اهتمام
  • كيفية تفعيل ميزة "تتبُّع الموقع الجغرافي"
  • كيفية إنشاء تطبيق Wander يتضمّن "خريطة Google"
  • كيفية إنشاء ميزات مخصّصة لتطبيقك، مثل العلامات والأنماط
  • كيفية تفعيل ميزة "تتبُّع الموقع الجغرافي" في تطبيقك

2. نظرة عامة على التطبيق

في هذا الدرس التطبيقي حول الترميز، ستنشئ تطبيق Wander الذي يعرض خريطة Google بتصميم مخصّص. يتيح لك تطبيق Wander إمكانية وضع علامات على المواقع الجغرافية وإضافة تراكبات وعرض موقعك الجغرافي في الوقت الفعلي.

5b12eda7f467bc2f.png

3- المهمة: إعداد المشروع والحصول على مفتاح واجهة برمجة التطبيقات

تتطلّب حزمة تطوير البرامج بالاستناد إلى بيانات "خرائط Google" للتطبيقات المتوافقة مع Android مفتاح واجهة برمجة تطبيقات. للحصول على مفتاح واجهة برمجة التطبيقات، سجِّل مشروعك في صفحة "واجهات برمجة التطبيقات والخدمات". يرتبط مفتاح واجهة برمجة التطبيقات بشهادة رقمية تربط التطبيق بمؤلفه. لمزيد من المعلومات حول استخدام الشهادات الرقمية وتوقيع تطبيقك، يُرجى الاطّلاع على مقالة توقيع تطبيقك.

في هذا الدرس التطبيقي، ستستخدم مفتاح واجهة برمجة التطبيقات لشهادة تصحيح الأخطاء. شهادة تصحيح الأخطاء غير آمنة بطبيعتها، كما هو موضّح في مقالة توقيع إصدار مخصص لتصحيح الأخطاء. تتطلّب تطبيقات Android المنشورة التي تستخدم حزمة تطوير البرامج بالاستناد إلى بيانات خرائط Google للتطبيقات المتوافقة مع Android مفتاح واجهة برمجة تطبيقات ثانيًا، وهو مفتاح شهادة الإصدار. لمزيد من المعلومات حول الحصول على شهادة إصدار، يُرجى الاطّلاع على الحصول على مفتاح API.

يتضمّن "استوديو Android" نموذج "نشاط خرائط Google" الذي ينشئ رمز نموذج مفيدًا. يتضمّن رمز النموذج ملف google_maps_api.xml يحتوي على رابط يسهّل الحصول على مفتاح واجهة برمجة التطبيقات.

الخطوة 1: إنشاء مشروع Wander باستخدام نموذج الخرائط

  1. أنشِئ مشروعًا جديدًا في "استوديو Android".
  2. اختَر نموذج نشاط "خرائط Google".

d6b874bb19ea68cd.png

  1. حدِّد اسمًا للمشروع Wander.
  2. اضبط الحد الأدنى لمستوى واجهة برمجة التطبيقات على المستوى 19. تأكَّد من أنّ اللغة هي Kotlin.
  3. انقر على إنهاء.
  4. بعد انتهاء إنشاء التطبيق، ألقِ نظرة على مشروعك والملفات التالية ذات الصلة بالخرائط التي ينشئها "استوديو Android" لك:

google_maps_api.xml: يمكنك استخدام ملف الإعداد هذا لتخزين مفتاح واجهة برمجة التطبيقات. ينشئ النموذج ملفّين باسم google_maps_api.xml: أحدهما للتصحيح والآخر للإصدار. يقع ملف مفتاح واجهة برمجة التطبيقات لشهادة تصحيح الأخطاء في src/debug/res/values. يقع ملف مفتاح واجهة برمجة التطبيقات لشهادة الإصدار في src/release/res/values. في هذا الدرس العملي، ستستخدم شهادة تصحيح الأخطاء فقط.

activity_maps.xml: يحتوي ملف التصميم هذا على جزء واحد يملأ الشاشة بأكملها. الفئة SupportMapFragment هي فئة فرعية من الفئة Fragment. SupportMapFragment هي أبسط طريقة لوضع خريطة في تطبيق، وهي عبارة عن برنامج تضمين لعرض خريطة من أجل التعامل تلقائيًا مع احتياجات مراحل النشاط الضرورية.

يمكنك تضمين SupportMapFragment في ملف تصميم باستخدام علامة <fragment> في أي ViewGroup، مع إضافة السمة name.

android:name="com.google.android.gms.maps.SupportMapFragment"

MapsActivity.java: ينشئ ملف MapsActivity.kt عنصر SupportMapFragment في طريقة onCreate()، ويستخدم getMapAsync() للفئة من أجل تهيئة نظام الخرائط والعرض تلقائيًا. يجب أن ينفّذ النشاط الذي يحتوي على SupportMapFragment الواجهة OnMapReadyCallback والطريقة onMapReady() الخاصة بهذه الواجهة. يتم استدعاء الطريقة onMapReady() عند تحميل الخريطة.

الخطوة 2: الحصول على مفتاح واجهة برمجة التطبيقات

  1. افتح إصدار تصحيح الأخطاء من ملف google_maps_api.xml.
  2. في الملف، ابحث عن تعليق يتضمّن عنوان URL طويلاً. تتضمّن مَعلمات عنوان URL معلومات محدّدة حول تطبيقك.
  3. انسخ عنوان URL والصقه في المتصفّح.
  4. اتّبِع التعليمات لإنشاء مشروع في صفحة "واجهات برمجة التطبيقات والخدمات". بسبب المَعلمات الواردة في عنوان URL المقدَّم، تعرف الصفحة أنّه يجب تفعيل حزمة تطوير البرامج بالاستناد إلى بيانات خرائط Google للتطبيقات المتوافقة مع Android تلقائيًا.
  5. انقر على إنشاء مفتاح واجهة برمجة تطبيقات.
  6. في الصفحة التالية، انتقِل إلى قسم "مفاتيح واجهة برمجة التطبيقات" وانقر على المفتاح الذي أنشأته للتو.
  7. انقر على تقييد المفتاح واختَر حزمة تطوير البرامج بالاستناد إلى بيانات خرائط Google للتطبيقات المتوافقة مع Android لتقييد استخدام المفتاح على تطبيقات Android.
  8. انسخ مفتاح واجهة برمجة التطبيقات الذي تم إنشاؤه. يبدأ بـ "AIza".
  9. في الملف google_maps_api.xml، الصِق المفتاح في السلسلة google_maps_key حيث يظهر النص YOUR_KEY_HERE.
  10. شغِّل تطبيقك. من المفترض أن تظهر لك خريطة مضمّنة في نشاطك مع علامة محدّدة في سيدني، أستراليا. (علامة Sydney هي جزء من النموذج ويمكنك تغييرها لاحقًا).

34dc9dd877c90996.png

الخطوة 3: إعادة تسمية mMap

يتضمّن MapsActivity lateinit خاصًا var باسم mMap، وهو من النوع GoogleMap. للتوافق مع اصطلاحات التسمية في Kotlin، غيِّر اسم mMap إلى map.

  1. في MapsActivity، انقر بزر الماوس الأيمن على mMap وانقر على إعادة تصميم > إعادة تسمية...

e713ccb3384450c6.png

  1. غيِّر اسم المتغيّر إلى map.

لاحظ كيف تتغيّر أيضًا جميع المراجع إلى mMap في الدالة onMapReady() إلى map.

4. المهمة: إضافة أنواع الخرائط

تتضمّن "خرائط Google" عدة أنواع من الخرائط: عادية ومختلطة وقمر صناعي وتضاريس و"بلا خريطة" (لعدم عرض أي خريطة على الإطلاق).

خريطة النواظم

خريطة القمر الصناعي

خريطة هجينة

خريطة التضاريس

يقدّم كل نوع من الخرائط أنواعًا مختلفة من المعلومات. على سبيل المثال، عند استخدام الخرائط للتنقّل في السيارة، من المفيد رؤية أسماء الشوارع، لذا يمكنك استخدام الخيار العادي. عند المشي لمسافات طويلة، قد تكون خريطة التضاريس مفيدة لتحديد المسافة المتبقية للوصول إلى القمة.

في هذه المهمة، عليك إجراء ما يلي:

  1. أضِف شريط تطبيقات يتضمّن قائمة خيارات تتيح للمستخدم تغيير نوع الخريطة.
  2. حرِّك الموقع الجغرافي الأوّلي للخريطة إلى الموقع الجغرافي لمنزلك.
  3. إضافة دعم للعلامات التي تشير إلى مواقع جغرافية فردية على الخريطة ويمكن أن تتضمّن تصنيفًا

إضافة قائمة لأنواع الخرائط

في هذه الخطوة، ستضيف شريط تطبيقات يتضمّن قائمة خيارات تتيح للمستخدم تغيير نوع الخريطة.

  1. لإنشاء ملف XML جديد للقائمة، انقر بزر الماوس الأيمن على دليل res واختَر جديد (New) > ملف موارد Android (Android Resource File).
  2. في مربّع الحوار، اكتب اسمًا للملف map_options.
  3. اختَر القائمة لنوع المرجع.
  4. انقر على موافق.
  5. في علامة التبويب الرمز، استبدِل الرمز في الملف الجديد بالرمز التالي لإنشاء خيارات قائمة الخريطة. تم حذف نوع الخريطة "بلا" لأنّ اختيار "بلا" يؤدي إلى عدم ظهور أي خريطة على الإطلاق. تتسبّب هذه الخطوة في حدوث خطأ، ولكنك ستعمل على حلّه في الخطوة التالية.
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:app="http://schemas.android.com/apk/res-auto">
   <item
       android:id="@+id/normal_map"
       android:title="@string/normal_map"
       app:showAsAction="never" />
   <item
       android:id="@+id/hybrid_map"
       android:title="@string/hybrid_map"
       app:showAsAction="never" />
   <item
       android:id="@+id/satellite_map"
       android:title="@string/satellite_map"
       app:showAsAction="never" />
   <item
       android:id="@+id/terrain_map"
       android:title="@string/terrain_map"
       app:showAsAction="never" />
</menu>
  1. في strings.xml، أضِف مراجع لسمات title من أجل حلّ الأخطاء.
<resources>
   ...
   <string name="normal_map">Normal Map</string>
   <string name="hybrid_map">Hybrid Map</string>
   <string name="satellite_map">Satellite Map</string>
   <string name="terrain_map">Terrain Map</string>
   <string name="lat_long_snippet">Lat: %1$.5f, Long: %2$.5f</string>
   <string name="dropped_pin">Dropped Pin</string>
   <string name="poi">poi</string>
</resources>
  1. في MapsActivity، يمكنك إلغاء طريقة onCreateOptionsMenu() وتوسيع القائمة من ملف الموارد map_options.
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
   val inflater = menuInflater
   inflater.inflate(R.menu.map_options, menu)
   return true
}
  1. في MapsActivity.kt، ألغِ طريقة onOptionsItemSelected(). غيِّر نوع الخريطة باستخدام ثوابت نوع الخريطة لعرض اختيار المستخدم.
override fun onOptionsItemSelected(item: MenuItem) = when (item.itemId) {
   // Change the map type based on the user's selection.
   R.id.normal_map -> {
       map.mapType = GoogleMap.MAP_TYPE_NORMAL
       true
   }
   R.id.hybrid_map -> {
       map.mapType = GoogleMap.MAP_TYPE_HYBRID
       true
   }
   R.id.satellite_map -> {
       map.mapType = GoogleMap.MAP_TYPE_SATELLITE
       true
   }
   R.id.terrain_map -> {
       map.mapType = GoogleMap.MAP_TYPE_TERRAIN
       true
   }
   else -> super.onOptionsItemSelected(item)
}
  1. شغِّل التطبيق.
  2. انقر على 428da163b831115b.png لتغيير نوع الخريطة. لاحظ كيف يتغيّر مظهر الخريطة بين الأوضاع المختلفة.

6fa42970d87f5dc7.png

5- المهمة: إضافة علامات

يتضمّن الإجراء onMapReady() بشكلٍ تلقائي رمزًا برمجيًا يضع علامة في سيدني، أستراليا، حيث تم إنشاء "خرائط Google". تعمل دالة معاودة الاتصال التلقائية أيضًا على تحريك الخريطة لتوسيطها على "سيدني".

في هذه المهمة، ستجعل كاميرا الخريطة تنتقل إلى منزلك، وتكبّر الخريطة إلى المستوى الذي تحدّده، وتضع علامة في ذلك الموقع الجغرافي.

الخطوة 1: تكبير منزلك وإضافة علامة

  1. في ملف MapsActivity.kt، ابحث عن طريقة onMapReady(). أزِل الرمز الذي يضع العلامة في سيدني ويحرّك الكاميرا. يجب أن تبدو طريقتك الآن على النحو التالي.
override fun onMapReady(googleMap: GoogleMap) {
   map = googleMap

}
  1. ابحث عن خطَّي الطول والعرض لمنزلك باتّباع هذه التعليمات.
  2. أنشئ قيمة لخط العرض وقيمة لخط الطول، وأدخِل قيمتَي الفاصلة العائمة.
val latitude = 37.422160
val longitude = -122.084270
  1. أنشئ عنصر LatLng جديدًا باسم homeLatLng. في العنصر homeLatLng، أدخِل القيم التي أنشأتها للتو.
val homeLatLng = LatLng(latitude, longitude)
  1. أنشئ val لتحديد مستوى التقريب الذي تريده على الخريطة. استخدِم مستوى التكبير/التصغير 15f.
val zoomLevel = 15f

يتحكّم مستوى التكبير/التصغير في مدى تكبير الخريطة. تقدّم لك القائمة التالية فكرة عن مستوى التفاصيل الذي يظهره كل مستوى من مستويات التكبير:

  • 1: العالم
  • 5: كتلة أرضية/قارة
  • 10: المدينة
  • 15: الشوارع
  • 20: المباني
  1. حرِّك الكاميرا إلى homeLatLng من خلال استدعاء الدالة moveCamera() على العنصر map وتمرير العنصر CameraUpdate باستخدام CameraUpdateFactory.newLatLngZoom(). مرِّر العنصر homeLatLng وzoomLevel.
map.moveCamera(CameraUpdateFactory.newLatLngZoom(homeLatLng, zoomLevel))
  1. أضِف علامة إلى الخريطة في homeLatLng.
map.addMarker(MarkerOptions().position(homeLatLng))

يجب أن تبدو طريقتك النهائية على النحو التالي:

override fun onMapReady(googleMap: GoogleMap) {
   map = googleMap

   //These coordinates represent the latitude and longitude of the Googleplex.
   val latitude = 37.422160
   val longitude = -122.084270
   val zoomLevel = 15f

   val homeLatLng = LatLng(latitude, longitude)
   map.moveCamera(CameraUpdateFactory.newLatLngZoom(homeLatLng, zoomLevel))
   map.addMarker(MarkerOptions().position(homeLatLng))
}
  1. شغِّل تطبيقك. من المفترض أن تنتقل الخريطة إلى منزلك، وتُكبَّر إلى المستوى المطلوب، ويتم وضع علامة على منزلك.

fc939024778ee76.png

الخطوة 2: السماح للمستخدمين بإضافة علامة باستخدام نقرة مع الاستمرار

في هذه الخطوة، ستضيف علامة عندما ينقر المستخدم مع الاستمرار على موقع جغرافي على الخريطة.

  1. أنشئ رمزًا أوليًا للدالة في MapsActivity باسم setMapLongClick() يأخذ GoogleMap كوسيطة.
  2. أضِف متتبِّعًا setOnMapLongClickListener إلى عنصر إنشاء الخريطة.
private fun setMapLongClick(map:GoogleMap) {
   map.setOnMapLongClickListener { }
}
  1. في setOnMapLongClickListener()، استدعِ طريقة addMarker(). مرِّر كائن MarkerOptions جديدًا مع ضبط الموضع على LatLng الذي تم تمريره.
private fun setMapLongClick(map: GoogleMap) {
   map.setOnMapLongClickListener { latLng ->
       map.addMarker(
           MarkerOptions()
               .position(latLng)
       )
   }
}
  1. في نهاية طريقة onMapReady()، استدعِ setMapLongClick() باستخدام map.
override fun onMapReady(googleMap: GoogleMap) {
   ...
  
   setMapLongClick(map)
}
  1. تشغيل تطبيقك
  2. انقر مع الاستمرار على الخريطة لوضع محدّد موقع في مكان معيّن.
  3. انقر على العلامة، ما يؤدي إلى توسيطها على الشاشة.

4ff8d1c1db3bca9e.png

الخطوة 3: إضافة نافذة معلومات للعلامة

في هذه الخطوة، ستضيف InfoWindow يعرض إحداثيات العلامة عند النقر عليها.

  1. في setMapLongClick()setOnMapLongClickListener()، أنشئ val لـ snippet. المقتطف هو نص إضافي يظهر بعد العنوان. تعرض المقتطفات خطوط الطول والعرض الخاصة بعلامة.
private fun setMapLongClick(map: GoogleMap) {
   map.setOnMapLongClickListener { latLng ->
       // A snippet is additional text that's displayed after the title.
       val snippet = String.format(
           Locale.getDefault(),
           "Lat: %1$.5f, Long: %2$.5f",
           latLng.latitude,
           latLng.longitude
       )
       map.addMarker(
           MarkerOptions()
               .position(latLng)
       )
   }
}
  1. في addMarker()، اضبط title العلامة على "دبوس تم إسقاطه" باستخدام مورد السلاسل النصية R.string.dropped_pin.
  2. اضبط قيمة snippet للعلامة على snippet.

تبدو الدالة المكتملة على النحو التالي:

private fun setMapLongClick(map: GoogleMap) {
   map.setOnMapLongClickListener { latLng ->
       // A Snippet is Additional text that's displayed below the title.
       val snippet = String.format(
           Locale.getDefault(),
           "Lat: %1$.5f, Long: %2$.5f",
           latLng.latitude,
           latLng.longitude
       )
       map.addMarker(
           MarkerOptions()
               .position(latLng)
               .title(getString(R.string.dropped_pin))
               .snippet(snippet)
              
       )
   }
}
  1. تشغيل تطبيقك
  2. انقر مع الاستمرار على الخريطة لإضافة علامة الموقع الجغرافي.
  3. انقر على محدّد الموقع لعرض نافذة المعلومات.

63f210e6e47dfa29.png

الخطوة 4: إضافة متتبِّع لنقاط الاهتمام

تظهر تلقائيًا نقاط الاهتمام على الخريطة مع الرموز المقابلة لها. تشمل نقاط الاهتمام المتنزّهات والمدارس والمباني الحكومية وغيرها. عند ضبط نوع الخريطة على normal، تظهر أيضًا نقاط الاهتمام الخاصة بالأنشطة التجارية على الخريطة. تمثّل نقاط الاهتمام الخاصة بالأنشطة التجارية المؤسسات، مثل المتاجر والمطاعم والفنادق.

في هذه الخطوة، ستضيف GoogleMap.OnPoiClickListener إلى الخريطة. يضع برنامج معالجة النقرات هذا علامة على الخريطة فورًا عندما ينقر المستخدم على نقطة اهتمام. يعرض متتبِّع النقر أيضًا نافذة معلومات تحتوي على اسم نقطة الاهتمام.

  1. أنشئ رمزًا أوليًا للدالة في MapsActivity باسم setPoiClick() يأخذ GoogleMap كوسيطة.
  2. في الطريقة setPoiClick()، اضبط قيمة OnPoiClickListener على GoogleMap الذي تم تمريره.
private fun setPoiClick(map: GoogleMap) {
   map.setOnPoiClickListener { poi ->

   }
}
  1. في setOnPoiClickListener()، أنشئ val poiMarker للعلامة .
  2. اضبطها على علامة باستخدام map.addMarker() مع MarkerOptions، مع ضبط title على اسم نقطة الاهتمام.
private fun setPoiClick(map: GoogleMap) {
   map.setOnPoiClickListener { poi ->
       val poiMarker = map.addMarker(
           MarkerOptions()
               .position(poi.latLng)
               .title(poi.name)
       )
   }
}
  1. في الدالة setOnPoiClickListener()، استدعِ showInfoWindow() على poiMarker لعرض نافذة المعلومات على الفور.
poiMarker.showInfoWindow()

يجب أن يبدو الرمز النهائي للدالة setPoiClick() على النحو التالي.

private fun setPoiClick(map: GoogleMap) {
   map.setOnPoiClickListener { poi ->
       val poiMarker = map.addMarker(
           MarkerOptions()
               .position(poi.latLng)
               .title(poi.name)
       )
       poiMarker.showInfoWindow()
   }
}
  1. في نهاية onMapReady()، اتّصِل بالرقم setPoiClick() وأدخِل map.
override fun onMapReady(googleMap: GoogleMap) {
   ...

   setPoiClick(map)
}
  1. شغِّل تطبيقك وابحث عن نقطة اهتمام، مثل حديقة أو مقهى.
  2. انقر على "نقطة الاهتمام" لوضع علامة عليها وعرض اسمها في نافذة معلومات.

f4b0972c75d5fa5f.png

6. المهمة: تخصيص مظهر خريطتك

يمكنك تخصيص "خرائط Google" بطرق عديدة، ما يمنح خريطتك مظهرًا فريدًا.

يمكنك تخصيص عنصر MapFragment باستخدام سمات XML المتاحة، كما تفعل عند تخصيص أي جزء آخر. ومع ذلك، في هذه الخطوة، يمكنك تخصيص شكل ومظهر المحتوى الخاص بـ MapFragment باستخدام طرق في العنصر GoogleMap.

لإنشاء نمط مخصّص للخريطة، عليك إنشاء ملف JSON يحدّد كيفية عرض العناصر في الخريطة. لست بحاجة إلى إنشاء ملف JSON هذا يدويًا. توفّر Google أداة تصميم الخرائط لمنصة خرائط Google التي تنشئ رمز JSON لك بعد تصميم خريطتك بشكل مرئي. في هذه المهمة، ستصمّم الخريطة باستخدام مظهر قديم، ما يعني أنّ الخريطة ستستخدم ألوانًا قديمة وستضيف طرقًا ملوّنة.

الخطوة 1: إنشاء نمط للخريطة

  1. انتقِل إلى https://mapstyle.withgoogle.com/ في المتصفّح.
  2. انقر على إنشاء نمط.
  3. اختَر Retro.

208b3d3aeab0d9b6.png

  1. انقر على خيارات إضافية.

4a35faaf9535ee82.png

  1. انقر على طريق > تعبئة.
  2. تغيير لون الطرق إلى أي لون تختاره (مثل الوردي)

92c3293749293a4c.png

  1. انقر على إنهاء.

f1bfe8585eb69480.png

  1. انسخ رمز JSON من مربّع الحوار الناتج، وإذا أردت، يمكنك تخزينه في ملاحظة نصية عادية لاستخدامه في الخطوة التالية.

3c32168b299d6420.png

الخطوة 2: إضافة النمط إلى الخريطة

  1. في "استوديو Android"، أنشئ دليل موارد في الدليل res وسمِّه raw. يمكنك استخدام موارد دليل raw مثل رمز JSON.
  2. أنشئ ملفًا في res/raw باسم map_style.json.
  3. الصِق رمز JSON المخزَّن في ملف الموارد الجديد.
  4. في MapsActivity، أنشئ متغيّر فئة TAG فوق طريقة onCreate(). يتم استخدام هذا المعرّف لأغراض التسجيل.
private val TAG = MapsActivity::class.java.simpleName
  1. في MapsActivity أيضًا، أنشئ دالة setMapStyle() تأخذ GoogleMap.
  2. في setMapStyle()، أضِف مربّع try{}.
  3. في المربّع try{}، أنشئ val success لنجاح عملية التنسيق. (أضِف كتلة الالتقاط التالية).
  4. في الحظر try{}، اضبط نمط JSON على الخريطة، واستدعِ setMapStyle() على العنصر GoogleMap. مرِّر عنصر MapStyleOptions الذي يحمّل ملف JSON.
  5. عيِّن النتيجة إلى success. تعرض الطريقة setMapStyle() قيمة منطقية تشير إلى حالة نجاح تحليل ملف التنسيق وضبط النمط.
private fun setMapStyle(map: GoogleMap) {
   try {
       // Customize the styling of the base map using a JSON object defined
       // in a raw resource file.
       val success = map.setMapStyle(
           MapStyleOptions.loadRawResourceStyle(
               this,
               R.raw.map_style
           )
       )
   }
}
  1. أضِف عبارة if ليكون success false. في حال عدم نجاح عملية التنسيق، اطبع سجلّاً يفيد بتعذّر عملية التحليل.
private fun setMapStyle(map: GoogleMap) {
   try {
       ...
       if (!success) {
           Log.e(TAG, "Style parsing failed.")
       }
   }
}
  1. أضِف كتلة catch{} للتعامل مع حالة عدم توفّر ملف نمط. في كتلة catch، إذا تعذّر تحميل الملف، يجب عرض الخطأ Resources.NotFoundException.
private fun setMapStyle(map: GoogleMap) {
   try {
       ...
   } catch (e: Resources.NotFoundException) {
       Log.e(TAG, "Can't find style. Error: ", e)
   }
}

يجب أن تبدو الطريقة المكتملة مثل مقتطف الرمز التالي:

private fun setMapStyle(map: GoogleMap) {
   try {
       // Customize the styling of the base map using a JSON object defined
       // in a raw resource file.
       val success = map.setMapStyle(
           MapStyleOptions.loadRawResourceStyle(
               this,
               R.raw.map_style
           )
       )

       if (!success) {
           Log.e(TAG, "Style parsing failed.")
       }
   } catch (e: Resources.NotFoundException) {
       Log.e(TAG, "Can't find style. Error: ", e)
   }
}
  1. أخيرًا، استدعِ طريقة setMapStyle() في طريقة onMapReady() مع تمرير عنصر GoogleMap.
override fun onMapReady(googleMap: GoogleMap) {
   ...
   setMapStyle(map)
}
  1. تشغيل تطبيقك
  2. اضبط الخريطة على الوضع normal، وسيظهر التصميم الجديد مع المظهر القديم والطرق باللون الذي اخترته.

b59d6cb81f02a14f.png

الخطوة 3: تصميم العلامة

يمكنك تخصيص خريطتك بشكل أكبر من خلال تصميم علامات الخريطة. في هذه الخطوة، عليك تغيير العلامات الحمراء التلقائية إلى علامات أكثر جاذبية.

  1. في طريقة onMapLongClick()، أضِف سطر الرمز البرمجي التالي إلى MarkerOptions() الخاص بـ طريقة وضع التصميم لاستخدام العلامة التلقائية، ولكن غيِّر اللون إلى الأزرق.
.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_BLUE))

يظهر الرمز onMapLongClickListener() الآن على النحو التالي:

map.setOnMapLongClickListener { latLng ->
   // A snippet is additional text that's displayed after the title.
   val snippet = String.format(
       Locale.getDefault(),
       "Lat: %1$.5f, Long: %2$.5f",
       latLng.latitude,
       latLng.longitude
   )
   map.addMarker(
       MarkerOptions()
           .position(latLng)
           .title(getString(R.string.dropped_pin))
           .snippet(snippet)
         .icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_BLUE))
   )
}
  1. شغِّل التطبيق. ستظهر العلامات التي تظهر بعد النقر مع الاستمرار باللون الأزرق. يُرجى العِلم أنّ علامات نقاط الاهتمام لا تزال حمراء لأنّك لم تُضِف نمطًا إلى طريقة onPoiClick().

b9916bca3c367e3.png

7. المهمة: إضافة تراكب

إحدى الطرق التي يمكنك من خلالها تخصيص خريطة Google هي الرسم فوقها. تكون هذه الطريقة مفيدة إذا كنت تريد إبراز نوع معيّن من المواقع الجغرافية، مثل أماكن الصيد الشهيرة.

  • الأشكال: يمكنك إضافة خطوط متعددة الأضلاع ومضلّعات ودوائر إلى الخريطة.
  • GroundOverlay العناصر: تراكب الأرضية هو صورة ثابتة على الخريطة. على عكس العلامات، يتم توجيه الصور المتراكبة على الأرض إلى سطح الأرض بدلاً من الشاشة. يؤدي تدوير الخريطة أو إمالتها أو تكبيرها إلى تغيير اتجاه الصورة. تكون الصور المتراكبة على الأرض مفيدة عندما تريد تثبيت صورة واحدة في منطقة واحدة على الخريطة.

الخطوة: إضافة طبقة أرضية

في هذه المهمة، ستضيف صورة على الأرض على شكل روبوت Android إلى موقع منزلك.

  1. نزِّل صورة Android هذه واحفظها في مجلد res/drawable. (تأكَّد من أنّ اسم الملف هو android.png).

61fabd56a0841b44.png

  1. في onMapReady()، بعد طلب نقل الكاميرا إلى موضع منزلك، أنشئ عنصر GroundOverlayOptions.
  2. عيِّن العنصر إلى متغيّر باسم androidOverlay.
val androidOverlay = GroundOverlayOptions()
  1. استخدِم طريقة BitmapDescriptorFactory.fromResource() لإنشاء عنصر BitmapDescriptor من مصدر الصورة الذي تم تنزيله.
  2. مرِّر عنصر BitmapDescriptor الناتج إلى طريقة image() الخاصة بعنصر GroundOverlayOptions.
val androidOverlay = GroundOverlayOptions()
   .image(BitmapDescriptorFactory.fromResource(R.drawable.android))
  1. أنشئ float overlaySize للعرض بالأمتار للتراكب المطلوب. في هذا المثال، يكون العرض 100f مناسبًا.

اضبط السمة position للعنصر GroundOverlayOptions من خلال استدعاء الطريقة position()، ومرِّر العنصر homeLatLng وoverlaySize.

val overlaySize = 100f
val androidOverlay = GroundOverlayOptions()
   .image(BitmapDescriptorFactory.fromResource(R.drawable.android))
   .position(homeLatLng, overlaySize)
  1. استدعِ الدالة addGroundOverlay() على العنصر GoogleMap ومرِّر العنصر GroundOverlayOptions.
map.addGroundOverlay(androidOverlay)
  1. شغِّل التطبيق.
  2. غيِّر قيمة zoomLevel إلى 18f لعرض صورة Android كتراكب.

b1b25b0acd6a9807.png

8. المهمة: تفعيل ميزة "تتبُّع الموقع الجغرافي"

يستخدم المستخدمون غالبًا "خرائط Google" لمعرفة موقعهم الجغرافي الحالي. لعرض الموقع الجغرافي للجهاز على الخريطة، يمكنك استخدام طبقة بيانات الموقع الجغرافي.

تضيف طبقة بيانات الموقع الجغرافي رمز موقعي الجغرافي إلى الخريطة.

f317f84dcb3ac3a1.png

عندما ينقر المستخدم على الزر، تتوسّط الخريطة الموقع الجغرافي للجهاز. يظهر الموقع الجغرافي كنقطة زرقاء إذا كان الجهاز ثابتًا، وكعلامة شيفرون زرقاء إذا كان الجهاز يتحرّك.

في هذه المهمة، عليك تفعيل طبقة بيانات الموقع الجغرافي.

الخطوة: طلب أذونات تحديد الموقع الجغرافي

يتطلّب تفعيل ميزة تتبُّع الموقع الجغرافي في "خرائط Google" سطرًا واحدًا من الرمز. ومع ذلك، يجب التأكّد من أنّ المستخدم قد منح أذونات تحديد الموقع الجغرافي (باستخدام نموذج أذونات التشغيل).

في هذه الخطوة، عليك طلب أذونات تحديد الموقع الجغرافي وتفعيل ميزة تتبُّع الموقع الجغرافي.

  1. في الملف AndroidManifest.xml، تأكَّد من أنّ الإذن FINE_LOCATION متوفّر. أضاف "استوديو Android" هذا الإذن عند اختيار نموذج "خرائط Google".
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
  1. في MapsActivity، أنشئ متغيّر فئة REQUEST_LOCATION_PERMISSION.
private val REQUEST_LOCATION_PERMISSION = 1
  1. للتحقّق من منح الأذونات، أنشئ طريقة في MapsActivity باسم isPermissionGranted(). في هذه الطريقة، تحقَّق مما إذا كان المستخدم قد منح الإذن.
private fun isPermissionGranted() : Boolean {
  return ContextCompat.checkSelfPermission(
       this,
      Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED
}
  1. لتفعيل ميزة تتبُّع الموقع الجغرافي في تطبيقك، أنشئ طريقة في MapsActivity باسم enableMyLocation() لا تأخذ أي وسيطات ولا تعرض أي نتائج. ابحث في الداخل عن إذن ACCESS_FINE_LOCATION. في حال منح الإذن، فعِّل طبقة الموقع الجغرافي. بخلاف ذلك، اطلب الحصول على الإذن.
private fun enableMyLocation() {
   if (isPermissionGranted()) {
       map.isMyLocationEnabled = true 
   }
   else {
       ActivityCompat.requestPermissions(
           this,
           arrayOf<String>(Manifest.permission.ACCESS_FINE_LOCATION),
           REQUEST_LOCATION_PERMISSION
       )
   }
}
  1. استخدِم الدالة enableMyLocation() من onMapReady() callback لتفعيل طبقة الموقع الجغرافي.
override fun onMapReady(googleMap: GoogleMap) {
   ...
   enableMyLocation()
}
  1. تجاوز طريقة onRequestPermissionsResult() تحقَّق مما إذا كانت قيمة requestCode تساوي REQUEST_LOCATION_PERMISSION. إذا كان الأمر كذلك، يعني ذلك أنّه تم منح الإذن. في حال منح الإذن، تحقَّق أيضًا مما إذا كانت مصفوفة grantResults تحتوي على PackageManager.PERMISSION_GRANTED في الخانة الأولى. إذا كان ذلك صحيحًا، يُرجى الاتصال بالرقم enableMyLocation().
override fun onRequestPermissionsResult(
   requestCode: Int,
   permissions: Array<String>,
   grantResults: IntArray) {
   if (requestCode == REQUEST_LOCATION_PERMISSION) {
       if (grantResults.contains(PackageManager.PERMISSION_GRANTED)) {
           enableMyLocation()
       }
   }
}
  1. شغِّل تطبيقك. من المفترض أن يظهر مربّع حوار يطلب الوصول إلى الموقع الجغرافي للجهاز. واصِل العملية وامنح الإذن.

da7e23e00ec762c1.png

تعرض الخريطة الآن الموقع الجغرافي الحالي للجهاز باستخدام نقطة زرقاء. لاحظ أنّه يتضمّن زر مشاركة الموقع الجغرافي. إذا حرّكت الخريطة بعيدًا عن موقعك الجغرافي ونقرت على هذا الزر، ستتم إعادة توسيط الخريطة على الموقع الجغرافي للجهاز.

5b12eda7f467bc2f.png

9- رمز الحلّ

نزِّل الرمز البرمجي لدرس البرمجة المكتمل.

$  git clone https://github.com/googlecodelabs/android-kotlin-geo-maps

بدلاً من ذلك، يمكنك تنزيل المستودع كملف zip وفك ضغطه وفتحه في Android Studio.

10. ملخّص

تهانينا! أضفت خريطة Google إلى تطبيق Android Kotlin وأضفت إليها أنماطًا.

11. مزيد من المعلومات

مستندات مطوّري تطبيقات Android:

المستندات المرجعية:

12. الدرس التطبيقي التالي حول الترميز

للحصول على روابط تؤدي إلى دروس تطبيقية حول الترميز الأخرى في هذه الدورة التدريبية، يمكنك الاطّلاع على الصفحة المقصودة للدروس التطبيقية حول الترميز الخاصة بدورة "تطبيقات متقدّمة متوافقة مع نظام Android باستخدام لغة Kotlin".