Add haptic feedback and iOS asks you for nothing, while Android wants one line in the manifest.
iOS needs no permission to play a haptic. Android needs android.permission.VIBRATE in the app manifest, and only for the APIs that drive the vibrator directly; Google's own recommended path, View.performHapticFeedback, needs no permission at all. Neither platform ever shows a person a dialog about this, so there is no denial to code against. What a person can refuse is the system-wide setting, and both platforms honour it under you without telling your code. Every API name, permission string and version below was read from Apple's and Google's own developer documentation on 3 October 2026.
Vibration feedback on iOS and Android starts from the same idea and diverges almost immediately, so this page takes them one at a time: the permission, the current API names and the ones they replaced, what the hardware has to be for a tap to exist at all, and why a haptic can never be the only way your app says something. Haptics are a finishing pass, which puts them with the rest of app design basics rather than with features.
See what one haptic needsThe short version
One manifest line on Android, nothing on iOS, and one switch neither of you controls.
The asymmetry is small, and it bites in a specific place. On iOS you call a feedback generator and the system decides whether anything happens, weighing the device, the app state, the battery level and other factors. Feedback plays only on a device with haptic hardware, only in the foreground, and only when the system Haptics setting is on. Apple says to trust the system and not to check these yourself, and that it ignores any request it cannot fulfil. On Android you declare the permission if your path needs it, play the effect, and the platform substitutes something it can manage.
So the bug you will meet is not a permission denial. It is a haptic that works on your phone, does nothing on an iPad, and cannot be confirmed at your desk at all, because the documented condition on both platforms is real hardware with a motor in it.
The permission each platform wants, and who actually gets asked
Android wants android.permission.VIBRATE declared in the app manifest. Google's haptics reference is specific about which calls need it: playing any VibrationEffect requires it, and so do the older one-shot and waveform vibrations. Using View.performHapticFeedback with a value from HapticFeedbackConstants requires no special permission, which is part of why Google marks that path as the recommended one and says it has the widest support.
iOS asks for nothing. Apple's haptics documentation describes no permission, no entitlement and no usage string in the Info.plist for playing feedback, and there is no dialog for the system to show. The UIKit feedback generators and Core Haptics are both open to any app that wants them.
Nobody is prompted on either platform, and this is where most pages about a haptic feedback app go wrong. Android's permission reference lists VIBRATE at protection level normal. Google's permissions guide says normal permissions are a sub-type of install-time permission, that they cover actions presenting very little risk, and that the system grants install-time permissions automatically when the user installs the app. The only place a person sees it is the install-time permission notice an app store shows on your listing. There is no revoke screen and no denial path, so code that requests vibration at runtime is asking for a prompt the platform has never shown.
What people do refuse is the feedback itself. Both platforms expose exactly one system-wide switch and both honour it beneath your code. Google names its setting touch feedback, says the feedback methods respect it by default, and notes that a custom implementation may have to read it directly through the HAPTIC_FEEDBACK_ENABLED key, where zero means off. Apple names its equivalent the system Haptics setting. Neither gives your code a callback when it flips.
Android Developers, Android haptics API reference, read 3 October 2026
The current API names, and the ones they quietly replaced
On iOS the entry point is a UIFeedbackGenerator subclass, and there are four. UIImpactFeedbackGenerator is for a collision or a snap into place, with styles light, medium, heavy, soft and rigid. UISelectionFeedbackGenerator is for a value changing. UINotificationFeedbackGenerator carries success, warning and error. Those three have been there since iOS 10. UICanvasFeedbackGenerator, for a drawing event such as an object snapping to a guide, is newer and needs iOS 17.5. Apple tells you not to instantiate the superclass itself. One rename to carry over: on UIImpactFeedbackGenerator the initialiser taking only a style is marked deprecated, and the current one takes a style and a view. In SwiftUI the same job is the sensoryFeedback modifier with a SensoryFeedback value, iOS 17 and later, and Core Haptics, iOS 13 and later, is the layer underneath for patterns you compose yourself from transient and continuous events with their own sharpness and intensity.
On Android there are three live approaches and Google ranks them. View.performHapticFeedback with a HapticFeedbackConstants value comes first: widest support, no permission, and the constants name the action rather than the sensation, so CONFIRM means a confirmation and REJECT means a failure. The only compatibility question is each constant's own API level, and those run from 3 to 34: LONG_PRESS from API level 3, CONTEXT_CLICK from 23, CONFIRM and REJECT from 30, and TOGGLE_ON, TOGGLE_OFF, SEGMENT_TICK and DRAG_START from 34. A predefined VibrationEffect, Android 10 and later, gives you CLICK, TICK and DOUBLE_CLICK through the vibrator service, and that path does need the permission.
Two Android APIs have been superseded, and the pages describing them are still ranking. VibrationEffect.Builder arrived in Android 16 and is now Google's preferred way to compose an effect; it supersedes VibrationEffect.Composition, which landed in Android 11 and remains only for compatibility on older releases. Presets take over from the short primitives, and envelopes, the piecewise linear kind, take over from the rise and fall primitives for anything continuous. The practical difference is fallback. Compositions built with the new builder get automatic platform substitution when a device cannot play an element, while the old Composition API plays nothing at all if a single primitive in it is unsupported, which is why that path also needs a per-primitive support check. Google separately says it strongly discourages the older createOneShot and createWaveform calls, describing them as too loud for regular feedback and worth using only to highlight an extremely important action.
Whichever you use, choose by what happened rather than by how it feels. Apple makes the same point in the Human Interface Guidelines: use a system pattern according to its documented meaning, and if that meaning does not fit your case, use a generic pattern or build your own. A REJECT on a failed submit is legible to anyone who has felt it elsewhere on the device. A reward tap fired when you add rating prompt logic to a screen is not, and it spends the attention you wanted for the request itself.
Check it
What this one haptic needs from you
Pick the platform and what the person just did. Every name and version here comes from Apple's or Google's own documentation, read 3 October 2026.
UIImpactFeedbackGenerator
Permission: none. Available from iOS 10, styles light to rigid. Neither platform shows the user a prompt, and the feedback is dropped in silence when the system setting is off or the device has no haptic hardware.
The hardware decides, and the system never tells you what it decided
Apple's rule here changes how you write the code, so it is worth stating plainly. Calling a feedback API does not play a haptic. It informs the system that an event happened, and the system then decides, based on the device, the app state, how much battery is left and other factors. Feedback plays only on a device with hardware for haptic feedback, only while your app is in the foreground, and only when the system Haptics setting is on. Apple's instruction is not to check the device type or app state to decide whether to trigger feedback, and to trust that it ignores any request it cannot fulfil.
That is comfortable until you need to know whether anything happened. If you are using Core Haptics rather than a feedback generator, Apple does hand you a check: fetch the hardware capabilities and read supportsHaptics. Its setup guide also names devices with no haptic support, and the list it gives includes iPad, iPod touch and Apple Vision Pro. Android's equivalents are blunter and more useful. The vibrator service is non-null even on a device with no motor, the calls simply have no effect, and hasVibrator tells you whether you have a real vibrator or a stub. hasAmplitudeControl tells you whether varying intensities will survive, because without it every non-zero amplitude is rounded up to full. areEffectsSupported answers only whether an effect is tuned for that device, and it is allowed to return unknown.
Neither platform lets you feel any of this at a desk. Apple's documented condition is hardware for haptic feedback, and we could not find an Apple page that states whether Simulator plays haptics at all, so treat a simulator run as proof that your code path fires and nothing more. Android covers the same case in its own words: a device without a vibrator returns a stub and the calls do nothing. Put a real iPhone and a real Android phone in the test loop before you tune anything, and do not promise a client a haptic you have only seen in a log line.
Latency is the other thing a desk cannot show you. On iOS the prepare method exists for it: it puts the Taptic Engine in a prepared state for a short period so the next feedback fires with lower latency. Apple calls it optional and highly recommended, and warns that calling prepare and triggering immediately buys nothing, because the system needs that gap to get ready. The engine returns to idle after you trigger feedback, after a few seconds pass, or when the generator is deallocated, so a Taptic Engine in your app is something you warm up just before a gesture rather than hold open. How much of a late tap a person actually notices belongs with keeping the app feeling fast rather than here.
Apple Developer, Playing haptic feedback in your app, read 3 October 2026
A haptic can never be the only way the app says something
Make haptics optional. That is Apple's own wording in the Human Interface Guidelines, and the sentence after it says to make sure people can still enjoy your app without them. It is not a courtesy. The system-wide switch exists on both platforms, people turn it off for battery or because they dislike it, and your code never hears about it. Any state you communicate with a tap alone is a state those users never receive.
That makes this an accessibility requirement rather than a preference. Pair every haptic with something visible, audible, or both, then check that the visible version carries the whole meaning on its own. Google's haptics documentation sends readers to its accessibility best practices for the same reason. The rest of that work, label text, contrast, target sizes and reading order, is the subject of mobile app accessibility, and a haptic added for polish is the cheapest item on that list to get wrong.
Two more constraints from the documentation catch people out. Apple warns that haptics produce enough physical force to be felt and asks you to make sure the vibration does not disrupt device features like the camera, the gyroscope or the microphone, so do not fire one during a capture. On Android, vibrating while your app is in the background requires vibration attributes that tell the system what the vibration is for, because only attentional haptics are supported for background use.
Then there is restraint, which is the part no API enforces. Apple's guidance is that a haptic can feel right when it happens occasionally and become tiresome when it plays frequently, and that the best haptic experience is often one people are not conscious of but miss when it is turned off. In practice: one tap for the thing that mattered, and nothing at all for scrolling, loading or arriving.
What each path needs, platform by platform
| What you are checking | iOS feedback generators | Android View constants | Android VibrationEffect |
|---|---|---|---|
| Permission to declare | none | none | VIBRATE, in the app manifest |
| Runtime prompt the user can refuse | No | No | No |
| Available from | iOS 10, Core Haptics from iOS 13 | per constant, from API level 3 | Android 10 for predefined effects |
| Fallback when the device cannot play it | system ignores what it cannot fulfil | Yes | predefined yes, old Composition API no |
| Honours a system-wide off switch | yes, the system Haptics setting | yes, the touch feedback setting | yes, and attributes set the purpose |
Adding the taps in an app you own
The code is small on both platforms. One generator call or one constant, dropped into the handler that already runs when the thing happens, plus a decision about which events deserve one at all. The editing is the work: a first pass almost always has three times too many, and the ones to cut are the ones that fire on something the user did not do.
Newly is an AI app builder. You describe the app in plain English and it writes a real React Native and TypeScript project you own, runs it on cloud iOS and Android simulators while it builds, then ships it to TestFlight and to Google Play internal testing. It is $25 a month and there is no free plan. A cloud simulator will show you that the haptic code runs, not what it feels like, so keep a real phone in the loop for this one. If you would rather wire it by hand, the project comes out as a ZIP from Settings or through the two-way GitHub sync in the Deploy tab.
And whatever wrapper sits at the JavaScript layer, the platform rules underneath do not change. If the library you use calls the Android vibrator service, your manifest still needs the VIBRATE line. If it calls a feedback generator on iOS, the system still decides whether anything happens, and it still will not tell you.
Questions people ask about haptic feedback
On iOS, no. Apple's haptics documentation describes no permission, no entitlement and no Info.plist usage string. On Android it depends on the API. Playing any VibrationEffect requires android.permission.VIBRATE declared in the app manifest, while View.performHapticFeedback with a HapticFeedbackConstants value requires no special permission at all. Neither platform prompts the user either way.
Decide which three events get a tap
List the events that genuinely deserve a haptic, pick the constant or the generator that matches what happened rather than how it feels, declare the manifest line if your Android path needs it, and plan a real phone into the test pass on both platforms before you tune anything.
Start building