إنشاء تطبيق للتنقّل

توضح هذه الصفحة بالتفصيل الميزات المختلفة لمكتبة تطبيقات السيارات التي يمكنك استخدامها لتنفيذ وظائف تطبيق التنقل خطوة بخطوة.

يُرجى توضيح توفُّر إمكانية التنقّل في ملف البيان.

يجب أن يذكر تطبيق التنقّل androidx.car.app.category.NAVIGATION فئة تطبيقات السيارات في فلتر الأهداف في CarAppService:

<application>
    ...
   <service
       ...
        android:name=".MyNavigationCarAppService"
        android:exported="true">
      <intent-filter>
        <action android:name="androidx.car.app.CarAppService" />
        <category android:name="androidx.car.app.category.NAVIGATION"/>
      </intent-filter>
    </service>
    ...
</application>

إتاحة عمليات التنقّل

لإتاحة أهداف التنقّل في تطبيقك، بما في ذلك الأهداف القادمة من "مساعد Google" باستخدام طلب صوتي، يجب أن يعالج تطبيقك هدف CarContext.ACTION_NAVIGATE في Session.onCreateScreen وSession.onNewIntent.

راجِع المستندات المتعلقة CarContext.startCarApp للحصول على تفاصيل عن تنسيق الغرض.

الوصول إلى نماذج التنقل

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

  • NavigationTemplate: تعرض أيضًا رسالة إعلامية اختيارية وتقديرات بشأن السفر أثناء التنقّل النشط.
  • MapWithContentTemplate: نموذج يسمح للتطبيق بعرض مربّعات خرائط تتضمّن نوعًا من المحتوى (على سبيل المثال، قائمة) يتم عرض المحتوى عادة كتراكب فوق مربعات الخريطة، مع ضبط المناطق المرئية والثابتة على الخريطة مع المحتوى.

للحصول على مزيد من التفاصيل عن كيفية تصميم واجهة المستخدم في تطبيق التنقّل باستخدام هذه النماذج، يمكنك الاطّلاع على تطبيقات التنقّل.

للوصول إلى نماذج التنقّل، يجب أن يتضمّن تطبيقك بيانًا للإذن androidx.car.app.NAVIGATION_TEMPLATES في ملف AndroidManifest.xml الخاص به:

<manifest ...>
  ...
  <uses-permission android:name="androidx.car.app.NAVIGATION_TEMPLATES"/>
  ...
</manifest>

مطلوب إذن إضافي لرسم الخرائط.

الانتقال إلى MapWithContentTemplate

بدءًا من المستوى 7 من واجهة برمجة تطبيقات Car App API، تم إيقاف MapTemplate وPlaceListNavigationTemplate وRoutePreviewNavigationTemplate نهائيًا. وستظلّ النماذج المتوقّفة متاحة، ولكن ننصح بشدة بنقلها إلى MapWithContentTemplate.

يمكن تنفيذ الوظائف التي توفّرها هذه النماذج باستخدام MapWithContentTemplate. اطّلِع على المقتطفات التالية للحصول على أمثلة:

نموذج الخريطة

Kotlin

// MapTemplate (deprecated)
val template = MapTemplate.Builder()
    .setPane(paneBuilder.build())
    .setActionStrip(actionStrip)
    .setHeader(header)
    .setMapController(mapController)
    .build()

// MapWithContentTemplate
val template = MapWithContentTemplate.Builder()
    .setContentTemplate(
        PaneTemplate.Builder(paneBuilder.build())
            .setHeader(header)
            .build())
    .setActionStrip(actionStrip)
    .setMapController(mapController)
    .build()

Java

// MapTemplate (deprecated)
MapTemplate template = new MapTemplate.Builder()
    .setPane(paneBuilder.build())
    .setActionStrip(actionStrip)
    .setHeader(header)
    .setMapController(mapController)
    .build();

// MapWithContentTemplate
MapWithContentTemplate template = new MapWithContentTemplate.Builder()
    .setContentTemplate(new PaneTemplate.Builder(paneBuilder.build())
        .setHeader(header)
        build())
    .setActionStrip(actionStrip)
    .setMapController(mapController)
    .build();

نموذج التنقّل في الأماكن

Kotlin

// PlaceListNavigationTemplate (deprecated)
val template = PlaceListNavigationTemplate.Builder()
    .setItemList(itemListBuilder.build())
    .setHeader(header)
    .setActionStrip(actionStrip)
    .setMapActionStrip(mapActionStrip)
    .build()

// MapWithContentTemplate
val template = MapWithContentTemplate.Builder()
    .setContentTemplate(
        ListTemplate.Builder()
            .setSingleList(itemListBuilder.build())
            .setHeader(header)
            .build())
    .setActionStrip(actionStrip)
    .setMapController(
        MapController.Builder()
            .setMapActionStrip(mapActionStrip)
            .build())
    .build()

Java

// PlaceListNavigationTemplate (deprecated)
PlaceListNavigationTemplate template = new PlaceListNavigationTemplate.Builder()
    .setItemList(itemListBuilder.build())
    .setHeader(header)
    .setActionStrip(actionStrip)
    .setMapActionStrip(mapActionStrip)
    .build();

// MapWithContentTemplate
MapWithContentTemplate template = new MapWithContentTemplate.Builder()
    .setContentTemplate(new ListTemplate.Builder()
        .setSingleList(itemListBuilder.build())
        .setHeader(header)
        .build())
    .setActionStrip(actionStrip)
    .setMapController(new MapController.Builder()
        .setMapActionStrip(mapActionStrip)
        .build())
    .build();

نموذج معاينة التنقل

Kotlin

// RoutePreviewNavigationTemplate (deprecated)
val template = RoutePreviewNavigationTemplate.Builder()
    .setItemList(
        ItemList.Builder()
            .addItem(
                Row.Builder()
                    .setTitle(title)
                    .build())
            .build())
    .setHeader(header)
    .setNavigateAction(
        Action.Builder()
            .setTitle(actionTitle)
            .setOnClickListener { ... }
            .build())
    .setActionStrip(actionStrip)
    .setMapActionStrip(mapActionStrip)
    .build()

// MapWithContentTemplate
val template = MapWithContentTemplate.Builder()
    .setContentTemplate(
        ListTemplate.Builder()
            .setSingleList(
                ItemList.Builder()
                    .addItem(
                        Row.Builder()
                            .setTitle(title)
                            .addAction(
                                Action.Builder()
                                    .setTitle(actionTitle)
                                    .setOnClickListener { ... }
                                    .build())
                            .build())
                    .build())
            .setHeader(header)
            .build())
    .setActionStrip(actionStrip)
    .setMapController(
        MapController.Builder()
            .setMapActionStrip(mapActionStrip)
            .build())
    .build()

Java

// RoutePreviewNavigationTemplate (deprecated)
RoutePreviewNavigationTemplate template = new RoutePreviewNavigationTemplate.Builder()
    .setItemList(new ItemList.Builder()
        .addItem(new Row.Builder()
            .setTitle(title))
            .build())
        .build())
    .setHeader(header)
    .setNavigateAction(new Action.Builder()
        .setTitle(actionTitle)
        .setOnClickListener(() -> { ... })
        .build())
    .setActionStrip(actionStrip)
    .setMapActionStrip(mapActionStrip)
    .build();

// MapWithContentTemplate
MapWithContentTemplate template = new MapWithContentTemplate.Builder()
    .setContentTemplate(new ListTemplate.Builder()
        .setSingleList(new ItemList.Builder()
            .addItem(new Row.Builder()
                  .setTitle(title))
                  .addAction(new Action.Builder()
                      .setTitle(actionTitle)
                      .setOnClickListener(() -> { ... })
                      .build())
                  .build())
            .build()))
        .setHeader(header)
        .build())
    .setActionStrip(actionStrip)
    .setMapController(new MapController.Builder()
        .setMapActionStrip(mapActionStrip)
        .build())
    .build();

يجب أن تنقل تطبيقات التنقل بيانات وصفية إضافية للتنقل مع المضيف. يستخدم المضيف المعلومات لتقديم معلومات إلى الوحدة الرئيسية للمركبة ولمنع تطبيقات التنقل من التعارض بشأن الموارد المشتركة.

يتم توفير البيانات الوصفية للتنقّل من خلال خدمة سيارات NavigationManager التي يمكن الوصول إليها من CarContext:

Kotlin

val navigationManager = carContext.getCarService(NavigationManager::class.java)

Java

NavigationManager navigationManager = carContext.getCarService(NavigationManager.class);

بدء التنقّل وإنهاؤه وإيقافه

لكي يتمكن المضيف من إدارة تطبيقات التنقل المتعددة، وإشعارات التوجيه، وبيانات مجموعات المركبات، يجب أن يكون على دراية بالحالة الحالية للتنقل. عندما يبدأ المستخدم التنقّل، يمكنك طلب NavigationManager.navigationStarted. وبالمثل، عند انتهاء التنقّل، مثلاً عند وصول المستخدم إلى وجهته أو عندما يلغي المستخدم التنقّل، يمكنك الاتصال بالرقم NavigationManager.navigationEnded.

لا تطلب الرقم NavigationManager.navigationEnded إلا عند انتهاء المستخدم من التنقّل. على سبيل المثال، إذا كنت بحاجة إلى إعادة احتساب المسار في منتصف الرحلة، استخدِم Trip.Builder.setLoading(true) بدلاً من ذلك.

في بعض الأحيان، يحتاج المضيف إلى تطبيق لإيقاف التنقّل والمكالمات onStopNavigation في عنصر NavigationManagerCallback يوفّره تطبيقك من خلال NavigationManager.setNavigationManagerCallback. يجب أن يتوقف التطبيق بعد ذلك عن إصدار معلومات الاتجاه التالي في شاشة المجموعة وإشعارات التنقّل والإرشاد الصوتي.

تعديل معلومات الرحلة

أثناء التنقّل النشط، يمكنك الاتصال بالرقم NavigationManager.updateTrip. يمكن استخدام المعلومات المقدّمة في هذه المكالمة بواسطة شاشات العرض العنقودي للمركبة وشاشة المعلومات الرأسية. بناءً على المركبة المحددة التي تتم قيادتها، لا يتم عرض جميع المعلومات للمستخدم. على سبيل المثال، تعرض الوحدة الرئيسية لسطح المكتب (DHU) السمة Step المُضافة إلى Trip، ولكنها لا تعرض معلومات Destination.

الرسم إلى شاشة المجموعة

لتقديم تجربة المستخدم الأكثر تفاعلية، ننصحك بعدم عرض البيانات الوصفية الأساسية على شاشة العرض في مجموعات المركبة. بدءًا من المستوى 6 من Car App API، أصبح بإمكان تطبيقات التنقّل عرض المحتوى الخاص بها مباشرةً على شاشة المجموعة (في المركبات المتوافقة)، مع فرض القيود التالية:

  • لا تتيح واجهة برمجة تطبيقات عرض المجموعة إمكانية عناصر التحكّم في الإدخال.
  • ويجب أن تعرض شاشة المجموعة مربّعات الخرائط فقط. ويمكن اختياريًا عرض تنقل نشط في المسار على هذه المربعات.
  • لا تتيح واجهة cluster Display API إلا استخدام NavigationTemplate
      .
    • على عكس الشاشات الرئيسية، قد لا تعرض شاشات العرض للمجموعات بشكل متّسق كل عناصر واجهة المستخدم الخاصة بـ NavigationTemplate، مثل التعليمات المفصّلة وبطاقات الوقت المقدر للوصول والإجراءات. مربعات الخرائط هي العنصر الوحيد الذي يتم عرضه في واجهة المستخدم بشكل متسق.

بيان دعم المجموعة

لإعلام التطبيق المضيف بأنّ تطبيقك يتيح العرض على شاشات المجموعة، يجب إضافة العنصر androidx.car.app.category.FEATURE_CLUSTER <category> إلى <intent-filter> الخاص بـ CarAppService كما هو موضّح في المقتطف التالي:

<application>
    ...
   <service
       ...
        android:name=".MyNavigationCarAppService"
        android:exported="true">
      <intent-filter>
        <action android:name="androidx.car.app.CarAppService" />
        <category android:name="androidx.car.app.category.NAVIGATION"/>
        <category android:name="androidx.car.app.category.FEATURE_CLUSTER"/>
      </intent-filter>
    </service>
    ...
</application>

دورة الحياة وإدارة الحالة

بدءًا من المستوى 6 لواجهة برمجة التطبيقات، يظل مسار دورة حياة تطبيق السيارة كما هو، ولكن الآن CarAppService::onCreateSession تأخذ مَعلمة من النوع SessionInfo توفّر معلومات إضافية عن Session التي يتم إنشاؤها (أي نوع العرض ومجموعة النماذج المتوافقة).

ويمكن للتطبيقات استخدام الفئة Session نفسها للتعامل مع كل من المجموعة والعرض الرئيسية، أو إنشاء Sessions خاصة بالشاشة لتخصيص السلوك على كل شاشة (كما هو موضّح في المقتطف التالي).

Kotlin

override fun onCreateSession(sessionInfo: SessionInfo): Session {
  return if (sessionInfo.displayType == SessionInfo.DISPLAY_TYPE_CLUSTER) {
    ClusterSession()
  } else {
    MainDisplaySession()
  }
}

Java

@Override
@NonNull
public Session onCreateSession(@NonNull SessionInfo sessionInfo) {
  if (sessionInfo.getDisplayType() == SessionInfo.DISPLAY_TYPE_CLUSTER) {
    return new ClusterSession();
  } else {
    return new MainDisplaySession();
  }
}

وما من ضمانات بشأن وقت أو ما إذا تم توفير شاشة المجموعة العنقودية، ومن الممكن أيضًا أن تكون المجموعة Session هي Session الوحيدة (على سبيل المثال، استبدل المستخدم الشاشة الرئيسية بتطبيق آخر أثناء تنقّل التطبيق بشكل نشط). تشير الاتفاقية "العادية" إلى أنّ التطبيق لا يتحكّم في عرض المجموعة إلا بعد استدعاء NavigationManager::navigationStarted. ومع ذلك، من الممكن أن يتم تقديم شاشة عرض المجموعة للتطبيق في أثناء عدم حدوث تنقّل نشط، أو ألا يتم مطلقًا تقديم عرض المجموعة. ولتطبيقك خيار التعامل مع هذه السيناريوهات من خلال عرض حالة مربّعات الخرائط الخاملة.

ينشئ المضيف مجلد منفصلاً وCarContext مثيلاً لكل Session. وهذا يعني أنّه عند استخدام طريقتَين مثل ScreenManager::push أو Screen::invalidate، لن تتأثّر سوى السمة Session التي تم ذكر اسمها. يجب أن تنشئ التطبيقات قنوات تواصل خاصة بها بين هذه الحالات إذا لزم الأمر عند الحاجة إلى التواصل على مستوى Session (على سبيل المثال، باستخدام أحداث البث أو أغنية فردية مشتركة أو غير ذلك).

اختبار دعم المجموعة

يمكنك اختبار عملية التنفيذ على كلٍّ من Android Auto وAndroid Automotive. في Android Auto، يتم ذلك من خلال ضبط وحدة Desktop Head Unit لمحاكاة شاشة مجموعة ثانوية. أمّا في نظام التشغيل Android Automotive، فتعمل على محاكاة صور النظام العامة للمستوى 30 لواجهة برمجة التطبيقات والمستويات الأعلى.

تخصيص تقييم السفر باستخدام نص أو رمز

لتخصيص الوقت المقدّر للسفر باستخدام نص أو رمز أو كليهما، استخدِم طريقة setTripIcon أو setTripText الطريقة الخاصة بالفئة TravelEstimate.Builder. تستخدم NavigationTemplate TravelEstimate لضبط النصوص والرموز بجانب الوقت المقدّر للوصول والوقت المتبقي والمسافة المتبقية أو بدلاً منها.

الشكل 1. تقدير السفر مع رمز ونص مخصّصَين

يستخدم المقتطف التالي setTripIcon وsetTripText لتخصيص الوقت المقدّر للسفر:

Kotlin

TravelEstimate.Builder(Distance.create(...), DateTimeWithZone.create(...))
      ...
      .setTripIcon(CarIcon.Builder(...).build())
      .setTripText(CarText.create(...))
      .build()

Java

new TravelEstimate.Builder(Distance.create(...), DateTimeWithZone.create(...))
      ...
      .setTripIcon(CarIcon.Builder(...).build())
      .setTripText(CarText.create(...))
      .build();

توفير إشعارات مفصَّلة

قدّم إرشادات التنقل اتّجاهات مفصّلة باستخدام إشعار التنقّل الذي يتم تحديثه بشكل متكرّر. ليتم التعامل معك كإشعار تنقل في شاشة السيارة، يجب أن تنفذ أداة إنشاء الإشعارات ما يلي:

  1. ضَع علامة على الإشعار باعتباره مستمرًا باستخدام الطريقة NotificationCompat.Builder.setOngoing.
  2. اضبط فئة الإشعار على Notification.CATEGORY_NAVIGATION.
  3. يمكنك تمديد الإشعار باستخدام CarAppExtender.

يظهر إشعار التنقل في التطبيق المصغَّر للسكك الحديدية أسفل شاشة السيارة. وإذا تم ضبط مستوى أهمية الإشعار على IMPORTANCE_HIGH، سيتم عرضه أيضًا كإشعار تنبيه (HUN). إذا لم يتم ضبط الأهمية باستخدام الطريقة CarAppExtender.Builder.setImportance، يتم استخدام أهمية قناة الإشعار.

يمكن للتطبيق ضبط PendingIntent في CarAppExtender الذي يتم إرساله إلى التطبيق عندما ينقر المستخدم على HUN أو التطبيق المصغّر لسكة الحديد.

إذا تم استدعاء NotificationCompat.Builder.setOnlyAlertOnce والقيمة true، سيصلك إشعار بالغ الأهمية مرة واحدة فقط في HUN.

يوضِّح المقتطف التالي كيفية إنشاء إشعار للتنقّل:

Kotlin

NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID)
    ...
    .setOnlyAlertOnce(true)
    .setOngoing(true)
    .setCategory(NotificationCompat.CATEGORY_NAVIGATION)
    .extend(
        CarAppExtender.Builder()
            .setContentTitle(carScreenTitle)
            ...
            .setContentIntent(
                PendingIntent.getBroadcast(
                    context,
                    ACTION_OPEN_APP.hashCode(),
                    Intent(ACTION_OPEN_APP).setComponent(
                        ComponentName(context, MyNotificationReceiver::class.java)),
                        0))
            .setImportance(NotificationManagerCompat.IMPORTANCE_HIGH)
            .build())
    .build()

Java

new NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID)
    ...
    .setOnlyAlertOnce(true)
    .setOngoing(true)
    .setCategory(NotificationCompat.CATEGORY_NAVIGATION)
    .extend(
        new CarAppExtender.Builder()
            .setContentTitle(carScreenTitle)
            ...
            .setContentIntent(
                PendingIntent.getBroadcast(
                    context,
                    ACTION_OPEN_APP.hashCode(),
                    new Intent(ACTION_OPEN_APP).setComponent(
                        new ComponentName(context, MyNotificationReceiver.class)),
                        0))
            .setImportance(NotificationManagerCompat.IMPORTANCE_HIGH)
            .build())
    .build();

حدِّث إشعار TBT بانتظام لتغييرات المسافة، ما يؤدي إلى تحديث التطبيق المصغَّر للسكة الحديدية، ولا يعرض سوى الإشعار على شكل HUN. يمكنك التحكّم في سلوك HUN من خلال ضبط أهمية الإشعار باستخدام CarAppExtender.Builder.setImportance. ويؤدي ضبط الأهمية على IMPORTANCE_HIGH إلى إظهار HUN. يؤدي تعيينه على أي قيمة أخرى فقط إلى تحديث التطبيق المصغَّر للسكك الحديدية.

إعادة تحميل محتوى PlaceList NavigationTemplate

يمكنك السماح للسائقين بإعادة تحميل المحتوى بنقرة زر واحدة أثناء تصفُّح قوائم الأماكن التي تم إنشاؤها باستخدام PlaceListNavigationTemplate. لتفعيل ميزة "إعادة تحميل القائمة"، نفِّذ طريقة onContentRefreshRequested الخاصة بواجهة OnContentRefreshListener واستخدِم PlaceListNavigationTemplate.Builder.setOnContentRefreshListener لتحديد إعدادات المستمع للنموذج.

يوضّح المقتطف التالي كيفية ضبط المستمع على النموذج:

Kotlin

PlaceListNavigationTemplate.Builder()
    ...
    .setOnContentRefreshListener {
        // Execute any desired logic
        ...
        // Then call invalidate() so onGetTemplate() is called again
        invalidate()
    }
    .build()

Java

new PlaceListNavigationTemplate.Builder()
        ...
        .setOnContentRefreshListener(() -> {
            // Execute any desired logic
            ...
            // Then call invalidate() so onGetTemplate() is called again
            invalidate();
        })
        .build();

ولا يظهر زر إعادة التحميل إلا في عنوان PlaceListNavigationTemplate إذا كان لدى المستمع قيمة محددة.

عندما ينقر المستخدم على زر "إعادة التحميل"، يتم استدعاء طريقة onContentRefreshRequested الخاصة بعملية التنفيذOnContentRefreshListener. ضمن onContentRefreshRequested، يمكنك استدعاء طريقة Screen.invalidate. بعد ذلك، يتصل المضيف مرة أخرى بطريقة Screen.onGetTemplate في تطبيقك لاسترداد النموذج باستخدام المحتوى الذي تمت إعادة تحميله. راجِع إعادة تحميل محتوى نموذج للحصول على مزيد من المعلومات عن إعادة تحميل النماذج. ما دام النموذج التالي الذي تم عرضه من خلال onGetTemplate من النوع نفسه، يتم احتسابه كعملية إعادة تحميل ولا يتم احتسابه ضمن حصة النموذج.

تقديم الإرشاد الصوتي

لتشغيل إرشادات التنقّل فوق مكبّرات صوت السيارة، يجب أن يطلب تطبيقك التركيز على الصوت. كجزء من AudioFocusRequest الخاص بك، يمكنك ضبط الاستخدام على AudioAttributes.USAGE_ASSISTANCE_NAVIGATION_GUIDANCE. ويجب أيضًا ضبط زيادة التركيز على AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK.

محاكاة التنقل

للتحقّق من وظيفة التنقّل في تطبيقك عند إرساله إلى "متجر Google Play"، على تطبيقك تنفيذ زر معاودة الاتصال NavigationManagerCallback.onAutoDriveEnabled. عند استدعاء ميزة معاودة الاتصال هذه، يجب أن يحاكي تطبيقك التنقل إلى الوجهة المحددة عندما يبدأ المستخدم التنقل. يمكن لتطبيقك الخروج من هذا الوضع عند بلوغ مراحل نشاط Session الحالية الحالة Lifecycle.Event.ON_DESTROY.

يمكنك اختبار استدعائك عملية تنفيذ onAutoDriveEnabled عن طريق تنفيذ الآتي من سطر الأوامر:

adb shell dumpsys activity service CAR_APP_SERVICE_NAME AUTO_DRIVE

يظهر ذلك في المثال التالي:

adb shell dumpsys activity service androidx.car.app.samples.navigation.car.NavigationCarAppService AUTO_DRIVE

التطبيق التلقائي لسيارة التنقّل

في Android Auto، يتوافق تطبيق سيارة التنقل التلقائي مع آخر تطبيق تنقل أطلقه المستخدم. يتلقّى التطبيق التلقائي أهداف التنقّل عندما يستدعي التطبيق أوامر التنقّل من خلال "مساعد Google" أو عندما يرسل تطبيق آخر نية لبدء التنقّل.

عرض تنبيهات التنقّل ضمن السياق

يعرض Alert معلومات مهمة للسائق من خلال إجراءات اختيارية&dash;بدون الخروج من سياق شاشة التنقّل. لتقديم أفضل تجربة للسائق، يعمل تطبيق "Alert" ضمن NavigationTemplate لتجنُّب حظر مسار التنقّل وتقليل تشتيت السائق.

يتوفّر "Alert" فقط في "NavigationTemplate". لإعلام المستخدم خارج NavigationTemplate، يمكنك استخدام إشعار تنبيه (HUN)، كما هو موضّح في عرض الإشعارات.

على سبيل المثال، يمكنك استخدام Alert لتنفيذ ما يلي:

  • أبلِغ السائق بآخر المعلومات المتعلقة بالتنقل الحالي، مثل أي تغيير في أحوال حركة المرور.
  • اطلب من السائق تحديث معلومات التنقّل الحالية، مثل وجود رادار سرعة متنقّل.
  • اقترِح مهمة قادمة واسأل السائق عما إذا كان يقبلها، مثل ما إذا كان السائق مستعدًا لاصطحاب شخص ما في طريقه.

يتألف Alert بشكل أساسي من عنوان والمدة الزمنية Alert. يتم تمثيل المدة الزمنية بشريط تقدّم. اختياريًا، يمكنك إضافة عنوان فرعي ورمز وما يصل إلى كائنَين من عناصر Action.

الشكل 2. تنبيه بشأن التنقّل ضمن السياق

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

إنشاء تنبيه

استخدِم Alert.Builder لإنشاء مثيل Alert:

Kotlin

Alert.Builder(
        /*alertId*/ 1,
        /*title*/ CarText.create("Hello"),
        /*durationMillis*/ 5000
    )
    // The fields below are optional
    .addAction(firstAction)
    .addAction(secondAction)
    .setSubtitle(CarText.create(...))
    .setIcon(CarIcon.APP_ICON)
    .setCallback(...)
    .build()

Java

new Alert.Builder(
        /*alertId*/ 1,
        /*title*/ CarText.create("Hello"),
        /*durationMillis*/ 5000
    )
    // The fields below are optional
    .addAction(firstAction)
    .addAction(secondAction)
    .setSubtitle(CarText.create(...))
    .setIcon(CarIcon.APP_ICON)
    .setCallback(...)
    .build();

إذا أردت الاستماع إلى طلبات إلغاء Alert أو إغلاقها، عليك إنشاء عملية تنفيذ لواجهة AlertCallback. مسارات طلبات "AlertCallback" هي:

  • في حال انتهاء مهلة Alert، يستدعي المضيف الطريقة AlertCallback.onCancel باستخدام القيمة AlertCallback.REASON_TIMEOUT. بعد ذلك، يستدعي الطريقة AlertCallback.onDismiss.

  • إذا نقر السائق على أحد أزرار الإجراءات، سيتصل المضيف بالرمز Action.OnClickListener ثم يتصل بالرقم AlertCallback.onDismiss.

  • إذا لم تكن العلامة Alert متاحة، يطلب المضيف AlertCallback.onCancel باستخدام القيمة AlertCallback.REASON_NOT_SUPPORTED. لا يستدعي المضيف AlertCallback.onDismiss، لأنه لم يتم عرض Alert.

ضبط مدة التنبيه

اختَر مدة Alert متوافقة مع احتياجات تطبيقك. المدة المقترحة للتنقل Alert هي 10 ثوانٍ. راجِع تنبيهات التنقّل للحصول على مزيد من المعلومات.

عرض تنبيه

لعرض Alert، يمكنك استدعاء طريقة AppManager.showAlert المتاحة من خلال CarContext في تطبيقك.

// Show an alert
carContext.getCarService(AppManager.class).showAlert(alert)
  • لا يؤدي الاتصال بالرقم showAlert باستخدام Alert يتضمّن قيمة alertId مشابه لرقم تعريف Alert المعروض حاليًا إلى تنفيذ أي إجراء. ولا يتم تعديل "Alert". لتعديل Alert، يجب إعادة إنشاؤه باستخدام alertId جديد.
  • يؤدي الاتصال بـ showAlert باستخدام Alert يتضمن alertId بطريقة مختلفة عن Alert المعروضة حاليًا إلى إزالة Alert المعروض حاليًا.

إغلاق تنبيه

على الرغم من أنّ Alert يتم إغلاقها تلقائيًا بسبب انتهاء المهلة أو تفاعل السائق، يمكنك أيضًا إغلاق Alert يدويًا، مثلاً إذا أصبحت معلوماتها قديمة. لإغلاق Alert، يمكنك استدعاء الطريقة dismissAlert مع alertId من Alert.

// Dismiss the same alert
carContext.getCarService(AppManager.class).dismissAlert(alert.getId())

لا يؤدي الاتصال بالرقم dismissAlert باستخدام alertId غير مطابق للسمة Alert المعروضة حاليًا إلى عدم اتخاذ أي إجراء. ولا يقدم استثناء.