54

I want to add haptic feedback to my application's buttons and control them programmatically to show button state (enabled and disabled). The default haptic feedback setter works only for long press. How can i make it work for simple button clicks.

And is there a way to have haptic feedback on events like touch move?

Bugs Happen
  • 2,169
  • 4
  • 33
  • 59
Kshitij Aggarwal
  • 5,287
  • 5
  • 34
  • 41

6 Answers6

123

UPDATE ON DECEMBER 24TH 2019:

The view must be enabled Haptic function by:

  1. Add android:hapticFeedbackEnabled="true" in xml.
  2. Or use view.setHapticFeedbackEnabled(true); in code

    (Cited from Ivan Chau)

However, one more thing to take into consideration is to enable Haptic Setting in virtual devices. This is annoying sometimes, so we have some flags come to help (which will ignore these enable Setting somehow):

view.performHapticFeedback(
    HapticFeedbackConstants.VIRTUAL_KEY, 
    HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING  // Ignore device's setting. Otherwise, you can use FLAG_IGNORE_VIEW_SETTING to ignore view's setting.
);

An example to Mayra is, for run the Haptic Feedback is by using this code.

View view = findViewById(...)
view.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY);

And this line of code can easy be include in you onclick action. The good part with this is you do not need to set a permission in the AndroidManifest (I do not need this on SdkVersion "7" (2.1 or 2.3 is 7 ))

Also note, in my code here, this will only be running if the user has enabled Haptic Feedback as global. See http://developer.android.com/reference/android/view/HapticFeedbackConstants.html for alway use it.

Nguyen Tan Dat
  • 3,780
  • 1
  • 23
  • 24
FIG-GHD742
  • 2,486
  • 1
  • 19
  • 27
  • 18
    Add `android:hapticFeedbackEnabled="true"` in button xml or use `btn.setHapticFeedbackEnabled( true );` in code – Ivan Chau Oct 25 '15 at 03:58
  • 1
    @IvanChau I tried putting in your code, to no avail. Is it because I need to specify a button and not a view? – MrPickles Jun 11 '18 at 14:25
74

Here is an answer, though it might not be the best implementation:

import android.view.View;
import android.os.Vibrator;

public class Main extends Activity implements OnClickListener
{
    private View myView;
    private Vibrator myVib;

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        myVib = (Vibrator) this.getSystemService(VIBRATOR_SERVICE);

        //myView can be any type of view, button, etc.
        myView = (View) this.findViewById(R.id.myView);
        myView.setOnClickListener(this);
    }
    
    @Override
    public void onClick(View v)
    {
        myVib.vibrate(50);
        //add whatever you want after this
    }
}

Don't forget, you also need to add the "android.permission.VIBRATE" permission to the program's manifest. You can do so by adding the following to the "AndroidManifest.xml" file:

<uses-permission android:name="android.permission.VIBRATE"/>
starball
  • 20,030
  • 7
  • 43
  • 238
RyanM
  • 5,680
  • 9
  • 45
  • 55
  • If you place the 'this.getSystemService(VIBRATOR_SERVICE);' inside of a button's onClickListener, then 'this' refers to the button itself which does not have the method getSystemService. Use this instead: 'getApplicationContext().getSystemService(VIBRATOR_SERVICE);' – Eric Leschinski Apr 13 '12 at 13:38
  • you can't always use getApplicationContext() inside an onClickListener – sudocoder Jan 21 '14 at 16:43
31

View has a performHapticFeedback function, which should allow you to perform it whenever you want, i.e., on an OnClick listener.

Cheryl Simon
  • 46,552
  • 15
  • 93
  • 82
  • 1
    I added the following code in the onClick method of the onClickListener but it didn't work btn_left .performHapticFeedback(HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING); Im not really sure how this flag works – Kshitij Aggarwal Feb 10 '10 at 04:48
  • 1
    Did you set haptic feedback to enabled? Per the documentation: http://developer.android.com/intl/fr/reference/android/view/View.html#performHapticFeedback(int) this is necessary to get any haptic feedback to play. I'm not sure about that constant, did you try using VIRTUAL_KEY? – Cheryl Simon Feb 10 '10 at 16:54
  • HapticFeedbackConstants.VIRTUAL_KEY is not available. Im currently using Android 1.5_r2 And yes the haptic feedback is enabled for the buttons in the xml itself. Still no luck – Kshitij Aggarwal Feb 11 '10 at 06:15
  • 3
    Didn't work for me until I added the second flag `HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING`, like in Hamid Vakilian's answer below. – npace Feb 14 '19 at 08:22
  • Won't it work without click? Actually I'm trying to use haptic feedback on success of failure response of an API call and that is working fine in Google Pixel device but not in samsung. – Anshul Tyagi Mar 07 '22 at 18:06
17
getWindow().getDecorView().performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY, HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING);

a straightforward approach you can use in an activity.

3

In addition to the previous answers please make sure that "Vibration Feedback" option is enabled from your device settings

Hoby
  • 1,024
  • 12
  • 24
1

In my case I was trying to preform haptic feedback when a dialog fragment opened. The existing answers to this question weren't working. I had to wrap in postDelayed to get it to work.

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)

    preformHapticFeedback()
}

private fun preformHapticFeedback() {
    val delay = 1L
    requireView().postDelayed(
        {
            requireView().performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY)
        },
        delay
    )
}
James
  • 4,573
  • 29
  • 32