ส่วนนี้จะอธิบายวิธีใช้ Navigation SDK กับไลบรารีแอป Android สำหรับรถยนต์เพื่อ แสดงประสบการณ์การนำทางของแอปในเครื่องเสียงติดรถยนต์ติด รถ หากระบบในรถยนต์ของผู้ใช้รองรับ Android Auto ผู้ใช้จะใช้แอปของคุณบนจอแสดงผลของรถได้โดยตรงด้วยการเชื่อมต่อโทรศัพท์กับเครื่องเสียง การนำทางด้วยเสียงจะทำงานบนลำโพงของรถด้วย
ไลบรารีแอป Android สำหรับรถยนต์ ช่วยให้แอปพลิเคชัน Android ทำงานบน Android Auto ได้โดยมีเทมเพลตภาพ ที่ได้รับอนุมัติเพื่อความปลอดภัยของผู้ขับขี่ เทมเพลตเหล่านี้จำกัดการควบคุม UI ในแผงควบคุมจากโทรศัพท์โดยมีจุดประสงค์เพื่อลดสิ่งรบกวนสมาธิของผู้ขับขี่
เมื่อเปิดใช้แอปที่ขับเคลื่อนโดย Navigation SDK ให้ทำงานร่วมกับ Android Auto คุณจะได้รับมุมมองเพิ่มเติมสำหรับประสบการณ์การนำทาง
ซึ่งจะช่วยให้มีมุมมองแผนที่ 2 มุมมอง ได้แก่ มุมมองสำหรับโทรศัพท์และมุมมองสำหรับเครื่องเล่นวิทยุ จอแสดงผลทั้ง 2 จอจะได้รับคำแนะนำจาก Navigator.java ซึ่งเป็นซิงเกิลตัน
ระบบในแผงควบคุมจะแสดงองค์ประกอบแบบอินเทอร์แอกทีฟที่ได้รับอนุมัติเพื่อความปลอดภัย เพื่อให้ผู้ใช้ไปยังจุดหมายได้อย่างปลอดภัยโดยไม่มีสิ่งรบกวนสมาธิมากเกินไป นอกจากนี้ ผู้ใช้ยังโต้ตอบกับฟังก์ชันการทำงานเฉพาะของแอปได้ด้วย เช่น การยอมรับหรือปฏิเสธคำสั่งซื้อ หรือการดูตำแหน่งของลูกค้าบนแผนที่ การอัปเดตสถานะการสั่งซื้ออาจปรากฏในเครื่องเสียงติดรถยนต์ด้วย
โทรศัพท์ที่เชื่อมต่อจะแสดงประสบการณ์การใช้งาน Navigation SDK มาตรฐาน หรือมุมมองหรือเวิร์กโฟลว์อื่นๆ ในแอปพลิเคชันต่อไปได้ ฟีเจอร์นี้ช่วยให้คุณยังคงมอบฟังก์ชันการทำงานที่กำหนดเองซึ่งอาจทำงานได้ไม่ดีบนหน้าจอรถ
ตั้งค่า
ส่วนแรกของการทำให้แอปทำงานร่วมกับ Android Auto คือการตั้งค่าบริการรถยนต์ด้วย Android Auto แล้วเปิดใช้ไลบรารี TurnByTurn ในแอป Navigation SDK
เริ่มต้นด้วย Android Auto
ก่อนที่จะเริ่มใช้ฟีเจอร์ Navigation SDK ที่ออกแบบมาให้ทำงานร่วมกับ Android Auto คุณต้องตั้งค่าบริการรถยนต์สำหรับแอปเพื่อให้ Android Auto ค้นพบแอปได้
ทำตามขั้นตอนต่อไปนี้ ซึ่งทั้งหมดอยู่ในเอกสารประกอบสำหรับนักพัฒนาแอป Android สำหรับ รถยนต์:
- ทำความคุ้นเคย กับฟีเจอร์พื้นฐานของ Android Auto
- ติดตั้ง ไลบรารีแอป Android สำหรับรถยนต์
- กำหนดค่า ไฟล์ Manifest ของแอปให้มี Android Auto
- ประกาศ ระดับ car-app ขั้นต่ำเป็น 1 ในไฟล์ Manifest
- สร้าง
ของคุณ
CarAppServiceและเซสชัน
ตั้งค่า Navigation SDK
เมื่อสร้างบริการแอปสำหรับรถยนต์แล้ว คุณก็พร้อมที่จะใช้ Navigation SDK
- ตั้งค่าโปรเจ็กต์ หาก ยังไม่ได้ผสานรวม Navigation SDK เข้ากับแอป
- เปิดใช้ฟีดคำแนะนำแบบ Turn-by-Turn สำหรับแอป
- ไม่บังคับ ใช้ไอคอนที่สร้าง จาก Navigation SDK
- วาดแผนที่
โดยใช้คลาส
NavigationViewForAutoบน Surface ของ Android Auto ที่มีให้ ในคลาสScreen - ป้อนข้อมูลจากไลบรารี TurnByTurn ลงในเทมเพลตการนำทางของ Android Auto
ตอนนี้คุณมีบริการที่ลงทะเบียนไว้สำหรับให้ข้อมูลการนำทางแก่แอป และแอปของคุณเชื่อมต่อกับ Android Auto ได้แล้ว คุณก็พร้อมที่จะสร้างองค์ประกอบการนำทางอื่นๆ ที่จำเป็นเพื่อให้แอปทำงานร่วมกับ Android Auto ได้อย่างถูกต้อง
- วาดแผนที่และ UI การนำทาง
- เปิดใช้การโต้ตอบกับแผนที่
- แสดงคำแนะนำการนำทาง
- ตรวจสอบว่าประเภทการเลี้ยวถูกต้อง
วาดแผนที่และ UI การนำทาง
คลาส NavigationViewForAuto จะแสดงแผนที่และ UI การนำทางบนหน้าจอ Android Auto โดยมีฟังก์ชันการทำงานส่วนใหญ่เหมือนกับ NavigationView สำหรับโทรศัพท์ แต่มีการโต้ตอบที่จำกัด ใช้ NavigationViewForAuto เพื่อวาด
ลงบน
Surface
ที่ 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 จะจำกัดการโต้ตอบกับ Surface ของหน้าจอไว้ที่ชุดเมธอด
SurfaceCallback
ใช้การเรียกกลับเหล่านี้เพื่อรองรับการโต้ตอบที่จำกัดของผู้ขับขี่กับแผนที่บนหน้าจอในแผงควบคุม ตัวอย่างเช่น onClick และ onScale จะสอดคล้องกับท่าทาง แตะ และ บีบ จากผู้ใช้ การเรียกกลับแบบอินเทอร์แอกทีฟต้องใช้ แผนที่
การดำเนินการ
แถบ
ดังนี้
หากต้องการรับการเรียกกลับแบบอินเทอร์แอกทีฟของแผนที่ แอปของคุณต้องใช้ปุ่ม Action.PAN
หากต้องการรองรับการดำเนินการเพิ่มเติมของผู้ใช้ ให้เพิ่มปุ่มลงในแถบการทำงานบนแผนที่
เปิดใช้การเรียกกลับของ Surface
@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));
}
แสดงคำแนะนำการนำทาง
ส่วนนี้จะกล่าวถึงวิธีตั้งค่า Observer สำหรับโพสต์การนำทางและป้อนข้อมูลคำแนะนำการนำทางลงในเทมเพลตการ์ดการเลี้ยว
เทมเพลตการนำทางของ Android Auto มีการ์ดการเลี้ยวที่แสดงข้อมูลการนำทางที่เกี่ยวข้องกับการเดินทางปัจจุบัน ไลบรารี TurnByTurn ใน Navigation SDK ให้ข้อมูลการนำทางนี้ ซึ่งโค้ดของคุณจะใช้เพื่อป้อนข้อมูลลงในเทมเพลตการนำทางของ Android Auto
ตั้งค่า Observer
ในตัวอย่างต่อไปนี้ SampleApplication เป็นคลาสแอปพลิเคชันที่กำหนดเองซึ่งเก็บออบเจ็กต์ MutableLiveData<NavInfo> เมื่อ Observer ได้รับการอัปเดตจากออบเจ็กต์ Navigator ระบบจะโพสต์ออบเจ็กต์ NavInfo นี้ไปยัง
NavInfoMutableLiveData ที่คลาส SampleApplication เก็บไว้
ตัวอย่างต่อไปนี้จะลงทะเบียน Observer สำหรับออบเจ็กต์นี้ในการ ติดตั้งใช้งานหน้าจอ 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 จะสอดคล้องกับการเลี้ยวที่ไลบรารี TurnByTurn มีให้แบบหนึ่งต่อหนึ่ง อย่างไรก็ตาม คุณต้องแปลงการเลี้ยวของ Navigation SDK เป็นการประกาศที่ถูกต้องในไลบรารีรถยนต์ของ Android Auto ตารางต่อไปนี้แสดงการจับคู่สำหรับช่องบางช่อง ตามด้วยยูทิลิตีตัวแปลงตัวอย่างเพื่อให้คุณใช้งานได้สะดวก
| การเลี้ยวของไลบรารี เลี้ยวต่อเลี้ยว | การเลี้ยวของ 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 ได้
- ป้อนข้อมูลลงในการแสดงผลฟีด: เข้าถึง ช่องข้อมูลสำหรับข้อมูลคำแนะนำและใช้ไอคอน