Add haptic feedback to events

One of the most basic use cases for haptics is to provide feedback to user interactions. Time pickers, the key press on a virtual keyboard, and text selection are common examples of good use cases for haptic feedback. For more information about when and how to apply haptics, read Haptics design principles.

This page describes three ways to provide haptic feedback.

These methods use primitives defined at the device level to provide high quality feedback tailored to the device in hand.

All haptic feedback methods respect the user's touch feedback settings by default.

Use View components to generate haptic feedback

Use the View.performHapticFeedback method to generate haptic feedback. The haptic constants defined by the HapticFeedbackConstants are focused on their functionality in an application, not the type of haptic effect performed.

The underlying implementation might vary depending on the device and hardware capabilities, but the app only needs to consider the type of feedback to provide in a particular context. By focusing on the functionality, you can enable haptic feedback for similar interactions. Users learn to associate different meanings to different haptic sensations over time.

Prerequisites: Enable haptic feedback

As long as the View is visible, haptic feedback can be used for its events. Some events, such as long press, have default haptics that are triggered if a listener on the view handles the event (returns true).

An Android View can disable haptic feedback by setting the View.hapticFeedbackEnabled property to false. Disabling this property results in default feedback.

The performHapticFeedback method also honors the system setting HAPTIC_FEEDBACK_ENABLED, which allows the user to potentially disable them for the entire system.

Unlike other haptic APIs, using HapticFeedbackConstants with a View doesn't require the VIBRATE permission.

Choose a HapticFeedbackConstant

When using View components with HapticFeedbackConstants, there's no need to evaluate specific device support, as these constants will have fallback behavior if necessary. The only consideration is the SDK level of the desired constant.

Example 1: Keypress

This is an example of how to add a haptic feedback to a touch input in View using touch listeners. The effects simulate the feeling of pressing down on a button and then releasing it.

Kotlin

class HapticTouchListener : View.OnTouchListener {
  override fun onTouch(View view, MotionEvent event) : Boolean {
    when (event.actionMasked) {
      MotionEvent.ACTION_DOWN ->
        view.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY)
      MotionEvent.ACTION_UP ->
        view.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY_RELEASE)
    }
    return true
  }
}

Java

class HapticTouchListener implements View.OnTouchListener {
  @Override
  public boolean onTouch(View view, MotionEvent event) {
    switch (event.getAction()) {
      case MotionEvent.ACTION_DOWN:
        view.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY);
        break;
      case MotionEvent.ACTION_UP:
        view.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY_RELEASE);
        break;
    }
    return true;
  }
}

Example 2: Submit button

Haptic feedback use cases go beyond simulating a physical interaction with the device. They might also be used to convey an abstract meaning. For example, the general expectation for a CONFIRM effect is a short and light vibration while a REJECT might be a stronger feedback to signal failure. This is illustrated in the following example for a submit button feedback.

Kotlin

submitButton.setOnClickListener { view ->
  val successful = performSubmit()
  if (successful) {
    view.performHapticFeedback(HapticFeedbackConstants.CONFIRM)
  } else {
    view.performHapticFeedback(HapticFeedbackConstants.REJECT)
  }
}

Java

submitButton.setOnClickListener(view -> {
  boolean successful = performSubmit();
  if (successful) {
    view.performHapticFeedback(HapticFeedbackConstants.CONFIRM);
  } else {
    view.performHapticFeedback(HapticFeedbackConstants.REJECT);
  }
});

Use a predefined VibrationEffect to generate haptic feedback

Using the View-based approach focuses on the user interaction. It is preferred for consistency across the system. However, specific predefined VibrationEffect APIs can also be invoked for customized haptic feedback effects.

Predefined effects are available as VibrationEffect constants, and can be checked for support and played with the Vibrator service as shown in the following examples.

Understand device support of VibrationEffect APIs

In basic usage, there should be no need to check for support of individual VibrationEffect APIs. The APIs such as Vibrator.areEffectsSupported and Vibrator.areAllEffectsSupported are used to determine if the device has a customized implementation of the constant. If a customized effect isn't present, your app can still play the effects and use a platform-defined fallback implementation.

For more details, see Predefined VibrationEffect.

Prerequisites: Load the Vibrator and the VIBRATE permission

Most vibrations can be played with the Vibrator service, which can be loaded as follows:

Kotlin

import android.os.Vibrator

val vibrator = context.getSystemService(Vibrator::class.java)

Java

import android.os.Vibrator;

Vibrator vibrator = context.getSystemService(Vibrator.class);

The app needs to have the VIBRATE permission in order to vibrate the device using this service. The permission can be added to the application manifest file:

<uses-permission android:name="android.permission.VIBRATE"/>

Play a predefined VibrationEffect

Predefined effects can be prepared using VibrationEffect.createPredefined, then played using one of the vibrate methods on Vibrator.

This example plays a Click effect.

Kotlin

val vibrator = context.getSystemService(Vibrator::class.java)
...
// Requires VIBRATE permission
vibrator.vibrate(VibrationEffect.createPredefined(VibrationEffect.EFFECT_CLICK))

Java

Vibrator vibrator = context.getSystemService(Vibrator.class);
...
// Requires VIBRATE permission
vibrator.vibrate(VibrationEffect.createPredefined(VibrationEffect.EFFECT_CLICK));

Use advanced compositions with primitives

The VibrationEffect.Composition API offers additional possibilities for haptic feedback. However, unlike effects, these primitives don't have system-level fallbacks, which means that careful attention needs to be paid to the primitives and other capabilities supported by the device.

Using these APIs is discussed in more detail in Creating Custom Haptic Effects.