يوضّح هذا القسم كيفية استخدام IDE SDK مع مكتبة تطبيقات "Android للسيارات" لعرض تجربة التنقّل في تطبيقك على وحدات الشاشة المتعلّقة بالسيارة في لوحة القيادة. إذا كان نظام شاشة السيارة لدى المستخدم متوافقًا مع Android Auto، يمكن للمستخدمين استخدام تطبيقك مباشرةً على شاشة السيارة من خلال ربط هواتفهم بالوحدة. يتم أيضًا تشغيل الإرشاد الصوتي من خلال مكبّرات الصوت في السيارة.
تتيح مكتبة التطبيقات المخصّصة لنظام التشغيل Android في السيارات تشغيل تطبيقات Android على Android Auto من خلال توفير مجموعة من نماذج رسومات مصوّرة تمت الموافقة عليها للحفاظ على أمان السائق. تحدّ هذه النماذج عمدًا من عناصر التحكّم في واجهة المستخدم في لوحة البيانات عن تلك الموجودة في الهاتف لتقليل انتباه السائق.
عند تفعيل تطبيقك المستنِد إلى حزمة تطوير البرامج (SDK) للتنقّل للعمل مع Android Auto، تقدّم عرضًا إضافيًا لتجربة التنقّل.
يسمح هذا الإجراء بعرضي خريطة، أحدهما للهاتف والآخر للوحدة الرئيسية. تتلقّى كلّ من
العروض إرشادات من Navigator.java
، وهو عنصر فريد.
يعرض النظام داخل لوحة البيانات العناصر التفاعلية المعتمدة على السلامة حتى يتمكّن المستخدم من الانتقال بأمان إلى وجهته بدون تشتيت غير مبرر. يمكن للمستخدم أيضًا التفاعل مع وظائف تطبيقك، مثل قبول الطلبات أو رفضها، أو عرض الموقع الجغرافي للعميل على الخريطة. يمكن أن تظهر تعديلات حالة الطلبات أيضًا في وحدة لوحة البيانات.
يمكن للهاتف المُرفَق مواصلة عرض تجربة حزمة تطوير البرامج (SDK) لنظام التنقّل العادية أو أي عرض أو عملية أخرى في تطبيقك. يتيح لك ذلك مواصلة توفير وظائف مخصّصة قد لا تعمل بشكل جيد على شاشة السيارة.
إعداد
يتضمن الجزء الأول من جعل تطبيقك متوافقًا مع Android Auto إعداد خدمة سيارة باستخدام Android Auto ثم تفعيل مكتبة TurnByTurn في تطبيق Navigation SDK.
بدء استخدام Android Auto
قبل بدء استخدام ميزات حزمة تطوير البرامج (SDK) لنظام التنقّل المصمّمة للعمل مع Android Auto، عليك إعداد خدمة سيارة لتطبيقك حتى يتمكّن Android Auto من اكتشافه.
اتبع هذه الخطوات والتي يمكن العثور عليها جميعًا في مستندات Android للسيارات:
- تعرَّف على الميزات الأساسية في Android Auto.
- ثبِّت مكتبة تطبيقات "Android للسيارات".
- اضبط ملف بيان تطبيقك لتضمين Android Auto.
- حدِّد مستوى 1 على الأقل لتطبيق السيارة في ملف البيان.
- أنشئ
CarAppService
وجلستك.
إعداد حزمة تطوير البرامج (SDK) للتنقّل
بعد إنشاء خدمة تطبيق السيارة، ستكون مستعدًا للعمل مع IDE SDK.
- إعداد مشروعك، إذا لم يسبق لك دمج حزمة SDK للتنقّل في تطبيقك
- عليك تفعيل خلاصة إرشادات TurnbyTurn لتطبيقك.
- اختياريّ. استخدام الرموز التي تم إنشاؤها من حزمة تطوير البرامج (SDK) لتطبيق Navigation
- ارسم
الخريطة
باستخدام فئة
NavigationViewForAuto
على سطح Android Auto المقدَّم في فئةScreen
. - تعبئة نموذج "التنقّل في Android Auto" بالبيانات من مكتبة TurnbyTurn
بعد أن أصبح لديك خدمة مسجَّلة لتوفير معلومات التنقّل في تطبيقك وبإمكان التطبيق ربطه بميزة Android Auto، أصبحت جاهزًا لإنشاء بقية عناصر التنقّل اللازمة لكي يعمل التطبيق بشكل صحيح مع Android Auto:
- رسم الخريطة وواجهة المستخدم الخاصة بالتنقّل
- تفعيل التفاعل مع الخريطة
- عرض اتجاهات التنقّل
- التأكّد من أنواع المناورات الصحيحة
رسم واجهة مستخدِم الخريطة والتنقّل
تعرض الفئة NavigationViewForAuto
واجهة المستخدم للخريطة والتنقّل على شاشات Android Auto. ويقدّم هذا الإصدار الكثير من الوظائف نفسها التي يوفّرها NavigationView
للهواتف، ولكن مع تفاعل محدود. استخدِم NavigationViewForAuto
للرسم
على
السطح
الذي يوفّره Android Auto:
private boolean isSurfaceReady(SurfaceContainer surfaceContainer) {
return surfaceContainer.getSurface() != null
&& surfaceContainer.getDpi() != 0
&& surfaceContainer.getHeight() != 0
&& surfaceContainer.getWidth() != 0;
}
@Override
public void onSurfaceAvailable(@NonNull SurfaceContainer surfaceContainer) {
if (!isSurfaceReady(surfaceContainer)) {
return;
}
virtualDisplay =
getCarContext()
.getSystemService(DisplayManager.class)
.createVirtualDisplay(
VIRTUAL_DISPLAY_NAME,
surfaceContainer.getWidth(),
surfaceContainer.getHeight(),
surfaceContainer.getDpi(),
surfaceContainer.getSurface(),
DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY);
presentation = new Presentation(getCarContext(), virtualDisplay.getDisplay());
navigationView = new NavigationViewForAuto(getCarContext());
navigationView.onCreate(null);
navigationView.onStart();
navigationView.onResume();
presentation.setContentView(navigationView);
presentation.show();
navigationView.getMapAsync(googleMap -> this.googleMap = googleMap);
}
@Override
public void onSurfaceDestroyed(@NonNull SurfaceContainer surfaceContainer) {
navigationView.onPause();
navigationView.onStop();
navigationView.onDestroy();
presentation.dismiss();
virtualDisplay.release();
}
تفعيل التفاعل مع الخريطة
لضمان سلامة السائق، يحدّ Android Auto من تفاعل سطح الشاشة مع سلسلة من طرق
SurfaceCallback. استخدِم طلبات الاستدعاء هذه للسماح للسائق بالتفاعل بشكل محدود مع الخريطة
على شاشة في لوحة القيادة. على سبيل المثال، يتوافق الرمزان onClick
وonScale
مع إيماءات النقر
والتصغير/التكبير التي ينفّذها المستخدم. يجب أن تستخدم استدعاءات التفاعل شريط إجراء الخريطة
على النحو التالي:
لتلقّي عمليات الاستدعاء المتعلّقة بالتفاعل مع الخريطة، يجب أن يستخدم تطبيقك زر Action.PAN.
لإتاحة إجراءات إضافية للمستخدم، أضِف أزرارًا إلى شريط إجراءات الخريطة.
تفعيل عمليات الاستدعاء على السطح
@NonNull
@Override
public Template onGetTemplate() {
return new NavigationTemplate.Builder()
.setActionStrip(new ActionStrip.Builder().build())
.setMapActionStrip(new ActionStrip.Builder().addAction(Action.PAN).build())
.build();
}
التكبير أو التصغير بإصبعَين
@Override
public void onScale(float focusX, float focusY, float scaleFactor) {
CameraUpdate update =
CameraUpdateFactory.zoomBy((scaleFactor - 1),
new Point((int) focusX, (int) focusY));
googleMap.animateCamera(update); // map is set in onSurfaceAvailable.
}
التصوير السينمائي
@Override
public void onScroll(float distanceX, float distanceY) {
googleMap.moveCamera(CameraUpdateFactory.scrollBy(distanceX, distanceY));
}
عرض اتجاهات التنقّل
يتناول هذا القسم كيفية إعداد مراقب لمشاركات التنقل وملء اتجاهات التنقل في قالب بطاقة الدوران.
يوفر نموذج التنقل في Android Auto بطاقة انعطاف تعرض معلومات التنقل ذات الصلة بالرحلة الحالية. وتوفر مكتبة TurnByTurn في حزمة تطوير البرامج (SDK) الخاصة بالتنقل هذه المعلومات التي يستخدمها الرمز الخاص بك لملء نموذج التنقل Android Auto.
إعداد "مراقب"
في المثال التالي، SampleApplication هي فئة تطبيق مخصّصة تحتفظ بكائن MutableLiveData<NavInfo>
. عندما يتلقّى المراقب
تعديلًا من عنصر المتصفّح، ينشر عنصر NavInfo
هذا في NavInfoMutableLiveData
الذي تديره فئة SampleApplication
.
يسجِّل المثال التالي مراقبًا لهذا العنصر في تنفيذه لشاشة Android Auto.
public SampleAndroidAutoNavigationScreen(@NonNull CarContext carContext,
SampleApplication application) {
super(carContext);
getCarContext().getCarService(AppManager.class).setSurfaceCallback(this);
application.getNavInfoMutableLiveData().observe(this, this::processNextStep);
}
تعبئة معلومات التنقّل
يوضّح مقتطف الرمز التالي كيفية تعبئة نموذج Android Auto باستخدام معلومات المسار الحالية، بما في ذلك الخطوات والمسافات والرموز. يمكنك الاطّلاع على المزيد من المعلومات حول عناصر العرض هذه في ملء عرض الخلاصة.
وسِّع القسم للاطّلاع على مثال الرمز البرمجي.
private RoutingInfo currentRoutingInfo; @NonNull @Override public Template onGetTemplate() { NavigationTemplate.Builder navigationTemplateBuilder = new NavigationTemplate.Builder() .setActionStrip(...) .setMapActionStrip(...) if (currentRoutingInfo != null) { navigationTemplateBuilder.setNavigationInfo(currentRoutingInfo); } return navigationTemplateBuilder.build(); } private void processNextStep(NavInfo navInfo) { if (navInfo == null || navinfo.getCurrentStep() == null) { return; } /** * Converts data received from the Navigation data feed * into Android-Auto compatible data structures. For more information * see the "Ensure correct maneuver types" below. */ Step currentStep = buildStepFromStepInfo(navInfo.getCurrentStep()); Distance distanceToStep = buildDistanceFromMeters(navInfo.getDistanceToCurrentStepMeters()); currentRoutingInfo = new RoutingInfo.Builder().setCurrentStep(currentStep, distanceToStep).build(); // Invalidate the current template which leads to another onGetTemplate call. invalidate(); } private Step buildStepFromStepInfo(StepInfo stepInfo) { IconCompat maneuverIcon = IconCompat.createWithBitmap(stepInfo.getManeuverBitmap()); Maneuver.Builder maneuverBuilder = newManeuver.Builder( ManeuverConverter .getAndroidAutoManeuverType(stepInfo.getManeuver())); CarIcon maneuverCarIcon = new CarIcon.Builder(maneuverIcon).build(); maneuverBuilder.setIcon(maneuverCarIcon); Step.Builder stepBuilder = new Step.Builder() .setRoad(stepInfo.getFullRoadName()) .setCue(stepInfo.getFullInstructionText()) .setManeuver(maneuverBuilder.build()); if (stepInfo.getLanes() != null && stepInfo.getLanesBitmap() != null) { for (Lane lane : buildAndroidAutoLanesFromStep(stepInfo)) { stepBuilder.addLane(lane); } IconCompat lanesIcon = IconCompat.createWithBitmap(stepInfo.getLanesBitmap()); CarIcon lanesImage = new CarIcon.Builder(lanesIcon).build(); stepBuilder.setLanesImage(lanesImage); } return stepBuilder.build(); } /* * Constructs a {@code Distance} object in imperial measurement units. * In a real world scenario, units would be based on locale. */ private Distance buildDistanceFromMeters(int distanceMeters) { // Distance can be negative so set the min distance to 0. int remainingFeet = (int) max(0, distanceMeters * DistanceConstants.FEET_PER_METER); double remainingMiles = ((double) remainingFeet) / DistanceConstants.FEET_PER_MILE; // Only use the tenths place digit if distance is less than 10 miles and show // feet if distance is less than 0.25 miles. if (remainingMiles >= DistanceConstants.MIN_MILES_TO_SHOW_INTEGER) { return Distance.create((int) round(remainingMiles), Distance.UNIT_MILES); } else if (remainingMiles >= 0.25) { return Distance.create((int) remainingMiles, Distance.UNIT_MILES); } else { return Distance.create(remainingFeet, Distance.UNIT_FEET); } }
التأكّد من صحة أنواع المناورة
تتطابق أنواع المناورات المستخدَمة في مكتبة Android Auto Car واحدة تلو الأخرى مع المناورات المقدَّمة من مكتبة TurnByTurn. ومع ذلك، يجب عليك تحويل مناورات حزمة تطوير البرامج (SDK) للتنقل إلى بيان صالح في مكتبة Android Auto Car. يعرض الجدول التالي التطابق لعدد من الحقول، متبوعًا بعينة من أدوات التحويل لراحتك.
اتّجاهات مفصّلة للتنقّل في المكتبة | مناورة Android Auto |
---|---|
DEPART |
TYPE_DEPART |
DESTINATION |
TYPE_DESTINATION |
DESTINATION_LEFT |
TYPE_DESTINATION_LEFT |
DESTINATION_RIGHT |
TYPE_DESTINATION_RIGHT |
TURN_U_TURN_CLOCKWISE |
TYPE_U_TURN_RIGHT |
ON_RAMP_LEFT |
TYPE_ON_RAMP_NORMAL_LEFT |
ON_RAMP_RIGHT |
TYPE_ON_RAMP_NORMAL_RIGHT |
ON_RAMP_SLIGHT_LEFT |
TYPE_ON_RAMP_SLIGHT_LEFT |
FORK_RIGHT |
TYPE_FORK_RIGHT |
وسِّع هذا القسم للاطّلاع على مثال الرمز البرمجي.
import com.google.android.libraries.mapsplatform.turnbyturn.model.Maneuver; import com.google.common.collect.ImmutableMap; import javax.annotation.Nullable; /** Converter that converts between turn-by-turn and Android Auto Maneuvers. */ public final class ManeuverConverter { private ManeuverConverter() {} // Map from turn-by-turn Maneuver to Android Auto Maneuver.Type. private static final ImmutableMap<Integer, Integer> MANEUVER_TO_ANDROID_AUTO_MANEUVER_TYPE = ImmutableMap.<Integer, Integer>builder() .put(Maneuver.DEPART, androidx.car.app.navigation.model.Maneuver.TYPE_DEPART) .put(Maneuver.DESTINATION, androidx.car.app.navigation.model.Maneuver.TYPE_DESTINATION) .put( Maneuver.DESTINATION_LEFT, androidx.car.app.navigation.model.Maneuver.TYPE_DESTINATION_LEFT) .put( Maneuver.DESTINATION_RIGHT, androidx.car.app.navigation.model.Maneuver.TYPE_DESTINATION_RIGHT) .put(Maneuver.STRAIGHT, androidx.car.app.navigation.model.Maneuver.TYPE_STRAIGHT) .put(Maneuver.TURN_LEFT, androidx.car.app.navigation.model.Maneuver.TYPE_TURN_NORMAL_LEFT) .put( Maneuver.TURN_RIGHT, androidx.car.app.navigation.model.Maneuver.TYPE_TURN_NORMAL_RIGHT) .put(Maneuver.TURN_KEEP_LEFT, androidx.car.app.navigation.model.Maneuver.TYPE_KEEP_LEFT) .put(Maneuver.TURN_KEEP_RIGHT, androidx.car.app.navigation.model.Maneuver.TYPE_KEEP_RIGHT) .put( Maneuver.TURN_SLIGHT_LEFT, androidx.car.app.navigation.model.Maneuver.TYPE_TURN_SLIGHT_LEFT) .put( Maneuver.TURN_SLIGHT_RIGHT, androidx.car.app.navigation.model.Maneuver.TYPE_TURN_SLIGHT_RIGHT) .put( Maneuver.TURN_SHARP_LEFT, androidx.car.app.navigation.model.Maneuver.TYPE_TURN_SHARP_LEFT) .put( Maneuver.TURN_SHARP_RIGHT, androidx.car.app.navigation.model.Maneuver.TYPE_ON_RAMP_SHARP_RIGHT) .put( Maneuver.TURN_U_TURN_CLOCKWISE, androidx.car.app.navigation.model.Maneuver.TYPE_U_TURN_RIGHT) .put( Maneuver.TURN_U_TURN_COUNTERCLOCKWISE, androidx.car.app.navigation.model.Maneuver.TYPE_U_TURN_LEFT) .put( Maneuver.MERGE_UNSPECIFIED, androidx.car.app.navigation.model.Maneuver.TYPE_MERGE_SIDE_UNSPECIFIED) .put(Maneuver.MERGE_LEFT, androidx.car.app.navigation.model.Maneuver.TYPE_MERGE_LEFT) .put(Maneuver.MERGE_RIGHT, androidx.car.app.navigation.model.Maneuver.TYPE_MERGE_RIGHT) .put(Maneuver.FORK_LEFT, androidx.car.app.navigation.model.Maneuver.TYPE_FORK_LEFT) .put(Maneuver.FORK_RIGHT, androidx.car.app.navigation.model.Maneuver.TYPE_FORK_RIGHT) .put( Maneuver.ON_RAMP_UNSPECIFIED, androidx.car.app.navigation.model.Maneuver.TYPE_ON_RAMP_NORMAL_RIGHT) .put( Maneuver.ON_RAMP_LEFT, androidx.car.app.navigation.model.Maneuver.TYPE_ON_RAMP_NORMAL_LEFT) .put( Maneuver.ON_RAMP_RIGHT, androidx.car.app.navigation.model.Maneuver.TYPE_ON_RAMP_NORMAL_RIGHT) .put( Maneuver.ON_RAMP_KEEP_LEFT, androidx.car.app.navigation.model.Maneuver.TYPE_ON_RAMP_NORMAL_LEFT) .put( Maneuver.ON_RAMP_KEEP_RIGHT, androidx.car.app.navigation.model.Maneuver.TYPE_ON_RAMP_NORMAL_RIGHT) .put( Maneuver.ON_RAMP_SLIGHT_LEFT, androidx.car.app.navigation.model.Maneuver.TYPE_ON_RAMP_SLIGHT_LEFT) .put( Maneuver.ON_RAMP_SLIGHT_RIGHT, androidx.car.app.navigation.model.Maneuver.TYPE_ON_RAMP_SLIGHT_RIGHT) .put( Maneuver.ON_RAMP_SHARP_LEFT, androidx.car.app.navigation.model.Maneuver.TYPE_ON_RAMP_SHARP_LEFT) .put( Maneuver.ON_RAMP_SHARP_RIGHT, androidx.car.app.navigation.model.Maneuver.TYPE_ON_RAMP_SHARP_RIGHT) .put( Maneuver.ON_RAMP_U_TURN_CLOCKWISE, androidx.car.app.navigation.model.Maneuver.TYPE_ON_RAMP_U_TURN_RIGHT) .put( Maneuver.ON_RAMP_U_TURN_COUNTERCLOCKWISE, androidx.car.app.navigation.model.Maneuver.TYPE_ON_RAMP_U_TURN_LEFT) .put( Maneuver.OFF_RAMP_LEFT, androidx.car.app.navigation.model.Maneuver.TYPE_OFF_RAMP_NORMAL_LEFT) .put( Maneuver.OFF_RAMP_RIGHT, androidx.car.app.navigation.model.Maneuver.TYPE_OFF_RAMP_NORMAL_RIGHT) .put( Maneuver.OFF_RAMP_KEEP_LEFT, androidx.car.app.navigation.model.Maneuver.TYPE_OFF_RAMP_SLIGHT_LEFT) .put( Maneuver.OFF_RAMP_KEEP_RIGHT, androidx.car.app.navigation.model.Maneuver.TYPE_OFF_RAMP_SLIGHT_RIGHT) .put( Maneuver.OFF_RAMP_SLIGHT_LEFT, androidx.car.app.navigation.model.Maneuver.TYPE_OFF_RAMP_SLIGHT_LEFT) .put( Maneuver.OFF_RAMP_SLIGHT_RIGHT, androidx.car.app.navigation.model.Maneuver.TYPE_OFF_RAMP_SLIGHT_RIGHT) .put( Maneuver.OFF_RAMP_SHARP_LEFT, androidx.car.app.navigation.model.Maneuver.TYPE_OFF_RAMP_NORMAL_LEFT) .put( Maneuver.OFF_RAMP_SHARP_RIGHT, androidx.car.app.navigation.model.Maneuver.TYPE_OFF_RAMP_NORMAL_RIGHT) .put( Maneuver.ROUNDABOUT_CLOCKWISE, androidx.car.app.navigation.model.Maneuver.TYPE_ROUNDABOUT_ENTER_AND_EXIT_CW) .put( Maneuver.ROUNDABOUT_COUNTERCLOCKWISE, androidx.car.app.navigation.model.Maneuver.TYPE_ROUNDABOUT_ENTER_AND_EXIT_CCW) .put( Maneuver.ROUNDABOUT_STRAIGHT_CLOCKWISE, androidx.car.app.navigation.model.Maneuver.TYPE_ROUNDABOUT_ENTER_CW) .put( Maneuver.ROUNDABOUT_STRAIGHT_COUNTERCLOCKWISE, androidx.car.app.navigation.model.Maneuver.TYPE_ROUNDABOUT_ENTER_CCW) .put( Maneuver.ROUNDABOUT_LEFT_CLOCKWISE, androidx.car.app.navigation.model.Maneuver .TYPE_ROUNDABOUT_ENTER_AND_EXIT_CW_WITH_ANGLE) .put( Maneuver.ROUNDABOUT_LEFT_COUNTERCLOCKWISE, androidx.car.app.navigation.model.Maneuver .TYPE_ROUNDABOUT_ENTER_AND_EXIT_CCW_WITH_ANGLE) .put( Maneuver.ROUNDABOUT_RIGHT_CLOCKWISE, androidx.car.app.navigation.model.Maneuver .TYPE_ROUNDABOUT_ENTER_AND_EXIT_CW_WITH_ANGLE) .put( Maneuver.ROUNDABOUT_RIGHT_COUNTERCLOCKWISE, androidx.car.app.navigation.model.Maneuver .TYPE_ROUNDABOUT_ENTER_AND_EXIT_CCW_WITH_ANGLE) .put( Maneuver.ROUNDABOUT_SLIGHT_LEFT_CLOCKWISE, androidx.car.app.navigation.model.Maneuver .TYPE_ROUNDABOUT_ENTER_AND_EXIT_CW_WITH_ANGLE) .put( Maneuver.ROUNDABOUT_SLIGHT_LEFT_COUNTERCLOCKWISE, androidx.car.app.navigation.model.Maneuver .TYPE_ROUNDABOUT_ENTER_AND_EXIT_CCW_WITH_ANGLE) .put( Maneuver.ROUNDABOUT_SLIGHT_RIGHT_CLOCKWISE, androidx.car.app.navigation.model.Maneuver .TYPE_ROUNDABOUT_ENTER_AND_EXIT_CW_WITH_ANGLE) .put( Maneuver.ROUNDABOUT_SLIGHT_RIGHT_COUNTERCLOCKWISE, androidx.car.app.navigation.model.Maneuver .TYPE_ROUNDABOUT_ENTER_AND_EXIT_CCW_WITH_ANGLE) .put( Maneuver.ROUNDABOUT_SHARP_LEFT_CLOCKWISE, androidx.car.app.navigation.model.Maneuver .TYPE_ROUNDABOUT_ENTER_AND_EXIT_CW_WITH_ANGLE) .put( Maneuver.ROUNDABOUT_SHARP_LEFT_COUNTERCLOCKWISE, androidx.car.app.navigation.model.Maneuver .TYPE_ROUNDABOUT_ENTER_AND_EXIT_CCW_WITH_ANGLE) .put( Maneuver.ROUNDABOUT_SHARP_RIGHT_CLOCKWISE, androidx.car.app.navigation.model.Maneuver .TYPE_ROUNDABOUT_ENTER_AND_EXIT_CW_WITH_ANGLE) .put( Maneuver.ROUNDABOUT_SHARP_RIGHT_COUNTERCLOCKWISE, androidx.car.app.navigation.model.Maneuver .TYPE_ROUNDABOUT_ENTER_AND_EXIT_CCW_WITH_ANGLE) .put( Maneuver.ROUNDABOUT_U_TURN_CLOCKWISE, androidx.car.app.navigation.model.Maneuver .TYPE_ROUNDABOUT_ENTER_AND_EXIT_CW_WITH_ANGLE) .put( Maneuver.ROUNDABOUT_U_TURN_COUNTERCLOCKWISE, androidx.car.app.navigation.model.Maneuver .TYPE_ROUNDABOUT_ENTER_AND_EXIT_CCW_WITH_ANGLE) .put( Maneuver.ROUNDABOUT_EXIT_CLOCKWISE, androidx.car.app.navigation.model.Maneuver.TYPE_ROUNDABOUT_EXIT_CW) .put( Maneuver.ROUNDABOUT_EXIT_COUNTERCLOCKWISE, androidx.car.app.navigation.model.Maneuver.TYPE_ROUNDABOUT_EXIT_CCW) .put(Maneuver.FERRY_BOAT, androidx.car.app.navigation.model.Maneuver.TYPE_FERRY_BOAT) .put(Maneuver.FERRY_TRAIN, androidx.car.app.navigation.model.Maneuver.TYPE_FERRY_TRAIN) .put(Maneuver.NAME_CHANGE, androidx.car.app.navigation.model.Maneuver.TYPE_NAME_CHANGE) .buildOrThrow(); /** Represents the roundabout turn angle for a slight turn in either right or left directions. */ private static final int ROUNDABOUT_ANGLE_SLIGHT = 10; /** Represents the roundabout turn angle for a normal turn in either right or left directions. */ private static final int ROUNDABOUT_ANGLE_NORMAL = 45; /** Represents the roundabout turn angle for a sharp turn in either right or left directions. */ private static final int ROUNDABOUT_ANGLE_SHARP = 135; /** Represents the roundabout turn angle for a u-turn in either right or left directions. */ private static final int ROUNDABOUT_ANGLE_U_TURN = 180; /** * Returns the corresponding {@link androidx.car.app.navigation.model.Maneuver.Type} for the given * direction {@link Maneuver} * * @throws {@link IllegalArgumentException} if the given maneuver does not have a corresponding * Android Auto Maneuver type. */ public static int getAndroidAutoManeuverType(@Maneuver int maneuver) { if (MANEUVER_TO_ANDROID_AUTO_MANEUVER_TYPE.containsKey(maneuver)) { return MANEUVER_TO_ANDROID_AUTO_MANEUVER_TYPE.get(maneuver); } throw new IllegalArgumentException( String.format( "Given turn-by-turn Maneuver %d cannot be converted to an Android Auto equivalent.", maneuver)); } /** * Returns the corresponding Android Auto roundabout angle for the given turn {@link Maneuver}. * Returns {@code null} if given maneuver does not involve a roundabout with a turn. */ @Nullable public static Integer getAndroidAutoRoundaboutAngle(@Maneuver int maneuver) { if (maneuver == Maneuver.ROUNDABOUT_LEFT_CLOCKWISE || maneuver == Maneuver.ROUNDABOUT_RIGHT_CLOCKWISE || maneuver == Maneuver.ROUNDABOUT_LEFT_COUNTERCLOCKWISE || maneuver == Maneuver.ROUNDABOUT_RIGHT_COUNTERCLOCKWISE) { return ROUNDABOUT_ANGLE_NORMAL; } if (maneuver == Maneuver.ROUNDABOUT_SHARP_LEFT_CLOCKWISE || maneuver == Maneuver.ROUNDABOUT_SHARP_RIGHT_CLOCKWISE || maneuver == Maneuver.ROUNDABOUT_SHARP_LEFT_COUNTERCLOCKWISE || maneuver == Maneuver.ROUNDABOUT_SHARP_RIGHT_COUNTERCLOCKWISE) { return ROUNDABOUT_ANGLE_SHARP; } if (maneuver == Maneuver.ROUNDABOUT_SLIGHT_LEFT_CLOCKWISE || maneuver == Maneuver.ROUNDABOUT_SLIGHT_RIGHT_CLOCKWISE || maneuver == Maneuver.ROUNDABOUT_SLIGHT_LEFT_COUNTERCLOCKWISE || maneuver == Maneuver.ROUNDABOUT_SLIGHT_RIGHT_COUNTERCLOCKWISE) { return ROUNDABOUT_ANGLE_SLIGHT; } if (maneuver == Maneuver.ROUNDABOUT_U_TURN_CLOCKWISE || maneuver == Maneuver.ROUNDABOUT_U_TURN_COUNTERCLOCKWISE) { return ROUNDABOUT_ANGLE_U_TURN; } return null; } }
مستندات ذات صلة
- تفعيل خلاصة الإرشادات المفصّلة: عليك دمج وظائف الإرشادات المفصّلة أولاً حتى يعمل تطبيقك مع Android Auto.
- ملء شاشة عرض الخلاصة: يمكنك الوصول إلى حقول البيانات للحصول على معلومات إرشادية واستخدام الرموز.