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