با Google Maps Platform Navigation SDK یک برنامه ناوبری ساده اندروید بسازید

۱. قبل از شروع

این آزمایشگاه کد به شما آموزش می‌دهد که یک برنامه اندروید ساده بسازید که از SDK ناوبری پلتفرم نقشه‌های گوگل برای پیمایش به یک مقصد از پیش تنظیم‌شده استفاده می‌کند.

این ظاهر برنامه شما پس از اتمام کار خواهد بود.

b6c535afde7abd20.png

پیش‌نیازها

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

آنچه یاد خواهید گرفت

  • چگونه یک برنامه اندروید ساده بسازیم که از Navigation SDK برای پیمایش به یک مقصد استفاده کند.
  • نحوه ادغام SDK ناوبری از مخزن راه دور Google Maven
  • نحوه مدیریت مجوزهای مکان و توافق‌نامه کاربر با شرایط کاربر نهایی Navigation SDK
  • نحوه مقداردهی اولیه SDK
  • نحوه تعیین مقصد و شروع راهنمای ناوبری.

آنچه نیاز دارید

  • آخرین نسخه پایدار اندروید استودیو نصب شده است. این آزمایشگاه کد با استفاده از اندروید استودیو Jellyfish ایجاد شده است. اگر از نسخه دیگری استفاده می‌کنید، ظاهر و طرح‌بندی رابط کاربری و اجزا ممکن است متفاوت باشد.
  • یک حساب گوگل و پروژه با قابلیت پرداخت فعال.
  • یک دستگاه اندروید در حالت توسعه‌دهنده با فعال بودن اشکال‌زدایی USB یا یک شبیه‌ساز اندروید. هر کدام را که انتخاب کنید، باید حداقل شرایط لازم برای Navigation SDK را داشته باشد.

۲. آماده شوید

اگر از قبل حساب کاربری پلتفرم گوگل کلود و پروژه‌ای با قابلیت پرداخت فعال ندارید، پروژه گوگل کلود خود را طبق دستورالعمل‌های شروع به کار با پلتفرم گوگل مپس https://developers.google.com/maps/gmp-get-started راه‌اندازی کنید.

پروژه Google Cloud خود را در کنسول انتخاب کنید

در کنسول ابری ، روی منوی کشویی پروژه کلیک کنید و پروژه‌ای را که می‌خواهید برای این آزمایشگاه کد استفاده کنید، انتخاب کنید.

منوی کشویی انتخابگر پروژه در کنسول گوگل کلود.

فعال کردن SDK ناوبری در پروژه شما

APIها و SDKهای پلتفرم نقشه‌های گوگل مورد نیاز برای این آزمایشگاه کد را در بازار ابری گوگل فعال کنید.

به APIها و خدمات > کتابخانه در کنسول ابری گوگل بروید و عبارت «Navigation SDK» را جستجو کنید.

شما باید یک نتیجه جستجو را ببینید.

صفحه کتابخانه API در کنسول Google Cloud، که صفحه Navigation SDK را نشان می‌دهد.

برای باز کردن صفحه جزئیات محصول، روی نتیجه‌ی «Navigation SDK» کلیک کنید. برای فعال کردن SDK در پروژه‌تان، روی دکمه‌ی «Enable» کلیک کنید.

این فرآیند را برای Google Maps SDK برای اندروید تکرار کنید.

ایجاد کلید API

یک کلید API در صفحه اعتبارنامه‌های Cloud Console ایجاد کنید. می‌توانید مراحل مرحله ۳ بخش شروع سریع در شروع به کار با پلتفرم Google Maps را دنبال کنید. همه درخواست‌ها به پلتفرم Google Maps نیاز به یک کلید API دارند.

۳. فایل‌های نمونه پروژه را دریافت کنید

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

برای دریافت کد این codelab، این مخزن گیت‌هاب را کلون کنید.

git clone https://github.com/googlemaps-samples/codelab-navigation-101-android-kotlin.git

اگر گیت را نصب ندارید، برای دریافت کد روی این دکمه کلیک کنید:

برای شروع هر چه سریع‌تر، این مخزن شامل تعدادی کد اولیه در پوشه Starter است تا به شما در دنبال کردن این آزمایشگاه کد کمک کند. پروژه اولیه یک رابط کاربری اولیه برنامه و پیکربندی ساخت را ارائه می‌دهد، اما Navigation SDK به آن اضافه نشده است. همچنین یک پروژه Solution تکمیل شده وجود دارد که در صورت تمایل می‌توانید به ادامه مطلب بروید یا پیشرفت خود را در هر زمانی بررسی کنید.

مخزن کلون شده را در اندروید استودیو باز کنید.

پس از اینکه مخزن را به صورت محلی کلون کردید، از اندروید استودیو برای باز کردن پوشه Starter به عنوان یک پروژه موجود استفاده کنید.

  1. از پنجره‌ی «به اندروید استودیو خوش آمدید»، روی دکمه‌ی «باز کردن» کلیک کنید.
  2. به پوشه‌ای که مخزن کلون‌شده را در آن ذخیره کرده‌اید بروید و پوشه Starter را که در بالاترین سطح پوشه " codelab-navigation-101-android-kotlin " قرار دارد، انتخاب کنید.
  3. بررسی کنید که پروژه ساخته و اجرا می‌شود.

یک دستگاه مجازی اضافه کنید یا یک دستگاه سخت‌افزاری متصل کنید

برای اتصال یک دستگاه اندروید به رایانه، دستورالعمل‌های اندروید استودیو در مورد نحوه اجرای برنامه‌ها روی یک دستگاه سخت‌افزاری را دنبال کنید. همچنین می‌توانید با استفاده از Android Virtual Device Manager (AVD) یک دستگاه مجازی را پیکربندی کنید. هنگام انتخاب یک شبیه‌ساز، مطمئن شوید که تصویری را انتخاب می‌کنید که شامل APIهای گوگل باشد.

در اندروید استودیو، روی گزینه‌ی منوی Run یا آیکون دکمه‌ی پخش کلیک کنید. در صورت درخواست، دستگاهی را انتخاب کنید.

۴. کیت توسعه نرم‌افزار ناوبری (Navigation SDK) را به برنامه خود اضافه کنید

کتابخانه‌ی Navigation SDK و کلید API خود را به پروژه‌تان اضافه کنید.

برای افزودن کتابخانه‌ی Navigation SDK به برنامه‌تان، باید build.gradle.kts در سطح برنامه را طوری تغییر دهید که Navigation SDK را از مخزن Google Maven دریافت کند و یک شماره نسخه پیکربندی کند.

یک متغیر در پیکربندی ساخت خود ایجاد کنید تا شماره نسخه Navigation SDK را ذخیره کند.

یک متغیر در build.gradle.kts سطح برنامه خود تنظیم کنید تا مقدار نسخه Navigation SDK مورد استفاده در برنامه شما را در خود جای دهد، تا در آینده به راحتی بتوانید آن را به آخرین نسخه تغییر دهید.

برای اطلاع از آخرین شماره نسخه ، یادداشت‌های انتشار Navigation SDK را بررسی کنید.

val navSdkVersion by extra("6.0.0")

همچنین می‌توانید مقادیر این متغیر و سایر متغیرها را با استفاده از کادر محاوره‌ای موجود در File > Project Structure > Variables تغییر دهید:

۶۶۸۳۳۲۷۳۶b۶۷dc۸۲.png

اضافه کردن یک وابستگی به پیکربندی ساخت

حالا وابستگی API زیر را به بلوک وابستگی‌ها در build.gradle.kts. نسخه مورد استفاده، مقدار ${navSdkVersion} خواهد بود که شما در build.gradle.kts سطح app خود تنظیم کرده‌اید:

dependencies {

   // Include the Google Navigation SDK.
   api("com.google.android.libraries.navigation:navigation:${navSdkVersion}")

...

کلید API خود را اضافه کنید

برای مدیریت کلید API از افزونه Secrets Gradle استفاده کنید

توصیه می‌کنیم از افزونه Secrets Gradle برای مدیریت ایمن کلید API در برنامه خود استفاده کنید. این افزونه به عنوان یک وابستگی در فایل build.gradle.kts سطح بالای شما به قالب اولیه پروژه اضافه شده است.

// Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins {
    id("com.google.android.libraries.mapsplatform.secrets-gradle-plugin") version "2.0.1" apply false
    //... other plugin definitions here
}

فایل secrets.properties را در دایرکتوری سطح بالای خود باز کنید و سپس YOUR_API_KEY را با کلید API خود جایگزین کنید. کلید خود را در این فایل ذخیره کنید زیرا secrets.properties از بررسی در سیستم کنترل نسخه مستثنی است.

MAPS_API_KEY=YOUR_API_KEY

برای اطلاعات بیشتر در مورد این موضوع، به بخش افزودن کلید API به برنامه خود در مستندات Navigation SDK مراجعه کنید.

محتوای local.defaults.properties را تأیید کنید

پروژه خالی همچنین شامل یک فایل local.defaults.properties در دایرکتوری سطح بالای شما، همان پوشه‌ای که فایل secrets.properties در آن قرار دارد، می‌باشد. آن را باز کنید و کد زیر را مشاهده کنید.

MAPS_API_KEY=DEFAULT_API_KEY

این فایل برای فراهم کردن یک مقدار پشتیبان برای ویژگی MAPS_API_KEY در صورتی که secrets.properties به پروژه اضافه نشده باشد، وجود دارد تا ساخت‌ها با شکست مواجه نشوند. نیازی به ویرایش این فایل نیست. اگر تعریف secrets.properties از MAPS_API_KEY پیدا نشود، مقدار پیش‌فرض، اجرای برنامه را در زمان اجرا متوقف می‌کند و خطای کلید API را نمایش می‌دهد.

بررسی کنید که آیا Manifest اندروید از کلید API که شما مشخص کرده‌اید استفاده می‌کند یا خیر.

فایل app/src/main/AndroidManifest.xml را باز کنید. متوجه خواهید شد که از ویژگی MAPS_API_KEY برای تنظیم کلید API برای برنامه استفاده شده است:

<meta-data
    android:name="com.google.android.geo.API_KEY"
    android:value="${MAPS_API_KEY}" />

فایل build.gradle.kts در سطح برنامه خود را باز کنید و ویژگی secrets را پیدا کنید.

تنظیم propertiesFileName افزونه باید روی secrets.properties تنظیم شود، و defaultPropertiesFileName باید local.defaults.properties بخواند.

secrets {
    // Optionally specify a different file name containing your secrets.
    // The plugin defaults to "local.properties"
    propertiesFileName = "secrets.properties"

    // A properties file containing default secret values. This file can be
    // checked in version control.
    defaultPropertiesFileName = "local.defaults.properties"
}

تمام فایل‌ها را ذخیره کنید و پروژه خود را با Gradle همگام‌سازی کنید.

۵. مجوزهای برنامه را پیکربندی کنید و یک رابط کاربری اولیه اضافه کنید

درخواست مجوز مکان دقیق

کیت توسعه نرم‌افزار ناوبری (Navigation SDK) برای کار به سیگنال‌های GPS وابسته است، بنابراین برنامه شما باید از کاربر بخواهد که به داده‌های موقعیت مکانی دقیق دسترسی داشته باشد. مجوز دسترسی به موقعیت مکانی دقیق را به عنوان فرزند عنصر <manifest> در AndroidManifest.xml اضافه کنید.

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools" >
   <uses-permission 
      android:name="android.permission.ACCESS_FINE_LOCATION"
   />
</manifest>

می‌توانید اطلاعات بیشتر در مورد مجوزهای موقعیت مکانی اندروید را در بخش «درخواست مجوزهای موقعیت مکانی» در مستندات توسعه‌دهندگان اندروید مطالعه کنید.

برای اجرای برنامه خود روی دستگاه اندروید ۱۴، با اضافه کردن تگ uses-permission زیر در همان مکانی که مجوز دسترسی دقیق به موقعیت مکانی قرار دارد، مجوز Foreground Service Location را درخواست کنید:

<uses-permission android:name="android.permission.FOREGROUND_SERVICE_LOCATION" />

یک فعالیت راه‌اندازی با یک رابط کاربری پایه اضافه کنید

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

فایل MainActivity.kt را در ویرایشگر کد باز کنید و کد را بررسی کنید، که یک رابط کاربری اولیه را نشان می‌دهد.

درخواست مجوزهای دسترسی به موقعیت مکانی در زمان اجرا

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

برای اطمینان از اینکه این بررسی هنگام شروع برنامه شما انجام می‌شود، کدی را به کلاس MainActivity خود، در متد override شده onCreate() از Activity خود اضافه کنید.

کد زیر بررسی می‌کند که آیا کاربر مجوز دسترسی به موقعیت مکانی مناسب را اعطا کرده است یا خیر. در غیر این صورت، درخواست مجوز می‌دهد. این کد را به متد onCreate() خود اضافه کنید.

    val permissions =
      if (VERSION.SDK_INT >= VERSION_CODES.TIRAMISU) {
        arrayOf(permission.ACCESS_FINE_LOCATION, permission.POST_NOTIFICATIONS)
      } else {
        arrayOf(permission.ACCESS_FINE_LOCATION)
      }

    if (permissions.any { !checkPermissionGranted(it) }) {

      if (permissions.any { shouldShowRequestPermissionRationale(it) }) {
        // Display a dialogue explaining the required permissions.
      }

      val permissionsLauncher =
        registerForActivityResult(
          RequestMultiplePermissions(),
          { permissionResults ->
            if (permissionResults.getOrDefault(permission.ACCESS_FINE_LOCATION, false)) {
              onLocationPermissionGranted()
            } else {
              finish()
            }
          },
        )

      permissionsLauncher.launch(permissions)
    } else {
      android.os.Handler(Looper.getMainLooper()).postDelayed({ onLocationPermissionGranted() }, SPLASH_SCREEN_DELAY_MILLIS)
    }
  }

  private fun checkPermissionGranted(permissionToCheck: String): Boolean =
    ContextCompat.checkSelfPermission(this, permissionToCheck) == PackageManager.PERMISSION_GRANTED

یک تابع جدید به کلاس MainActivity خود با نام onLocationPermissionGranted اضافه کنید که خروجی را زمانی که کاربر اجازه اشتراک‌گذاری موقعیت مکانی خود را می‌دهد، مدیریت می‌کند. در مراحل بعدی، کدی را برای راه‌اندازی یک فعالیت ناوبری جدید به اینجا اضافه خواهیم کرد.

private fun onLocationPermissionGranted() {
   //code to initialize Navigation SDK will go here
}

پروژه خود را بسازید. اگر خطایی در ساخت دارید، آنها را پیدا کرده و برطرف کنید.

پروژه خود را روی یک دستگاه مجازی جدید اجرا کنید. هنگام نصب و شروع برنامه، باید پنجره درخواست مجوز ظاهر شود.

۶. یک رابط کاربری ناوبری اضافه کنید

دو راه برای اضافه کردن یک رابط کاربری ناوبری وجود دارد: SupportNavigationFragment یا NavigationView .

برای سادگی، codelab از NavigationView استفاده می‌کند.

طرح‌بندی را ویرایش کنید

برای افزودن طرح‌بندی برای NavigationView، res/layout/activity_main.xml را ویرایش کنید.

  1. فایل را باز کنید و به نمای کد بروید.
  2. کل محتوای فایل را با یک طرح‌بندی جدید از یک NavigationView درون یک RelativeLayout مانند مثال زیر جایگزین کنید. از آنجایی که شما فقط یک نمای ناوبری به برنامه اضافه خواهید کرد، یک طرح‌بندی ساده کافی است.
  3. به NavigationView خود، شناسه‌ی " @+id/navigation_view " بدهید.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
   android:layout_width="match_parent"
   android:layout_height="match_parent">
 <com.google.android.libraries.navigation.NavigationView
     android:id="@+id/navigation_view"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
      />
</RelativeLayout>

تنظیم فعالیت ناوبری

در اندروید استودیو، فایل MainActivity.kt را در ویرایشگر باز کنید.

برای اطمینان از عملکرد صحیح ناوبری در برنامه خود، چند کد تنظیمات اولیه اضافه کنید. در فایل MainActivity.kt، تغییرات زیر را اعمال کنید:

  1. یک متغیر در کلاس MainActivity خود تعریف کنید تا به NavigationView شما ارجاع دهد:
private lateinit var navView: NavigationView
  1. برای دریافت ارجاع به NavigationView کدی را به متد onCreate() اضافه کنید:
navView = findViewById(R.id.navigation_view)
navView.onCreate(savedInstanceState)
  1. برای اطمینان از روشن ماندن صفحه نمایش در طول هدایت ناوبری، کدی را به متد onCreate() اضافه کنید:
// Ensure the screen stays on during nav.
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
  1. کدی که ViewCompat.setOnApplyWindowInsetsListener را فراخوانی می‌کند، ویرایش کنید تا به شناسه‌ی NavigationView شما ارجاع دهد.
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.navigation_view)) { v, insets ->
  val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
  v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
  insets
}
  1. یک متد showToast() به کلاس اضافه کنید تا بازخورد را به کاربر نشان دهد:
private fun showToast(errorMessage: String) {
   Toast.makeText(this@MainActivity, errorMessage, Toast.LENGTH_LONG).show()
}

۷. مقداردهی اولیه‌ی SDK ناوبری

حالا که تنظیمات اولیه‌ی فعالیت ناوبری (Navigation activity) را انجام داده‌اید، می‌توانید SDK ناوبری (Navigation SDK) را مقداردهی اولیه کنید. برای انجام این کار، کد زیر را به فایل MainActivity.kt خود اضافه کنید:

/** Starts the Navigation API, capturing a reference when ready. */
@SuppressLint("MissingPermission")
private fun initializeNavigationApi() {
   NavigationApi.getNavigator(
       this,
       object : NavigatorListener {
           override fun onNavigatorReady(navigator: Navigator) {
               // store a reference to the Navigator object
               mNavigator = navigator
               // code to start guidance will go here
           }

           override fun onError(@NavigationApi.ErrorCode errorCode: Int) {
               when (errorCode) {
                   NavigationApi.ErrorCode.NOT_AUTHORIZED -> {
                       // Note: If this message is displayed, you may need to check that
                       // your API_KEY is specified correctly in AndroidManifest.xml
                       // and is been enabled to access the Navigation API
                       showToast(
                           "Error loading Navigation API: Your API key is " +
                                   "invalid or not authorized to use Navigation."
                       )
                   }
                   NavigationApi.ErrorCode.TERMS_NOT_ACCEPTED -> {
                       showToast(
                           "Error loading Navigation API: User did not " +
                                   "accept the Navigation Terms of Use."
                       )
                   }
                   else -> showToast("Error loading Navigation API: $errorCode")
               }
           }
       },
   )

}

این کد یک متد جدید به نام initializeNavigationApi() ایجاد می‌کند. این متد با فراخوانی NavigationApi.getNavigator() به یک شیء Navigator ارجاع می‌دهد و یک NavigatorListener برای مدیریت فراخوانی پیاده‌سازی می‌کند.

توجه داشته باشید که وقتی Navigation API مقداردهی اولیه می‌شود، متد NavigationListener.onNavigatorReady فراخوانی می‌شود و یک شیء Navigator به عنوان پارامتر به آن ارسال می‌شود. کد بالا متغیر mNavigator که قبلاً تعریف کرده‌اید را با شیء Navigator مقداردهی اولیه شده‌ای که به این متد ارسال شده است، به‌روزرسانی می‌کند.

در نهایت، از متد onLocationPermissionGranted یک فراخوانی به متد initializeNavigationApi خود اضافه کنید.

private fun onLocationPermissionGranted() {
   initializeNavigationApi()
}

۸. برای رویدادهای ناوبری کلیدی، شنونده اضافه کنید

وقتی کاربران شما از راهنمایی‌ها پیروی می‌کنند، SDK ناوبری رویدادهایی را فعال می‌کند که می‌توانند برنامه را در مورد تغییرات کلیدی وضعیت در طول مسیر، مانند زمانی که کاربر تغییر مسیر می‌دهد یا به مقصد خود می‌رسد، مطلع کنند. در فایل MainActivity.kt، شنونده‌هایی را برای مدیریت این رویدادها اضافه کنید:

  1. درون کلاس MainActivity ، دو متغیر برای ارجاع به اشیاء شنونده رویداد تعریف کنید:
private var arrivalListener: Navigator.ArrivalListener? = null
private var routeChangedListener: Navigator.RouteChangedListener? = null
  1. یک متد registerNavigationListeners() اضافه کنید تا هنگام مقداردهی اولیه Navigator، شنونده‌ها را تنظیم کند. این متد Navigator.clearDestinations() را برای تنظیم مجدد NavigationView هنگام اجرای رویداد Arrival فراخوانی می‌کند:
/**
* Registers a number of example event listeners that show an on screen message when certain
* navigation events occur (e.g. the driver's route changes or the destination is reached).
*/
private fun registerNavigationListeners() {
   withNavigatorAsync {
       arrivalListener =
           Navigator.ArrivalListener { // Show an onscreen message
               showToast("User has arrived at the destination!")
               mNavigator?.clearDestinations()
           }
       mNavigator?.addArrivalListener(arrivalListener)

       routeChangedListener =
           Navigator.RouteChangedListener { // Show an onscreen message when the route changes
               showToast("onRouteChanged: the driver's route changed")
           }
       mNavigator?.addRouteChangedListener(routeChangedListener)
   }
}
  1. یک فراخوانی به registerNavigationListeners() از کد فراخوانی onNavigatorReady در متد initializeNavigationApi اضافه کنید:
override fun onNavigatorReady(navigator: Navigator) {
   // store a reference to the Navigator object
   mNavigator = navigator

   //listen for events en route
   registerNavigationListeners()


}
  1. رابط کاربری را پیکربندی کنید. می‌توانید جنبه‌های مختلف رابط کاربری ناوبری را هنگام اجرای راهنمایی کنترل کنید. یکی از سفارشی‌سازی‌های مهم، موقعیت دوربین است. یک فراخوانی به متد setTaskRemovedBehaviour از شیء navigator اضافه کنید که در onNavigatorReady برمی‌گردد و به صورت زیر است. این کار باعث می‌شود که راهنمایی و اعلان در صورت حذف برنامه، خاتمه یابد:
// Disables the guidance notifications and shuts down the app and background service
// when the user dismisses/swipes away the app from Android's recent tasks.
navigator.setTaskRemovedBehavior(Navigator.TaskRemovedBehavior.QUIT_SERVICE)
  1. برای تعیین CameraPerspective یک فراخوانی به GoogleMap.followMyLocation اضافه کنید. دسترسی به GoogleMap از طریق متد NavigatorView.getMapAsync() به شرح زیر است:
navView.getMapAsync {
   googleMap  ->
   googleMap.followMyLocation(GoogleMap.CameraPerspective.TILTED)
}
  1. برای اطمینان از اینکه ناوبری در طول چرخه حیات برنامه به راحتی کار می‌کند، متدهای زیر را در کلاس MainActivity خود پیاده‌سازی کنید:
override fun onSaveInstanceState(savedInstanceState: Bundle) {
   super.onSaveInstanceState(savedInstanceState)

   navView.onSaveInstanceState(savedInstanceState)
}

override fun onTrimMemory(level: Int) {
   super.onTrimMemory(level)
   navView.onTrimMemory(level)
}

override fun onStart() {
   super.onStart()
   navView.onStart()
}

override fun onResume() {
   super.onResume()
   navView.onResume()
}

override fun onPause() {
   navView.onPause()
   super.onPause()
}

override fun onConfigurationChanged(configuration: Configuration) {
   super.onConfigurationChanged(configuration)
   navView.onConfigurationChanged(configuration)
}

override fun onStop() {
   navView.onStop()
   super.onStop()
}

override fun onDestroy() {
   navView.onDestroy()
   withNavigatorAsync {
       // Unregister event listeners to avoid memory leaks.
       if (arrivalListener != null) {
           navigator.removeArrivalListener(arrivalListener)
       }
       if (routeChangedListener != null) {
           navigator.removeRouteChangedListener(routeChangedListener)
       }

       navigator.simulator?.unsetUserLocation()
       navigator.cleanup()
   }
   super.onDestroy()
}

۹. یک مقصد تعیین کنید

اکنون آماده‌اید تا مقصد را تعیین کنید و راهنمای ناوبری را شروع کنید. در فایل MainActivity.kt، تغییرات زیر را اعمال کنید:

  1. یک متد جدید navigateToPlace() اضافه کنید که مقصد ناوبری را تنظیم می‌کند و یک پارامتر placeId می‌پذیرد.
/**
* Requests directions from the user's current location to a specific place (provided by the
* Place ID).
*/
private fun navigateToPlace(placeId: String) {

}
  1. در متد navigateToPlace() خود، از متد Waypoint.builder() برای ایجاد یک Waypoint از Place ID ارسال شده به متد استفاده کنید. خطای UnsupportedPlaceIdException که ممکن است رخ دهد را مدیریت کنید، برای مواقعی که Place ID به یک آدرس دقیق تبدیل نمی‌شود:
val waypoint: Waypoint? =
// Set a destination by using a Place ID (the recommended method)
try {
   Waypoint.builder().setPlaceIdString(placeId).build()
} catch (e: Waypoint.UnsupportedPlaceIdException) {
   showToast("Place ID was unsupported.")
   return
}
  1. کد زیر را به متد navigateToPlace() خود اضافه کنید تا با استفاده از Waypoint یک مقصد تعیین کنید:
val pendingRoute = mNavigator?.setDestination(waypoint)

// Set an action to perform when a route is determined to the destination
pendingRoute?.setOnResultListener { code ->
   when (code) {
       RouteStatus.OK -> {
           // Code to start guidance will go here
       }

       RouteStatus.ROUTE_CANCELED -> showToast("Route guidance canceled.")
       RouteStatus.NO_ROUTE_FOUND,
       RouteStatus.NETWORK_ERROR ->
           // TODO: Add logic to handle when a route could not be determined
           showToast("Error starting guidance: $code")

       else -> showToast("Error starting guidance: $code")
   }
}

شیء Navigator دارای یک متد setDestinations() است که می‌تواند پارامترهای متنوعی را بپذیرد. ابتدایی‌ترین گزینه، ارائه یک Waypoint است. این متد به طور پیش‌فرض حالت سفر DRIVING را انتخاب می‌کند که برای خودروهای چهارچرخ مناسب است. متد setDestinations() یک شیء ListenableResultFuture را برمی‌گرداند که حاوی یک شیء RouteStatus است. RouteStatus نشان می‌دهد که آیا مسیری به مقصد پیدا شده است یا خیر و در صورت پیدا نشدن، به شما امکان می‌دهد حالت‌های مختلف خطا را مدیریت کنید.

  1. برای بهبود تجربه کاربری ناوبری، تغییرات پیکربندی بیشتری ایجاد کنید:
// Hide the toolbar to maximize the navigation UI
supportActionBar?.hide()

// Enable voice audio guidance (through the device speaker)
mNavigator?.setAudioGuidance(Navigator.AudioGuidance.VOICE_ALERTS_AND_GUIDANCE)


// Simulate vehicle progress along the route (for demo/debug builds)
if (BuildConfig.DEBUG) {
   mNavigator?.simulator?.simulateLocationsAlongExistingRoute(
       SimulationOptions().speedMultiplier(5f)
   )
}

این تغییرات شامل بهبودهای زیر است:

  • پنهان کردن نوار اکشن برای به حداکثر رساندن فضا برای رابط کاربری ناوبری.
  • فعال کردن راهنمای صوتی برای بیان هشدارها و دستورالعمل‌های ناوبری.
  • راه‌اندازی شبیه‌ساز برای اشکال‌زدایی با تعیین یک ضریب سرعت.
  1. یک شناسه مکان (Place ID) پیدا کنید که به عنوان مقصد شما عمل کند. در حالت ایده‌آل، این مکان نباید خیلی از موقعیت مکانی کاربر دور باشد. از ابزار یافتن شناسه مکان پلتفرم نقشه‌های گوگل (Google Maps Platform Place ID Finder) استفاده کنید یا یک شناسه مکان (Place ID) را از طریق فراخوانی API مکان‌ها (Places API) دریافت کنید.

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

  1. یک شیء همراه به کلاس MainActivity خود اضافه کنید تا یک مکان شروع و یک شناسه مکان را ذخیره کند. Codelab از یک مکان شروع در لندن و شناسه مکان میدان ترافالگار استفاده خواهد کرد:
companion object{
   const val TRAFALGAR_SQUARE ="ChIJH-tBOc4EdkgRJ8aJ8P1CUxo" //London, UK
   val startLocation = LatLng(51.345678, -0.1234456)
}
  1. یک فراخوانی به متد navigateToPlace() از تابع onNavigatorReady درون متد initializeNavigationApi اضافه کنید و یک شاخه از منطق که در حالت Debug اجرا می‌شود و موقعیت مکانی کاربر را تنظیم می‌کند، اضافه کنید:
// Disables the guidance notifications and shuts down the app and background service
// when the user dismisses/swipes away the app from Android's recent tasks.
navigator.setTaskRemovedBehavior(Navigator.TaskRemovedBehavior.QUIT_SERVICE)

mNavigator = navigator

if (BuildConfig.DEBUG) {
   mNavigator?.simulator?.setUserLocation(MainActivity.startLocation)
}
//listen for events en route
registerNavigationListeners()

navView.getMapAsync {
   googleMap  ->
   googleMap.followMyLocation(GoogleMap.CameraPerspective.TILTED)
}

//navigate to a destination
navigateToPlace(MainActivity.TRAFALGAR_SQUARE)

۱۰. کد خود را بسازید و اجرا کنید

اولین باری که برنامه را اجرا می‌کنید، باید مجوزهای موقعیت مکانی را به برنامه اعطا کنید و شرایط استفاده از Navigation SDK را بپذیرید.

نکته: اجرای برنامه، متد setDestinations() را فراخوانی می‌کند که پس از ۱۰۰۰ مقصد اول استفاده شده، هزینه‌ای را متحمل می‌شود. برای اطلاعات بیشتر به بخش «استفاده و صورتحساب» مراجعه کنید.

93aa433000a14dfc.png

پنجره‌ی محاوره‌ایِ «شرایط کاربر نهاییِ» SDK ناوبری.

تنظیم مکان

به طور پیش‌فرض، ممکن است مکان دستگاه شبیه‌سازی‌شده روی پردیس گوگل در مانتین ویو کالیفرنیا تنظیم شده باشد، مگر اینکه شما مکانی را در کد یا با استفاده از کادر محاوره‌ای ویژگی‌های شبیه‌ساز تنظیم کرده باشید.

در این صورت، ممکن است متوجه شوید که برنامه نمی‌تواند مسیری را به Place ID که پیکربندی کرده‌اید (به طور پیش‌فرض، Sydney Opera House، سیدنی، استرالیا) پیدا کند. این موضوع با پیامی با عنوان "No route found" که توسط متد showToast() شما نمایش داده می‌شود، نشان داده خواهد شد.

نمای نقشه برنامه ناوبری که دفتر گوگل در مانتین ویو، کالیفرنیا را نشان می‌دهد.

کدگذاری دقیق محل شروع

برای تنظیم یک مکان متفاوت در کد، خط زیر را در متد navigateToPlace() در MainActivity.kt، قبل از فراخوانی mNavigator.startGuidance() اضافه کنید:

mNavigator?.simulator?.setUserLocation(startLocation)

شروع شبیه‌ساز در یک مکان پیش‌فرض دلخواه شما

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

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

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

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

برنامه را مجدداً راه اندازی کنید و اکنون باید به مقصد مورد نظر هدایت شود.

تصویری از برنامه ناوبری که به مقصد راهنمایی می‌کند.

۱۱. تبریک می‌گویم!

شما این آزمایشگاه کدنویسی را به پایان رساندید. آفرین - به مقصد خود رسیدید! کدنویسی خوبی داشته باشید :-)

55812f33256c0596.png

۱۲. ادامه دادن

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