Alfred replaces your phone's assistant shortcut with a lightweight overlay — long-press the side button, speak, and what you said is delivered to a self-hosted n8n webhook where an AI agent (or any workflow) does the actual work. Built with Kotlin and Jetpack Compose for a Samsung Galaxy S24 Ultra, but should behave on any Android 14+ device.
| Mode | How it works |
|---|---|
| Task | Speak a task; capture auto-stops when you pause. Sent as type: "task", response arrives as a notification. |
| Note | Open-ended dictation with a manual stop button. Sent as type: "note". |
| Convo | Back-and-forth conversation — your question is sent as type: "convo" and the workflow's reply is spoken aloud via TTS, then Alfred listens again. |
The overlay remembers your last-used mode. Task and Note sends run through a foreground service, so you can switch apps immediately — the result lands as an expandable notification and is recorded in a history screen (tap the notification or open it from Settings).
- Install the APK from Releases (sideload; Android 14+).
- Open Alfred → gear icon → set your n8n webhook URL and auth (Bearer token, Basic, or a custom header — matching n8n's Header Auth credential). Credentials are encrypted at rest via Google Tink with an Android Keystore master key.
- Test connection to confirm the workflow answers.
- Set Alfred as your assistant: Settings → Apps → Default apps → Digital assistant app (Samsung: Settings → Advanced features → Side button → Press and hold → Digital assistant app), or via adb:
adb shell cmd role add-role-holder android.app.role.ASSISTANT com.yshah.alfred
- In Alfred's Settings, request the battery optimization exemption so background delivery survives aggressive OEM power management.
Alfred POSTs JSON to your webhook:
{
"type": "task | note | convo | ping",
"text": "the transcribed speech",
"timestamp": "2026-07-01T21:00:00Z",
"sessionId": "uuid-per-capture"
}Route on type in your workflow (ping is the Settings test-connection probe). The response is parsed leniently — any of these work:
- A JSON object or single-element array containing a
responseText,output,text,response,message, orreplystring field (n8n AI Agent nodes commonly produce[{"output": "..."}]) - n8n's streaming NDJSON event format (the final
itemevent'scontentis used) - Plain text, or an empty body (any HTTP 2xx counts as delivered)
Convo mode uses a short (~20s) timeout since you're actively waiting for a spoken reply; Task/Note allow up to 5 minutes in the background.
./gradlew :app:assembleDebug # debug APK
./gradlew :app:assembleRelease # minified, signed release (needs your own keystore.properties)Release signing reads keystore.properties (see app/build.gradle.kts); without it the release build is unsigned. See CLAUDE.md for toolchain notes and hard-won platform gotchas (Samsung side-button behavior, broken on-device speech recognition, n8n response-shape quirks).
- Camera mode was prototyped and deferred — n8n received multipart fields as separate binary files; needs the part-encoding issue resolved first.
- Convo multi-turn continuity depends on your workflow maintaining session state (correlate on
sessionId); the first turn is solid. - Speech-to-text uses the system's Google recognizer, which may process audio off-device — the on-device-only recognizer proved unreliable on the S24 Ultra.
Personal project, provided as-is with no license granted for redistribution — but feel free to read and learn from it.