Android SDK
The Pulsar Android SDK provides haptic feedback through three building blocks: Presets, PatternComposer, and RealtimeComposer. All are accessed through the main Pulsar class.
Requirements
Section titled “Requirements”- Android API 24+ (Android 7.0)
- Kotlin 1.9+
Installation
Section titled “Installation”Add Pulsar as a Gradle dependency:
dependencies { implementation("com.swmansion:pulsar:1.0.0")}Create a Pulsar instance with an Android Context:
import com.swmansion.pulsar.Pulsar
val pulsar = Pulsar(context)Presets
Section titled “Presets”A collection of ready-to-use haptic patterns accessed through pulsar.getPresets().
val presets = pulsar.getPresets()Built-in presets
Section titled “Built-in presets”| Method | Description |
|---|---|
afterglow() | A three-beat phrase that dissolves gently, ideal for soft endings or gradually quieting feedback. |
aftershock() | A firm opening that settles calmly, ideal for transitions needing a strong start and a gentle finish. |
alarm() | Relentless and urgent, best for critical errors or emergencies that require immediate attention. |
anvil() | The full weight of a massive collision, conveys sheer physical force and momentum. |
applause() | A growing wave of appreciation, ideal for celebratory moments or social approval. |
Example
val presets = pulsar.getPresets()
presets.applause()System presets
Section titled “System presets”These mirror standard haptic feedback styles shared across platforms.
| Method | Description |
|---|---|
systemImpactHeavy() | Heavy impact |
systemImpactLight() | Light impact |
systemImpactMedium() | Medium impact |
systemImpactRigid() | Rigid impact |
systemImpactSoft() | Soft impact |
Example
val presets = pulsar.getPresets()
presets.systemImpactMedium()Android-specific system presets
Section titled “Android-specific system presets”Android exposes additional system effects beyond the cross-platform set.
| Method | Description |
|---|---|
systemCalendarDate() | HapticFeedbackConstants.CALENDAR_DATE |
systemClockTick() | HapticFeedbackConstants.CLOCK_TICK |
systemConfirm() | HapticFeedbackConstants.CONFIRM |
systemContextClick() | HapticFeedbackConstants.CONTEXT_CLICK |
systemDragCrossing() | HapticFeedbackConstants.DRAG_CROSSING |
Example
val presets = pulsar.getPresets()
presets.systemPrimitiveClick()Playing by name
Section titled “Playing by name”You can play any preset by its string name using getByName(). This returns a Preset? that you call play() on.
Available names:
AfterglowAftershockAlarmAnvilApplauseAscentBalloonPopBarrage
Example
val presets = pulsar.getPresets()
// Direct callpresets.dogBark()
// By namepresets.getByName("SystemImpactMedium")?.play()PatternComposer
Section titled “PatternComposer”Composes and plays custom haptic patterns. Get a new instance from pulsar.getPatternComposer(). Each call returns a fresh composer, so you can manage multiple patterns independently.
val composer = pulsar.getPatternComposer()Methods
Section titled “Methods”parsePattern(hapticsData)
Section titled “parsePattern(hapticsData)”Parses a PatternData object and prepares it for playback.
fun parsePattern(hapticsData: PatternData)play()
Section titled “play()”Plays the previously parsed pattern.
fun play()stop()
Section titled “stop()”Stops all playback.
fun stop()Example
Section titled “Example”val composer = pulsar.getPatternComposer()
val pattern = PatternData( continuousPattern = ContinuousPattern( amplitude = listOf( ValuePoint(time = 0, value = 0f), ValuePoint(time = 200, value = 1f), ValuePoint(time = 400, value = 0f), ), frequency = listOf( ValuePoint(time = 0, value = 0.3f), ValuePoint(time = 400, value = 0.8f), ) ), discretePattern = listOf( ConfigPoint(time = 0, amplitude = 1f, frequency = 0.5f), ConfigPoint(time = 100, amplitude = 0.5f, frequency = 0.5f), ))
composer.parsePattern(pattern)composer.play()RealtimeComposer
Section titled “RealtimeComposer”Provides real-time haptic control with live amplitude and frequency modulation. Useful for gesture-driven or continuously evolving haptic experiences. Get the shared instance from pulsar.getRealtimeComposer().
val realtime = pulsar.getRealtimeComposer()An optional strategy parameter controls how continuous haptics are simulated:
val realtime = pulsar.getRealtimeComposer(strategy = RealtimeComposerStrategy.ENVELOPE)| Strategy | Description |
|---|---|
ENVELOPE | Envelope API approximation (API 36+) |
PRIMITIVE_TICK | Composition API with varying tick intervals |
PRIMITIVE_COMPLEX | Multiple primitives selected based on frequency |
ENVELOPE_WITH_DISCRETE_PRIMITIVES | Default. Envelope API for continuous events (API 36+); composition primitives for discrete events (API 33+). |
Methods
Section titled “Methods”set(amplitude, frequency)
Section titled “set(amplitude, frequency)”Updates the ongoing haptic with new amplitude and frequency values. Automatically starts playback if it is not already active. Values should be in the 0-1 range.
fun set(amplitude: Float, frequency: Float)playDiscrete(amplitude, frequency)
Section titled “playDiscrete(amplitude, frequency)”Plays a single discrete haptic event.
fun playDiscrete(amplitude: Float, frequency: Float)stop()
Section titled “stop()”Stops the active continuous haptic.
fun stop()isActive()
Section titled “isActive()”Returns true if a continuous haptic is currently playing.
fun isActive(): BooleanExample
Section titled “Example”val realtime = pulsar.getRealtimeComposer()
// Start a continuous hapticrealtime.set(amplitude = 0.5f, frequency = 0.8f)
// Update parameters over timerealtime.set(amplitude = 1.0f, frequency = 0.3f)
// Play a one-off discrete eventrealtime.playDiscrete(amplitude = 0.7f, frequency = 0.5f)
// Stoprealtime.stop()Settings
Section titled “Settings”Configuration methods available directly on the Pulsar instance.
| Method | Description |
|---|---|
enableHaptics(state: Boolean) | Enable or disable all haptic feedback |
enableSound(state: Boolean) | Enable or disable audio simulation |
enableCache(state: Boolean) | Enable or disable preset caching |
clearCache() | Clear the preset cache |
preloadPresets(presetNames: List<String>) | Preload presets by name for faster playback |
stopHaptics() | Stop all currently playing haptics |
hapticSupport() | Returns the device’s CompatibilityMode |
forceHapticsSupportLevel(mode: CompatibilityMode) | Override the detected support level |
enableImpulseCompositionMode(state: Boolean) | Enable or disable VibrationEffect.Composition for impulse-only presets (enabled by default) |
Example
Section titled “Example”val pulsar = Pulsar(context)
// Preload frequently used presetspulsar.preloadPresets(listOf("Earthquake", "Success"))
// Disable haptics temporarilypulsar.enableHaptics(false)
// Check device supportval support = pulsar.hapticSupport()if (support >= CompatibilityMode.STANDARD_SUPPORT) { pulsar.getPresets().success()}PatternData
Section titled “PatternData”Describes a complete haptic pattern with discrete pulses and continuous envelope curves.
data class PatternData( val continuousPattern: ContinuousPattern, val discretePattern: List<ConfigPoint>)ContinuousPattern
Section titled “ContinuousPattern”Represents continuous haptic curves for amplitude and frequency.
data class ContinuousPattern( val amplitude: List<ValuePoint>, val frequency: List<ValuePoint>)ValuePoint
Section titled “ValuePoint”A single point in a continuous curve.
data class ValuePoint( val time: Long, // Milliseconds from pattern start val value: Float // Normalized value (0-1))ConfigPoint
Section titled “ConfigPoint”A single discrete haptic event.
data class ConfigPoint( val time: Long, // Milliseconds from pattern start val amplitude: Float, // Intensity (0-1) val frequency: Float // Sharpness (0-1))Use discretePattern for distinct taps and impacts. Use continuousPattern envelopes to shape a sustained haptic over time.
CompatibilityMode
Section titled “CompatibilityMode”The haptic capability level of the current device, returned by pulsar.hapticSupport(). The SDK gracefully degrades based on what the device supports.
enum class CompatibilityMode { NO_SUPPORT, // No haptic support MINIMAL_SUPPORT, // Timing-only vibration (API 26+) LIMITED_SUPPORT, // Amplitude control (API 26+) STANDARD_SUPPORT, // Envelope API (API 36+) ADVANCED_SUPPORT, // Envelope + frequency profile (API 36+)}RealtimeComposerStrategy
Section titled “RealtimeComposerStrategy”Controls how continuous haptics are rendered on the device.
enum class RealtimeComposerStrategy { ENVELOPE, // Envelope API approximation (API 36+) PRIMITIVE_TICK, // Composition API with varying intervals PRIMITIVE_COMPLEX, // Multiple primitives based on frequency ENVELOPE_WITH_DISCRETE_PRIMITIVES, // Envelope for continuous; primitives for discrete}Preset
Section titled “Preset”The interface that all preset implementations conform to.
interface Preset { fun play()}