Why Control Vibration on Android? From "Buzz" to a Tactile Masterpiece
\n\nHave you ever wondered why some apps vibrate pleasantly and precisely, while others feel like a neighbor's drill through the wall? It's all about vibration frequency and amplitude. On Stack Overflow, the question "How to make an Android device vibrate with different frequency?" has garnered thousands of views — and for good reason. Developers want not just to "turn on the vibrator," but to create meaningful haptic feedback: a light touch, a pulsing alarm signal, or an imitation of a mechanical button press.
\n\nIn this article, we'll break down how to control vibration on Android using Kotlin. You'll learn what APIs exist, how they've evolved from Android 8 to Android 14, and which approach to choose for your project. Let's go!
\n\nA Brief History Lesson: From Vibrator to VibratorManager
\n\nFor a long time, Android developers used the Vibrator class and the vibrate(long milliseconds) method. Simple, but sad: no control over frequency. With the arrival of Android 8 (API 26), Google introduced VibrationEffect — a powerful tool for creating complex vibration patterns. And in Android 12 (API 31), they added VibratorManager, which allows you to control multiple vibrators (for example, on foldable devices).
Today we have three main approaches:
\n- \n
- Vibrator + VibrationEffect (API 26+) — basic, but flexible. \n
- VibratorManager (API 31+) — modern, for multi-vibrator devices. \n
- Legacy Vibrator.vibrate() — only for backward compatibility. \n
We'll focus on the first two, as they provide control over frequency and amplitude.
\n\nPreparation: Vibration Permission
\n\nBefore you trigger an "earthquake," don't forget to add the permission to AndroidManifest.xml:
<uses-permission android:name="android.permission.VIBRATE" />\n\nWithout it, your code will simply be ignored — no errors, but no vibration either.
\n\nMethod 1: VibrationEffect — Controlling Frequency and Amplitude (API 26+)
\n\nThe VibrationEffect class allows you to create vibration with a specified frequency (via amplitude) and duration. Frequency in Android is not set directly in hertz — instead, amplitude (0–255) is used, which is hardware-converted into frequency. The higher the amplitude, the more intense the vibration.
Simple Vibration with Amplitude
\n\nval vibrator = getSystemService(Context.VIBRATOR_SERVICE) as Vibrator\n\n// Vibration for 500 ms with maximum amplitude (255)\nval effect = VibrationEffect.createOneShot(500, VibrationEffect.DEFAULT_AMPLITUDE)\nvibrator.vibrate(effect)\n\nVibration with Different Frequency (Amplitude)
\n\nWant a weak vibration? Specify an amplitude of 50:
\nval weakVibration = VibrationEffect.createOneShot(300, 50)\nvibrator.vibrate(weakVibration)\n\nAmplitude 255 is maximum, 1 is barely noticeable. Experiment!
\n\nPatterns: Vibration with Pauses
\n\nSometimes you need not just a "buzz," but a pulse. Use createWaveform:
val timings = longArrayOf(0, 200, 100, 300) // pause, vibration, pause, vibration\nval amplitudes = intArrayOf(0, 200, 0, 150) // amplitude for each stage\n\nval pattern = VibrationEffect.createWaveform(timings, amplitudes, -1) // -1 = do not repeat\nvibrator.vibrate(pattern)\n\nThe first element of timings is the initial delay. Usually set to 0. amplitudes must be the same length. If you pass null instead of the amplitude array, the maximum amplitude will be used for all stages.
Method 2: VibratorManager — For Modern Devices (API 31+)
\n\nStarting with Android 12, it is recommended to use VibratorManager