햅틱 프레임워크용 UX 기초

햅틱을 중심으로 빌드된 모든 Android 프레임워크 개선사항은 동일한 속도로 진화하는 일련의 UX 원칙을 따릅니다. 현재 원칙은 윙윙거리는 진동명확한 햅틱으로 바꾸고 리치 햅틱을 탐색하는 것입니다.

UX 원칙

그림 1. 현재 원칙

다음 표에는 사용 가능한 모든 햅틱 API가 나와 있습니다.

API 메서드 추가된 연도
android.view.HapticFeedbackConstants
  • CONTEXT_CLICK
  • CLOCK_TICK
  • VIRTUAL_KEY
  • KEYBOARD_TAP
  • LONG_PRESS
2016년 이전
  • KEYBOARD_PRESS
  • KEYBOARD_RELEASE
  • TEXT_HANDLE_MOVE
  • VIRTUAL_KEY_RELEASE
2017년(Android 8)
  • CONFIRM
  • REJECT
  • GESTURE_START
  • GESTURE_END
2020년(Android 11)
android.View
  • performHapticFeedback()
2016년 이전
android.os.Vibrator
  • vibrate()
  • hasVibrator()
2016년 이전
  • hasAmplitudeControl()
2017년(Android 8)
  • areAllEffectsSupported()
  • areAllPrimitivesSupported()
  • areEffectsSupported()
  • arePrimitivesSupported()
2020년(Android 11)
android.os.VibrationEffect
  • createOneShot()
  • createWaveform()
2017년(Android 8)
  • EFFECT_TICK
  • EFFECT_CLICK
  • EFFECT_HEAVY_CLICK
  • EFFECT_DOUBLE_CLICK
  • createPredefined()
2019년(Android 10)
android.os.VibrationEffect.Composition
  • PRIMITIVE_TICK
  • PRIMITIVE_CLICK
  • addPrimitive()
  • compose()
2020년(Android 11)
android.media.AudioAttributes.Builder
  • setHapticChannelsMuted()
2019년(Android 10)

윙윙거리는 진동

무선 호출기와 피처폰 시절에는 품질은 낮지만 전력 효율은 좋은 ERM 버저 기반 진동이 무음 모드에서 청각적 벨소리 대신 사용되었습니다. 크고 불쾌한 청각적 노이즈를 생성하는 기존 하드웨어 구성요소는 품질이 낮은 인상(예: 값싸고 고장난 휴대전화)을 전달하여 햅틱 UX에 해를 끼칠 수 있습니다.

명확한 햅틱

명확한 햅틱개별 상태 변화의 감각을 지원합니다(예: 전원 켜짐/꺼짐 프로세스 중에 바이너리 변경). 개별 어포던스 특성으로 인해 명확한 햅틱은 단일 항목으로 생성됩니다(예: 입력 이벤트 하나당 햅틱 효과 하나).

Android의 목표는 윙윙거리거나 흐릿한 감각이 아닌 강력하면서도 선명한 감각의 명확한 햅틱을 제공하는 것입니다.

명확한 햅틱을 지원하기 위해 만들어진 사전 정의된 햅틱 상수는 다음과 같습니다.

HapticFeedbackConstants의 경우:

  • CLOCK_TICK
  • CONFIRM
  • CONTEXT_CLICK
  • GESTURE_END
  • GESTURE_START
  • KEYBOARD_PRESS
  • KEYBOARD_RELEASE
  • KEYBOARD_TAP
  • LONG_PRESS
  • REJECT
  • TEXT_HANDLE_MOVE
  • VIRTUAL_KEY
  • VIRTUAL_KEY_RELEASE

VibrationEffect의 경우:

  • EFFECT_CLICK
  • EFFECT_DOUBLE_CLICK
  • EFFECT_HEAVY_CLICK
  • EFFECT_TICK

기기 제조업체와 개발자 사이의 일반적인 지식 구축은 Android 생태계에서 전반적인 햅틱 품질을 높이는 핵심입니다. 기본 체크리스트, 하드웨어 평가, CDD를 사용하여 햅틱 구현에 관해 자세히 알아보세요.

누르기 및 놓기

그림 3. 누르기 및 놓기

리치 햅틱

리치 햅틱은 성장하는 햅틱 카테고리로, 단일 임펄스 기반 효과를 뛰어넘습니다. Android의 목표는 높은 구성 가능성과 미세한 수준의 조정 가능성을 갖춘 리치 햅틱을 지원하는 것입니다. 다음 사용 사례는 Android 11 이하에서 지원됩니다.

리치 햅틱

그림 4. 슬라이딩 텍스처가 있는 리치 햅틱

드래그 및 스와이프

그림 5. 드래그 및 스와이프

사용 사례 1: 슬라이딩 텍스처

손가락으로 터치 스크린을 슬라이드하는 동안 햅틱 효과가 반복되면(예: 드래그, 스와이프, 팬텀 햅틱 텍스처로 터치 스크린 탐색) 반복되는 햅틱 효과는 선명하고 섬세한 것이 좋습니다.

개별 효과가 선명하지 않고 윙윙거리면 반복 사이의 간격이 없어질 수 있습니다. 결과적으로 여러 개의 개별 신호가 아닌 하나의 긴 윙윙거림이 됩니다.

진폭이 충분히 섬세하지 않으면 인지된 햅틱 에너지가 반복을 통해 축적되어 반복이 끝날 때는 압도적으로 강한 햅틱이 발생합니다.

스와이프 및 드래그 동작을 위한 간단한 노출 영역 햅틱 텍스처 구현

HapticFeedbackConstants에서 CLOCK_TICKTEXT_HANDLE_MOVE를 사용합니다. 이러한 상수는 반복과 진폭의 특성을 사전 정의합니다.

자체 효과 만들기

자체 효과를 만들려면 VibrationEffect.Composition에서 PRIMITIVE_CLICKPRIMITIVE_TICK의 시퀀스를 결합하여 디자인을 구성합니다. addPrimitive(int primitiveID, float scale, int delay)를 사용하여 반복 및 진폭 비율의 특성을 조정할 수 있습니다. 지원 여부는 Vibrator HAL 인터페이스CAP_COMPOSE_EFFECTS 기능에 따라 달라집니다.

사용 사례 2: ease-in 효과가 적용된 긴 진동

긴 진동은 0에서 타겟 진폭까지 전환되는 부드러운 진폭 진동입니다. 긴 진동은 쉽게 인지할 수 있는, 주의를 끄는 햅틱을 생성할 수 있습니다. 그러나 갑작스러운 긴 진동은 조용한 환경에서 사용자를 놀라게 할 수 있고 청각적으로 윙윙거리는 노이즈를 생성할 때가 많습니다. 좀 더 기분 좋은 긴 진동을 생성하려면 긴 진동이 시작될 때 ease-in 효과를 적용합니다. 이렇게 하면 타겟 진폭으로 이어지는 부드러운 진폭 전환이 생성됩니다.

ease-in 효과 적용

  1. android.os.Vibrator.hasAmplitudeControl()을 사용하여 진폭 제어의 하드웨어 기능을 확인합니다.

    • 다양한 진폭으로 ease-in 효과를 생성하려면 결과가 true여야 합니다.
  2. VibrationEffect.createWaveform(timings[], amplitudes[], int repeat)을 사용합니다.

  3. 그림 6과 같이 일련의 timings[]amplitudes[]를 조정하여 ease-in 곡선을 생성합니다.

긴 진동

그림 6. 긴 진동 ease-in 곡선

사용 사례 3: 오디오 결합 햅틱

오디오 결합 햅틱은 사용자의 주의를 끌기 위해 오디오 리듬과 결합된 햅틱 패턴입니다.

오디오 결합 햅틱: 이점

오디오 결합 햅틱을 구현하려면 명확한 햅틱을 긴 진동과 결합합니다. 명확한 햅틱의 강하지만 짧은 햅틱 감각은 개별 리듬 패턴을 전달합니다. 이는 긴 진동이 제공하는 높은 수준의 자극과 결합될 때 사용자의 주의를 끌기 좋습니다.

감각 리듬 패턴을 고려하는 것이 중요합니다. 리듬감이 없으면 사용자는 햅틱 감각을 임의의 윙윙거림으로 인지하고 무시하기 쉽습니다.

오디오 결합

그림 7. 오디오 결합 햅틱 예

오디오 결합 햅틱: 구현 도움말

오디오 결합 햅틱을 구현하려면 오디오 채널과 햅틱 채널 모두의 콘텐츠 재생을 기본적으로 알고 있어야 합니다. 다음 사항에 유의하세요.

  • MediaPlayer 또는 SoundPool 클래스를 사용합니다.

    • 특수 메타데이터 키(ANDROID_HAPTIC 다음에 여러 햅틱 채널이 뒤따름)가 있는 OGG 형식의 애셋은 햅틱 데이터의 존재와 MediaPlayerSoundPool을 사용한 재생을 나타냅니다.
  • audio_policy_configuration.xml에서 햅틱 및 오디오 재생 지원을 나타냅니다.

    • 햅틱 채널 AUDIO_CHANNEL_OUT_HAPTIC_A|B가 있는 출력 프로필을 사용합니다.
    • 햅틱 채널이 있는 출력 스트림의 경우 햅틱 채널은 데이터에서 추가 채널로 표시됩니다.

    출력 스트림의 채널 마스크가 다음과 같다면

    AUDIO_CHANNEL_OUT_STEREO_HAPTIC_A

    모든 샘플은 다음과 같아야 합니다.

    AUDIO_LEFT_CHANNEL,AUDIO_RIGHT_CHANNEL,HAPTIC_CHANNEL_A

  • AudioAttributes.Builder( ).setHapticChannelsMuted(boolean muted)false로 변경하여 햅틱 채널을 재생합니다.

    • 기본적으로 햅틱 채널은 음소거(true)됩니다.
    • 사용 사례에는 동기식 햅틱과 피드백이 있는 벨소리와 UI 사운드가 있습니다.
  • Vibrator HAL은 외부 제어 지원을 구현해야 합니다.

오디오 결합 햅틱

그림 8. 오디오 결합 햅틱 구현

오디오 결합 햅틱: 햅틱 생성기

HapticGenerator는 Android 12에서 도입된 오디오 효과로, 오디오 채널에서 햅틱 데이터를 생성한 다음 실시간으로 오디오 결합 햅틱으로 재생할 수 있습니다. 효과는 그림 9와 같이 AudioTrack에 적용됩니다.

햅틱 생성기 아키텍처

그림 9. 햅틱 생성기 아키텍처

햅틱 생성기 알고리즘에서 고품질 햅틱이 생성되도록 하려면 오디오 파형에 적용되는 필터 체인의 구성 매개변수를 조정하여 생성 알고리즘을 기기 진동기 모터에 맞춰 미세 조정합니다. 이 섹션에서는 이러한 매개변수를 자세히 설명하고 하드웨어 사양에 맞게 미세 조정하는 방법을 소개합니다.

  1. 대역 필터의 공진 주파수

    진동기 공진 주파수란 햅틱 액추에이터의 출력이 최대인 주파수입니다. 이 매개변수는 더 넓은 대역폭을 얻기 위해 안티 레저네이터를 조정하여 응답 전달 함수를 부분적으로 평탄화합니다. Android 프레임워크는 자동으로 이 값을 Vibrator HAL 메서드 IVibrator.getResonantFrequency의 출력에 연결합니다.

    이 매개변수의 기본값은 150Hz입니다. 여기에 있는 코드에서 수정할 수 있습니다.

  2. 느린 포락선을 위한 정규화 파워

    이 매개변수는 부분 정규화(자동 게인 컨트롤)에서 지수를 결정합니다. 기본값은 -0.8입니다. 즉, 동적 범위 변형의 80%가 이 게인 컨트롤 단계에서 삭제됩니다. 여기에 있는 코드에서 수정할 수 있습니다.

  3. 대역 저지 필터의 Q 인자

    진동기 품질 인자(Q 인자)는 다음 두 매개변수로 결정됩니다.

    • Zero Q: 공진을 부분적으로 취소하는 대역 저지 필터에서 0의 품질 인자입니다.

    • Pole Q: 대역 저지 필터에서 극의 품질 인자입니다.

    더 낮은 주파수를 강화하고 알고리즘 응답을 넓히기 위해 이 두 값의 비율에 따라 공진 억제를 제한합니다. 예를 들어 Zero Q의 기본값이 8이고 Pole Q의 기본값 4이면 비율은 2가 되므로 2를 인수로(6dB) 공진 억제를 제한합니다. Android 프레임워크는 두 값을 Vibrator HAL 메서드 IVibrator.getQFactor의 출력에 연결합니다.

    기본값에 기기의 모터 강도 감쇠가 반영되지 않으면 두 값을 동시에 수정하여 두 값 모두 늘리거나 줄이는 것이 좋습니다. Zero Q 대 Pole Q의 비율은 1보다 커야 합니다. 여기에 있는 코드에서 수정할 수 있습니다.

  4. 왜곡을 위한 코너 주파수

    코너 주파수는 큐브 왜곡을 사용하여 저수준 진동을 억제하고 고수준 진동을 개선하는 저역 필터에 의해 적용됩니다. 기본값은 300Hz입니다. 여기에 있는 코드에서 수정할 수 있습니다.

  5. 왜곡을 위한 입력 게인 및 큐브 기준점

    입력 파형에 적용되는 비선형 왜곡 필터는 이러한 매개변수를 사용하여 낮은 주파수 신호의 진폭을 줄이고 높은 주파수의 진폭을 늘립니다.

    • 입력 게인 인자의 기본값은 0.3입니다.
    • 큐브 기준점의 기본값은 0.1입니다.

    두 값을 함께 수정하는 것이 좋습니다. 여기에 있는 코드에서 확인할 수 있습니다.

    이 필터에 의해 적용된 함수에 관한 자세한 내용은 여기에서 제공되는 구현을 참고하세요. 두 매개변수가 출력에 미치는 영향을 자세히 알아보려면 필터의 주파수 응답을 그래프로 그리고 주파수 응답이 다양한 매개변수 값에서 어떻게 변화하는지 관찰하는 것이 좋습니다.

  6. 왜곡을 위한 출력 게인

    이 매개변수는 최종 진동 진폭을 제어합니다. 이는 진동 진폭을 1 미만으로 제한하는 소프트 리미터 다음에 적용되는 최종 게인입니다. 기본값은 1.5이며 여기에 있는 코드에서 수정할 수 있습니다. 진동이 너무 미미하면 값을 늘리고 액추에이터 하드웨어에서 덜거덕거리는 소리가 들리면 값을 줄입니다.