Android पर एआर में आस-पास की जगहें दिखाएं (Kotlin)

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

ऐब्स्ट्रैक्ट

इस कोडलैब में, आपको यह सिखाया जाएगा कि Android पर ऑगमेंटेड रिएलिटी (एआर) में आस-पास की जगहों को दिखाने के लिए, Google Maps Platform से मिले डेटा का इस्तेमाल कैसे करें.

2344909dd9a52c60.png

ज़रूरी शर्तें

  • Android Studio का इस्तेमाल करके, Android डेवलपमेंट की बुनियादी जानकारी
  • Kotlin की जानकारी

आपको क्या सीखने को मिलेगा

  • डिवाइस के कैमरे और जगह की जानकारी को ऐक्सेस करने के लिए, उपयोगकर्ता से अनुमति मांगें.
  • डिवाइस की जगह की जानकारी के आस-पास की जगहों की जानकारी पाने के लिए, Places API के साथ इंटिग्रेट करें.
  • हॉरिजॉन्टल प्लेन वाली सतहों का पता लगाने के लिए, ARCore के साथ इंटिग्रेट करें. इससे वर्चुअल ऑब्जेक्ट को Sceneform का इस्तेमाल करके, 3D स्पेस में ऐंकर और प्लेस किया जा सकता है.
  • SensorManager का इस्तेमाल करके, डिवाइस की जगह की जानकारी इकट्ठा करें. साथ ही, Maps SDK for Android Utility Library का इस्तेमाल करके, वर्चुअल ऑब्जेक्ट को सही हेडिंग पर रखें.

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

2. सेट अप करें

Android Studio

इस कोडलैब में Android 10.0 (एपीआई लेवल 29) का इस्तेमाल किया गया है. इसके लिए, आपके पास Android Studio में Google Play services इंस्टॉल होना ज़रूरी है. इन दोनों डिपेंडेंसी को इंस्टॉल करने के लिए, यह तरीका अपनाएं:

  1. एसडीके मैनेजर पर जाएं. इसे ऐक्सेस करने के लिए, Tools > SDK Manager पर क्लिक करें.

6c44a9cb9cf6c236.png

  1. देखें कि Android 10.0 इंस्टॉल है या नहीं. अगर ऐसा नहीं है, तो Android 10.0 (Q) के बगल में मौजूद चेकबॉक्स को चुनकर इसे इंस्टॉल करें. इसके बाद, ठीक है पर क्लिक करें. आखिर में, दिखने वाले डायलॉग बॉक्स में फिर से ठीक है पर क्लिक करें.

368f17a974c75c73.png

  1. आखिर में, Google Play services इंस्टॉल करें. इसके लिए, एसडीके टूल टैब पर जाएं. इसके बाद, Google Play services के बगल में मौजूद चेकबॉक्स को चुनें. इसके बाद, ठीक है पर क्लिक करें. इसके बाद, दिखने वाले डायलॉग में ठीक है को फिर से चुनें**.**

497a954b82242f4b.png

ज़रूरी एपीआई

इस कोडलैब के लिए, यहां दिए गए सेक्शन के तीसरे चरण में जाकर Android के लिए Maps SDK और Places API चालू करें.

Google Maps Platform का इस्तेमाल शुरू करना

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

  1. बिलिंग खाता बनाएं.
  2. प्रोजेक्ट बनाएं.
  3. Google Maps Platform API और SDK टूल चालू करें. इनकी सूची पिछले सेक्शन में दी गई है.
  4. एपीआई पासकोड जनरेट करें.

ज़रूरी नहीं है: Android Emulator

अगर आपके पास ARCore की सुविधा वाला डिवाइस नहीं है, तो Android Emulator का इस्तेमाल करके, एआर सीन को सिम्युलेट किया जा सकता है. साथ ही, अपने डिवाइस की जगह की जानकारी को फ़र्ज़ी बनाया जा सकता है. इस अभ्यास में Sceneform का इस्तेमाल किया जाएगा. इसलिए, आपको यह भी पक्का करना होगा कि आपने "Sceneform के साथ काम करने के लिए, एम्युलेटर को कॉन्फ़िगर करें" में दिए गए चरणों का पालन किया हो.

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

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

अगर आपने git इंस्टॉल किया है, तो रिपॉज़िटरी को क्लोन किया जा सकता है.

git clone https://github.com/googlecodelabs/display-nearby-places-ar-android.git

इसके अलावा, सोर्स कोड को डाउनलोड करने के लिए, यहां दिए गए बटन पर क्लिक करें.

कोड मिलने के बाद, starter डायरेक्ट्री में मौजूद प्रोजेक्ट खोलें.

4. प्रोजेक्ट अवलोकन

पिछले चरण में डाउनलोड किए गए कोड को एक्सप्लोर करें. इस रिपॉज़िटरी में, आपको app नाम का एक मॉड्यूल दिखेगा. इसमें com.google.codelabs.findnearbyplacesar पैकेज शामिल है.

AndroidManifest.xml

इस कोडलैब में ज़रूरी सुविधाओं का इस्तेमाल करने के लिए, AndroidManifest.xml फ़ाइल में ये एट्रिब्यूट तय किए गए हैं:

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

<!-- Sceneform requires OpenGL ES 3.0 or later. -->
<uses-feature
   android:glEsVersion="0x00030000"
   android:required="true" />

<!-- Indicates that app requires ARCore ("AR Required"). Ensures the app is visible only in the Google Play Store on devices that support ARCore. For "AR Optional" apps remove this line. -->
<uses-feature android:name="android.hardware.camera.ar" />

uses-permission के लिए, यह बताया गया है कि इन सुविधाओं का इस्तेमाल करने से पहले, उपयोगकर्ता को कौनसी अनुमतियां देनी होंगी. इसके बारे में यहां बताया गया है:

  • android.permission.INTERNET—इससे आपका ऐप्लिकेशन, नेटवर्क ऑपरेशन कर सकता है और इंटरनेट पर डेटा फ़ेच कर सकता है. जैसे, Places API के ज़रिए जगहों की जानकारी.
  • android.permission.CAMERA—कैमरे का ऐक्सेस ज़रूरी है, ताकि डिवाइस के कैमरे का इस्तेमाल करके ऑगमेंटेड रिएलिटी में ऑब्जेक्ट दिखाए जा सकें.
  • android.permission.ACCESS_FINE_LOCATION—जगह की जानकारी का ऐक्सेस ज़रूरी है, ताकि डिवाइस की जगह की जानकारी के हिसाब से आस-पास की जगहों का पता लगाया जा सके.

uses-feature के लिए, यह बताया गया है कि इस ऐप्लिकेशन को कौनसी हार्डवेयर सुविधाएं चाहिए. इसके लिए, ये सुविधाएं बताई गई हैं:

  • OpenGL ES वर्शन 3.0 ज़रूरी है.
  • इसके लिए, ARCore की सुविधा वाला डिवाइस होना ज़रूरी है.

इसके अलावा, ऐप्लिकेशन ऑब्जेक्ट में ये मेटाडेटा टैग जोड़े जाते हैं:

<application
  android:allowBackup="true"
  android:icon="@mipmap/ic_launcher"
  android:label="@string/app_name"
  android:roundIcon="@mipmap/ic_launcher_round"
  android:supportsRtl="true"
  android:theme="@style/AppTheme">
  
  <!-- 
     Indicates that this app requires Google Play Services for AR ("AR Required") and causes
     the Google Play Store to download and install Google Play Services for AR along with
     the app. For an "AR Optional" app, specify "optional" instead of "required". 
  -->

  <meta-data
     android:name="com.google.ar.core"
     android:value="required" />

  <meta-data
     android:name="com.google.android.geo.API_KEY"
     android:value="@string/google_maps_key" />

  <!-- Additional elements here --> 

</application>

पहली मेटा-डेटा एंट्री से यह पता चलता है कि इस ऐप्लिकेशन को चलाने के लिए ARCore ज़रूरी है. वहीं, दूसरी एंट्री से यह पता चलता है कि Maps SDK for Android को Google Maps Platform API पासकोड कैसे दिया जाता है.

build.gradle

build.gradle में, ये अतिरिक्त डिपेंडेंसी बताई गई हैं:

dependencies {
    // Maps & Location
    implementation 'com.google.android.gms:play-services-location:17.0.0'
    implementation 'com.google.android.gms:play-services-maps:17.0.0'
    implementation 'com.google.maps.android:maps-utils-ktx:1.7.0'

    // ARCore
    implementation "com.google.ar.sceneform.ux:sceneform-ux:1.15.0"

    // Retrofit
    implementation "com.squareup.retrofit2:retrofit:2.7.1"
    implementation "com.squareup.retrofit2:converter-gson:2.7.1"
}

यहां हर डिपेंडेंसी के बारे में कम शब्दों में जानकारी दी गई है:

  • ग्रुप आईडी com.google.android.gms वाली लाइब्रेरी, जैसे कि play-services-location और play-services-maps का इस्तेमाल, डिवाइस की जगह की जानकारी को ऐक्सेस करने और Google Maps से जुड़ी सुविधाओं को ऐक्सेस करने के लिए किया जाता है.
  • com.google.maps.android:maps-utils-ktx, Maps SDK for Android Utility Library के लिए Kotlin एक्सटेंशन (KTX) लाइब्रेरी है. इस लाइब्रेरी में इस फ़ंक्शन का इस्तेमाल, वर्चुअल ऑब्जेक्ट को असल जगह पर रखने के लिए किया जाएगा.
  • com.google.ar.sceneform.ux:sceneform-ux, Sceneform लाइब्रेरी है. इसकी मदद से, आपको OpenGL के बारे में जाने बिना ही, असली जैसे दिखने वाले 3D सीन रेंडर करने की सुविधा मिलेगी.
  • ग्रुप आईडी com.squareup.retrofit2 में मौजूद डिपेंडेंसी, Retrofit डिपेंडेंसी हैं. इनकी मदद से, Places API के साथ इंटरैक्ट करने के लिए, एचटीटीपी क्लाइंट को तुरंत लिखा जा सकता है.

प्रोजेक्ट का स्ट्रक्चर

यहां आपको ये पैकेज और फ़ाइलें मिलेंगी:

  • **api—**इस पैकेज में ऐसी क्लास होती हैं जिनका इस्तेमाल, Retrofit का इस्तेमाल करके Places API से इंटरैक्ट करने के लिए किया जाता है.
  • **ar—**इस पैकेज में ARCore से जुड़ी सभी फ़ाइलें होती हैं.
  • **मॉडल—**इस पैकेज में एक डेटा क्लास Place शामिल है. इसका इस्तेमाल, Places API से मिले किसी एक प्लेस की जानकारी को कैप्सूल करने के लिए किया जाता है.
  • MainActivity.kt—यह आपके ऐप्लिकेशन में मौजूद एक Activity है. यह मैप और कैमरे का व्यू दिखाएगा.

5. सीन सेट अप करना

ऑगमेंटेड रिएलिटी (एआर) वाले कॉम्पोनेंट से शुरू करके, ऐप्लिकेशन के मुख्य कॉम्पोनेंट के बारे में जानें.

MainActivity में एक SupportMapFragment होता है, जो मैप ऑब्जेक्ट को दिखाने का काम करता है. साथ ही, इसमें ArFragmentPlacesArFragment—की एक सबक्लास होती है, जो ऑगमेंटेड रिएलिटी सीन को दिखाने का काम करती है.

ऑगमेंटेड रिएलिटी (एआर) सेटअप करना

ऑगमेंटेड रिएलिटी सीन दिखाने के अलावा, PlacesArFragment उपयोगकर्ता से कैमरे की अनुमति का अनुरोध भी करेगा. ऐसा तब होगा, जब उपयोगकर्ता ने पहले से अनुमति न दी हो. getAdditionalPermissions तरीके को बदलकर भी अतिरिक्त अनुमतियों का अनुरोध किया जा सकता है. आपको जगह की जानकारी इस्तेमाल करने की अनुमति भी देनी होगी. इसलिए, इस बात की जानकारी दें और getAdditionalPermissions तरीके को बदलें:

class PlacesArFragment : ArFragment() {

   override fun getAdditionalPermissions(): Array<String> =
       listOf(Manifest.permission.ACCESS_FINE_LOCATION)
           .toTypedArray()
}

इसे चलाएं

Android Studio में, starter डायरेक्ट्री में मौजूद स्केलेटन कोड खोलें. अगर टूलबार से चलाएं > 'ऐप्लिकेशन' चलाएं पर क्लिक करके, ऐप्लिकेशन को अपने डिवाइस या एम्युलेटर पर डिप्लॉय किया जाता है, तो आपको सबसे पहले जगह की जानकारी और कैमरे की अनुमति चालू करने के लिए कहा जाएगा. आगे बढ़ें और अनुमति दें पर क्लिक करें. इसके बाद, आपको कैमरे का व्यू और मैप का व्यू एक साथ इस तरह दिखना चाहिए:

e3e3073d5c86f427.png

हवाई जहाज़ों का पता लगाना

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

2a9b6ea7dcb2e249.png

ये सफ़ेद बिंदु, ARCore के दिशा-निर्देश हैं. इनसे पता चलता है कि किसी हॉरिज़ॉन्टल प्लेन का पता चल गया है. इन प्लेन की मदद से, "ऐंकर" बनाया जा सकता है. इससे वर्चुअल ऑब्जेक्ट को असली जगह पर रखा जा सकता है.

ARCore और यह आपके आस-पास के माहौल को कैसे समझता है, इस बारे में ज़्यादा जानने के लिए, इसके बुनियादी सिद्धांतों के बारे में पढ़ें.

6. आस-पास की जगहें पाना

इसके बाद, आपको डिवाइस की मौजूदा जगह की जानकारी को ऐक्सेस करके दिखाना होगा. इसके बाद, Places API का इस्तेमाल करके, आस-पास की जगहों की जानकारी फ़ेच करनी होगी.

Maps सेटअप करना

Google Maps Platform API कुंजी

आपने Places API से क्वेरी करने और Maps SDK for Android का इस्तेमाल करने के लिए, Google Maps Platform API पासकोड बनाया था. gradle.properties फ़ाइल खोलें और "YOUR API KEY HERE" स्ट्रिंग को अपनी बनाई गई API (एपीआई) कुंजी से बदलें.

मैप पर डिवाइस की जगह की जानकारी दिखाना

एपीआई पासकोड जोड़ने के बाद, मैप पर एक हेल्पर जोड़ें. इससे उपयोगकर्ताओं को यह समझने में मदद मिलेगी कि वे मैप में कहां हैं. इसके लिए, setUpMaps तरीके पर जाएं. इसके बाद, setUpMaps कॉल में, googleMap.isMyLocationEnabled को true. पर सेट करें. ऐसा करने से, मैप पर नीले रंग का बिंदु दिखेगा.mapFragment.getMapAsync

private fun setUpMaps() {
   mapFragment.getMapAsync { googleMap ->
       googleMap.isMyLocationEnabled = true
       // ...
   }
}

मौजूदा जगह की जानकारी पाना

डिवाइस की जगह की जानकारी पाने के लिए, आपको FusedLocationProviderClient क्लास का इस्तेमाल करना होगा. इसका इंस्टेंस पाने का काम, MainActivity के onCreate तरीके में पहले ही किया जा चुका है. इस ऑब्जेक्ट का इस्तेमाल करने के लिए, getCurrentLocation तरीके को भरें. यह एक लैम्ब्डा आर्ग्युमेंट स्वीकार करता है, ताकि इस तरीके को कॉल करने वाले व्यक्ति को जगह की जानकारी दी जा सके.

इस तरीके को पूरा करने के लिए, FusedLocationProviderClient ऑब्जेक्ट की lastLocation प्रॉपर्टी को ऐक्सेस किया जा सकता है. इसके बाद, addOnSuccessListener को इस तरह जोड़ा जा सकता है:

fusedLocationClient.lastLocation.addOnSuccessListener { location ->
    currentLocation = location
    onSuccess(location)
}.addOnFailureListener {
    Log.e(TAG, "Could not get location")
}

getCurrentLocation तरीके को setUpMaps तरीके में दिए गए getMapAsync में मौजूद लैम्ब्डा से कॉल किया जाता है. इसी तरीके से आस-पास की जगहों की जानकारी फ़ेच की जाती है.

जगहों के नेटवर्क पर कॉल शुरू करना

getNearbyPlaces तरीके के कॉल में, ध्यान दें कि placesServices.nearbyPlaces तरीके में ये पैरामीटर पास किए जाते हैं—एपीआई पासकोड, डिवाइस की जगह की जानकारी, मीटर में रेडियस (जो 2 कि॰मी॰ पर सेट है), और जगह का टाइप (फ़िलहाल, park पर सेट है).

val apiKey = "YOUR API KEY"
placesService.nearbyPlaces(
   apiKey = apiKey,
   location = "${location.latitude},${location.longitude}",
   radiusInMeters = 2000,
   placeType = "park"
)

नेटवर्क कॉल पूरा करने के लिए, उस एपीआई कुंजी को पास करें जिसे आपने gradle.properties फ़ाइल में तय किया है. कोड का यह स्निपेट, आपकी build.gradle फ़ाइल में android > defaultConfig कॉन्फ़िगरेशन में तय किया गया है:

android {
   defaultConfig {
       resValue "string", "google_maps_key", (project.findProperty("GOOGLE_MAPS_API_KEY") ?: "")
   }
}

इससे स्ट्रिंग रिसॉर्स की वैल्यू google_maps_key, बिल्ड टाइम पर उपलब्ध हो जाएगी.

नेटवर्क कॉल पूरा करने के लिए, getString ऑब्जेक्ट पर Context के ज़रिए इस स्ट्रिंग रिसॉर्स को पढ़ा जा सकता है.

val apiKey = this.getString(R.string.google_maps_key)

7. एआर में जगहें

अब तक आपने ये काम किए हैं:

  1. ऐप्लिकेशन को पहली बार चलाने पर, उपयोगकर्ता से कैमरा और जगह की जानकारी ऐक्सेस करने की अनुमतियों का अनुरोध किया गया हो
  2. हॉरिजॉन्टल प्लेन को ट्रैक करना शुरू करने के लिए, ARCore सेट अप करना
  3. अपने एपीआई पासकोड की मदद से Maps SDK टूल सेट अप करना
  4. डिवाइस की मौजूदा जगह की जानकारी मिली
  5. Places API का इस्तेमाल करके, आस-पास की जगहों (खास तौर पर पार्क) की जानकारी फ़ेच की गई

इस गतिविधि को पूरा करने के लिए, आपको उन जगहों को ऑगमेंटेड रिएलिटी में दिखाना होगा जिनकी जानकारी फ़ेच की जा रही है.

सीन को समझना

ARCore, डिवाइस के कैमरे से असली दुनिया के सीन को समझ पाता है. इसके लिए, वह हर इमेज फ़्रेम में दिलचस्प और अलग-अलग पॉइंट का पता लगाता है. इन पॉइंट को फ़ीचर पॉइंट कहा जाता है. जब ये फ़ीचर पॉइंट क्लस्टर किए जाते हैं और एक ही हॉरिज़ॉन्टल प्लेन पर मौजूद होते हैं, जैसे कि टेबल और फ़्लोर, तो ARCore इस सुविधा को ऐप्लिकेशन के लिए हॉरिज़ॉन्टल प्लेन के तौर पर उपलब्ध करा सकता है.

जैसा कि आपने पहले देखा, जब किसी प्लैन का पता चल जाता है, तो ARCore उपयोगकर्ता को सफ़ेद बिंदु दिखाकर गाइड करता है.

2a9b6ea7dcb2e249.png

ऐंकर जोड़ना

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

setUpAr में, OnTapArPlaneListener को PlacesArFragment से अटैच किया गया है. एआर सीन में किसी प्लैन पर टैप करने पर, यह लिसनर शुरू हो जाता है. इस कॉल में, आपको श्रोता के तौर पर दिए गए HitResult से Anchor और AnchorNode बनाने हैं. इसके लिए, यह तरीका अपनाएं:

arFragment.setOnTapArPlaneListener { hitResult, _, _ ->
   val anchor = hitResult.createAnchor()
   anchorNode = AnchorNode(anchor)
   anchorNode?.setParent(arFragment.arSceneView.scene)
   addPlaces(anchorNode!!)
}

AnchorNode में, सीन में मौजूद चाइल्ड नोड ऑब्जेक्ट—PlaceNode इंस्टेंस अटैच किए जाएंगे. इन्हें addPlaces तरीके से हैंडल किया जाता है.

इसे चलाएं

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

f93eb87c98a0098d.png

आखिरी चरण में, डिवाइस पर Maps SDK for Android Utility Library और SensorManager का इस्तेमाल करके, इस समस्या को ठीक करें.

8. जगहों को पोज़िशन करना

ऑगमेंटेड रिएलिटी में वर्चुअल जगह के आइकॉन को सटीक हेडिंग में रखने के लिए, आपको दो तरह की जानकारी की ज़रूरत होगी:

  • जहां उत्तर दिशा है
  • उत्तर और हर जगह के बीच का ऐंगल

उत्तर दिशा का पता लगाना

डिवाइस पर मौजूद पोज़िशन सेंसर (जियोमैग्नेटिक और एक्सलरोमीटर) का इस्तेमाल करके, उत्तर दिशा का पता लगाया जा सकता है. इन दोनों सेंसर का इस्तेमाल करके, डिवाइस की जगह की जानकारी रीयल-टाइम में इकट्ठा की जा सकती है. पोजीशन सेंसर के बारे में ज़्यादा जानने के लिए, डिवाइस का ओरिएंटेशन कैलकुलेट करना लेख पढ़ें.

इन सेंसर को ऐक्सेस करने के लिए, आपको SensorManager हासिल करना होगा. इसके बाद, उन सेंसर पर SensorEventListener रजिस्टर करना होगा. MainActivity के लाइफ़साइकल के तरीकों में, ये चरण पहले से ही पूरे किए जा चुके हैं:

override fun onCreate(savedInstanceState: Bundle?) {
   super.onCreate(savedInstanceState)
   // ...
   sensorManager = getSystemService()!!
   // ...
}

override fun onResume() {
   super.onResume()
   sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD)?.also {
       sensorManager.registerListener(
           this,
           it,
           SensorManager.SENSOR_DELAY_NORMAL
       )
   }
   sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER)?.also {
       sensorManager.registerListener(
           this,
           it,
           SensorManager.SENSOR_DELAY_NORMAL
       )
   }
}

override fun onPause() {
   super.onPause()
   sensorManager.unregisterListener(this)
}

onSensorChanged तरीके में, एक SensorEvent ऑब्जेक्ट दिया जाता है. इसमें किसी सेंसर के डेटा के बारे में जानकारी होती है, जो समय के साथ बदलती रहती है. आगे बढ़ें और उस तरीके में यह कोड जोड़ें:

override fun onSensorChanged(event: SensorEvent?) {
   if (event == null) {
       return
   }
   if (event.sensor.type == Sensor.TYPE_ACCELEROMETER) {
       System.arraycopy(event.values, 0, accelerometerReading, 0, accelerometerReading.size)
   } else if (event.sensor.type == Sensor.TYPE_MAGNETIC_FIELD) {
       System.arraycopy(event.values, 0, magnetometerReading, 0, magnetometerReading.size)
   }

   // Update rotation matrix, which is needed to update orientation angles.
   SensorManager.getRotationMatrix(
       rotationMatrix,
       null,
       accelerometerReading,
       magnetometerReading
   )
   SensorManager.getOrientation(rotationMatrix, orientationAngles)
}

ऊपर दिया गया कोड, सेंसर टाइप की जांच करता है. इसके बाद, टाइप के आधार पर, सेंसर की सही रीडिंग (एक्सलरोमीटर या मैग्नेटोमीटर की रीडिंग) को अपडेट करता है. सेंसर की इन रीडिंग का इस्तेमाल करके, अब यह पता लगाया जा सकता है कि डिवाइस के हिसाब से उत्तर दिशा कितने डिग्री पर है. यानी, orientationAngles[0] की वैल्यू का पता लगाया जा सकता है.

स्फ़ेरिकल हेडिंग

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

हेडिंग का हिसाब लगाने के लिए, Maps SDK for Android की यूटिलिटी लाइब्रेरी का इस्तेमाल करें. इसमें स्फ़ेरिकल ज्योमेट्री की मदद से, दूरी और हेडिंग का हिसाब लगाने के लिए कुछ हेल्पर फ़ंक्शन शामिल होते हैं. ज़्यादा जानकारी के लिए, लाइब्रेरी की यह खास जानकारी पढ़ें.

इसके बाद, यूटिलिटी लाइब्रेरी में मौजूद sphericalHeading तरीके का इस्तेमाल किया जाएगा. यह दो LatLng ऑब्जेक्ट के बीच हेडिंग/बियरिंग का हिसाब लगाता है. यह जानकारी, Place.kt में तय किए गए getPositionVector तरीके के लिए ज़रूरी है. यह तरीका आखिर में एक Vector3 ऑब्जेक्ट दिखाता है. इसका इस्तेमाल हर PlaceNode, एआर स्पेस में अपनी जगह की जानकारी के तौर पर करेगा.

उस तरीके में हेडिंग की परिभाषा को इससे बदलें:

val heading = latLng.sphericalHeading(placeLatLng)

ऐसा करने पर, आपको इस तरह की परिभाषा मिलेगी:

fun Place.getPositionVector(azimuth: Float, latLng: LatLng): Vector3 {
   val placeLatLng = this.geometry.location.latLng
   val heading = latLng.sphericalHeading(placeLatLng)
   val r = -2f
   val x = r * sin(azimuth + heading).toFloat()
   val y = 1f
   val z = r * cos(azimuth + heading).toFloat()
   return Vector3(x, y, z)
}

लोकल पोज़िशन

एआर में जगहों को सही तरीके से ओरिएंट करने का आखिरी चरण यह है कि सीन में PlaceNode ऑब्जेक्ट जोड़ते समय, getPositionVector के नतीजे का इस्तेमाल किया जाए. आगे बढ़ें और MainActivity में addPlaces पर जाएं. यह उस लाइन के ठीक नीचे होता है जहां हर placeNode पर पैरंट सेट किया जाता है (placeNode.setParent(anchorNode) के ठीक नीचे). placeNode के localPosition को getPositionVector को कॉल करने के नतीजे पर सेट करें. जैसे:

val placeNode = PlaceNode(this, place)
placeNode.setParent(anchorNode)
placeNode.localPosition = place.getPositionVector(orientationAngles[0], currentLocation.latLng)

डिफ़ॉल्ट रूप से, getPositionVector तरीके से नोड की y दूरी को 1 मीटर पर सेट किया जाता है. यह getPositionVector तरीके में बताई गई y वैल्यू के मुताबिक होता है. अगर आपको इस दूरी को 2 मीटर पर सेट करना है, तो ज़रूरत के मुताबिक वैल्यू में बदलाव करें.

इस बदलाव के बाद, जोड़े गए PlaceNode ऑब्जेक्ट अब सही हेडिंग में दिखने चाहिए. अब ऐप्लिकेशन को चलाकर देखें कि क्या नतीजे मिलते हैं!

9. बधाई हो

यहां तक पहुंचने के लिए बधाई!

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