skip to Main Content

The Easiest Way to Add Haptic Feedback in Compose Multiplatform

January 11, 20266 minute read

  

While mobile UI development has successfully shifted to declarative paradigms, interacting with hardware APIs, especially for haptic feedback, remains mostly imperative.

To simplify this, we created the Jindong library, which tackles the complexity of implementing haptic feedback in Compose Multiplatform applications. Using the Compose Runtime, developers can now specify haptic patterns as structural descriptions.

The Imperative Way

For example, implementing a standard Android API for creating a waveform vibration requires parallel arrays of timing and amplitude values.

Before (Imperative Android API):

https://medium.com/media/2edf385f5496120ac131cfa87443b88d/href

Adjusting the duration of a specific beat requires recalculating array indices. Not to mention, this logic is platform-dependent, requiring entirely different code for iOS Core Haptics.

The Declarative DSL Way

Jindong abstracts these low-level details into a Domain Specific Language (DSL). The developer defines the feedback structure, and the library handles execution.

After (Jindong Declarative API):

https://medium.com/media/9a4ab794fd98086f2850c327108ced6e/href

Here, the developer defines the pattern (a sequence repeated three times), and the library handles the platform-specific execution details. The difference isn’t just syntax — it’s about who controls execution.

Declarative programming focuses on defining the logic and relationships of the target without specifying how to achieve them.

“Describe what, not how.”

Introducing the Jindong library

Jindong is a declarative haptic feedback library for Compose Multiplatform(supports Android and iOS). It allows developers to define complex vibration patterns using a structural DSL, identical to how UI layouts are defined.

The project has been made open-source; you can now explore the source code and documentation below:

Note: Jindong[tɕindooŋ] (진동) is the Korean word for “vibration”. We chose this name to reflect the library’s core purpose, as it’s a familiar term for the Korean creators of this library.

Getting Started

Jindong is now available on Maven Central 🎉. Add the dependency to your commonMain source set:

implementation("io.github.compose-jindong:jindong:<version>")

Requirements:

  • Android: API Level 26+ (for full Waveform support)
  • iOS: iOS 13+ (Core Haptics)

Lifecycle Management

One of the biggest pain points in imperative haptics is lifecycle management. What happens if the user navigates away while a long vibration pattern is playing?

In the imperative world, you must manually call vibrator.cancel() in onPause or onDispose.
With Jindong, haptic patterns are tied to the Compose lifecycle.

  • Automatic Cancellation: When the Composable leaves the composition, the haptic engine stops immediately.
  • Reactive Updates: Just like LaunchedEffect, if your trigger key changes while a pattern is playing, Jindong automatically cancels the current pattern and restarts with the new state.

https://medium.com/media/01123e6e0e16e2f92acf84ab6b16fa84/href

Practical Examples

Here are some practical examples that can be applied using Jindong.

Screen Entry Feedback

Use Unit as a key to trigger haptic immediately when entering a screen:

https://medium.com/media/a79463a4178471325088974a21623c6e/href

Button Tap Feedback

https://medium.com/media/6be9e310a2671ddb5a298162fecc949d/href

Success Notification

https://medium.com/media/347eb20874548fb05a09d25fa02525dc/href

Error Alert

https://medium.com/media/3fb96d2943ce5ded8898c0d9ce9b8628/href

Fade Out Effect

https://medium.com/media/660a5f295805a2ff3503d6fbb6c7232a/href

Heartbeat Pattern

https://medium.com/media/4c113bf56119ee355618d5b9e3f5c05d/href

Internals of Jindong: Compose Runtime & CMP

What Does Compose Runtime Do?

The Compose runtime is a tree management engine that is agnostic to UI rendering. Jindong relies on two fundamental components of the Compose runtime:

  • ComposeNode: This is the generic function that emits a node into the tree. In Jindong, every DSL function (such as Haptic, Delay, and Sequence) calls ComposeNode internally to create a specific implementation of HapticNode.
  • Applier: The runtime needs to know how to attach these nodes together. The applier handles the structural updates of the HapticNode tree which will be traversed to collect ScheduledHapticEvents for playback.

Just as Compose UI builds a LayoutNode tree to render pixels, Jindong builds a HapticNode tree to synthesize vibrations. This allows us to use standard Compose features such as SideEffect, remember, along with standard Kotlin control flow (if/when/for), to naturally construct dynamic haptic experiences.

Compose Multiplatform Implementation

Jindong follows a standard CMP architecture:

  1. Common Layer: Contains the Compose DSL definitions, Nodes, and the HapticPattern data model. All timing calculations and pattern compilations happen here, ensuring consistent behavior across platforms.
  2. Platform Layer (Executor):
  • Android: Converts HapticPattern into VibrationEffect (using VibrationEffect.createWaveform).
  • iOS: Converts HapticPattern into CHHapticPattern for Core Haptics.

Android and iOS handle vibration intensity differently. Android relies on an amplitude integer (1–255), while iOS Core Haptics uses a normalized float (0.0–1.0). Jindong creates a unified abstraction layer, allowing developers to think in normalized percentages (e.g., intensity = 0.5f) without worrying about platform-specific math.

Unit Testing

Jindong has 100+ unit tests for verification, using Kotest to verify the logic of each component node. For the Android implementation, we use Robolectric to verify the interaction with the Android Framework. Instead of relying on expensive physical devices for CI, we utilize ShadowVibrator to inspect the VibrationEffect sent to the system.

The Next Step

We successfully completed Phase 1 (Core Architecture & MVP) in just one week. This includes the full implementation of the Node system, the initial DSL, platform executors for Android and iOS, and the comprehensive test suite mentioned above.

Future milestones include:

  • Advanced Modifiers
  • Parallel Support (overlapping iOS transient haptic events)
  • Pre-built Patterns (e.g., Pulse, Ramp, Heartbeat)
  • Platform-specific interop APIs

Wrap Up

We developed Jindong to solve the complexity of implementing haptic feedback in Compose Multiplatform applications. By leveraging the Compose Runtime, developers can define haptic patterns as structural descriptions rather than sequences of motor commands.

Jindong is open source. We are actively seeking feedback on our API design and contributors to help with Phase 2 features. Check out the repository, try the sample app, and let us know what you think!

Please stay tuned! XD

Reference


The Easiest Way to Add Haptic Feedback in Compose Multiplatform was originally published in ProAndroidDev on Medium, where people are continuing the conversation by highlighting and responding to this story.

 

Web Developer, Web Design, Web Builder, Project Manager, Business Analyst, .Net Developer

No Comments

This Post Has 0 Comments

Leave a Reply

Back To Top