Android المتقدم في Kotlin 04.1: Android Maps

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

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

في هذا الدرس، يمكنك إنشاء تطبيق "خرائط Google" يُسمى Wander الذي يعرض الخرائط المخصصة ويعرض موقع المستخدم.

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

معرفة ما يلي:

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

ما ستتعرَّف عليه

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

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

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

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

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

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

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

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

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()، ويستخدم الفئة&#39؛ getMapAsync() لإعداد نظام الخرائط والعرض تلقائيًا. يجب أن ينفذ النشاط الذي يتضمن SupportMapFragment واجهة OnMapReadyCallback وطريقة onMapReady() هذه الواجهة. يتم استدعاء طريقة onMapReady() عند تحميل الخريطة.

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

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

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

MapsActivity لديه lateinit var خاص يُسمى mMap، وهو من النوع GoogleMap. لمتابعة اصطلاحات تسمية لغة Kotlin، عليك تغيير اسم mMap إلى map.

  1. في MapsActivity، انقر بزر الماوس الأيمن على mMap، ثم انقر على Reagent > Reset...

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

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

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

الخريطة العادية

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

خريطة مختلطة

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

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

في هذه المهمة، يمكنك:

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

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

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

  1. لإنشاء ملف XML جديد في القائمة، انقر بزر الماوس الأيمن على الدليل res واختَر جديد > Android Resource File.
  2. في مربّع الحوار، أدخِل اسمًا للملف map_options.
  3. اختَر القائمة لنوع المورد.
  4. انقر على حسنًا.
  5. في علامة التبويب الرمز، استبدل الرمز في الملف الجديد بالرمز التالي لإنشاء خيارات قائمة الخريطة. يتم حذف نوع الخريطة "none"; ; &;;;;;;;ٍٍّّ;ٍّ;لا يسمح أو يحتاج إلى إضافة ; تؤدي هذه الخطوة إلى حدوث خطأ، ولكن يمكنك حلها في الخطوة التالية.
<?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. انقر على لتغيير نوع الخريطة. لاحِظ كيفية تغيُّر شكل الخريطة بين الأوضاع المختلفة.

بشكل تلقائي، تتضمن استدعاء 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. شغِّل تطبيقك. يجب تحريك الخريطة إلى منزلك، وتكبير/تصغيرها إلى المستوى المطلوب، ووضع علامة على منزلك.

الخطوة 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. انقر على محدّد الموقع الذي يؤدي إلى توسيطه على الشاشة.

الخطوة 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. ضبط العلامة's 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. انقر على محدّد الموقع لعرض نافذة المعلومات.

الخطوة 4: إضافة أداة معالجة نقاط الاهتمام

تظهر نقاط الاهتمام (POS) بشكل تلقائي على الخريطة مع الرموز المقابلة لها. تشمل نقاط الاهتمام المتنزهات والمدارس والمباني الحكومية وغيرها. عند ضبط نوع الخريطة على 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. انقر على نقطة الاهتمام لوضع علامة عليها وعرض اسم نقطة الاهتمام في نافذة معلومات.

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

يمكنك تخصيص كائن MapFragment باستخدام سمات XML المتاحة، كما يمكنك تخصيص أي كسر آخر. ولكن في هذه الخطوة، يمكنك تخصيص شكل محتوى MapFragment ومضمونه باستخدام الطرق المتوفرة في الكائن GoogleMap.

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

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

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

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

  1. في قائمة نوع الميزة، حدد طريق &gt؛ملء.
  2. يمكنك تغيير لون الطرق إلى أي لون تختاره (مثل الوردي).

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

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

الخطوة 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. في حال عدم نجاح النمط، يمكنك طباعة سجل تعذّر تحليله.
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، وسيكون النمط الجديد مرئيًا بأنماط قديمة وطرق للألوان التي اخترتها.

الخطوة 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().

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

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

الخطوة: إضافة تراكب الأرض

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

  1. يمكنك تنزيل صورة Android هذه وحفظها في مجلد res/drawable. (تأكد من أن اسم الملف هو android.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 كتراكب.

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

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

في هذه المهمة، فعِّل طبقة بيانات الموقع.

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

يتطلب تفعيل تتبُّع الموقع الجغرافي في "خرائط 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() لتفعيل طبقة الموقع.
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. شغِّل تطبيقك. يجب أن يكون هناك مربع حوار يطلب الوصول إلى موقع الجهاز. هيا، امنح الإذن.

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

نزِّل الرمز للدرس التطبيقي النهائي للترميز.

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


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

تنزيل الملف بتنسيق zip

  • لاستخدام Maps API، ستحتاج إلى مفتاح واجهة برمجة تطبيقات من Google API Console.
  • في "استوديو Android"، يؤدي استخدام نموذج النشاط على "خرائط Google" إلى إنشاء Activity مع SupportMapFragment واحد في تنسيق التطبيق. يضيف النموذج أيضًا ACCESS_FINE_PERMISSION إلى بيان التطبيق ويطبّق OnMapReadyCallback في نشاطك، كما يلغي طريقة onMapReady() المطلوبة.

لتغيير نوع الخريطة GoogleMap في وقت التشغيل، استخدم طريقة GoogleMap.setMapType(). يمكن أن تكون خريطة Google أحد أنواع الخرائط التالية:

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

لمحة عن "خرائط Google":

  • المُحدِّد هو مؤشر لموقع جغرافي مُحدَّد.
  • وعند النقر التلقائي على العلامة، يكون سلوكها هو عرض نافذة معلومات تتضمّن معلومات عن الموقع الجغرافي.
  • تظهر نقاط الاهتمام (POS) بشكل تلقائي على الخريطة الأساسية مع الرموز المقابلة لها. تشمل نقاط الاهتمام المتنزهات والمدارس والمباني الحكومية وغيرها.
  • بالإضافة إلى ذلك، تظهر نقاط الاهتمام للنشاط التجاري (المتاجر والمطاعم والفنادق وغيرها) بشكل تلقائي على الخريطة عندما يكون نوع الخريطة normal.
  • يمكنك تسجيل النقرات على نقاط الاهتمام باستخدام OnPoiClickListener.
  • يمكنك تغيير المظهر المرئي لجميع عناصر خريطة Google تقريبًا باستخدام معالج النمط. ينشئ معالج التصميم ملف JSON الذي تم إدخاله في خريطة Google باستخدام طريقة setMapStyle().
  • يمكنك تخصيص علاماتك عن طريق تغيير اللون التلقائي، أو استبدال رمز العلامة التلقائي بصورة مخصصة.

معلومات مهمة أخرى:

  • يمكنك استخدام تراكب الأرض لإصلاح صورة لموقع جغرافي.
  • استخدِم عنصر GroundOverlayOptions لتحديد الصورة وحجمها بالأمتار وموضع الصورة. تمرير هذا الكائن إلى طريقة GoogleMap.addGroundOverlay() لضبط التراكب على الخريطة.
  • يمكنك تفعيل ميزة تتبُّع الموقع الجغرافي عن طريق ضبط map.isMyLocationEnabled = true من خلال منح تطبيقك الإذن بالوصول إلى ACCESS_FINE_LOCATION.
  • لا يتناول هذا الدرس التطبيقي هذا الدرس التطبيقي حول الترميز، ولكن يمكنك تقديم معلومات إضافية عن أحد المواقع الجغرافية باستخدام ميزة التجوّل الافتراضي من Google التي تُعدّ صورة بانورامية قابلة للتنقل في موقع جغرافي معيّن.

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

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

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