Using Haptics in Mobile Apps
Add tactile feedback that feels considered, not annoying — Core Haptics on iOS, the new VibratorManager on Android, and Expo cross-platform helpers.
Haptics are the difference between an app that *feels* alive and one that doesn't. iPhones ship the Taptic Engine — a precise linear actuator that can play complex patterns. Modern Android phones increasingly ship LRA actuators with the new VibratorManager API. Both expose simple "light/medium/heavy" presets and rich, file-driven patterns. Used well, haptics confirm actions, signal limits, and reinforce identity.
Key Takeaways
- Use UIImpactFeedbackGenerator / UINotificationFeedbackGenerator on iOS for simple cues; Core Haptics for rich patterns.
- On Android, use VibratorManager + VibrationEffect.createPredefined / createWaveform.
- Expo Haptics covers the 80% case across both platforms with one API.
- Always respect the user's system-level haptics setting and avoid haptics on cold-start screens.
Haptics at a Glance
What It Is & How It Works
What it is. A linear resonant actuator (LRA) or eccentric rotating mass (ERM) motor in the device. The OS exposes a high-level (presets) and low-level (patterns / waveforms) API on top of it.
How it works. On iOS you create a feedback generator (impact / notification / selection) or a CHHapticEngine pattern. On Android you ask the system Vibrator service to play predefined or composed waveforms.
Units & signal. Intensity (0-1), sharpness (0-1), duration (ms), pattern array of (duration, amplitude) pairs.
What You Can Build With It
Action confirmations
Light tap when the user toggles a switch or hits a button.
Example: A camera shutter button with a light impact on tap.
Error / warning cues
Notification feedback (success / warning / error) that complements an alert.
Example: A login screen using the error notification haptic on bad password.
Reach indicators in scrollers
Subtle bumps when scrolling past a section or hitting an end-stop.
Example: A picker wheel ticking each step.
Game feedback
Rich patterns (explosions, footsteps, weapon firing).
Example: A racing game using AHAP patterns to mimic engine RPM.
Permissions & Setup
iOS exposes haptics with no permission. Android needs the VIBRATE manifest permission, which is install-time only.
iOS · Info.plist
No permission required
Android · AndroidManifest.xml
android.permission.VIBRATE
Code Examples
Setup
- Expo: `npx expo install expo-haptics`
- iOS: import CoreHaptics for advanced patterns; UIKit for simple presets
- Android: add VIBRATE permission and use VibratorManager (API 31+)
import * as Haptics from 'expo-haptics';
export const tap = () => Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Light);
export const success = () => Haptics.notificationAsync(Haptics.NotificationFeedbackType.Success);
export const error = () => Haptics.notificationAsync(Haptics.NotificationFeedbackType.Error);
export const tick = () => Haptics.selectionAsync();Tip: With Newly, you describe the feature you want and the AI agent wires up the sensor, permissions, and UI for you. Try it free.
Best Practices
Pair haptics with visual / audio
A haptic without a visual change is easy to miss; together they make actions feel decisive.
Prepare generators on iOS
Call `prepare()` ahead of time on UIFeedbackGenerator to remove first-tap latency.
Throttle long sequences
Continuous vibrations drain battery and annoy users; cap pattern duration and frequency.
Honour the user's settings
Check Settings > Sounds & Haptics (iOS) and Settings > Sound & vibration (Android) preferences before firing patterns; expo-haptics already respects the Silent switch.
Common Pitfalls
Firing on every render
A haptic per render = a buzzing brick. Debounce on actual state change.
Mitigation: Trigger from event handlers, not effect callbacks.
Overusing notification haptics
Success / warning / error are special; using them for every micro-interaction dilutes meaning.
Mitigation: Reserve them for completing flows, not in-flight actions.
Assuming Android has Taptic Engine quality
Many budget Androids have ERM motors that ignore amplitude entirely.
Mitigation: Test on representative low-end devices and feature-detect.
When To Use It (And When Not To)
Good fit
- Confirming user actions (toggles, taps, selections)
- Surfacing errors and successes in flows
- End-stop / boundary feedback in scrollable UIs
- Game effects and immersive interactions
Look elsewhere if…
- Background notifications (use system push)
- Continuous vibration as ambient effect
- Replacing screen-reader / a11y feedback
- Anything that fires more than 5-10 times per second sustained
Frequently Asked Questions
How do I write rich haptic patterns?
On iOS, ship AHAP files and load them with `CHHapticEngine.playPattern(from:)`. On Android, build VibrationEffect.Composition for nuanced sequences.
Why don't my Android haptics feel as crisp as iPhone?
Hardware varies wildly. Use predefined effects (EFFECT_CLICK, EFFECT_TICK) when you can — those are tuned per device.
Can I trigger haptics from the background?
Generally no — both OSes restrict background vibration to system events.
How do I check if haptics are supported?
On iOS, `CHHapticEngine.capabilitiesForHardware().supportsHaptics`. On Android, `Vibrator.hasVibrator()` and (API 31+) `hasAmplitudeControl()`.
Build with the Haptics on Newly
Ship a haptics-powered feature this week
Newly turns a description like “use the haptics to action confirmations” into a real React Native app — permissions, native modules and UI included. Full source code is yours, and you can publish to the App Store and Google Play directly from the dashboard.
Want a deeper dive on the underlying APIs? See Expo Sensors, Apple Core Motion and Android sensor framework.
