Skip to content

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.

  • Android API 24+ (Android 7.0)
  • Kotlin 1.9+

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)

A collection of ready-to-use haptic patterns accessed through pulsar.getPresets().

val presets = pulsar.getPresets()
MethodDescription
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()

These mirror standard haptic feedback styles shared across platforms.

MethodDescription
systemImpactHeavy()Heavy impact
systemImpactLight()Light impact
systemImpactMedium()Medium impact
systemImpactRigid()Rigid impact
systemImpactSoft()Soft impact

Example

val presets = pulsar.getPresets()
presets.systemImpactMedium()

Android exposes additional system effects beyond the cross-platform set.

MethodDescription
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()

You can play any preset by its string name using getByName(). This returns a Preset? that you call play() on.

Available names:

  • Afterglow
  • Aftershock
  • Alarm
  • Anvil
  • Applause
  • Ascent
  • BalloonPop
  • Barrage

Example

val presets = pulsar.getPresets()
// Direct call
presets.dogBark()
// By name
presets.getByName("SystemImpactMedium")?.play()

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()

Parses a PatternData object and prepares it for playback.

fun parsePattern(hapticsData: PatternData)

Plays the previously parsed pattern.

fun play()

Stops all playback.

fun stop()
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()

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)
StrategyDescription
ENVELOPEEnvelope API approximation (API 36+)
PRIMITIVE_TICKComposition API with varying tick intervals
PRIMITIVE_COMPLEXMultiple primitives selected based on frequency
ENVELOPE_WITH_DISCRETE_PRIMITIVESDefault. Envelope API for continuous events (API 36+); composition primitives for discrete events (API 33+).

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)

Plays a single discrete haptic event.

fun playDiscrete(amplitude: Float, frequency: Float)

Stops the active continuous haptic.

fun stop()

Returns true if a continuous haptic is currently playing.

fun isActive(): Boolean
val realtime = pulsar.getRealtimeComposer()
// Start a continuous haptic
realtime.set(amplitude = 0.5f, frequency = 0.8f)
// Update parameters over time
realtime.set(amplitude = 1.0f, frequency = 0.3f)
// Play a one-off discrete event
realtime.playDiscrete(amplitude = 0.7f, frequency = 0.5f)
// Stop
realtime.stop()

Configuration methods available directly on the Pulsar instance.

MethodDescription
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)
val pulsar = Pulsar(context)
// Preload frequently used presets
pulsar.preloadPresets(listOf("Earthquake", "Success"))
// Disable haptics temporarily
pulsar.enableHaptics(false)
// Check device support
val support = pulsar.hapticSupport()
if (support >= CompatibilityMode.STANDARD_SUPPORT) {
pulsar.getPresets().success()
}

Describes a complete haptic pattern with discrete pulses and continuous envelope curves.

data class PatternData(
val continuousPattern: ContinuousPattern,
val discretePattern: List<ConfigPoint>
)

Represents continuous haptic curves for amplitude and frequency.

data class ContinuousPattern(
val amplitude: List<ValuePoint>,
val frequency: List<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)
)

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.

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+)
}

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
}

The interface that all preset implementations conform to.

interface Preset {
fun play()
}