내비게이션 앱 빌드

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

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

내비게이션 앱은 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: 활성 내비게이션 중에 선택적 정보 메시지나 경로 안내 및 예상 이동경로와 함께 지도를 표시합니다.
  • PlaceListNavigationTemplate: 상응하는 마커를 지도에 그릴 수 있는 장소 목록을 표시합니다.
  • RoutePreviewNavigationTemplate: 하나를 선택하여 지도에서 강조표시할 수 있는 경로 목록을 표시합니다.

이러한 템플릿을 사용하여 내비게이션 앱의 사용자 인터페이스를 디자인하는 방법에 관한 자세한 내용은 자동차용 Android 앱 라이브러리 디자인 가이드라인을 참고하세요.

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

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

지도 그리기

내비게이션 애플리케이션은 Surface에 액세스하여 관련 템플릿에 지도를 그릴 수 있습니다.

그러면 SurfaceCallback 인스턴스를 AppManager 자동차 서비스로 설정하여 SurfaceContainer 객체에 액세스할 수 있습니다.

Kotlin

carContext.getCarService(AppManager::class.java).setSurfaceCallback(surfaceCallback)

자바

carContext.getCarService(AppManager.class).setSurfaceCallback(surfaceCallback);

SurfaceCallbackSurface의 속성이 변경될 때 다른 콜백과 함께 SurfaceContainer를 사용할 수 있는 경우 콜백을 제공합니다.

노출 영역에 액세스하려면 앱은 AndroidManifest.xml에서 androidx.car.app.ACCESS_SURFACE 권한을 선언해야 합니다.

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

지도에 표시되는 영역

호스트는 지도 위에 여러 템플릿의 사용자 인터페이스 요소를 그릴 수 있습니다. 호스트는 SurfaceCallback.onVisibleAreaChanged를 호출하여 막히지 않고 사용자에게 완전히 표시되는 영역을 전달합니다. 변경 횟수를 최소화하기 위해 호스트는 현재 템플릿에 따라 표시되는 가장 큰 직사각형을 사용하여 SurfaceCallback.onStableAreaChanged 메서드도 호출합니다.

예를 들어 내비게이션 앱에서 상단에 작업 표시줄이 있는 NavigationTemplate을 사용하는 경우 작업 표시줄은 사용자가 지도 공간을 더 만들기 위해 잠시 화면과 상호작용하지 않을 때 자체적으로 숨겨질 수 있습니다. 이 경우 동일한 직사각형을 사용하는 onStableAreaChangedonVisibleAreaChanged 콜백이 있습니다. 작업 표시줄을 숨기면 더 큰 영역으로 onVisibleAreaChanged만 호출됩니다. 사용자가 화면과 상호작용하면 다시 첫 번째 직사각형으로 onVisibleAreaChanged만 호출됩니다.

어두운 모드

내비게이션 애플리케이션은 Android Auto 앱 품질 가이드라인에 설명된 대로 호스트가 조건이 충족된다고 판단하면 적절한 어두운 색상으로 Surface 인스턴스에 지도를 다시 그려야 합니다.

어두운 지도를 그려야 하는지 판단하려면 CarContext.isDarkMode 메서드를 사용하면 됩니다. 어두운 모드 상태가 변경될 때마다 Session.onCarConfigurationChanged 호출을 수신합니다.

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

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

Kotlin

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

자바

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

내비게이션 시작, 종료, 중지

호스트에서 여러 내비게이션 앱, 경로 알림, 차량 계기판 데이터를 관리하려면 현재 내비게이션 상태를 알고 있어야 합니다. 사용자가 내비게이션을 시작하면 앱은 NavigationManager.navigationStarted를 호출해야 합니다. 마찬가지로 내비게이션이 종료되면(예: 사용자가 목적지에 도착하거나 사용자가 내비게이션을 취소할 때) 앱은 NavigationManager.navigationEnded를 호출해야 합니다.

사용자가 내비게이션을 완료한 경우에만 NavigationManager.navigationEnded를 호출해야 합니다. 예를 들어 이동 중에 경로를 다시 계산해야 한다면 Trip.Builder.setLoading(true)를 대신 사용하세요.

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

경로 정보

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

정보가 계기판에 도달하는지 테스트하려면 간단한 계기판 디스플레이를 보여 주도록 데스크톱 헤드 단위(DHU) 도구를 구성하면 됩니다. 다음 콘텐츠로 cluster.ini 파일을 만듭니다.

[general]
instrumentcluster = true

그런 다음 추가 명령줄 매개변수를 사용하여 DHU를 호출할 수 있습니다.

dhu -c cluster.ini

세부 경로 안내 알림

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

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

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

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

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

자바

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이 표시되고 그 외 다른 값으로 설정하면 레일 위젯만 업데이트됩니다.

음성 안내

자동차 스피커로 내비게이션 안내를 재생하려면 앱에서 오디오 포커스를 요청해야 합니다. 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에서 기본 내비게이션 자동차 앱은 사용자가 마지막으로 실행한 내비게이션 앱에 따라 작동합니다. 예를 들어, 사용자가 어시스턴트를 통해 내비게이션 명령어를 호출하거나 다른 앱에서 내비게이션을 시작하는 인텐트를 전송하는 경우 기본 내비게이션 자동차 앱에서 내비게이션 인텐트를 수신합니다.

사용자가 지도와 상호작용하도록 허용

Car App API 수준 2부터는 NavigationTemplate에서 지도에 확대/축소와 화면 이동을 추가하여 사용자가 지도의 다른 부분을 볼 수 있습니다.

SurfaceCallback 메서드

SurfaceCallback에는 사용자가 NavigationTemplate: onScale, onScroll, onFling에 지도 상호작용을 추가할 수 있는 세 개의 콜백 메서드가 있습니다. 이러한 콜백이 사용자 상호작용과 어떻게 관련이 있는지 알아보려면 아래의 표를 참고하세요.

상호작용 SurfaceCallback 메서드
손가락 모으기(확대/축소) onScale
원터치 드래그 onScroll
원터치 플링 onFling
두 번 탭 onScale(템플릿 호스트에서 결정하는 배율 사용)
화면 이동 모드에서 로터리 이동 onScroll(템플릿 호스트에서 결정하는 거리 요소 사용)

지도 작업 스트립

NavigationTemplate은 확대/축소, 중심 재설정, 나침반 표시 또는 앱에서 표시하도록 선택할 수 있는 다른 작업과 같은 지도 관련 작업을 위해 지도 작업 스트립을 가질 수 있습니다. 지도 작업 스트립은 작업 깊이에 영향을 주지 않고 새로고침할 수 있는 아이콘 전용 버튼을 최대 네 개까지 가질 수 있습니다. 작업 스트립과 마찬가지로 지도 작업 스트립은 유휴 상태 시 숨겨지고 활성 상태에 다시 표시됩니다.

지도 상호작용 콜백을 수신하려면 지도 작업 스트립에 Action.PAN 버튼을 추가해야 합니다. 앱이 지도 작업 스트립에 Action.PAN 버튼을 생략하면 SurfaceCallback 메서드로부터 사용자 입력을 수신하지 않게 되고 호스트는 이전에 활성화된 화면 이동 모드를 종료합니다. 사용자가 화면 이동 버튼을 누르면 호스트가 화면 이동 모드로 전환됩니다. 터치스크린에는 화면 이동 버튼이 표시되지 않습니다.

화면 이동 모드

화면 이동 모드에서는 템플릿 호스트가 터치 입력을 사용하지 않는 기기(예: 로터리 컨트롤러, 터치패드)의 사용자 입력을 적절한 SurfaceCallback 메서드로 변환합니다. 사용자 작업에 관한 응답으로 NavigationTemplate BuildersetPanModeListener 메서드를 사용하여 화면 이동 모드에 진입하거나 화면 이동 모드를 종료합니다. 사용자가 화면 이동 모드에 있는 동안 호스트는 템플릿에서 다른 UI 구성요소를 숨길 수 있습니다.

안정화된 영역

안정화된 영역은 유휴 상태와 활성 상태 사이에 업데이트됩니다. 앱은 지도 작업 스트립으로 인해 지도상에 중요한 정보가 가려지지 않도록 운전 관련 정보(예: 속도, 속도 제한, 안정화된 영역의 크기에 따른 도로 경고)를 표시해야 합니다.