अपने Android ऐप्लिकेशन (Kotlin) में मैप जोड़ना

1. शुरू करने से पहले

यह कोडलैब आपको Android के लिए Maps SDK टूल को अपने ऐप्लिकेशन से इंटिग्रेट करने और मुख्य सुविधाओं का इस्तेमाल करने का तरीका बताता है. यह ऐप्लिकेशन सैन फ़्रांसिस्को, अमेरिका, अमेरिका में साइकल की दुकानों का मैप दिखाता है.

f05e1ca27ff42bf6.png

ज़रूरी बातें

  • Kotlin और Android डेवलपमेंट की बुनियादी जानकारी

आप क्या कर पाएंगे!

  • किसी Android ऐप्लिकेशन में Google Maps जोड़ने के लिए, Android के लिए Maps SDK चालू करें और उसका इस्तेमाल करें.
  • मार्कर जोड़ें, कस्टमाइज़ करें, और क्लस्टर बनाएं.
  • मैप पर पॉलीलाइन और पॉलीगॉन बनाएं.
  • कैमरे की दिखावट को प्रोग्रामैटिक तौर पर कंट्रोल करें.

आपको इनकी ज़रूरत होगी

2. सेट अप करें

नीचे दिए गए चालू करने के चरण के लिए , आपको Android के लिए Maps SDK टूल को चालू करना होगा.

Google Maps Platform सेट अप करना

अगर आपके पास पहले से Google Cloud Platform खाता नहीं है और बिलिंग की सुविधा चालू की गई है, तो कृपया बिलिंग खाता और प्रोजेक्ट बनाने के लिए, Google Maps Platform का इस्तेमाल शुरू करना गाइड देखें.

  1. Cloud Console में, प्रोजेक्ट ड्रॉप-डाउन मेन्यू पर क्लिक करें और वह प्रोजेक्ट चुनें जिसे आप इस कोडलैब के लिए इस्तेमाल करना चाहते हैं.

  1. Google Cloud Marketplace में, इस कोडलैब के लिए ज़रूरी Google Maps Platform API और SDK टूल चालू करें. ऐसा करने के लिए, इस वीडियो या इस दस्तावेज़ में दिया गया तरीका अपनाएं.
  2. Cloud Console के क्रेडेंशियल पेज में एपीआई कुंजी जनरेट करें. आप इस वीडियो या इस दस्तावेज़ में दिया गया तरीका अपना सकते हैं. Google Maps Platform पर सभी अनुरोधों के लिए एपीआई कुंजी ज़रूरी है.

3. तुरंत शुरू करना

इसे शुरू करने में आपकी मदद करने के लिए, यहां कुछ # कोड दिया गया है, ताकि इस कोडलैब के साथ आपको मदद मिल सके. आप जब चाहें, इस कार्यक्रम में हिस्सा ले सकते हैं. हालांकि, अगर आप इस समस्या को खुद हल करने के सभी तरीके जानना चाहते हैं, तो पढ़ते रहें.

  1. अगर आपने git इंस्टॉल किया हुआ है, तो रिपॉज़िटरी क्लोन करें.
git clone https://github.com/googlecodelabs/maps-platform-101-android.git

इसके अलावा, आप सोर्स कोड डाउनलोड करने के लिए इस बटन पर क्लिक कर सकते हैं.

  1. कोड मिलने के बाद, Android Studio में starter डायरेक्ट्री में मिलने वाला प्रोजेक्ट खोलें.

4. Google Maps जोड़ें

इस सेक्शन में, आपको Google Maps जोड़ना होगा, ताकि जब आप ऐप्लिकेशन लॉन्च करें, तो वह लोड हो जाए.

d1d068b5d4ae38b9.png

अपनी एपीआई कुंजी जोड़ें

आपने पहले जो एपीआई कुंजी बनाई थी वह ऐप्लिकेशन को दी जानी चाहिए, ताकि Android के लिए Maps SDK टूल, आपकी कुंजी को आपके ऐप्लिकेशन से जोड़ सके.

  1. इसे उपलब्ध कराने के लिए, local.properties नाम की फ़ाइल को अपने प्रोजेक्ट की रूट डायरेक्ट्री में खोलें (उसी लेवल पर जहां gradle.properties और settings.gradle हैं).
  2. उस फ़ाइल में, उस नई कुंजी के बारे में GOOGLE_MAPS_API_KEY बताएं जिसे आपने एपीआई कुंजी के तौर पर बनाया है.

local.properties

GOOGLE_MAPS_API_KEY=YOUR_KEY_HERE

ध्यान दें कि local.properties, GIF डेटा स्टोर करने की जगह में .gitignore फ़ाइल की सूची में है. ऐसा इसलिए है, क्योंकि आपकी एपीआई कुंजी को संवेदनशील जानकारी माना जाता है. अगर हो सके, तो इसे सोर्स कंट्रोल में नहीं देखना चाहिए.

  1. इसके बाद, अपने एपीआई को बिना अनुमति के सार्वजनिक करें, ताकि वह आपके ऐप्लिकेशन में इस्तेमाल किया जा सके. अपने ऐप्लिकेशन में Android के लिए सीक्रेट Gradle प्लग इन app/ फ़ाइल में मौजूद build.gradle फ़ाइल शामिल करें. plugins ब्लॉक में नीचे दी गई लाइन जोड़ें:

ऐप्लिकेशन-लेवल build.gradle

plugins {
    // ...
    id 'com.google.android.libraries.mapsplatform.secrets-gradle-plugin'
}

आपको अपने प्रोजेक्ट-लेवल की build.gradle फ़ाइल में बदलाव करना होगा, ताकि नीचे दिए गए क्लासपाथ को शामिल किया जा सके:

प्रोजेक्ट-लेवल build.gradle

buildscript {
    dependencies {
        // ...
        classpath "com.google.android.libraries.mapsplatform.secrets-gradle-plugin:secrets-gradle-plugin:1.3.0"
    }
}

यह प्लग इन, आपकी local.properties फ़ाइल में तय किए गए बटन को Android मेनिफ़ेस्ट फ़ाइल में बिल्ड वैरिएबल के तौर पर और बिल्ड टाइम में Gradle से जनरेट की गई BuildConfig क्लास के वैरिएबल के तौर पर उपलब्ध कराएगा. इस प्लग इन का इस्तेमाल करके, उन बॉयलरप्लेट कोड को हटा दिया जाता है जो local.properties से प्रॉपर्टी पढ़ने के लिए ज़रूरी होते, ताकि यह आपके पूरे ऐप्लिकेशन में ऐक्सेस किया जा सके.

Google Maps में डिपेंडेंसी जोड़ना

  1. अब आपकी एपीआई कुंजी को ऐप्लिकेशन में ऐक्सेस किया जा सकता है. इसके बाद, अपने ऐप्लिकेशन की build.gradle फ़ाइल में Android डिपेंडेंसी के लिए Maps SDK टूल जोड़ें.

इस कोडलैब के साथ मिलने वाले स्टार्टर प्रोजेक्ट में, इस डिपेंडेंसी को आपके लिए पहले ही जोड़ा जा चुका है.

build.gradle

dependencies {
   // Dependency to include Maps SDK for Android
   implementation 'com.google.android.gms:play-services-maps:17.0.0'
}
  1. इसके बाद, आपने एपीआई कुंजी को पास करने के लिए AndroidManifest.xml में एक नया meta-data टैग जोड़ा है. ऐसा करने के लिए, meta-data और Android Studio में इस फ़ाइल को खोलें. इसके बाद, app/src/main में मौजूद अपनी AndroidManifest.xml फ़ाइल के application ऑब्जेक्ट में इस meta-data टैग को जोड़ें.

AndroidManifest.xml

<meta-data
   android:name="com.google.android.geo.API_KEY"
   android:value="${GOOGLE_MAPS_API_KEY}" />
  1. इसके बाद, app/src/main/res/layout/ निर्देशिका में activity_main.xml नाम की एक नई लेआउट फ़ाइल बनाएं और इसे इस तरह तय करें:

activity_main.xml

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:tools="http://schemas.android.com/tools"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   tools:context=".MainActivity">

   <fragment
       class="com.google.android.gms.maps.SupportMapFragment"
       android:id="@+id/map_fragment"
       android:layout_width="match_parent"
       android:layout_height="match_parent" />

</FrameLayout>

इस लेआउट में FrameLayout शामिल है, जिसमें एक SupportMapFragment है. इस फ़्रैगमेंट में वह GoogleMaps ऑब्जेक्ट शामिल है जिसका इस्तेमाल आप बाद के चरणों में करते हैं.

  1. आखिर में, onCreate तरीके को बदलने के लिए नीचे दिया गया कोड जोड़कर, app/src/main/java/com/google/codelabs/buildyourfirstmap में मौजूद MainActivity क्लास को अपडेट करें, ताकि आप अभी-अभी बनाए गए नए लेआउट से इसके कॉन्टेंट सेट कर सकें.

MainActivity

override fun onCreate(savedInstanceState: Bundle?) {
   super.onCreate(savedInstanceState)
   setContentView(R.layout.activity_main)
}
  1. अब आगे बढ़ें और ऐप्लिकेशन चलाएं. अब आपको अपने डिवाइस की स्क्रीन पर मैप लोड दिखेगा.

5. क्लाउड-आधारित मैप स्टाइलिंग (ज़रूरी नहीं)

क्लाउड पर आधारित मैप स्टाइल का इस्तेमाल करके आप अपने मैप की शैली को पसंद के मुताबिक बना सकते हैं.

एक मैप आईडी बनाएं

अगर आपने अभी तक मैप शैली के साथ कोई मैप आईडी नहीं बनाया है, तो नीचे दिए गए चरणों को पूरा करने के लिए मैप आईडी गाइड देखें:

  1. एक मैप आईडी बनाएं.
  2. किसी मैप आईडी को किसी मैप शैली से जोड़ें.

अपने ऐप्लिकेशन में मैप आईडी जोड़ना

आपने जो मैप आईडी बनाया है उसका इस्तेमाल करने के लिए, activity_main.xml फ़ाइल में बदलाव करें और SupportMapFragment के map:mapId एट्रिब्यूट में अपना मैप आईडी पास करें.

activity_main.xml

<fragment xmlns:map="http://schemas.android.com/apk/res-auto"
    class="com.google.android.gms.maps.SupportMapFragment"
    <!-- ... -->
    map:mapId="YOUR_MAP_ID" />

जब आप इसे पूरा कर लें, तब आगे बढ़ें और अपनी चुनी हुई शैली में अपना मैप देखने के लिए ऐप्लिकेशन चलाएं!

6. मार्कर जोड़ें

इस टास्क में, आप मैप पर मार्कर जोड़ते हैं. ये मैप में आपकी पसंद की जगहों को हाइलाइट करते हैं. पहले, आप उन जगहों की सूची लाते हैं जो आपको स्टार्टर प्रोजेक्ट में दी गई हैं. इसके बाद, उन जगहों को मैप में जोड़ें. इस उदाहरण में, ये साइकल की दुकानें हैं.

bc5576877369b554.png

Google मैप का रेफ़रंस पाना

सबसे पहले, आपको GoogleMap ऑब्जेक्ट का रेफ़रंस लेना होगा, ताकि आप उसके तरीकों का इस्तेमाल कर सकें. ऐसा करने के लिए, setContentView() पर कॉल करने के तुरंत बाद, MainActivity.onCreate() तरीके में यह कोड जोड़ें:

MainActivity.onCreate()

val mapFragment = supportFragmentManager.findFragmentById(   
    R.id.map_fragment
) as? SupportMapFragment
mapFragment?.getMapAsync { googleMap ->
    addMarkers(googleMap)
}

लागू करने से पहले, आपने SupportFragmentManager ऑब्जेक्ट पर findFragmentById() तरीका इस्तेमाल करके पिछले चरण में SupportMapFragment को जोड़ा था. एक बार पहचान मिलने के बाद, getMapAsync() कॉल को lambda से पास करके शुरू किया जाता है. यह Lambda है जहां GoogleMap ऑब्जेक्ट को पास किया गया है. इस lambda में, addMarkers() मेथड को कॉल किया जाता है, जिसके बारे में जल्द ही बताया गया है.

दी गई श्रेणी: Places रीडर

स्टार्टर प्रोजेक्ट में, PlacesReader क्लास आपके लिए उपलब्ध है. यह क्लास 49 जगहों की सूची पढ़ती है जो places.json नाम की JSON फ़ाइल में सेव हैं और उन्हें List<Place> के तौर पर दिखाती हैं. ये जगहें खुद सैन फ़्रांसिस्को, कैलिफ़ोर्निया, अमेरिका के आस-पास मौजूद साइकल की दुकानों की सूची दिखाती हैं.

अगर आप इस क्लास को लागू करने के बारे में जानना चाहते हैं, तो इसे GitHub पर ऐक्सेस कर सकते हैं या Android Studio में PlacesReader क्लास को खोल सकते हैं.

PlaceReader

package com.google.codelabs.buildyourfirstmap.place

import android.content.Context
import com.google.codelabs.buildyourfirstmap.R
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import java.io.InputStream
import java.io.InputStreamReader

/**
* Reads a list of place JSON objects from the file places.json
*/
class PlacesReader(private val context: Context) {

   // GSON object responsible for converting from JSON to a Place object
   private val gson = Gson()

   // InputStream representing places.json
   private val inputStream: InputStream
       get() = context.resources.openRawResource(R.raw.places)

   /**
    * Reads the list of place JSON objects in the file places.json
    * and returns a list of Place objects
    */
   fun read(): List<Place> {
       val itemType = object : TypeToken<List<PlaceResponse>>() {}.type
       val reader = InputStreamReader(inputStream)
       return gson.fromJson<List<PlaceResponse>>(reader, itemType).map {
           it.toPlace()
       }
   }

जगहों की जानकारी लोड करें

साइकल की दुकानों की सूची लोड करने के लिए, MainActivity नाम वाली प्रॉपर्टी जोड़ें, जिसका नाम places है. इसे इस तरह परिभाषित करें:

MainActivity.जगहें

private val places: List<Place> by lazy {
   PlacesReader(this).read()
}

यह कोड PlacesReader पर read() तरीके का इस्तेमाल करता है, जो List<Place> दिखाता है. Place में name नाम की प्रॉपर्टी होती है, जगह का नाम होता है, और latLng—ऐसे निर्देशांक होते हैं जहां जगह मौजूद होती है.

जगह

data class Place(
   val name: String,
   val latLng: LatLng,
   val address: LatLng,
   val rating: Float
)

मैप में मार्कर जोड़ें

अब जब जगहों की सूची स्टोरेज में लोड हो गई है, तो अगला चरण मैप पर इन जगहों को दिखाना है.

  1. MainActivity नाम की एक विधि बनाएं, जिसका नाम addMarkers() हो और इसे इस तरह परिभाषित करें:

MainActivity.addmarkers()

/**
* Adds marker representations of the places list on the provided GoogleMap object
*/
private fun addMarkers(googleMap: GoogleMap) {
   places.forEach { place ->
       val marker = googleMap.addMarker(
           MarkerOptions()
               .title(place.name)
               .position(place.latLng)
       )
   }
}

इस तरीके से places की सूची में दोहराया जाता है. इसके बाद, दिए गए GoogleMap ऑब्जेक्ट पर addMarker() का तरीका शुरू किया जाता है. मार्कर को MarkerOptions ऑब्जेक्ट को इंस्टैंशिएट करके बनाया जाता है, जिससे आप मार्कर को पसंद के मुताबिक बना सकते हैं. इस स्थिति में, मार्कर का शीर्षक और स्थिति दी जाती है, जो साइकल की दुकान के नाम और उसके निर्देशांकों को दिखाता है.

  1. आगे बढ़ें और ऐप्लिकेशन चलाएं और अभी-अभी जोड़े गए मार्कर देखने के लिए सैन फ़्रांसिस्को में जाएं!

7. मार्कर कस्टमाइज़ करें

मार्कर के लिए ऐसे कई कस्टमाइज़ेशन विकल्प उपलब्ध हैं जिन्हें आपने अभी-अभी जोड़ा है, ताकि उपयोगकर्ताओं को अलग दिखाई देने और उपयोगी जानकारी देने में उन्हें सहायता मिले. इस काम में, आप हर मार्कर की इमेज को पसंद के मुताबिक बना सकते हैं. साथ ही, मार्कर पर टैप करके मिलने वाली जानकारी विंडो को भी पसंद के मुताबिक बना सकते हैं.

a26f82802fe838e9.png

जानकारी विंडो जोड़ना

डिफ़ॉल्ट रूप से, किसी मार्कर पर टैप करने पर जानकारी विंडो में शीर्षक और स्निपेट (अगर सेट है) दिखते हैं. आप इसे कस्टमाइज़ करें, ताकि इसमें जगह और #39; के पते और रेटिंग जैसी अन्य जानकारी दिख सके.

मार्कर_info_contents.xml बनाएं

सबसे पहले, marker_info_contents.xml नाम की एक नई लेआउट फ़ाइल बनाएं.

  1. ऐसा करने के लिए, Android Studio के प्रोजेक्ट व्यू में app/src/main/res/layout फ़ोल्डर पर दायां क्लिक करें और नया > लेआउट रिसॉर्स फ़ाइल को चुनें.

8cac51fcbef9171b.png

  1. डायलॉग बॉक्स में, फ़ाइल नाम फ़ील्ड में marker_info_contents और Root element फ़ील्ड में LinearLayout टाइप करें. इसके बाद, ठीक है पर क्लिक करें.

8783af12baf07a80.png

इस लेआउट फ़ाइल को बाद में जानकारी विंडो में मौजूद कॉन्टेंट को दिखाने के लिए बढ़ाया जाता है.

  1. नीचे दिए गए कोड स्निपेट में कॉन्टेंट कॉपी करें, जो वर्टिकल LinearLayout व्यू ग्रुप में तीन TextViews जोड़ता है और फ़ाइल का डिफ़ॉल्ट कोड ओवरराइट कर देता है.

mark_info_contents.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:tools="http://schemas.android.com/tools"
   android:orientation="vertical"
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"
   android:gravity="center_horizontal"
   android:padding="8dp">

   <TextView
       android:id="@+id/text_view_title"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:textColor="@android:color/black"
       android:textSize="18sp"
       android:textStyle="bold"
       tools:text="Title"/>

   <TextView
       android:id="@+id/text_view_address"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:textColor="@android:color/black"
       android:textSize="16sp"
       tools:text="123 Main Street"/>

   <TextView
       android:id="@+id/text_view_rating"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:textColor="@android:color/black"
       android:textSize="16sp"
       tools:text="Rating: 3"/>

</LinearLayout>

InfoविंडोAdapter को लागू करना

कस्टम जानकारी विंडो के लिए लेआउट फ़ाइल बनाने के बाद, अगला चरण है GoogleMap.InfoविंडोAdapter इंटरफ़ेस लागू करना. इस इंटरफ़ेस में getInfoWindow() और getInfoContents() दो तरीके हैं. दोनों तरीकों में एक वैकल्पिक View ऑब्जेक्ट मिलता है, जिसमें पहले का इस्तेमाल विंडो को पसंद के मुताबिक बनाने के लिए किया जाता है. वहीं, दूसरा ऑब्जेक्ट अपने कॉन्टेंट को पसंद के मुताबिक बना सकता है. अपने मामले में, आप दोनों को लागू करते हैं और getInfoWindow() में शून्य दिखाते हुए getInfoContents() के रिटर्न को पसंद के मुताबिक बनाते हैं, जो यह बताता है कि डिफ़ॉल्ट विंडो का इस्तेमाल किया जाना चाहिए.

  1. Android Studio में प्रोजेक्ट व्यू के app/src/main/java/com/google/codelabs/buildyourfirstmap फ़ोल्डर पर दायां क्लिक करें. इसके बाद, MarkerInfoWindowAdapter वाले पैकेज में, MarkerInfoWindowAdapter के नाम से एक नई Kotlin फ़ाइल बनाएं. इसके बाद, नया > Kotlin फ़ाइल/क्लास चुनें.

3975ba36eba9f8e1.png

  1. डायलॉग बॉक्स में, MarkerInfoWindowAdapter टाइप करें और फ़ाइल को हाइलाइट करके रखें.

992235af53d3897f.png

  1. फ़ाइल बनाने के बाद, नीचे दिए गए कोड स्निपेट में मौजूद कॉन्टेंट को अपनी नई फ़ाइल में कॉपी करें.

मार्कर जानकारी विंडो अडैप्टर

import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.widget.TextView
import com.google.android.gms.maps.GoogleMap
import com.google.android.gms.maps.model.Marker
import com.google.codelabs.buildyourfirstmap.place.Place

class MarkerInfoWindowAdapter(
    private val context: Context
) : GoogleMap.InfoWindowAdapter {
   override fun getInfoContents(marker: Marker?): View? {
       // 1. Get tag
       val place = marker?.tag as? Place ?: return null

       // 2. Inflate view and set title, address, and rating
       val view = LayoutInflater.from(context).inflate(
           R.layout.marker_info_contents, null
       )
       view.findViewById<TextView>(
           R.id.text_view_title
       ).text = place.name
       view.findViewById<TextView>(
           R.id.text_view_address
       ).text = place.address
       view.findViewById<TextView>(
           R.id.text_view_rating
       ).text = "Rating: %.2f".format(place.rating)

       return view
   }

   override fun getInfoWindow(marker: Marker?): View? {
       // Return null to indicate that the 
       // default window (white bubble) should be used
       return null
   }
}

getInfoContents() तरीके के कॉन्टेंट में, दिए गए मार्कर को Place टाइप में कास्ट किया जाता है और कास्ट करना मुमकिन नहीं है, तो यह तरीका शून्य (##39) सेट करता है और आप Marker पर टैग प्रॉपर्टी सेट नहीं करते. हालांकि, अगले चरण में आप ऐसा करते हैं.

इसके बाद, marker_info_contents.xml लेआउट को इनफ़्लेट किया जाता है. इसके बाद, TextViews में Place टैग पर टेक्स्ट सेट किया जाता है.

MainActivity को अपडेट करें

अपने अब तक बनाए गए सभी कॉम्पोनेंट को चिपकाने के लिए, आपको MainActivity क्लास में दो लाइनें जोड़नी होंगी.

सबसे पहले, getMapAsync विधि कॉल के अंदर, कस्टम InfoWindowAdapter, MarkerInfoWindowAdapter को पास करने के लिए, GoogleMap ऑब्जेक्ट पर setInfoWindowAdapter() विधि शुरू करें और MarkerInfoWindowAdapter का एक नया इंस्टेंस बनाएं.

  1. getMapAsync() lambda में addMarkers() वाले तरीके से कॉल करने के बाद, नीचे दिया गया कोड जोड़कर ऐसा करें.

MainActivity.onCreate()

// Set custom info window adapter
googleMap.setInfoWindowAdapter(MarkerInfoWindowAdapter(this))

आखिर में, आपको हर जगह को मैप पर जोड़े गए हर मार्कर पर टैग प्रॉपर्टी के तौर पर सेट करना होगा.

  1. ऐसा करने के लिए, addMarkers() फ़ंक्शन में, places.forEach{} कॉल में यह बदलाव करें:

MainActivity.addmarkers()

places.forEach { place ->
   val marker = googleMap.addMarker(
       MarkerOptions()
           .title(place.name)
           .position(place.latLng)
           .icon(bicycleIcon)
   )

   // Set place as the tag on the marker object so it can be referenced within
   // MarkerInfoWindowAdapter
   marker.tag = place
}

पसंद के मुताबिक मार्कर इमेज जोड़ें

मार्कर इमेज को पसंद के मुताबिक बनाना, आपके मैप पर मार्कर के ज़रिए दिखाई जाने वाली जगह के प्रकार को बताने का एक मज़ेदार तरीका है. इस चरण में, मैप पर मौजूद हर दुकान को दिखाने के लिए, आप डिफ़ॉल्ट लाल मार्कर के बजाय साइकल को दिखाएंगे. स्टार्टर प्रोजेक्ट में, app/src/res/drawable में साइकिल आइकॉन ic_directions_bike_black_24dp.xml शामिल है. आप इसका इस्तेमाल करते हैं.

6eb7358bb61b0a88.png

मार्कर पर कस्टम बिट मैप सेट करें

वेक्टर को इकट्ठा करने वाले साइकल के आइकॉन, आपके मैप पर अगला कदम होगा कि हर मार्कर और #39; आइकॉन के रूप में ड्रॉ किया जा सकता है. MarkerOptions में icon एक तरीका है. इसे पूरा करने के लिए, आपको BitmapDescriptor का इस्तेमाल करना होता है.

सबसे पहले, आपको उस वेक्टर ड्रॉ करने की सुविधा को बदलना होगा जिसे आपने अभी-अभी BitmapDescriptor में जोड़ा है. स्टार्टर प्रोजेक्ट में BitMapHelper नाम की एक फ़ाइल का vectorToBitmap() शामिल है, जो हेल्पर फ़ंक्शन के तौर पर काम करता है.

बिट मैपहेल्पर

package com.google.codelabs.buildyourfirstmap

import android.content.Context
import android.graphics.Bitmap
import android.graphics.Canvas
import android.util.Log
import androidx.annotation.ColorInt
import androidx.annotation.DrawableRes
import androidx.core.content.res.ResourcesCompat
import androidx.core.graphics.drawable.DrawableCompat
import com.google.android.gms.maps.model.BitmapDescriptor
import com.google.android.gms.maps.model.BitmapDescriptorFactory

object BitmapHelper {
   /**
    * Demonstrates converting a [Drawable] to a [BitmapDescriptor], 
    * for use as a marker icon. Taken from ApiDemos on GitHub:
    * https://github.com/googlemaps/android-samples/blob/main/ApiDemos/kotlin/app/src/main/java/com/example/kotlindemos/MarkerDemoActivity.kt
    */
   fun vectorToBitmap(
      context: Context,
      @DrawableRes id: Int, 
      @ColorInt color: Int
   ): BitmapDescriptor {
       val vectorDrawable = ResourcesCompat.getDrawable(context.resources, id, null)
       if (vectorDrawable == null) {
           Log.e("BitmapHelper", "Resource not found")
           return BitmapDescriptorFactory.defaultMarker()
       }
       val bitmap = Bitmap.createBitmap(
           vectorDrawable.intrinsicWidth,
           vectorDrawable.intrinsicHeight,
           Bitmap.Config.ARGB_8888
       )
       val canvas = Canvas(bitmap)
       vectorDrawable.setBounds(0, 0, canvas.width, canvas.height)
       DrawableCompat.setTint(vectorDrawable, color)
       vectorDrawable.draw(canvas)
       return BitmapDescriptorFactory.fromBitmap(bitmap)
   }
}

इस तरीके में Context, एक ड्रॉ करने लायक रिसॉर्स आईडी, और एक कलर इंटिजर होता है. साथ ही, यह BitmapDescriptor का प्रतिनिधित्व करता है.

हेल्पर वाले तरीके का इस्तेमाल करके, bicycleIcon नाम की नई प्रॉपर्टी का एलान करें और यह जानकारी दें: MainActivity.bicycleIcon

private val bicycleIcon: BitmapDescriptor by lazy {
   val color = ContextCompat.getColor(this, R.color.colorPrimary)
   BitmapHelper.vectorToBitmap(this, R.drawable.ic_directions_bike_black_24dp, color)
}

यह प्रॉपर्टी आपके ऐप्लिकेशन में पहले से तय रंग colorPrimary का इस्तेमाल करती है. इसका इस्तेमाल, साइकल के आइकॉन को रंगने और इसे BitmapDescriptor के तौर पर दिखाने के लिए किया जाता है.

  1. इस प्रॉपर्टी का इस्तेमाल करके, अपने आइकॉन को पसंद के मुताबिक बनाने के लिए, addMarkers() वाले तरीके में MarkerOptions का icon तरीका शुरू करें. ऐसा करने पर, मार्कर प्रॉपर्टी कुछ इस तरह दिखेगी:

MainActivity.addmarkers()

val marker = googleMap.addMarker(
    MarkerOptions()
        .title(place.name)
        .position(place.latLng)
        .icon(bicycleIcon)
)
  1. अपडेट किए गए मार्कर देखने के लिए ऐप्लिकेशन चलाएं!

8. क्लस्टर मार्कर

मैप में आप जितनी दूर ज़ूम इन करते हैं, इसके आधार पर आपने देखा होगा कि आपने जो मार्कर जोड़े हैं वे ओवरलैप कर रहे हैं. ओवरलैप करने वाले मार्कर के साथ इंटरैक्ट करना और बहुत ज़्यादा शोर बनाना बहुत कठिन होता है, जिससे आपके ऐप्लिकेशन की उपयोगिता पर असर पड़ता है.

68591edc86d73724.png

इसके लिए उपयोगकर्ता अनुभव को बेहतर बनाने के लिए, जब भी आपके पास कोई बड़ा डेटासेट इकट्ठा होता है, तब मार्कर मार्कर को लागू करने का यह सबसे सही तरीका है. क्लस्टरिंग के साथ, जब आप मैप को ज़ूम इन और ज़ूम आउट करते हैं, तो आस-पास के मार्कर इस तरह इकट्ठा किए जाते हैं:

f05e1ca27ff42bf6.png

इसे लागू करने के लिए, आपको Android Utility लाइब्रेरी के लिए Maps SDK टूल की मदद लेनी होगी.

Android Utility लाइब्रेरी के लिए Maps SDK टूल

Android Utility लाइब्रेरी के लिए Maps SDK टूल, Android के लिए Maps SDK टूल की सुविधाओं को बेहतर बनाने के तरीके के तौर पर बनाया गया है. इसमें मार्कर क्लस्टरिंग, हीटमैप, KML और GeoJson सहायता, पॉलीलाइन एन्कोडिंग, और डिकोडिंग जैसी बेहतर सुविधाएं हैं. साथ ही, गोल आकार वाली ज्यामिति के कुछ मददगार फ़ंक्शन भी हैं.

अपनी build.gradle को अपडेट करना

उपयोगिता लाइब्रेरी को Android के लिए मैप SDK टूल से अलग से पैकेज किया गया है, इसलिए आपको अपनी build.gradle फ़ाइल में एक और डिपेंडेंसी जोड़नी होगी.

  1. आगे बढ़ें और अपनी app/build.gradle फ़ाइल के dependencies सेक्शन को अपडेट करें.

build.gradle

implementation 'com.google.maps.android:android-maps-utils:1.1.0'
  1. इस लाइन को जोड़ने पर, आपको नई डिपेंडेंसी लाने के लिए प्रोजेक्ट सिंक करना होगा.

b7b030ec82c007fd.png

क्लस्टर लागू करना

अपने ऐप्लिकेशन पर क्लस्टर लागू करने के लिए, इन तीन चरणों का पालन करें:

  1. ClusterItem इंटरफ़ेस लागू करें.
  2. DefaultClusterRenderer क्लास को सब-क्लास करें.
  3. ClusterManager बनाएं और आइटम जोड़ें.

ClusterItem इंटरफ़ेस लागू करना

मैप पर क्लस्टर करने लायक मार्कर दिखाने वाले सभी ऑब्जेक्ट को ClusterItem इंटरफ़ेस लागू करना होगा. आपके केस का मतलब है कि Place मॉडल को ClusterItem का पालन करना होगा. आगे बढ़ें और Place.kt फ़ाइल खोलें और इसमें नीचे दिए गए बदलाव करें:

जगह

data class Place(
   val name: String,
   val latLng: LatLng,
   val address: String,
   val rating: Float
) : ClusterItem {
   override fun getPosition(): LatLng =
       latLng

   override fun getTitle(): String =
       name

   override fun getSnippet(): String =
       address
}

ClusterItem इन तीन तरीकों के बारे में बताता है:

  • getPosition(), जो जगह LatLng का प्रतिनिधित्व करता है.
  • getTitle(), जो जगह के नाम #39 दिखाता है
  • getSnippet(), जो जगह के पते#33 दिखाता है.

डिफ़ॉल्टClusterRenderer क्लास को सब-क्लास करें

क्लस्टर लागू करने के लिए ज़िम्मेदार क्लास, ClusterManager, अंदरूनी तौर पर ClusterRenderer क्लास का इस्तेमाल करता है, ताकि क्लस्टर बनाने के दौरान आप उसे पैन कर सकें और मैप को ज़ूम कर सकें. डिफ़ॉल्ट रूप से, यह डिफ़ॉल्ट रेंडरर के साथ आता है, DefaultClusterRenderer, जो ClusterRenderer को लागू करता है. आसान मामलों में, यह काफ़ी होना चाहिए. हालांकि, आपके मामले में, मार्कर को कस्टमाइज़ करने की ज़रूरत होती है, इसलिए आपको इस क्लास का विस्तार करना होगा और उसमें कस्टमाइज़ेशन जोड़ने होंगे.

आगे बढ़ें और पैकेज com.google.codelabs.buildyourfirstmap.place में Kotlin फ़ाइल PlaceRenderer.kt बनाएं और इसे इस तरह से बताएं:

जगह बनाने वाला

package com.google.codelabs.buildyourfirstmap.place

import android.content.Context
import androidx.core.content.ContextCompat
import com.google.android.gms.maps.GoogleMap
import com.google.android.gms.maps.model.BitmapDescriptor
import com.google.android.gms.maps.model.Marker
import com.google.android.gms.maps.model.MarkerOptions
import com.google.codelabs.buildyourfirstmap.BitmapHelper
import com.google.codelabs.buildyourfirstmap.R
import com.google.maps.android.clustering.ClusterManager
import com.google.maps.android.clustering.view.DefaultClusterRenderer

/**
* A custom cluster renderer for Place objects.
*/
class PlaceRenderer(
   private val context: Context,
   map: GoogleMap,
   clusterManager: ClusterManager<Place>
) : DefaultClusterRenderer<Place>(context, map, clusterManager) {

   /**
    * The icon to use for each cluster item
    */
   private val bicycleIcon: BitmapDescriptor by lazy {
       val color = ContextCompat.getColor(context,
           R.color.colorPrimary
       )
       BitmapHelper.vectorToBitmap(
           context,
           R.drawable.ic_directions_bike_black_24dp,
           color
       )
   }

   /**
    * Method called before the cluster item (the marker) is rendered.
    * This is where marker options should be set.
    */
   override fun onBeforeClusterItemRendered(
      item: Place,
      markerOptions: MarkerOptions
   ) {
       markerOptions.title(item.name)
           .position(item.latLng)
           .icon(bicycleIcon)
   }

   /**
    * Method called right after the cluster item (the marker) is rendered.
    * This is where properties for the Marker object should be set.
    */
   override fun onClusterItemRendered(clusterItem: Place, marker: Marker) {
       marker.tag = clusterItem
   }
}

यह क्लास इन दो फ़ंक्शन को ओवरराइड करती है:

  • onBeforeClusterItemRendered(), जिसे मैप पर क्लस्टर को रेंडर करने से पहले कॉल किया जाता है. यहां, आप MarkerOptions की मदद से कस्टमाइज़ेशन कर सकते हैं—इस मामले में, यह मार्कर' का शीर्षक, पोज़िशन, और आइकॉन सेट करता है.
  • onClusterItemRenderer(), जिसे मार्कर के मैप पर रेंडर किए जाने के तुरंत बाद कॉल किया जाता है. यहां आप बनाए गए Marker ऑब्जेक्ट को ऐक्सेस कर सकते हैं—इस मामले में, यह मार्कर और #39;s टैग प्रॉपर्टी को सेट करता है.

ClusterManager बनाएं और आइटम जोड़ें

आखिर में, क्लस्टर की सुविधा पाने के लिए, आपको MainActivity में बदलाव करना होगा, ताकि ClusterManager को इंस्टैंशिएट किया जा सके और उस पर ज़रूरी डिपेंडेंसी दी जा सके. ClusterManager, मार्कर (ClusterItem ऑब्जेक्ट) को अंदरूनी तौर पर जोड़ने का काम करता है. इसलिए, मैप पर सीधे मार्कर जोड़ने के बजाय, इस ज़िम्मेदारी को ClusterManager में शामिल किया जाता है. इसके अलावा, ClusterManager setInfoWindowAdapter() के अंदर भी कॉल कर सकते हैं. इसलिए, कस्टम जानकारी वाली विंडो को ClusterManger's MarkerManager.Collection ऑब्जेक्ट पर सेट किया जाना होगा.

  1. शुरू करने के लिए, MainActivity.onCreate() के getMapAsync() कॉल में Lambda के कॉन्टेंट में बदलाव करें. आगे बढ़ें और addMarkers() और setInfoWindowAdapter() पर कॉल को टिप्पणी करें. इसके बजाय, addClusteredMarkers() नाम का एक तरीका शुरू करें, जिसे आप आगे तय करते हैं.

MainActivity.onCreate()

mapFragment?.getMapAsync { googleMap ->
    //addMarkers(googleMap)
    addClusteredMarkers(googleMap)

    // Set custom info window adapter.
    // googleMap.setInfoWindowAdapter(MarkerInfoWindowAdapter(this))
}
  1. इसके बाद, MainActivity में addClusteredMarkers() के बारे में बताएं.

MainActivity.addClusteredMarkers()

/**
* Adds markers to the map with clustering support.
*/
private fun addClusteredMarkers(googleMap: GoogleMap) {
   // Create the ClusterManager class and set the custom renderer.
   val clusterManager = ClusterManager<Place>(this, googleMap)
   clusterManager.renderer =
       PlaceRenderer(
           this,
           googleMap,
           clusterManager
       )

   // Set custom info window adapter
   clusterManager.markerCollection.setInfoWindowAdapter(MarkerInfoWindowAdapter(this))

   // Add the places to the ClusterManager.
   clusterManager.addItems(places)
   clusterManager.cluster()

   // Set ClusterManager as the OnCameraIdleListener so that it
   // can re-cluster when zooming in and out.
   googleMap.setOnCameraIdleListener {
       clusterManager.onCameraIdle()
   }
}

इस तरीके से ClusterManager को इंस्टैंशिएट किया जाता है, कस्टम रेंडरर को PlacesRenderer भेजा जाता है, सभी जगहों को जोड़ा जाता है, और cluster() तरीके को शुरू किया जाता है. साथ ही, ClusterManager, मैप ऑब्जेक्ट पर setInfoWindowAdapter() तरीके का इस्तेमाल करता है. इसलिए, कस्टम ऑब्जेक्ट विंडो को ClusterManager.markerCollection ऑब्जेक्ट पर सेट करना होगा. आखिर में, जब आप उपयोगकर्ता के मैप पर पैन और ज़ूम करने के लिए क्लस्टरिंग बदलना चाहते हैं, तो googleMap को OnCameraIdleListener दिया जाता है, जैसे कि जब कैमरा इस्तेमाल में नहीं होता, तो clusterManager.onCameraIdle() को शुरू किया जाता है.

  1. क्लस्टर की नई दुकानें देखने के लिए, ऐप्लिकेशन का इस्तेमाल करें!

9. मैप पर जानकारी देने के लिए ड्रॉ करें

जब आप मैप पर बनाने के लिए पहले से ही एक तरीका एक्सप्लोर कर चुके हैं, तब Android के लिए Maps SDK टूल कई दूसरे तरीकों से इस पर काम कर सकता है. जैसे, मैप पर काम की जानकारी दिखाने के लिए.

उदाहरण के लिए, अगर आप मैप पर रास्ते और इलाके दिखाना चाहते हैं, तो उन्हें पॉलीलाइन और पॉलीगॉन का इस्तेमाल करके मैप पर दिखा सकते हैं. इसके अलावा, अगर आप कोई इमेज ज़मीन की सतह पर ठीक करना चाहते हैं, तो आप ग्राउंड ओवरले का इस्तेमाल कर सकते हैं.

इस टास्क में, आप मार्कर को टैप करने पर उसके आकार (खास तौर पर सर्कल) को बनाने का तरीका जानेंगे.

आमने-सामने

क्लिक लिसनर जोड़ें

आम तौर पर, आप मार्कर के ज़रिए क्लिक लिसनर जोड़ने का तरीका, GoogleMap के ज़रिए सीधे setOnMarkerClickListener() ऑब्जेक्ट पर setOnMarkerClickListener() लिसनर के ज़रिए पास करते हैं. हालांकि, क्योंकि आप क्लस्टर का इस्तेमाल कर रहे हैं, इसलिए क्लिक लिसनर ClusterManager को दिया जाना चाहिए.

  1. MainActivity में addClusteredMarkers() तरीके में, cluster() को शुरू करने के तुरंत बाद नीचे दी गई लाइन जोड़ें.

MainActivity.addClusteredMarkers()

// Show polygon
clusterManager.setOnClusterItemClickListener { item ->
   addCircle(googleMap, item)
   return@setOnClusterItemClickListener false
}

इस तरीके से लिसनर जोड़ा जाता है और addCircle() मैथड को शुरू किया जाता है. आखिर में, यह बताने के लिए कि इस तरीके ने इस इवेंट का इस्तेमाल नहीं किया है, false को इस तरीके से लौटा दिया जाता है.

  1. इसके बाद, आपको MainActivity में प्रॉपर्टी circle और तरीका addCircle() तय करना होगा.

MainActivity.addCircle()

private var circle: Circle? = null

/**
* Adds a [Circle] around the provided [item]
*/
private fun addCircle(googleMap: GoogleMap, item: Place) {
   circle?.remove()
   circle = googleMap.addCircle(
       CircleOptions()
           .center(item.latLng)
           .radius(1000.0)
           .fillColor(ContextCompat.getColor(this, R.color.colorPrimaryTranslucent))
           .strokeColor(ContextCompat.getColor(this, R.color.colorPrimary))
   )
}

circle प्रॉपर्टी को सेट किया जाता है, ताकि जब भी किसी नए मार्कर पर टैप किया जाए, तो पिछला सर्कल हटा दिया जाए और एक नया मार्कर जोड़ दिया जाए. ध्यान दें कि सर्कल जोड़ने के लिए एपीआई, काफ़ी हद तक मार्कर जोड़ने जैसा ही है.

  1. आगे बढ़ें और बदलाव देखने के लिए ऐप्लिकेशन चलाएं.

10. कैमरा कंट्रोल

अपने आखिरी टास्क के तौर पर, आप कैमरे के कुछ कंट्रोल देखते हैं, ताकि आप किसी खास इलाके के आस-पास के व्यू पर फ़ोकस कर सकें.

कैमरा और व्यू

जब आप ऐप्लिकेशन चलाते हैं, तो कैमरा अफ़्रीका महाद्वीप दिखाता है. साथ ही, आपने जो मार्कर जोड़े हैं उन्हें ढूंढने के लिए आपको बहुत मेहनत से पैन और ज़ूम से सैन फ़्रांसिस्को जाना होगा. दुनिया को एक्सप्लोर करने का यह एक मज़ेदार तरीका हो सकता है. हालांकि, अगर आप मार्कर को तुरंत दिखाना चाहते हैं, तो यह काम का नहीं है.

इस काम में मदद करने के लिए, आप कैमरे की स्थिति को प्रोग्रामैटिक तरीके से सेट कर सकते हैं, ताकि व्यू अपने हिसाब से बीच में हो.

  1. कैमरे के व्यू में बदलाव करने के लिए, getMapAsync() कॉल में आगे दिया गया कोड जोड़ें, ताकि ऐप्लिकेशन लॉन्च होने पर यह सैन फ़्रांसिस्को की जगह पर शुरू हो सके.

MainActivity.onCreate()

mapFragment?.getMapAsync { googleMap ->
   // Ensure all places are visible in the map.
   googleMap.setOnMapLoadedCallback {
       val bounds = LatLngBounds.builder()
       places.forEach { bounds.include(it.latLng) }
       googleMap.moveCamera(CameraUpdateFactory.newLatLngBounds(bounds.build(), 20))
   }
}

पहले, setOnMapLoadedCallback() को कॉल किया जाता है, ताकि कैमरा अपडेट सिर्फ़ मैप लोड होने के बाद ही किया जा सके. यह चरण ज़रूरी है, क्योंकि कैमरा अपडेट कॉल करने से पहले, डाइमेंशन जैसी मैप प्रॉपर्टी का हिसाब लगाना होता है.

Lambda में, एक नया LatLngBounds ऑब्जेक्ट बनाया गया है, जो मैप पर एक आयताकार क्षेत्र बताता है. सभी जगहों की सीमाओं के अंदर पक्का करने के लिए, इसमें सभी जगह LatLng की वैल्यू शामिल करके इसे लगातार बनाया जाता है. इस ऑब्जेक्ट के बन जाने के बाद, GoogleMap पर moveCamera() तरीके को शुरू किया जाता है और CameraUpdateFactory.newLatLngBounds(bounds.build(), 20) के ज़रिए इसे CameraUpdate दिया जाता है.

  1. ऐप्लिकेशन खोलें और देखें कि कैमरा अब सैन फ़्रांसिस्को में शुरू हो गया है.

कैमरे में हुए बदलावों पर ध्यान देना

कैमरे की स्थिति को बदलने के अलावा, आप उपयोगकर्ता के मैप पर इधर-उधर जाने पर भी कैमरे के अपडेट सुन सकते हैं. अगर आपका कैमरा आस-पास घूमता है, तो आपको यूज़र इंटरफ़ेस (यूआई) में बदलाव करना पड़ सकता है.

सिर्फ़ मनोरंजन के लिए, कैमरा चलते समय मार्कर को पारदर्शी बनाने के लिए आप कोड में बदलाव करते हैं.

  1. addClusteredMarkers() तरीके में, आगे बढ़ें और पैसे चुकाने के तरीके के सबसे नीचे की ओर ये लाइनें जोड़ें:

MainActivity.addClusteredMarkers()

// When the camera starts moving, change the alpha value of the marker to translucent.
googleMap.setOnCameraMoveStartedListener {
   clusterManager.markerCollection.markers.forEach { it.alpha = 0.3f }
   clusterManager.clusterMarkerCollection.markers.forEach { it.alpha = 0.3f }
}

इससे OnCameraMoveStartedListener जुड़ जाता है, ताकि जब भी कैमरा चलना शुरू करे, तो सभी मार्कर' (क्लस्टर और मार्कर) ऐल्फ़ा मान 0.3f में बदल जाएं, ताकि मार्कर पारदर्शी दिखें.

  1. आखिर में, कैमरा बंद होने पर ट्रांसपेरंट मार्कर को वापस अपारदर्शिता में बदलने के लिए, addClusteredMarkers() तरीके में setOnCameraIdleListener के कॉन्टेंट में यह बदलाव करें:

MainActivity.addClusteredMarkers()

googleMap.setOnCameraIdleListener {
   // When the camera stops moving, change the alpha value back to opaque.
   clusterManager.markerCollection.markers.forEach { it.alpha = 1.0f }
   clusterManager.clusterMarkerCollection.markers.forEach { it.alpha = 1.0f }

   // Call clusterManager.onCameraIdle() when the camera stops moving so that reclustering
   // can be performed when the camera stops moving.
   clusterManager.onCameraIdle()
}
  1. आगे बढ़ें और नतीजे देखने के लिए ऐप्लिकेशन चलाएं!

11. मैप KTX

Kotlin ऐप्लिकेशन के एक या एक से ज़्यादा Google Maps Platform Android SDK टूल का इस्तेमाल करने वाले, Kotlin एक्सटेंशन या KTX लाइब्रेरी उपलब्ध हैं. इनसे कोरूटीन, एक्सटेंशन प्रॉपर्टी/फ़ंक्शन वगैरह जैसी Kotlin लैंग्वेज की सुविधाओं का फ़ायदा लिया जा सकता है. हर Google Maps SDK टूल में उससे जुड़ी एक KTX लाइब्रेरी मौजूद है, जैसा कि नीचे दिखाया गया है:

Google Maps Platform KTX डायग्राम

इस टास्क में, आप Maps KTX और Maps Utils KTX लाइब्रेरी का इस्तेमाल अपने ऐप्लिकेशन के लिए करेंगे. साथ ही, पिछले टास्क&#39 को रीफ़ैक्टर करेंगे; ताकि आप अपने ऐप्लिकेशन में Kotlin की खास भाषाओं की सुविधाओं का इस्तेमाल कर सकें.

  1. अपने ऐप्लिकेशन-लेवल build.gradle फ़ाइल में KTX डिपेंडेंसी शामिल करना

ऐप्लिकेशन, Android के लिए Maps SDK और Android Utility लाइब्रेरी के लिए Maps SDK टूल, दोनों का इस्तेमाल करता है. इसलिए, आपको इन लाइब्रेरी से जुड़ी KTX लाइब्रेरी शामिल करनी होंगी. इस टास्क में, AndroidX Lifecycle KTX लाइब्रेरी में मौजूद सुविधा का भी इस्तेमाल किया जाएगा. इसलिए, यह निर्भरता भी अपने ऐप्लिकेशन में build.gradle फ़ाइल में शामिल करें.

build.gradle

dependencies {
    // ...

    // Maps SDK for Android KTX Library
    implementation 'com.google.maps.android:maps-ktx:3.0.0'

    // Maps SDK for Android Utility Library KTX Library
    implementation 'com.google.maps.android:maps-utils-ktx:3.0.0'

    // Lifecycle Runtime KTX Library
    implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.3.1'
}
  1. GoogleMap.addmarker() और GoogleMap.addCircle() एक्सटेंशन फ़ंक्शन का इस्तेमाल करना

Maps KTX लाइब्रेरी पिछले और इस्तेमाल किए गए GoogleMap.addMarker(MarkerOptions) और GoogleMap.addCircle(CircleOptions) के लिए, DSL-शैली का एपीआई विकल्प देती है. ऊपर बताए गए एपीआई का इस्तेमाल करने के लिए, मार्कर या सर्कल के विकल्प वाली क्लास बनाना ज़रूरी है, जबकि KTX विकल्पों के साथ आप lambda में मार्कर या सर्कल के विकल्प सेट कर सकते हैं.

इन एपीआई का इस्तेमाल करने के लिए, MainActivity.addMarkers(GoogleMap) और MainActivity.addCircle(GoogleMap) के तरीके अपडेट करें:

MainActivity.addmarkers(GoogleMap)

/**
 * Adds markers to the map. These markers won't be clustered.
 */
private fun addMarkers(googleMap: GoogleMap) {
    places.forEach { place ->
        val marker = googleMap.addMarker {
            title(place.name)
            position(place.latLng)
            icon(bicycleIcon)
        }
        // Set place as the tag on the marker object so it can be referenced within
        // MarkerInfoWindowAdapter
        marker.tag = place
    }
}

MainActivity.addCircle(GoogleMap)

/**
 * Adds a [Circle] around the provided [item]
 */
private fun addCircle(googleMap: GoogleMap, item: Place) {
    circle?.remove()
    circle = googleMap.addCircle {
        center(item.latLng)
        radius(1000.0)
        fillColor(ContextCompat.getColor(this@MainActivity, R.color.colorPrimaryTranslucent))
        strokeColor(ContextCompat.getColor(this@MainActivity, R.color.colorPrimary))
    }
}

ऊपर दिए गए तरीकों से इस तरीके को फिर से लिखना बहुत आसान है. साथ ही, इसे Kotlin और #39;s रेंडर वाले फ़ंक्शन के साथ लिटरल का इस्तेमाल करके पढ़ना मुमकिन है.

  1. SupportMapFragment.awaitMap() और GoogleMap.awaitMapLoad() एक्सटेंशन सस्पेंडिंग फ़ंक्शन का इस्तेमाल करना

Maps KTX लाइब्रेरी, कोरूटीन के लिए इस्तेमाल किए जाने वाले सस्पेंड फ़ंक्शन एक्सटेंशन भी उपलब्ध कराती है. खास तौर पर, हम SupportMapFragment.getMapAsync(OnMapReadyCallback) और GoogleMap.setOnMapLoadedCallback(OnMapLoadedCallback) के लिए, फ़ंक्शन के विकल्प निलंबित कर रहे हैं. इन वैकल्पिक एपीआई का इस्तेमाल करने से कॉलबैक पास करने की ज़रूरत नहीं होती. साथ ही, आपको सीरियल और सिंक्रोनस तरीके से इन तरीकों का जवाब पाने की सुविधा मिलती है.

ये तरीके फ़ंक्शन को निलंबित कर रहे हैं, इसलिए उनका इस्तेमाल कोरूटीन के अंदर होना चाहिए. लाइफ़साइकल रनटाइम KTX लाइब्रेरी, लाइफ़साइकल की जानकारी वाले कोरूटीन स्कोप उपलब्ध कराने के लिए, एक्सटेंशन ऑफ़र करती है, ताकि कोरूटीन चलाए जाने पर उन्हें सही लाइफ़साइकल इवेंट में रोका और रोका जा सके.

इन सिद्धांतों को मिलाकर, MainActivity.onCreate(Bundle) तरीका अपडेट करें:

MainActivity.onCreate(बंडल)

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
    val mapFragment =
        supportFragmentManager.findFragmentById(R.id.map_fragment) as SupportMapFragment
    lifecycleScope.launchWhenCreated {
        // Get map
        val googleMap = mapFragment.awaitMap()

        // Wait for map to finish loading
        googleMap.awaitMapLoad()

        // Ensure all places are visible in the map
        val bounds = LatLngBounds.builder()
        places.forEach { bounds.include(it.latLng) }
        googleMap.moveCamera(CameraUpdateFactory.newLatLngBounds(bounds.build(), 20))

        addClusteredMarkers(googleMap)
    }
}

lifecycleScope.launchWhenCreated कोरूटीन का दायरा, ब्लॉक को एक्ज़ीक्यूट करेगा, जब गतिविधि कम से कम तय की गई स्थिति में होगी. यह भी ध्यान रखें कि GoogleMap ऑब्जेक्ट को वापस पाने और मैप के लोड होने तक इंतज़ार करने के लिए, कॉल को SupportMapFragment.awaitMap() और GoogleMap.awaitMapLoad() से बदल दिया गया है. सस्पेंड करने के इन फ़ंक्शन का इस्तेमाल करके, कोड को रीफ़ैक्ट करने में मदद मिलती है. इसकी मदद से, आप एक जैसे क्रम में, एक जैसे कॉलबैक वाले कोड लिख सकते हैं.

  1. आगे बढ़ें और रीफ़ैक्टर किए गए बदलावों के साथ ऐप्लिकेशन को फिर से बनाएं!

12. बधाई हो

बधाई हो! आपने बहुत सारा कॉन्टेंट कवर किया है और उम्मीद है कि आपको Android के लिए Maps SDK में दी गई मुख्य सुविधाओं की बेहतर जानकारी होगी.

ज़्यादा जानें

  • Android के लिए जगहें SDK टूल—अपने आस-पास के कारोबारों का पता लगाने के लिए, जगहों के डेटा का रिच सेट देखें.
  • android-maps-ktx—एक ओपन सोर्स लाइब्रेरी है, जिसकी मदद से आप Android के लिए Maps SDK टूल और Android Utility लाइब्रेरी के लिए Maps SDK टूल को Kotlin के साथ आसानी से इस्तेमाल करने लायक बना सकते हैं.
  • android-place-ktx—एक ओपन सोर्स लाइब्रेरी, जो आपको Kotlin के हिसाब से Android के लिए जगहें SDK टूल के साथ इंटिग्रेट करने की अनुमति देती है.
  • android-samples—GitHub के सैंपल कोड में, इस कोडलैब में शामिल सभी सुविधाओं के बारे में बताया गया है.
  • Google Maps Platform की मदद से Android ऐप्लिकेशन बनाने के लिए, Kotlin कोडलैब की ज़्यादा जानकारी