اندروید پیشرفته در Kotlin 04.1: Android Google Maps

1. قبل از شروع

ساختن برنامه‌ها با Google Maps به شما امکان می‌دهد ویژگی‌هایی مانند تصاویر ماهواره‌ای، کنترل‌های رابط کاربری قوی برای نقشه‌ها، ردیابی موقعیت مکانی و نشانگرهای مکان را به برنامه خود اضافه کنید. می‌توانید با نمایش اطلاعات از مجموعه داده‌های خود، مانند مکان‌های معروف ماهیگیری یا کوهنوردی، به Google Maps استاندارد ارزش اضافه کنید. همچنین می‌توانید بازی‌هایی بسازید که در آن بازیکن دنیای فیزیکی را کشف کند، مانند شکار گنج یا حتی بازی‌های واقعیت افزوده.

در این درس، شما یک اپلیکیشن Google Maps به نام Wander ایجاد می کنید که نقشه های سفارشی شده را نمایش می دهد و موقعیت مکانی کاربر را نشان می دهد.

پیش نیازها

آگاهی از موارد زیر:

  • چگونه یک برنامه اندروید پایه بسازیم و آن را با استفاده از اندروید استودیو اجرا کنیم.
  • نحوه ایجاد و مدیریت منابع، مانند رشته ها.
  • نحوه تغییر کد و تغییر نام متغیرها با استفاده از Android Studio.
  • نحوه استفاده از نقشه گوگل به عنوان کاربر
  • نحوه تنظیم مجوزهای زمان اجرا

چیزی که یاد خواهید گرفت

  • چگونه یک کلید API را از کنسول API Google دریافت کنید و کلید برنامه خود را ثبت کنید
  • چگونه یک نقشه گوگل را در برنامه خود ادغام کنیم
  • نحوه نمایش انواع مختلف نقشه
  • نحوه استایل دادن به نقشه گوگل
  • چگونه نشانگرها را به نقشه خود اضافه کنید
  • نحوه فعال کردن کاربر برای قرار دادن نشانگر در یک نقطه مورد علاقه (POI)
  • نحوه فعال کردن ردیابی موقعیت مکانی
  • نحوه ایجاد اپلیکیشن The Wander که دارای نقشه گوگل تعبیه شده است
  • نحوه ایجاد ویژگی های سفارشی برای برنامه خود، مانند نشانگرها و استایل
  • چگونه ردیابی موقعیت مکانی را در برنامه خود فعال کنیم

2. نمای کلی برنامه

در این کد لبه، شما اپلیکیشن Wander را ایجاد می کنید که نقشه گوگل را با استایل سفارشی نمایش می دهد. برنامه Wander به شما امکان می‌دهد نشانگرها را روی مکان‌ها رها کنید، پوشش‌هایی اضافه کنید و موقعیت مکانی خود را به‌طور هم‌زمان ببینید.

5b12eda7f467bc2f.png

3. وظیفه: پروژه را راه اندازی کنید و یک کلید API دریافت کنید

Maps SDK برای Android به یک کلید API نیاز دارد. برای دریافت کلید API، پروژه خود را در صفحه API & Services ثبت کنید. کلید API به یک گواهی دیجیتال گره خورده است که برنامه را به نویسنده آن پیوند می دهد. برای اطلاعات بیشتر درباره استفاده از گواهی‌های دیجیتال و امضای برنامه، به امضای برنامه خود مراجعه کنید.

در این کد لبه، شما از کلید API برای گواهی اشکال زدایی استفاده می کنید. گواهی اشکال زدایی از نظر طراحی ناامن است، همانطور که در Sign your debug build توضیح داده شده است. برنامه‌های منتشرشده Android که از Maps SDK برای Android استفاده می‌کنند، به یک کلید API دوم نیاز دارند: کلید گواهی انتشار. برای اطلاعات بیشتر درباره دریافت گواهی انتشار، به دریافت کلید API مراجعه کنید.

Android Studio شامل یک الگوی Google Maps Activity است که کد قالب مفیدی را تولید می کند. کد الگو شامل یک فایل google_maps_api.xml حاوی پیوندی است که به دست آوردن یک کلید API را ساده می کند.

مرحله 1: پروژه Wander را با الگوی نقشه ها ایجاد کنید

  1. یک پروژه Android Studio جدید ایجاد کنید.
  2. الگوی Google Maps Activity را انتخاب کنید.

d6b874bb19ea68cd.png

  1. نام پروژه را Wander .
  2. حداقل سطح API را روی API 19 تنظیم کنید. مطمئن شوید که زبان کاتلین است.
  3. روی Finish کلیک کنید.
  4. پس از اتمام ساخت برنامه، به پروژه خود و فایل های مرتبط با نقشه های زیر که Android Studio برای شما ایجاد می کند، نگاهی بیندازید:

google_maps_api.xml — شما از این فایل پیکربندی برای نگه داشتن کلید API خود استفاده می کنید. این الگو دو فایل google_maps_api.xml ایجاد می کند: یکی برای اشکال زدایی و دیگری برای انتشار. فایل کلید API برای گواهی اشکال زدایی در src/debug/res/values ​​قرار دارد. فایل کلید API برای گواهی انتشار در 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: کلید API را دریافت کنید

  1. نسخه اشکال زدایی فایل google_maps_api.xml را باز کنید.
  2. در فایل به دنبال نظری با URL طولانی باشید. پارامترهای URL شامل اطلاعات خاصی در مورد برنامه شما هستند.
  3. URL را کپی کرده و در مرورگر پیست کنید.
  4. برای ایجاد پروژه در صفحه APIs & Services، دستورات را دنبال کنید. به دلیل پارامترهای موجود در URL ارائه شده، صفحه می داند که Maps SDK برای Android به طور خودکار فعال می شود.
  5. روی ایجاد کلید API کلیک کنید.
  6. در صفحه بعد به بخش API Keys رفته و روی کلیدی که ایجاد کردید کلیک کنید.
  7. روی Restrict Key کلیک کنید و Maps SDK for Android را انتخاب کنید تا استفاده از کلید به برنامه‌های Android محدود شود.
  8. کلید API تولید شده را کپی کنید. با " AIza" شروع می شود.
  9. در فایل google_maps_api.xml ، کلید را در رشته google_maps_key جایی که عبارت YOUR_KEY_HERE را نشان می دهد، قرار دهید.
  10. برنامه خود را اجرا کنید شما باید یک نقشه جاسازی شده در فعالیت خود با یک نشانگر در سیدنی، استرالیا ببینید. (نشانگر سیدنی بخشی از الگو است و بعداً آن را تغییر می دهید.)

34dc9dd877c90996.png

مرحله 3: تغییر نام mMap

MapsActivity دارای یک lateinit var خصوصی به نام mMap است که از نوع GoogleMap است. برای پیروی از قراردادهای نامگذاری Kotlin، نام mMap را به map تغییر دهید.

  1. در MapsActivity ، روی mMap راست کلیک کنید و روی Refactor > Rename...

e713ccb3384450c6.png

  1. نام متغیر را به map تغییر دهید.

توجه کنید که چگونه تمام ارجاعات به mMap در تابع onMapReady() نیز به map تغییر می کند.

4. وظیفه: اضافه کردن انواع نقشه

نقشه های گوگل شامل چندین نوع نقشه است: معمولی، ترکیبی، ماهواره ای، زمینی و "هیچ" (به هیچ وجه بدون نقشه).

نقشه معمولی

نقشه ماهواره ای

نقشه ترکیبی

نقشه زمین

هر نوع نقشه انواع مختلفی از اطلاعات را ارائه می دهد. به عنوان مثال، هنگام استفاده از نقشه ها برای پیمایش در ماشین، دیدن نام خیابان ها مفید است، بنابراین می توانید از گزینه عادی استفاده کنید. وقتی در حال پیاده‌روی هستید، نقشه زمین می‌تواند برای تصمیم‌گیری برای اینکه چقدر بیشتر باید صعود کنید تا به قله بروید، مفید باشد.

در این وظیفه شما:

  1. یک نوار برنامه با منوی گزینه‌ها اضافه کنید که به کاربر امکان می‌دهد نوع نقشه را تغییر دهد.
  2. مکان شروع نقشه را به مکان خانه خود منتقل کنید.
  3. برای نشانگرها پشتیبانی اضافه کنید، که مکان‌های منفرد را روی نقشه نشان می‌دهند و می‌توانند شامل یک برچسب باشند.

اضافه کردن منو برای انواع نقشه

در این مرحله یک نوار برنامه با منوی گزینه ها اضافه می کنید که به کاربر اجازه می دهد نوع نقشه را تغییر دهد.

  1. برای ایجاد یک فایل XML منوی جدید، روی دایرکتوری res خود کلیک راست کرده و New > Android Resource File را انتخاب کنید.
  2. در گفتگو، نام فایل map_options بگذارید.
  3. منو را برای نوع منبع انتخاب کنید.
  4. روی OK کلیک کنید.
  5. در سربرگ Code ، کد موجود در فایل جدید را با کد زیر جایگزین کنید تا گزینه های منوی نقشه ایجاد شود. نوع نقشه "هیچ" حذف شده است زیرا "هیچ" منجر به فقدان نقشه می شود. این مرحله باعث ایجاد خطا می شود، اما در مرحله بعد آن را برطرف می کنید.
<?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 Maps ایجاد شده، قرار می‌دهد. تماس پیش‌فرض نیز نقشه را متحرک می‌کند تا به سیدنی حرکت کند.

در این کار، دوربین نقشه را به خانه خود منتقل می‌کنید، تا سطحی که مشخص می‌کنید زوم می‌کنید و یک نشانگر در آنجا قرار می‌دهید.

مرحله 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. با فراخوانی تابع moveCamera() روی شی map ، دوربین را به homeLatLng منتقل کنید و با استفاده از CameraUpdateFactory.newLatLngZoom() یک شی CameraUpdate ارسال کنید. از شی 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: شنونده POI را اضافه کنید

به طور پیش فرض، نقاط مورد علاقه (POI) همراه با نمادهای مربوطه روی نقشه ظاهر می شوند. POI شامل پارک ها، مدارس، ساختمان های دولتی و موارد دیگر می شود. وقتی نوع نقشه روی normal تنظیم شود، POI های تجاری نیز روی نقشه ظاهر می شوند. کسب و کار POI نشان دهنده مشاغلی مانند فروشگاه ها، رستوران ها و هتل ها است.

در این مرحله یک GoogleMap.OnPoiClickListener را به نقشه اضافه می کنید. این کلیک شنونده بلافاصله هنگامی که کاربر روی یک POI کلیک می کند یک نشانگر روی نقشه قرار می دهد. شنونده کلیک همچنین یک پنجره اطلاعاتی را نشان می دهد که حاوی نام POI است.

  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 به نام POI تنظیم کند.
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. برنامه خود را اجرا کنید و یک POI مانند پارک یا کافی شاپ پیدا کنید.
  2. روی POI ضربه بزنید تا یک نشانگر روی آن قرار دهید و نام POI در یک پنجره اطلاعات نمایش داده شود.

f4b0972c75d5fa5f.png

6. وظیفه: به نقشه خود سبک دهید

می‌توانید نقشه‌های گوگل را به روش‌های مختلفی سفارشی کنید و به نقشه خود ظاهر و احساسی منحصربفرد بدهید.

شما می توانید یک شی MapFragment را با استفاده از ویژگی های XML موجود سفارشی کنید، همانطور که هر قطعه دیگری را سفارشی می کنید. با این حال، در این مرحله، ظاهر و احساس محتوای MapFragment را با استفاده از روش‌هایی روی شی GoogleMap سفارشی می‌کنید.

برای ایجاد یک سبک سفارشی برای نقشه خود، یک فایل JSON ایجاد می کنید که نحوه نمایش ویژگی های نقشه را مشخص می کند. لازم نیست این فایل JSON را به صورت دستی ایجاد کنید. Google Maps Platform Styling Wizard را ارائه می‌کند، که پس از استایل بصری نقشه خود، JSON را برای شما تولید می‌کند. در این کار، نقشه را با تم رترو استایل می‌دهید، به این معنی که نقشه از رنگ‌های قدیمی استفاده می‌کند و جاده‌های رنگی را اضافه می‌کنید.

مرحله 1: یک سبک برای نقشه خود ایجاد کنید

  1. در مرورگر خود به https://mapstyle.withgoogle.com/ بروید.
  2. Create a Style را انتخاب کنید.
  3. Retro را انتخاب کنید.

208b3d3aeab0d9b6.png

  1. روی گزینه های بیشتر کلیک کنید.

4a35faaf9535ee82.png

  1. جاده > پر کردن را انتخاب کنید.
  2. رنگ جاده ها را به هر رنگی که انتخاب می کنید (مانند صورتی) تغییر دهید.

92c3293749293a4c.png

  1. روی Finish کلیک کنید.

f1bfe8585eb69480.png

  1. کد JSON را از دیالوگ به دست آمده کپی کنید و در صورت تمایل آن را در یک یادداشت متنی ساده ذخیره کنید تا در مرحله بعد از آن استفاده کنید.

3c32168b299d6420.png

مرحله 2: سبک را به نقشه خود اضافه کنید

  1. در اندروید استودیو، در فهرست 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 برای موفقیت در استایل ایجاد کنید. (شما بلوک catch زیر را اضافه می کنید.)
  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. برای false بودن success یک عبارت if اضافه کنید. اگر یک ظاهر طراحی ناموفق بود، گزارشی را چاپ کنید که تجزیه ناموفق است.
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() را در متد GoogleMap onMapReady() فراخوانی کنید.
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. برنامه را اجرا کنید. نشانگرهایی که پس از کلیک طولانی شما ظاهر می شوند اکنون به رنگ آبی در می آیند. توجه داشته باشید که نشانگرهای POI همچنان قرمز هستند زیرا استایلی را به متد onPoiClick() اضافه نکردید.

b9916bca3c367e3.png

7. وظیفه: اضافه کردن یک پوشش

یکی از راه‌هایی که می‌توانید نقشه گوگل را سفارشی کنید، کشیدن روی آن است. اگر می خواهید نوع خاصی از مکان را برجسته کنید، مانند نقاط محبوب ماهیگیری، این تکنیک مفید است.

  • شکل ها: می توانید چند خط ، چند ضلعی و دایره را به نقشه اضافه کنید.
  • اشیاء GroundOverlay : روکش زمین تصویری است که روی نقشه ثابت می شود. بر خلاف نشانگرها، روکش‌های زمین به جای صفحه نمایش، به سطح زمین می‌روند. چرخش، کج کردن، یا بزرگنمایی نقشه، جهت تصویر را تغییر می دهد. پوشش های زمین زمانی مفید هستند که می خواهید یک تصویر واحد را در یک منطقه روی نقشه ثابت کنید.

مرحله: یک روکش زمین اضافه کنید

در این کار، یک روکش زمین به شکل اندروید به محل خانه خود اضافه می کنید.

  1. این تصویر اندروید را دانلود کرده و در پوشه 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 تغییر دهید تا تصویر اندروید را به صورت همپوشانی ببینید.

b1b25b0acd6a9807.png

8. وظیفه: ردیابی موقعیت مکانی را فعال کنید

کاربران اغلب از Google Maps برای دیدن مکان فعلی خود استفاده می کنند. برای نمایش مکان دستگاه بر روی نقشه خود، می توانید از لایه مکان-داده استفاده کنید.

لایه مکان-داده نماد موقعیت مکانی من را به نقشه اضافه می کند.

f317f84dcb3ac3a1.png

وقتی کاربر روی دکمه ضربه می زند، نقشه بر روی مکان دستگاه متمرکز می شود. اگر دستگاه ثابت است، مکان به صورت یک نقطه آبی و اگر دستگاه در حال حرکت است به صورت یک شورون آبی نشان داده می شود.

در این کار، لایه مکان-داده را فعال می کنید.

مرحله: درخواست مجوزهای مکان

فعال کردن ردیابی موقعیت مکانی در Google Maps به یک خط کد نیاز دارد. با این حال، باید مطمئن شوید که کاربر مجوزهای مکان را داده است (با استفاده از مدل مجوز زمان اجرا).

در این مرحله شما مجوزهای موقعیت مکانی را درخواست می کنید و ردیابی موقعیت مکانی را فعال می کنید.

  1. در فایل AndroidManifest.xml ، بررسی کنید که مجوز FINE_LOCATION از قبل وجود داشته باشد. زمانی که شما الگوی Google Maps را انتخاب کردید، Android Studio این مجوز را وارد کرد.
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
  1. در MapsActivity ، یک متغیر کلاس REQUEST_LOCATION_PERMISSION ایجاد کنید.
private val REQUEST_LOCATION_PERMISSION = 1
  1. برای بررسی اینکه آیا مجوزها اعطا شده اند یا خیر، روشی به نام isPermissionGranted() در MapsActivity ایجاد کنید. در این روش بررسی کنید که آیا کاربر مجوز را داده است یا خیر.
private fun isPermissionGranted() : Boolean {
  return ContextCompat.checkSelfPermission(
       this,
      Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED
}
  1. برای فعال کردن ردیابی موقعیت مکانی در برنامه خود، روشی به نام enableMyLocation() در MapsActivity ایجاد کنید که هیچ آرگومانی نمی‌گیرد و چیزی را بر نمی‌گرداند. در داخل، مجوز 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. برای فعال کردن لایه مکان، از روی () onMapReady() enableMyLocation() فراخوانی کنید.
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

همچنین می‌توانید مخزن را به صورت فایل فشرده دانلود کنید، آن را از حالت فشرده خارج کرده و در اندروید استودیو باز کنید.

10. خلاصه

تبریک می گویم! شما یک نقشه گوگل را به برنامه اندروید Kotlin اضافه کردید و به آن استایل دادید.

11. بیشتر بدانید

مستندات توسعه دهنده اندروید:

مستندات مرجع:

12. Codelab بعدی

برای پیوند به دیگر کدهای این دوره، صفحه فرود Android Advanced in Kotlin Codelabs را ببینید.