Android - 진동, Vibrator, VibrationEffect 예제

App은 VibratorService를 통해 디바이스를 진동을 발생시킬 수 있습니다.

안드로이드 버전 별로 API 변경 사항이 있었고, 예전 SDK의 구현 방법부터 최근(Android 12 이상) SDK의 구현 방법을 모두 소개합니다.

자신의 앱이 SDK API 30(Android 12) 이상으로 컴파일된다면, Legacy 방식의 예제는 안보셔도 되고 Android 12의 예제 코드를 보시면 됩니다.

1. Vibrator의 SDK API History

지금까지 안드로이드 버전 업데이트에 따른 Vibrator API의 변경사항 간단히 정리하였습니다.

1.1 Android O(API 26) 미만

Android O(API 26) 미만의 버전에서는 Vibrator가 제공되었고, 다음 API들을 사용하여 진동을 발생시켰습니다. 이 API들은 Android O에서 Deprecated 되었습니다.

  • Vibrator.vibrate(long milliseconds)
  • Vibrator.vibrate(long[] pattern, int repeat)

1.2 Android O(API 26) 이상, Android 11(API 30) 이하

Android O(API 26) 이상에서는 VibrationEffect를 인자로 전달받는 Vibrate() API가 추가되었고, 이것을 사용하여 진동을 발생시키도록 권장하고 있습니다.

  • Vibrator.vibrate(VibrationEffect vibe)

1.3 Android 12(API 31) 이상

Android 12에서는 Vibrator가 deprecated 되었습니다. 대신 VibratorManager가 추가되었습니다. 앞으로 VibratorManager를 사용하셔야 합니다.

2. Example: vibrate()을 이용한 진동 발생 (API 26 미만)

Target SDK API 별로, 진동을 발생시키는 예제를 소개합니다.

Vibrator 객체는 다음과 같이 얻을 수 있습니다.

val vibrator = getSystemService(Context.VIBRATOR_SERVICE) as Vibrator

Vibrator.vibrator() API는 다음과 같은 기능을 제공합니다.

  • 진동 발생 (1회)
  • 패턴 진동 발생 (1회)
  • 진동 반복

전체 코드는 GitHub - Vibration에서 확인하실 수 있습니다.

2.1 진동 발생 (1회)

vibrate()으로 시간을 인자로 전달하면, 그 시간만큼 진동이 발생됩니다. 시간의 단위는 millisecond입니다.

다음 코드를 실행시키면 200ms 진동이 1회 발생합니다.

val vibrator = getSystemService(Context.VIBRATOR_SERVICE) as Vibrator
vibrator.vibrate(200) // 200 ms

2.2 패턴 진동 발생 (1회)

다음과 같이 패턴 배열을 인자로 전달하면, 입력된 패턴으로 진동이 발생됩니다. 두번째 인자는 반복을 의미하며, 0이 반복, -1은 반복하지 말라는 의미입니다.

val vibrator = getSystemService(Context.VIBRATOR_SERVICE) as Vibrator
val pattern = longArrayOf(100, 200, 100, 200, 100, 200)
vibrator.vibrate(pattern, -1)

패턴 배열에서, 짝수 Index는 대기하는 시간이고, 홀수 Index는 진동이 발생되는 시간을 의미합니다.

Index 0: 100  // wait for 100ms
Index 1: 200  // vibrate for 200ms
Index 2: 100  // wait for 100ms
Index 3: 200  // vibrate for 200ms
Index 4: 100  // wait for 100ms
Index 5: 200  // vibrate for 200ms

2.3 진동 반복

아래 코드는 패턴 진동이 발생되고, 무한히 진동을 발생시킵니다. 인자 Repeat = 0은 무한히 반복하라는 의미입니다.

val vibrator = getSystemService(Context.VIBRATOR_SERVICE) as Vibrator
val pattern = longArrayOf(100, 200, 100, 200, 100, 200)
vibrator.vibrate(pattern, 0)

반복을 멈추려면 다음과 같이 cancel()을 호출하면 됩니다.

val vibrator = getSystemService(Context.VIBRATOR_SERVICE) as Vibrator
vibrator.cancel()

2.4 진동 취소

반복을 멈추거나 진동을 취소하려면, 다음과 같이 cancel()을 호출하면 됩니다.

val vibrator = getSystemService(Context.VIBRATOR_SERVICE) as Vibrator
vibrator.cancel()

3. Example: VibrationEffect를 이용한 진동 발생 (API 26 이상, API 30 이하)

VibrationEffect는 다음과 같은 객체 생성 메소드를 제공합니다.

  • VibrationEffect.createOneShot()
  • VibrationEffect.createWaveform()

전체 코드는 GitHub - Vibration에서 확인하실 수 있습니다.

3.1 진동 발생 (1회)

패턴이 없는 진동을 발생시키려면 VibrationEffect.createOneShot()으로 VibrationEffect를 생성해야 합니다.

val vibrator = getSystemService(Context.VIBRATOR_SERVICE) as Vibrator
val effect = VibrationEffect.createOneShot(
        200, VibrationEffect.DEFAULT_AMPLITUDE)
vibrator.vibrate(effect)

첫번째 인자는 발생시키려는 진동 시간이며, 단위는 millisecond입니다. 두번째 인자는 진동 세기로, 1 ~ 255의 값을 전달해야 합니다. 기본 진동 세기를 사용하려면 DEFAULT_AMPLITUDE를 전달하면 됩니다.

3.2 패턴 진동 발생 (1회)

패턴으로 진동을 발생시키려면 Vibrator.createWaveform()으로 VibrationEffect를 생성해야 합니다.

createWaveform()의 첫번째 인자로 패턴(timing)이 전달되며, 두번째 인자는 Repeat으로, -1은 반복하지 않음, 0 이상은 반복을 의미합니다.

val vibrator = getSystemService(Context.VIBRATOR_SERVICE) as Vibrator
val timing = longArrayOf(100, 200, 100, 200, 100, 200)
val effect = VibrationEffect.createWaveform(timing, -1)
vibrator.vibrate(effect)

패턴 배열의 짝수 Index는 대기 시간, 홀수 Index는 진동이 발생되는 시간입니다.

Index 0: 100  // wait for 100ms
Index 1: 200  // vibrate for 200ms
Index 2: 100  // wait for 100ms
Index 3: 200  // vibrate for 200ms
Index 4: 100  // wait for 100ms
Index 5: 200  // vibrate for 200ms

3.3 패턴(진동 세기 조절) 진동 발생 (1회)

전달되는 패턴의 진동 세기를 조절할 수도 있습니다.

다음과 같이 진동 패턴(timing)과 길이가 동일한 진동 세기(aplitudes) 배열을 인자로 전달합니다.

val vibrator = getSystemService(Context.VIBRATOR_SERVICE) as Vibrator
val timing = longArrayOf(100, 200, 100, 200, 100, 200)
val amplitudes = intArrayOf(0, 50, 0, 100, 0, 200)
val effect = VibrationEffect.createWaveform(timing, amplitudes, -1)
vibrator.vibrate(effect)

진동 패턴과 진동 세기 배열의 길이는 모두 동일해야 합니다. 패턴의 0번 Index는 진동 세기의 0번 Index에 대응됩니다.

즉, 다음과 같이 동작합니다.

Index 0: 100  // wait for 100ms, Amplitude: 0
Index 1: 200  // vibrate for 200ms, Amplitude: 50
Index 2: 100  // wait for 100ms, Amplitude: 0
Index 3: 200  // vibrate for 200ms, Amplitude: 50
Index 4: 100  // wait for 100ms, Amplitude: 0
Index 5: 200  // vibrate for 200ms, Amplitude: 50

3.4 진동 반복

createWaveform()의 마지막 인자로 진동을 반복시킬지 결정합니다. -1은 반복하지 않음, 0 이상은 패턴의 Index부터 배열 마지막까지만 반복하는 것을 의미합니다.

즉, 아래 코드에서 repeat 인자를 0으로 전달하면 패턴 진동을 한번 발생시키고 0번째 Index부터 마지막까지 무한히 반복합니다. (Index 0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 0 -> 1 ...)

val timing = longArrayOf(100, 200, 100, 200, 100, 200)
val amp = intArrayOf(0, 50, 0, 100, 0, 200)
val effect = VibrationEffect.createWaveform(timing, amp, 0)
vibrator.vibrate(effect)

만약 repeat 인자로 4를 전달하면, 패턴 진동을 한번 발생시키고, Index 4에서 5까지를 무한히 반복합니다. (Index 0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 4 -> 5 -> 4 -> 5 -> 4 ...)

val timing = longArrayOf(100, 200, 100, 200, 100, 200)
val amp = intArrayOf(0, 50, 0, 100, 0, 200)
val effect = VibrationEffect.createWaveform(timing, amp, 4)
vibrator.vibrate(effect)

3.5 진동 취소

반복을 멈추거나 진동을 취소하려면, 다음과 같이 cancel()을 호출하면 됩니다.

val vibrator = getSystemService(Context.VIBRATOR_SERVICE) as Vibrator
vibrator.cancel()

4. Example: Android 12의 VibrationManager를 이용한 진동 발생 (API 31 이상)

Android 12에서 VibratorManager가 추가되었고, 다음과 같이 VibratorManager를 가져올 수 있습니다.

private val vibratorManager: VibratorManager by lazy {
    getSystemService(Context.VIBRATOR_MANAGER_SERVICE) as VibratorManager
}

전체 코드는 GitHub - VibratorManagerInAndroid12에서 확인하실 수 있습니다.

4.1 진동 발생 (1회)

다음 코드를 실행시키면 500ms 진동이 1회 발생합니다.

val vibrationEffect = VibrationEffect.createOneShot(
    500L,
    VibrationEffect.DEFAULT_AMPLITUDE
)
val combinedVibration = CombinedVibration.createParallel(vibrationEffect)
vibratorManager.vibrate(combinedVibration)

첫번째 인자는 발생시키려는 진동 시간이며, 단위는 millisecond입니다. 두번째 인자는 진동 세기로, 1 ~ 255의 값을 전달해야 합니다. 기본 진동 세기를 사용하려면 DEFAULT_AMPLITUDE를 전달하면 됩니다.

4.2 패턴 진동 발생 (1회)

아래 코드는 설정한 패턴으로 1회 진동을 발생시킵니다.

val timing = longArrayOf(100, 200, 100, 200, 100, 200)
val vibrationEffect = VibrationEffect.createWaveform(timing, -1)
val combinedVibration = CombinedVibration.createParallel(vibrationEffect)
vibratorManager.vibrate(combinedVibration)

createWaveform()의 첫번째 인자로 패턴(timing)이 전달되며, 두번째 인자는 repeat으로, -1은 반복하지 않음, 0 이상은 반복을 의미합니다.

패턴 배열의 짝수 Index는 대기 시간, 홀수 Index는 진동이 발생되는 시간입니다.

Index 0: 100  // wait for 100ms
Index 1: 200  // vibrate for 200ms
Index 2: 100  // wait for 100ms
Index 3: 200  // vibrate for 200ms
Index 4: 100  // wait for 100ms
Index 5: 200  // vibrate for 200ms

4.3 패턴(진동 세기 조절) 진동 발생 (1회)

전달되는 패턴의 진동 세기를 조절할 수도 있습니다. 다음과 같이 진동 패턴(timing)과 길이가 동일한 진동 세기(aplitudes) 배열을 인자로 전달합니다. 인자 repeat = -1은 반복하지 않음을 의미합니다.

val timing = longArrayOf(100, 200, 100, 200, 100, 200)
val amplitudes = intArrayOf(0, 50, 0, 100, 0, 200)
val vibrationEffect = VibrationEffect.createWaveform(timing, amplitudes, -1)
val combinedVibration = CombinedVibration.createParallel(vibrationEffect)
vibratorManager.vibrate(combinedVibration)

진동 패턴과 진동 세기 배열의 길이는 모두 동일해야 합니다. 패턴의 0번 Index는 진동 세기의 0번 Index에 대응됩니다.

즉, 다음과 같이 동작합니다.

Index 0: 100  // wait for 100ms, Amplitude: 0
Index 1: 200  // vibrate for 200ms, Amplitude: 50
Index 2: 100  // wait for 100ms, Amplitude: 0
Index 3: 200  // vibrate for 200ms, Amplitude: 50
Index 4: 100  // wait for 100ms, Amplitude: 0
Index 5: 200  // vibrate for 200ms, Amplitude: 50

4.4 진동 반복

repeat 인자를 0 이상으로 전달하면 진동을 반복합니다.

예를 들면, 아래 코드에서 repeat 인자를 0으로 전달하면 패턴 진동을 한번 발생시키고 0번째 Index부터 마지막까지 무한히 반복합니다. (Index 0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 0 -> 1 ...)

val timing = longArrayOf(100, 200, 100, 200, 100, 200)
val amplitudes = intArrayOf(0, 50, 0, 100, 0, 200)
val vibrationEffect = VibrationEffect.createWaveform(timing, amplitudes, 0)
val combinedVibration = CombinedVibration.createParallel(vibrationEffect)
vibratorManager.vibrate(combinedVibration)

만약 repeat 인자로 4를 전달하면, 패턴 진동을 한번 발생시키고, Index 4에서 5까지를 무한히 반복합니다. (Index 0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 4 -> 5 -> 4 -> 5 -> 4 ...)

val timing = longArrayOf(100, 200, 100, 200, 100, 200)
val amplitudes = intArrayOf(0, 50, 0, 100, 0, 200)
val vibrationEffect = VibrationEffect.createWaveform(timing, amplitudes, 4)
val combinedVibration = CombinedVibration.createParallel(vibrationEffect)
vibratorManager.vibrate(combinedVibration)

4.5 진동 취소

cancel()을 호출하여 동작 중인 진동을 취소할 수 있습니다.

vibratorManager.cancel()
Loading script...

Related Posts

codechachaCopyright ©2019 codechacha