TV 기기에는 앱과 상호작용하기 위한 보조 하드웨어 기기(기본 리모컨, 포인터 리모컨 또는 게임 컨트롤러)가 필요합니다. 일관된 사용자 환경을 제공하려면 앱이 방향 패드(D패드) 입력을 지원하고, 컨트롤러가 오프라인으로 전환되는 것을 처리하고, 포인터 리모컨을 비롯한 여러 컨트롤러 유형의 입력을 지원해야 합니다.
D패드 최소 컨트롤
TV 기기용 기본 컨트롤러는 D패드입니다. 일반적으로 앱은 위, 아래, 왼쪽, 오른쪽, 선택, 뒤로, 홈 버튼만 있는 리모컨에서 작동해야 합니다. 앱이 일반적으로 추가 컨트롤이 있는 게임 컨트롤러가 필요한 게임인 경우 이러한 D패드 컨트롤만으로 게임플레이를 지원해 보세요. 그렇지 않은 경우 컨트롤러가 필요하다는 경고를 사용자에게 표시하고 D패드 컨트롤러를 사용하여 게임을 정상적으로 종료하도록 합니다.
TV 기기의 D패드 컨트롤러를 사용한 탐색에 관한 자세한 내용은 TV 탐색을 참고하세요.
컨트롤러 연결 해제 처리
TV 컨트롤러는 블루투스 기기인 경우가 많으며, 주기적으로 절전 모드로 전환되고 TV 기기에서 연결이 해제되어 전원을 절약하려고 시도할 수 있습니다. 즉, 이러한 다시 연결 이벤트를 처리하도록 앱이 구성되지 않은 경우 앱이 중단되거나 다시 시작될 수 있습니다. 이러한 이벤트는 다음 상황에서 발생할 수 있습니다.
- 몇 분 길이의 동영상이 재생되는 동안 D패드나 게임 컨트롤러가 절전 모드로 전환되거나 TV 기기에서 연결이 해제되었다가 나중에 다시 연결될 수 있습니다.
- 게임 플레이 중에 아직 연결되지 않은 게임 컨트롤러를 사용하여 새 플레이어가 게임에 참여할 수 있습니다.
- 게임 플레이 중에 플레이어가 게임을 종료하고 게임 컨트롤러를 분리할 수 있습니다.
연결 해제 및 다시 연결 이벤트가 적용되는 TV 앱 활동은 앱 매니페스트에서 다시 연결 이벤트를 처리하도록 구성해야 합니다. 다음 코드 샘플은 키보드나 탐색 기기 연결, 연결 해제, 재연결 등 구성 변경을 처리하도록 활동을 사용 설정하는 방법을 보여줍니다.
<activity
android:name="com.example.android.TvActivity"
android:label="@string/app_name"
android:configChanges="keyboard|keyboardHidden|navigation"
android:theme="@style/Theme.Leanback">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LEANBACK_LAUNCHER" />
</intent-filter>
...
</activity>
이 구성 변경을 통해 앱은 Android 프레임워크에 의해 다시 시작되지 않고 재연결 이벤트를 통해 계속 실행될 수 있습니다. 이는 좋은 사용자 환경이 아닙니다.
다양한 D패드 입력 처리
TV 기기 사용자는 TV와 함께 사용하는 컨트롤러가 두 개 이상일 수 있습니다. 예를 들어 사용자에게 기본 D패드 컨트롤러, 포인터 리모컨 또는 게임 컨트롤러가 있을 수 있습니다. D패드 기능에 사용될 때 게임 컨트롤러에서 제공하는 키 코드는 기본 D패드에서 전송하는 키 코드와 다를 수 있습니다.
사용자가 앱을 작동하기 위해 컨트롤러를 전환하지 않아도 되도록 D패드 입력의 변형을 처리합니다. 입력 변형 처리에 관한 자세한 내용은 방향 패드 입력 처리를 참고하세요.
포인터 리모컨 지원
일부 TV 기기는 에어마우스나 터치 감지 방향 패드 (트랙패드)가 있는 리모컨과 같은 포인터 리모컨을 지원합니다. 포인터 리모컨을 지원하면 사용자가 포인트 앤 클릭, 마우스 오버, 스와이프, 드래그 동작을 사용하여 앱과 상호작용할 수 있으므로 호환 하드웨어에서 더 원활한 환경을 제공하면서도 전체 D패드 호환성을 유지할 수 있습니다.
매니페스트에서 포인터 원격 지원 선언
앱이 포인터 및 터치 입력으로 탐색할 수 있음을 나타내려면 android.software.leanback.supports_touch 메타데이터가 true로 설정된 앱 매니페스트를 구성합니다.
<manifest ...>
<!-- Signal whether the app is adaptive or built just for TV -->
<uses-feature
android:name="android.software.leanback"
android:required="true|false" />
<!-- Ensure the app can be installed on conventional TVs -->
<uses-feature
android:name="android.hardware.touchscreen"
android:required="false" />
<!-- Signal whether the app supports pointer remotes -->
<meta-data
android:name="android.software.leanback.supports_touch"
android:value="true" />
<application ...>
...
</application>
</manifest>
클릭, 마우스 오버, 스크롤 상호작용 지원
포인터 리모컨을 지원할 때는 다음 상호작용에서 UI 구성요소가 커서 및 터치 입력에 적절하게 응답하는지 확인하세요.
- 클릭 및 선택: 포커스 가능하고 선택 가능한 모든 UI 요소는 포인터 리모컨으로 클릭할 수 있어야 하며 D패드 선택(
KEYCODE_DPAD_CENTER) 동작과 일치해야 합니다. - 시각적 마우스 오버 상태: 포인터 커서가 선택 가능한 항목 위에 있을 때를 나타내는 명확한 시각적 마우스 오버 효과를 제공합니다.
- Jetpack Compose:
Modifier.hoverable()를 사용하거나InteractionSource를 사용하여 마우스 오버 상태를 관찰합니다. 자세한 내용은 사용자 상호작용 처리를 참고하세요. - 뷰:
android:state_hovered="true"를 사용하여 상태 목록 드로어블을 사용하여 마우스 오버 상태를 정의합니다.
- Jetpack Compose:
- 스와이프 및 플링 스크롤: 터치 감지 중앙 D패드 버튼에서 스와이프 또는 플링 동작으로 트리거되는 가로 및 세로 스크롤은 스크롤 가능한 모든 콘텐츠에서 원활하게 작동해야 합니다.
- 드래그 스크롤: 사용자는 스크롤 가능한 컨테이너에서 세로 (위아래) 또는 가로 (좌우)로 드래그하여 스크롤할 수 있어야 합니다.
- Jetpack Compose: 표준 스크롤 가능한 컨테이너는 기본적으로 포인터 및 터치 스크롤을 지원합니다. 맞춤 구현은 Compose의 포인터 입력을 참고하세요.
- 뷰: 표준 스크롤 가능 뷰는 기본적으로 터치 스크롤을 지원합니다. 맞춤 입력 처리는 터치 및 입력을 참고하세요.
- 미디어 재생 스크러빙: TV 프로그램, 영화 등 미디어 재생 중에 사용자는 포인트하고 클릭하여 과거 또는 미래 타임스탬프로 이동할 수 있어야 하며, 진행률 표시줄을 따라 드래그(스크러빙)하여 특정 시간으로 이동할 수 있어야 합니다.
버튼 이벤트 처리
사용자가 컨트롤러의 버튼을 클릭하면 앱은 KeyEvent이 포함된 이벤트를 수신합니다. 버튼의 의도된 동작은 재생, 일시중지, 중지와 같은 미디어 이벤트일 수도 있고 선택, 탐색과 같은 TV 유형 이벤트일 수도 있습니다. 우수한 사용자 환경을 제공하려면 컨트롤러 버튼에 일관된 동작을 할당하세요.
TV UI 이벤트
다음 표와 같이 KeyEvent 유형을 생성하는 버튼에 TV UI 동작을 할당합니다.
KeyEvent |
동작 |
|---|---|
KEYCODE_BACK KEYCODE_BUTTON_B |
뒤로 |
KEYCODE_BUTTON_SELECT, KEYCODE_BUTTON_A, KEYCODE_ENTER, KEYCODE_DPAD_CENTER, KEYCODE_NUMPAD_ENTER |
선택 |
KEYCODE_DPAD_UP, KEYCODE_DPAD_DOWN, KEYCODE_DPAD_LEFT, KEYCODE_DPAD_RIGHT |
탐색 |
미디어 이벤트
사용자가 미디어를 시청할 때 다음 표와 같이 KeyEvent 유형을 생성하는 버튼에 동작을 할당합니다. 앱이 MediaSession를 제어하는 경우 MediaControllerAdapter를 사용하여 표에 표시된 MediaControllerCompat.TransportControls 메서드 중 하나를 호출합니다. 이 맥락에서 선택 버튼은 재생 또는 일시중지 버튼으로 작동합니다.
KeyEvent |
TransportControls 호출 | 동작 |
|---|---|---|
BUTTON_SELECT, BUTTON_A, ENTER, DPAD_CENTER, KEYCODE_NUMPAD_ENTER |
play() |
재생 |
BUTTON_START, BUTTON_SELECT, BUTTON_A, ENTER, DPAD_CENTER, KEYCODE_NUMPAD_ENTER |
pause() |
일시중지 |
BUTTON_R1 |
skipToNext() |
다음으로 건너뛰기 |
BUTTON_L1 |
skipToPrevious() |
이전으로 건너뛰기 |
DPAD_RIGHT, BUTTON_R2, AXIS_RTRIGGER, AXIS_THROTTLE |
fastForward() |
빨리 감기 |
DPAD_LEFT, BUTTON_L2, AXIS_LTRIGGER, AXIS_BRAKE |
rewind() |
되감기 |
| 해당 사항 없음 | stop() |
중지 |
적절한 뒤로 버튼 동작 제공
뒤로 버튼은 전환 버튼으로 작동해서는 안 됩니다. 예를 들어 메뉴를 열고 닫는 데 모두 사용하지 마세요. 플레이어가 방문한 이전 화면을 탐색할 때만 빵 부스러기 스타일로 뒤로 이동하는 데 사용하세요.
뒤로 버튼은 선형의 뒤로 탐색만 실행하므로 이 버튼을 사용하여 다른 버튼으로 열린 인앱 메뉴를 종료하고 앱으로 돌아갈 수 있습니다. 뒤로 버튼을 연속으로 누르면 항상 Android TV 홈 화면으로 이동해야 합니다. 예: 게임 플레이 > 게임 일시중지 화면 > 게임 기본 화면 > Android TV 홈 화면 또는 TV 프로그램 재생 > TV 앱 기본 화면
Android TV 홈 화면
탐색 디자인에 관한 자세한 내용은 뒤로 및 위로 탐색 디자인을 참고하세요. 구현에 관해 알아보려면 올바른 뒤로 탐색 제공을 참고하세요.
게임 컨트롤러 처리
Android TV용 게임을 빌드할 때는 표준 TV 리모컨과 전용 게임 컨트롤러 모두에서 작동하도록 제어 체계를 설계하세요.
D패드 컨트롤 지원
이 제어 세트는 Android TV 기기의 기본값이므로 D패드 컨트롤을 중심으로 제어 체계를 계획하세요. 플레이어는 핵심 게임플레이를 제어할 뿐만 아니라 메뉴와 광고를 탐색하는 등 게임의 모든 측면에 D패드를 사용할 수 있어야 합니다. 따라서 Android TV 게임에서 '탭하여 계속하세요'와 같은 언어로 터치 인터페이스를 참조하지 않아야 합니다.
플레이어와 컨트롤러의 상호작용을 어떻게 형성하느냐가 훌륭한 사용자 경험을 달성하는 데 핵심이 될 수 있습니다. 다음 권장사항을 고려해 보세요.
- 컨트롤러 요구사항을 미리 알림: Google Play 설명을 사용하여 컨트롤러에 관한 기대치를 플레이어에게 알립니다. 게임이 D패드만 있는 게임패드보다 조이스틱이 있는 게임패드에 더 적합한 경우 이를 명확하게 밝히세요. 게임에 적합하지 않은 컨트롤러를 사용하는 플레이어는 경험이 좋지 않아 게임에 나쁜 평가를 줄 수 있습니다.
- 일관된 버튼 매핑 사용: 직관적인 버튼 매핑은 좋은 사용자 환경의 핵심입니다. 예를 들어 A 버튼을 사용하여 수락하고 B 버튼을 사용하여 취소하는 등 허용된 관습을 따릅니다. 사용자가 버튼을 재매핑하도록 허용하여 유연성을 제공할 수도 있습니다. 버튼 매핑에 관한 자세한 내용은 컨트롤러 작업 처리를 참고하세요.
- 컨트롤러 기능 감지 및 적절한 조정: 컨트롤러와 게임 간의 일치를 최적화하기 위해 컨트롤러의 기능을 쿼리합니다. 예를 들어 플레이어가 컨트롤러를 공중에서 흔들어 물체를 조종하도록 의도했지만 플레이어의 컨트롤러에 가속도계 및 자이로스코프 하드웨어가 없으면 흔들어도 작동하지 않습니다. 컨트롤러를 쿼리하고 움직임 감지가 지원되지 않으면 사용 가능한 대체 제어 체계로 전환합니다. 컨트롤러 기능 쿼리에 관한 자세한 내용은 다양한 Android 버전에서 컨트롤러 지원을 참고하세요.
적절한 버튼 사용
일부 게임 컨트롤러는 시작, 검색 또는 메뉴 버튼을 제공하지 않습니다. UI가 이러한 버튼의 사용에 의존하지 않는지 확인하세요.
여러 컨트롤러 처리
여러 플레이어가 각자 컨트롤러를 사용하여 게임을 플레이하는 경우 각 플레이어-컨트롤러 쌍을 매핑하는 것이 중요합니다. 컨트롤러 번호 식별을 구현하는 방법에 관한 자세한 내용은 getControllerNumber()를 참고하세요.
컨트롤러 연결 해제 처리
게임 플레이 중에 컨트롤러가 연결 해제되면 게임을 일시중지하고 연결 해제된 플레이어에게 컨트롤러를 다시 연결하라는 메시지가 표시된 대화상자를 표시합니다.
또한 대화상자에서 문제 해결 팁을 제공합니다. 예를 들어 플레이어에게 '블루투스 연결을 확인하세요'라고 말합니다. 입력 기기 지원 구현에 관한 자세한 내용은 컨트롤러 작업 처리 및 블루투스 개요를 참고하세요.
컨트롤러 안내 표시
게임에서 시각적 게임 컨트롤 안내를 제공하는 경우 브랜딩이 없는 컨트롤러 이미지를 사용하고 Android와 호환되는 버튼만 포함하세요.
Android 호환 컨트롤러의 샘플 이미지를 보려면 Android TV 게임패드 템플릿 (ZIP)을 다운로드하세요. 검은색 배경의 흰색 컨트롤러와 흰색 배경의 검은색 컨트롤러가 PNG 파일과 Adobe® Illustrator® 파일로 포함되어 있습니다(그림 1 참고).