Languages
| Language | What it does in HaptiBraille |
|---|---|
| Dart | Almost everything: every screen, the Braille translator, the timing engine, training, analytics, storage and the tests. |
| Kotlin | The Android code that talks directly to the vibration motor (HapticChannel.kt). |
| Swift | The iPhone app shell, generated by Flutter. The iPhone vibration code is still to come. |
| Gradle Kotlin DSL | Android build settings: app ID, Java version and SDK versions. |
| XML | The Android manifest: app name and permissions for vibration and the microphone. |
| YAML | The package list, font list and versions (pubspec.yaml). |
Framework and tools
| Tool | Version | Why |
|---|---|---|
| Flutter | 3.47 stable | Google's toolkit for building one app for Android and iPhone from a single codebase. |
| Dart SDK | 3.13 | The language Flutter apps are written in. |
| Android SDK | API 36 | Builds and runs the Android app. Minimum supported phone: Android 7 (API 24). |
| Android NDK | 28.2 | Native build tools required by Flutter's Android build. |
| Gradle | 9.3 | Builds the installable APK file. |
| Java (JDK) | 17 | Runs Gradle and the Kotlin compiler. |
Packages
| Package | What it is | What we use it for |
|---|---|---|
| flutter_riverpod | State management | Shares the timing settings, playback, training session and progress between screens, and lets tests swap in fakes. |
| hive, hive_flutter | On-device database | Saves timing settings and every training answer as plain JSON. |
| speech_to_text | Phone speech recognition | Talk to me, dictation, and spoken training answers. |
| fl_chart | Charts | Accuracy and reading-speed lines, and the per-letter accuracy bars. |
| clock | A replaceable clock | Times playback and answers in a way tests can control. |
| flutter_test, flutter_lints | Testing and code style | 28 automated tests, and zero analyzer warnings. |
We deliberately didn't use a ready-made vibration package. Those usually offer "vibrate for X milliseconds". We need exact rhythms with different strengths played as one uninterrupted pattern, so we wrote a small bridge straight to Android's own API.
How the code is organised
The app follows Clean Architecture: separate layers with one job each. The core rules (what Braille is, how timing works, how answers are scored) don't depend on screens, storage or hardware, so they are easy to test and easy to swap.
HapticChannel plays the waveform on the motor.The heart of it, in code
This Dart function turns one Braille cell into a rhythm. It is the whole idea of temporal Braille in about twenty lines (lib/domain/engine/haptic_translation_engine.dart):
if (p.cellAnchorEnabled) { // soft start-of-letter tick
out.pulse(anchor(p.anchorDuration, p.anchorIntensity));
out.silence(intra);
}
for (var slot = 0; slot < 6; slot++) { // the six dots, in order
if (slot > 0) out.silence(intra); // gap between dots
if (cell.isRaisedAt(slot)) {
out.pulse(dot(p.dotDuration, p.intensity, slot)); // raised: tap
} else {
out.silence(p.emptySlotDuration); // flat: silence
}
}
And this Kotlin code plays the result on the phone (android/…/HapticChannel.kt). On Android 13 and newer it is marked as accessibility vibration, so it still works when the user has turned off touch vibration:
val effect = VibrationEffect.createWaveform(timings, amplitudes, -1) // -1: play once
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
v.vibrate(effect, VibrationAttributes.createForUsage(USAGE_ACCESSIBILITY))
} else {
v.vibrate(effect)
}
Ready for AI
- All text passes through one interface,
ITextProcessor, so an AI could summarise a long email before it is vibrated. - Learning data exports as versioned JSON that an AI can read to spot where someone struggles.
HapticProfileModel.scaled()slows or speeds up every pause at once, so an AI coach could adjust the reading speed automatically.- An empty
AgentServicemarks where the AI connection will go.
This website
Plain HTML, CSS and JavaScript with no framework and no build step. The background dot field is drawn on a canvas. The "Feel it" demo uses the same timing rules as the app and the browser's Vibration API, which works in Chrome on Android. Fonts: Bricolage Grotesque for headings and Atkinson Hyperlegible for text.
All the source code for the app and this site is on GitHub.