إنشاء تطبيق تنقّل بسيط لنظام التشغيل Android باستخدام حزمة تطوير البرامج (SDK) لميزة التنقّل في "منصّة خرائط Google"

إنشاء تطبيق تنقّل بسيط لنظام التشغيل Android باستخدام حزمة تطوير البرامج (SDK) لميزة التنقّل في "منصّة خرائط Google"

لمحة عن هذا الدرس التطبيقي حول الترميز

subjectتاريخ التعديل الأخير: أكتوبر 10, 2024
account_circleتأليف: Ed Boiling

1. قبل البدء

يعلّمك هذا الدرس التطبيقي كيفية إنشاء تطبيق Android بسيط يستخدم حزمة تطوير البرامج (SDK) للتنقّل في "منصة خرائط Google" للانتقال إلى وجهة تم ضبطها مسبقًا.

هذا هو الشكل الذي سيبدو عليه تطبيقك عند الانتهاء منه.

b6c535afde7abd20.png

  • المعرفة الأساسية بتطوير تطبيقات Android باستخدام لغة Kotlin
  • الإلمام ببعض المفاهيم الأساسية لحزمة تطوير البرامج (SDK) في "خرائط Google" مثل الخرائط والمواقع الجغرافية والإحداثيات

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

  • كيفية إنشاء تطبيق Android بسيط يستخدم حزمة SDK للتنقل للانتقال إلى وجهة معيّنة.
  • كيفية دمج حزمة SDK للتنقّل من مستودع Maven البعيد من Google
  • كيفية إدارة أذونات الموقع الجغرافي واتفاقية المستخدم مع بنود المستخدم النهائي لحزمة Navigation SDK
  • كيفية إعداد حزمة تطوير البرامج (SDK)
  • كيفية ضبط وجهة وبدء إرشادات التنقّل

المتطلبات

  • تم تثبيت أحدث إصدار ثابت من "استوديو Android". تم إنشاء هذا الدرس التطبيقي حول الترميز باستخدام Android Studio Jellyfish. إذا كنت تستخدم إصدارًا مختلفًا، قد يختلف مظهر الواجهة والمكوّنات وتنسيقها.
  • حساب Google ومشروع تم تفعيل الفوترة فيهما
  • جهاز Android في وضع مطور البرامج مع تفعيل تصحيح أخطاء USB، أو محاكي Android. يجب أن تستوفي حزمة SDK التي تختارها الحد الأدنى من متطلبات حزمة SDK لميزة التنقّل.

2. الإعداد

إذا لم يكن لديك حساب على Google Cloud Platform ومشروع تم تفعيل الفوترة فيه، يمكنك إعداد مشروعك على Google Cloud باتّباع تعليمات بدء استخدام "منصة خرائط Google" https://developers.google.com/maps/gmp-get-started.

اختيار مشروع Google Cloud في وحدة التحكّم

في Cloud Console، انقر على القائمة المنسدلة للمشروع واختَر المشروع الذي تريد استخدامه في هذا الدرس التطبيقي حول الترميز.

القائمة المنسدلة لأداة اختيار المشاريع في وحدة التحكّم في Google Cloud.

تفعيل حزمة تطوير البرامج (SDK) للتنقّل في مشروعك

فعِّل واجهات برمجة تطبيقات Google Maps Platform وحِزم SDK المطلوبة لهذا الدليل التعليمي في Google Cloud Marketplace.

انتقِل إلى "واجهات برمجة التطبيقات والخدمات" > "المكتبة" في Google Cloud Console وابحث عن "مجموعة تطوير البرامج (SDK) لنظام التنقّل".

من المفترض أن تظهر لك نتيجة بحث واحدة.

شاشة "مكتبة واجهات برمجة التطبيقات" في Google Cloud Console، تعرِض صفحة Navigation SDK

انقر على نتيجة حزمة تطوير البرامج Navigation SDK لفتح صفحة "تفاصيل المنتج". انقر على زر التفعيل لتفعيل حزمة تطوير البرامج (SDK) في مشروعك.

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

إنشاء مفتاح واجهة برمجة التطبيقات

أنشئ مفتاح واجهة برمجة التطبيقات في صفحة بيانات الاعتماد في Cloud Console. يمكنك اتّباع الخطوات الواردة في الخطوة 3 من قسم البدء السريع في مقالة بدء استخدام "منصة خرائط Google". تتطلّب جميع الطلبات المرسَلة إلى "منصّة خرائط Google" مفتاح واجهة برمجة التطبيقات.

3. الحصول على نماذج ملفات المشروع

يصف هذا القسم كيفية إعداد مشروع أساسي فارغ على "استوديو Android" من خلال استنساخ الملفات من مستودع GitHub الخاص بهذا الدرس التطبيقي حول الترميز. يحتوي مستودع Github على نُسخة سابقة ونُسخة لاحقة من رمز ورشة التعلم البرمجي. سيبدأ ورشة رموز البرامج بنموذج مشروع فارغ وسيتم تطويره إلى أن يصل إلى الحالة النهائية. يمكنك استخدام المشروع النهائي في المستودع كمرجع إذا واجهتك مشكلة.

يمكنك استنساخ مستودع Github هذا للحصول على رمز هذا الدرس التطبيقي حول الترميز.

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

إذا لم يكن لديك git مثبّتًا، انقر على هذا الزر للحصول على الرمز:

لمساعدتك في البدء في أسرع وقت ممكن، يحتوي Repo على بعض رموز بدء الاستخدام في مجلد "Starter" لمساعدتك في متابعة هذا الدرس التطبيقي حول الترميز. يوفر مشروع إجراء التفعيل واجهة مستخدم أساسية للتطبيق وتكوينًا للتصميم، ولكن لم تتم إضافة حزمة SDK للتنقل إليه. هناك أيضًا مشروع "Solution" مكتمل إذا أردت المتابعة أو التحقّق من مستوى تقدّمك في أي وقت.

فتح المستودع المنسوخ في "استوديو Android"

بعد استنساخ المستودع على الجهاز، استخدِم "استوديو Android" لفتح مجلد "Starter" كمشروع حالي.

  1. من مربّع الحوار "مرحبًا بك في Android Studio"، انقر على الزر "فتح".
  2. انتقِل إلى المجلد الذي حفظت فيه المستودع المُنشئ من النسخة، واختَر المجلد Starter داخل المجلد "codelab-navigation-101-android-kotlin" في المستوى الأعلى.
  3. تأكَّد من إنشاء المشروع وتشغيله.

إضافة جهاز افتراضي أو ربط جهاز مادي

لتوصيل جهاز Android بالكمبيوتر، اتّبِع تعليمات Android Studio حول كيفية تشغيل التطبيقات على جهاز أجهزة. وبدلاً من ذلك، يمكنك ضبط جهاز افتراضي باستخدام مدير الأجهزة الافتراضية لنظام التشغيل Android (AVD). عند اختيار محاكي، احرص على اختيار صورة تتضمّن واجهات برمجة التطبيقات من Google.

في Android Studio، انقر على خيار القائمة "تشغيل" أو على رمز زر التشغيل. اختَر جهازًا كما هو مطلوب.

4. إضافة حزمة تطوير البرامج (SDK) لنظام التنقّل إلى تطبيقك

أضِف مكتبة "حزمة تطوير البرامج (SDK) للتنقل" ومفتاح واجهة برمجة التطبيقات إلى مشروعك.

لإضافة مكتبة Navigation SDK إلى تطبيقك، عليك تعديل الملفّ build.gradle.kts على مستوى التطبيق لتحميل حزمة Navigation SDK من مستودع Google Maven وضبط رقم إصدار.

أنشئ متغيّرًا في إعدادات الإنشاء لتخزين رقم إصدار حزمة SDK للملاحة.

يمكنك إعداد متغيّر في build.gradle.kts على مستوى التطبيق لتضمين قيمة إصدار حزمة تطوير البرامج (SDK) للتنقل المستخدَم في تطبيقك، حتى يكون من السهل التغيير إلى أحدث إصدار في المستقبل.

اطّلِع على ملاحظات إصدار حزمة تطوير البرامج (SDK) لنظام التنقّل لمعرفة رقم أحدث إصدار.

val navSdkVersion by extra("6.0.0")

يمكنك أيضًا تعديل قيم هذا العنصر ومتغيرات أخرى باستخدام مربع الحوار الموجود في الملف > هيكل المشروع > المتغيرات:

668332736b67dc82.png

إضافة تبعية إلى إعدادات الإصدار

أضِف الآن التبعية التالية لواجهة برمجة التطبيقات إلى مجموعة الملحقات في build.gradle.kts.على مستوى التطبيق. سيكون الإصدار المستخدَم هو قيمة ${navSdkVersion} التي ضبطتها للتو في build.gradle.kts على مستوى التطبيق:

dependencies {

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

...

إضافة مفتاح واجهة برمجة التطبيقات

استخدام المكوّن الإضافي Secrets Gradle لإدارة مفتاح واجهة برمجة التطبيقات

ننصحك باستخدام المكوّن الإضافي Secret Gradle لإدارة مفتاح واجهة برمجة التطبيقات بأمان في تطبيقك. تمت إضافة المكون الإضافي إلى نموذج المشروع الأولي كتبعية في ملف 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 بمفتاح واجهة برمجة التطبيقات الخاص بك. عليك تخزين مفتاحك في هذا الملف لأنّه تم استبعاد secrets.properties من التحقق من نظام التحكم في الإصدار.

MAPS_API_KEY=YOUR_API_KEY

لمزيد من المعلومات حول هذا الموضوع، يُرجى الاطّلاع على إضافة مفتاح واجهة برمجة التطبيقات إلى تطبيقك في مستندات حزمة 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، ستؤدي القيمة التلقائية إلى إيقاف تشغيل التطبيق أثناء وقت التشغيل، مع ظهور خطأ في مفتاح واجهة برمجة التطبيقات.

التأكّد من أنّ بيان Android يستخدم مفتاح واجهة برمجة التطبيقات الذي حدّدته

افتح app/src/main/AndroidManifest.xml. ستلاحظ أنّه يتم استخدام السمة MAPS_API_KEY لضبط مفتاح واجهة برمجة التطبيقات للتطبيق:

<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.

5. ضبط أذونات التطبيق وإضافة واجهة مستخدم أساسية

طلب إذن تحديد الموقع الجغرافي الدقيق

وتعتمد حزمة تطوير البرامج (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>

يمكنك الاطّلاع على مزيد من المعلومات حول أذونات الموقع الجغرافي على Android في قسم طلب أذونات الموقع الجغرافي من مستندات مطوّري تطبيقات Android.

لتشغيل تطبيقك على جهاز يعمل بالإصدار 14 من نظام التشغيل Android، اطلب إذن الموقع الجغرافي للخدمة التي تعمل في المقدّمة من خلال إضافة علامة uses-permission التالية في المكان نفسه الذي يتوفّر فيه إذن الوصول إلى الموقع الجغرافي الدقيق:

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

إضافة نشاط إطلاق باستخدام واجهة مستخدم أساسية

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

افتح الملف MainActivity.kt في محرِّر الرموز البرمجية وتحقّق من الرمز الذي يعرض واجهة مستخدم أساسية.

طلب أذونات الوصول إلى الموقع الجغرافي في وقت التشغيل

على تطبيقك بدء طلب الوصول إلى الموقع الجغرافي الدقيق قبل بدء حزمة Navigation SDK.

لضمان حدوث هذه العملية عند بدء تشغيل تطبيقك، أضِف بعض الرموز إلى صف MainActivity في طريقة onCreate() التي تم إلغاؤها في سجلّ "نشاطك".

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

أنشئ مشروعك. إذا كانت لديك أي أخطاء في عملية الإنشاء، ابحث عنها وأصلِحها.

يمكنك تنفيذ مشروعك على جهاز افتراضي جديد. من المفترض أن يظهر لك مربّع حوار طلب الأذونات عند تثبيت التطبيق وتشغيله.

6. إضافة واجهة مستخدم للتنقّل

هناك طريقتان لإضافة واجهة مستخدم للتنقّل: SupportNavigationFragment أو 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>

إعداد نشاط "التنقّل"

في Android Studio، افتح ملف MainActivity.kt في المحرِّر.

أضِف بعض رموز الإعداد الأساسية لضمان عمل تجربة التنقّل بشكلٍ صحيح في تطبيقك. في ملف MainActivity.kt، أدخِل التغييرات التالية:

  1. يُرجى تعريف متغيّر في فئة MainActivity للإشارة إلى NavigationView:
private lateinit var navView: NavigationView
  1. أضِف بعض الرموز إلى طريقة onCreate() للحصول على مرجع إلى NavigationView:
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()
}

7. إعداد حزمة تطوير البرامج (SDK) للتنقّل

بعد إكمال الإعداد الأساسي لنشاط التنقّل، يمكنك إعداد حزمة تطوير البرامج (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(). تحصل هذه الطريقة على مرجع إلى كائن Navigator من خلال استدعاء NavigationApi.getNavigator() ويتم تنفيذ NavigatorListener للتعامل مع معاودة الاتصال.

يُرجى العلم بأنّه عند إعداد واجهة برمجة تطبيقات التنقّل، سيتم استدعاء الطريقة NavigationListener.onNavigatorReady، مع تمرير عنصر Navigator كمَعلمة. سيعدّل الرمز أعلاه المتغيّر mNavigator الذي حدّدته سابقًا باستخدام العنصر Navigator الذي تمّت إعداده والذي تمّ تمريره إلى هذه الطريقة.

أخيرًا، أضِف طلبًا لاستدعاء طريقة initializeNavigationApi من طريقة onLocationPermissionGranted.

private fun onLocationPermissionGranted() {
   initializeNavigationApi()
}

8. إضافة أدوات استماع لأحداث التنقل الرئيسية

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

  1. ضمن فئة MainActivity، يمكنك تحديد متغيّرَين للإشارة إلى كائنات مستمعي الأحداث:
private var arrivalListener: Navigator.ArrivalListener? = null
private var routeChangedListener: Navigator.RouteChangedListener? = null
  1. أضِف طريقة registerNavigationListeners() لإعداد المستمعين عند بدء تشغيل Navigator. تستدعي هذه الطريقة Navigator.clearDestinations() لإعادة ضبط NavigationView عند تنشيط حدث الوصول:
/**
* 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. أضِف طلبًا إلى GoogleMap.followMyLocation لتحديد CameraPerspective. يتم الوصول إلى 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()
}

9. تحديد وجهة

أصبحت الآن جاهزًا لضبط وجهة وبدء التوجيهات للتنقّل. في ملف 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 من رقم تعريف المكان الذي يتم تمريره إلى الطريقة. يمكنك معالجة الخطأ UnsupportedPlaceIdException الذي يمكن أن ينتج عن ذلك، وذلك في الحالات التي لا يُحدّد فيها رقم تعريف المكان عنوانًا دقيقًا:
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() لتحديد وجهة باستخدام نقطة الطريق:
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. ابحث عن رقم تعريف مكان سيكون بمثابة وجهتك. من الأفضل ألا يكون هذا الموقع الجغرافي بعيدًا جدًا عن الموقع الجغرافي للمستخدم. استخدِم أداة البحث عن معرّف المكان في "منصة خرائط Google" أو احصل على معرّف مكان من طلب Places API.

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

  1. أضِف عنصرًا مصاحبًا إلى فئة MainActivity لتخزين موقع البداية ومعرّف مكان. سيستخدم درس تطبيقي حول الترميز موقع البدء في لندن ورقم تعريف المكان في ميدان ترافالغار:
companion object{
   const val TRAFALGAR_SQUARE ="ChIJH-tBOc4EdkgRJ8aJ8P1CUxo" //London, UK
   val startLocation = LatLng(51.345678, -0.1234456)
}
  1. أضِف استدعاءً إلى طريقة navigateToPlace() من استدعاء onNavigatorReady داخل طريقة initializeNavigationApi، وأضِف فرعًا من المنطق الذي سيتم تنفيذه في وضع تصحيح الأخطاء، والذي يضبط الموقع الجغرافي للمستخدم:
// 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)

10. إنشاء التعليمات البرمجية وتشغيلها

عند تشغيل التطبيق لأول مرة، ستحتاج إلى منح أذونات تحديد الموقع الجغرافي للتطبيق وقبول بنود استخدام حزمة تطوير البرامج (SDK) للتنقل.

ملاحظة: سيؤدي تشغيل التطبيق إلى استدعاء الطريقة setDestinations() التي تفرض رسومًا بعد استخدام أوّل 1,000 وجهة. راجِع الاستخدام والفوترة للحصول على مزيد من المعلومات.

93aa433000a14dfc.png

مربّع الحوار لعبارات المستخدمين النهائيين في حزمة تطوير البرامج (SDK) للتنقّل

تحديد الموقع الجغرافي

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

إذا كان الأمر كذلك، قد لا يتمكن التطبيق من العثور على مسار إلى معرّف المكان الذي ضبطته (بشكل تلقائي، دار أوبرا سيدني، سيدني، أستراليا). ستتم الإشارة إلى ذلك من خلال رسالة مفادها "لم يتم العثور على مسار"، ويتم عرضها من خلال طريقة showToast().

عرض الخريطة في تطبيق &quot;التنقّل&quot; يعرض مكتب Google في ماونتن فيو، كاليفورنيا

ترميز الموقع الجغرافي لنقطة البداية بشكل ثابت

لضبط موقع جغرافي مختلف في الرمز، أضِف السطر التالي في طريقة navigateToPlace() في MainActivity.kt قبل طلب mNavigator.startGuidance():

mNavigator?.simulator?.setUserLocation(startLocation)

تشغيل المحاكي في موقع جغرافي تلقائي من اختيارك

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

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

مربّع حوار عناصر التحكّم الموسّعة في &quot;مدير أجهزة Android&quot;، يعرض أداة اختيار الأماكن وخريطة تركّز على شاطئ بوندي في أستراليا

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

أعِد تشغيل التطبيق ومن المفترض أن يتم الانتقال الآن إلى الوجهة.

لقطة شاشة لتطبيق التنقّل الذي يقدّم إرشادات إلى الوجهة

11. تهانينا!

لقد أكملت هذا الدليل التعليمي حول البرمجة. أحسنت - لقد وصلت إلى وجهتك. نتمنى لك التوفيق في الترميز :-)

55812f33256c0596.png

12. الاستخدام المتقدم

إذا أردت الارتقاء بتطوير تطبيقك، يمكنك الاطّلاع على المواضيع التالية للحصول على أفكار ملهمة.