내비게이션 앱 빌드

이 페이지에서는 세부 경로 안내 내비게이션 앱의 기능을 구현하는 데 활용할 수 있는 자동차 앱 라이브러리의 다양한 기능을 자세하게 설명합니다.

매니페스트에서 내비게이션 지원 선언

내비게이션 앱은 CarAppService의 인텐트 필터에서 androidx.car.app.category.NAVIGATION 자동차 앱 카테고리를 선언해야 합니다.

<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 어시스턴트에서 오는 인텐트를 포함하여 앱의 내비게이션 인텐트를 지원하려면 Session.onCreateScreenSession.onNewIntent에서 CarContext.ACTION_NAVIGATE 인텐트를 처리해야 합니다.

인텐트 형식에 관한 자세한 내용은 CarContext.startCarApp 문서를 참고하세요.

내비게이션 템플릿에 액세스

내비게이션 앱은 표시 경로를 표시하는 다음 템플릿에 액세스할 수 있습니다. 지도에 백그라운드 표시, 내비게이션이 진행 중일 때는 세부 경로 안내 있습니다.

  • NavigationTemplate: 내비게이션이 진행 중일 때 선택적 정보 메시지와 예상 이동 시간도 표시합니다.
  • MapWithContentTemplate: 앱이 일종의 콘텐츠로 지도 타일을 렌더링할 수 있게 해주는 템플릿( 목록). 콘텐츠는 일반적으로 콘텐츠 위에 오버레이로 렌더링되며 지도가 표시되고 콘텐츠에 맞춰 조정되는 안정적인 영역이 있는 지도 타일

다음을 사용하여 내비게이션 앱의 사용자 인터페이스를 디자인하는 방법에 관한 자세한 내용은 내비게이션 앱을 참고하세요.

내비게이션 템플릿에 액세스하려면 앱은 AndroidManifest.xml 파일에서 androidx.car.app.NAVIGATION_TEMPLATES 권한을 선언해야 합니다.

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

지도를 그리려면 추가 권한이 필요합니다.

MapWithContentTemplate으로 이전

자동차 앱 API 수준 7부터 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()

자바

// 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()

자바

// 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();

RoutePreviewNavigationTemplate

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()

자바

// 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();

내비게이션 앱은 추가 내비게이션 메타데이터를 호스트에 전달해야 합니다. 호스트는 이 정보를 사용하여 차량 헤드 단위에 정보를 제공하고 내비게이션 애플리케이션이 공유 리소스를 두고 충돌하는 것을 방지합니다.

내비게이션 메타데이터는 CarContext에서 액세스할 수 있는 NavigationManager 자동차 서비스를 통해 제공됩니다.

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)를 대신 사용하세요.

호스트에서 앱의 내비게이션 중지가 필요하여 NavigationManager.setNavigationManagerCallback를 통해 앱이 제공하는 NavigationManagerCallback 객체에서 onStopNavigation을 호출하는 경우도 있습니다. 그러면 앱은 계기판 디스플레이, 내비게이션 알림, 음성 안내에서 다음 회전 정보 발행을 중지해야 합니다.

경로 정보 업데이트

내비게이션이 진행 중일 때 앱은 NavigationManager.updateTrip을 호출해야 합니다. 이 호출에서 제공된 정보는 차량의 계기판과 헤드업 디스플레이에서 사용할 수 있습니다. 운전하는 특정 차량에 따라 사용자에게 일부 정보가 표시되지 않을 수도 있습니다. 예를 들어 데스크톱 헤드 단위(DHU)에는 Trip에 추가된 Step이 표시되지만 Destination 정보는 표시되지 않습니다.

계기판 디스플레이에 그리기

가장 몰입도 높은 사용자 환경을 제공하기 위해 차량의 계기판 디스플레이에 기본 메타데이터를 표시하는 것 이상을 원할 수 있습니다. 자동차 앱 API 수준 6부터 내비게이션 앱에서는 자체 콘텐츠를 계기판 디스플레이(지원되는 차량)에 직접 렌더링할 수 있지만 다음과 같은 제한사항이 있습니다.

  • 계기판 디스플레이 API가 입력 컨트롤을 지원하지 않습니다.
  • 계기판 디스플레이에는 지도 타일만 표시됩니다. 원하는 경우 이 타일에 활성 경로 내비게이션을 표시할 수 있습니다.
  • 계기판 디스플레이 API는 NavigationTemplate 사용만 지원합니다.
    • 기본 디스플레이와 달리 계기판 디스플레이에는 세부 경로 안내, 도착예정시간 카드, 작업과 같은 모든 NavigationTemplate UI 요소가 일관되게 표시되지 않을 수 있습니다. 지도 타일이 일관되게 표시되는 유일한 UI 요소입니다.

계기판 지원 선언

호스트 애플리케이션에 앱이 계기판 디스플레이에서의 렌더링을 지원한다고 알리려면 CarAppService<intent-filter>androidx.car.app.category.FEATURE_CLUSTER <category> 요소를 추가해야 합니다(다음 스니펫 참고).

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

수명 주기 및 상태 관리

API 수준 6부터 자동차 앱 수명 주기 흐름이 동일하게 유지되지만 이제 CarAppService::onCreateSession이 생성 중인 Session에 관한 추가 정보(예: 디스플레이 유형, 지원되는 템플릿 집합)를 제공하는 SessionInfo 유형 매개변수를 사용합니다.

앱은 동일한 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를 호출한 후에만 계기판 디스플레이를 제어할 수 있다는 것입니다. 그러나 활성 탐색이 발생하지 않는 동안 앱에 계기판 디스플레이가 제공되거나, 계기판 디스플레이가 아예 제공되지 않을 수 있습니다. 이러한 시나리오는 앱이 앱의 유휴 상태 지도 타일을 렌더링하여 처리합니다.

호스트는 Session별로 별도의 바인더 및 CarContext 인스턴스를 생성합니다. 즉, ScreenManager::push 또는 Screen::invalidate와 같은 메서드를 사용하면 메서드가 호출되는 Session에서만 영향을 받습니다. 앱은 교차 Session 통신이 필요한 경우 이러한 인스턴스 간에 자체 통신 채널을 만들어야 합니다(예: 브로드캐스트, 공유 싱글톤 또는 다른 것을 사용하여).

계기판 지원 테스트

Android Auto와 Android Automotive OS에서 모두 구현을 테스트할 수 있습니다. Android Auto의 경우 보조 계기판 디스플레이를 에뮬레이션하도록 데스크톱 헤드 단위를 구성하면 됩니다. Android Automotive OS의 경우 API 수준 30 이상의 일반 시스템 이미지가 계기판 디스플레이를 에뮬레이션합니다.

텍스트 또는 아이콘을 사용하여 TravelEstimate 맞춤설정

텍스트 또는 아이콘으로 예상 이동 시간을 맞춤설정하려면 TravelEstimate.Builder 클래스의 setTripIcon 또는 setTripText 메서드를 사용하세요. NavigationTemplateTravelEstimate를 사용하여 도착 예정 시간, 남은 시간, 남은 거리와 함께(또는 그 대신에) 선택적으로 텍스트와 아이콘을 설정합니다.

그림 1. 맞춤 아이콘과 텍스트가 포함된 예상 이동 시간

다음 스니펫에서는 setTripIconsetTripText를 사용하여 예상 이동 시간을 맞춤설정합니다.

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();

세부 경로 안내 알림 제공

세부 경로 안내(TBT) 내비게이션 안내는 자주 업데이트되는 내비게이션 알림을 사용하여 제공합니다. 자동차 화면에서 내비게이션 알림으로 간주되려면 알림 빌더에서 다음을 실행해야 합니다.

  1. NotificationCompat.Builder.setOngoing 메서드를 사용하여 알림을 진행 중으로 표시합니다.
  2. 알림 카테고리를 Notification.CATEGORY_NAVIGATION으로 설정합니다.
  3. CarAppExtender를 사용하여 알림을 확장합니다.

내비게이션 알림은 자동차 화면 하단의 레일 위젯에 표시됩니다. 알림의 중요도 수준이 IMPORTANCE_HIGH로 설정된 경우 헤드업 알림(HUN)으로도 표시됩니다. 중요도가 CarAppExtender.Builder.setImportance 메서드를 사용하여 설정되지 않으면 알림 채널의 중요도가 사용됩니다.

앱은 사용자가 HUN이나 레일 위젯을 탭할 때 앱에 전송될 PendingIntentCarAppExtender에서 설정할 수 있습니다.

NotificationCompat.Builder.setOnlyAlertOncetrue 값으로 호출하면 중요도가 높은 알림이 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으로만 표시해야 합니다. CarAppExtender.Builder.setImportance 메서드로 알림의 중요도를 설정하여 HUN 동작을 제어할 수 있습니다. 중요도를 IMPORTANCE_HIGH로 설정하면 HUN이 표시되고 그 외 다른 값으로 설정하면 레일 위젯만 업데이트됩니다.

PlaceListNavigationTemplate 콘텐츠 새로고침

운전자가 PlaceListNavigationTemplate으로 빌드된 장소 목록을 탐색하면서 버튼 하나만 탭하여 콘텐츠를 새로고침하도록 할 수 있습니다. 목록 새로고침을 설정하려면 OnContentRefreshListener 인터페이스의 onContentRefreshRequested 메서드를 구현하고, 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의 헤더에 표시됩니다.

사용자가 새로고침 버튼을 클릭하면 OnContentRefreshListener 구현의 onContentRefreshRequested 메서드가 호출됩니다. 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에서 기본 내비게이션 자동차 앱은 사용자가 마지막으로 실행한 내비게이션 앱에 해당합니다. 사용자가 어시스턴트를 통해 내비게이션 명령어를 호출하거나 다른 앱에서 내비게이션을 시작하는 인텐트를 전송하는 경우 기본 앱에서 내비게이션 인텐트를 수신합니다.

컨텍스트 내 내비게이션 알림 표시

Alert은 내비게이션 화면의 컨텍스트를 벗어나지 않고 운전자에게 중요한 정보와 선택적 작업을 표시합니다. 운전자에게 최상의 환경을 제공하기 위해 AlertNavigationTemplate 내에서 작동하여 내비게이션 경로를 차단하지 않고 운전자 주의 분산 행동을 최소화합니다.

AlertNavigationTemplate 내에서만 사용할 수 있습니다. NavigationTemplate 외부의 사용자에게 알리려면 알림 표시의 설명대로 헤드업 알림(HUN)을 사용하는 것이 좋습니다.

예를 들어 Alert을 사용하여 다음 작업을 할 수 있습니다.

  • 운전자에게 교통상황 변경 등 현재 내비게이션과 관련된 업데이트를 알립니다.
  • 운전자에게 이동식 과속 단속 카메라의 존재 등 현재 내비게이션과 관련된 업데이트를 요청합니다.
  • 예정된 작업을 제안하고 운전자가 수락할지를 묻습니다(예: 운전자가 도중에 누군가를 태울지).

기본 형태에서 Alert은 제목과 Alert 지속 시간으로 구성됩니다. 지속 시간은 진행률 표시줄로 표시됩니다. 원할 경우 부제목, 아이콘, 최대 2개의 Action 객체를 추가할 수 있습니다.

그림 2. 컨텍스트 내 내비게이션 알림

Alert이 표시된 후에는 운전자 상호작용으로 인해 NavigationTemplate에서 나가는 경우 다른 템플릿으로 이전되지 않습니다. Alert 시간이 초과되거나 사용자가 작업을 실행하거나 앱에서 Alert을 닫을 때까지 원래 NavigationTemplate에 유지됩니다.

알림 만들기

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 지속 시간을 선택합니다. 권장되는 내비게이션 Alert의 지속 시간은 10초입니다. 내비게이션 알림을 참고하세요. 를 참조하세요.

알림 표시

Alert을 표시하려면 앱의 CarContext를 통해 사용할 수 있는 AppManager.showAlert 메서드를 호출합니다.

// Show an alert
carContext.getCarService(AppManager.class).showAlert(alert)
  • 현재 표시되고 있는 Alert과 ID가 동일한 alertId를 갖는 Alert을 사용하여 showAlert을 호출하면 아무 일도 일어나지 않습니다. Alert은 업데이트되지 않습니다. Alert을 업데이트하려면 새 alertId를 사용하여 다시 만들어야 합니다.
  • 현재 표시되고 있는 Alert과 다른 alertId를 갖는 Alert을 사용하여 showAlert을 호출하면 현재 표시되고 있는 Alert이 닫힙니다.

알림 닫기

Alert은 시간 제한 또는 운전자 상호작용으로 인해 자동으로 닫히지만 수동으로 Alert을 닫을 수도 있습니다(예: 정보가 오래된 경우). Alert을 닫으려면 AlertalertId를 사용하여 dismissAlert 메서드를 호출하세요.

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

현재 표시되고 있는 Alert과 일치하지 않는 alertId를 사용하여 dismissAlert을 호출하면 아무 일도 일어나지 않습니다. 예외가 발생하지는 않습니다.