Как заставить Android устройство вибрировать с разной частотой и амплитудой на Kotlin?
Современное управление вибрацией в Android на Kotlin
Вы абсолютно правы — старый метод vibrate(long) устарел и не дает контроля над частотой и амплитудой. Начиная с Android 8 (API 26) и особенно в Android 12+ появился мощный API VibrationEffect и VibratorManager. Вот как решить все три ваши задачи.
1. Базовая настройка и проверка
Сначала получите доступ к вибратору через VibratorManager (рекомендуемый способ для API 31+):
// Для Android 12+ (API 31+)
val vibratorManager = getSystemService(Context.VIBRATOR_MANAGER_SERVICE) as VibratorManager
val vibrator = vibratorManager.defaultVibrator
// Для всех версий (обратная совместимость)
val vibrator = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
val manager = getSystemService(Context.VIBRATOR_MANAGER_SERVICE) as VibratorManager
manager.defaultVibrator
} else {
@Suppress("DEPRECATION")
getSystemService(Context.VIBRATOR_SERVICE) as Vibrator
}
// Всегда проверяйте наличие вибратора
if (!vibrator.hasVibrator()) return
2. Вибрация с заданной частотой (Гц)
Частота вибрации задается через VibrationEffect.Prebaked или через кастомные эффекты. Для точной частоты (например, 100 Гц) используйте VibrationEffect.Composition:
// Создаем эффект вибрации с частотой 100 Гц на 1 секунду
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { // API 33+
val effect = VibrationEffect.startComposition()
.addEffect(
VibrationEffect.createWaveform(
longArrayOf(0, 1000), // сразу начать, длиться 1 сек
intArrayOf(128), // амплитуда 50% (0-255)
-1 // не повторять
),
VibrationEffect.Composition.PRIMITIVE_QUICK_RISE // быстрый старт
)
.compose()
vibrator.vibrate(effect)
} else {
// Для старых версий — просто вибрация с амплитудой
val effect = VibrationEffect.createWaveform(
longArrayOf(0, 1000),
intArrayOf(128),
-1
)
vibrator.vibrate(effect)
}
3. Шаблон с паузами (последовательность вибраций)
Создайте паттерн из чередующихся "вибрация/тишина":
// Паттерн: вибрация 200мс, пауза 100мс, вибрация 400мс, пауза 200мс, вибрация 200мс
val timings = longArrayOf(0, 200, 100, 400, 200, 200) // [задержка, вибрация, пауза, вибрация...]
val amplitudes = intArrayOf(0, 255, 0, 128, 0, 64) // амплитуды для каждого отрезка
val effect = VibrationEffect.createWaveform(timings, amplitudes, -1) // -1 = не повторять
vibrator.vibrate(effect)
// Для бесконечного повторения (например, для будильника):
val repeatingEffect = VibrationEffect.createWaveform(timings, amplitudes, 0) // повторять с индекса 0
vibrator.vibrate(repeatingEffect)
4. Пульсирующая вибрация с нарастанием
Для эффекта "пульсации" комбинируйте примитивы:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
val composition = VibrationEffect.startComposition()
.addPrimitive(VibrationEffect.Composition.PRIMITIVE_QUICK_RISE, 0.5f, 0) // 50% силы
.addPrimitive(VibrationEffect.Composition.PRIMITIVE_TICK, 0.3f, 200) // через 200мс
.addPrimitive(VibrationEffect.Composition.PRIMITIVE_SLOW_RISE, 1.0f, 400) // еще через 400мс
.compose()
vibrator.vibrate(composition)
}
5. Полный пример для вашего случая
class VibrationHelper(private val context: Context) {
private val vibrator: Vibrator by lazy {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
val manager = context.getSystemService(Context.VIBRATOR_MANAGER_SERVICE) as VibratorManager
manager.defaultVibrator
} else {
@Suppress("DEPRECATION")
context.getSystemService(Context.VIBRATOR_SERVICE) as Vibrator
}
}
fun vibrateNotification() {
// Короткая слабая вибрация (50% амплитуды, 100мс)
val effect = VibrationEffect.createWaveform(
longArrayOf(0, 100),
intArrayOf(128),
-1
)
vibrator.vibrate(effect)
}
fun vibrateAlarm() {
// Длинная сильная с повторением
val effect = VibrationEffect.createWaveform(
longArrayOf(0, 1000, 500, 1000),
intArrayOf(255, 0, 255),
0 // повторять
)
vibrator.vibrate(effect)
}
fun vibrateGamePulse() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
val effect = VibrationEffect.startComposition()
.addPrimitive(VibrationEffect.Composition.PRIMITIVE_QUICK_RISE, 0.8f, 0)
.addPrimitive(VibrationEffect.Composition.PRIMITIVE_SLOW_RISE, 1.0f, 300)
.compose()
vibrator.vibrate(effect)
}
}
}
Важные замечания
- Разрешения: Для API 26+ не требуется дополнительных разрешений в манифесте, но для Android 13+ (API 33) нужно добавить
<uses-permission android:name="android.permission.VIBRATE" />. - Амплитуда: Работает только на устройствах с поддержкой амплитудной модуляции (большинство современных смартфонов). Значения от 0 (нет вибрации) до 255 (максимум).
- Частота: Точная частота (в Гц) доступна только через
VibrationEffect.Compositionна API 33+, на старых устройствах используйте длительность и амплитуду для имитации. - Тестирование: На эмуляторе вибрация может не работать — проверяйте на реальном устройстве.
Альтернативный подход: использование AudioTrack для кастомной вибрации
Если вам нужна очень точная частота вибрации (например, для тактильной обратной связи в играх) или вы работаете со старыми устройствами без поддержки VibrationEffect, можно использовать хак с AudioTrack и генерацией низкочастотного звука. Однако этот метод работает не на всех устройствах и требует разрешения RECORD_AUDIO.
fun vibrateWithFrequency(context: Context, frequencyHz: Int, durationMs: Int) {
val vibrator = context.getSystemService(Context.VIBRATOR_SERVICE) as Vibrator
if (!vibrator.hasVibrator()) return
// Генерируем синусоиду нужной частоты
val sampleRate = 44100
val Ответов пока нет.
Войдите чтобы оставить ответ