Automated Call Answering with Custom Audio Playback

A root-enabled Android app that auto-answers calls and plays selected audio directly into the voice stream — built for specialized communication scenarios.

Project Overview

RoleAndroid Developer
Duration
May 25’Jun 25’
Team SizeSolo Developer
PlatformsAndroid

This was one of those projects where the requirements pushed right up against Android’s limits. The client needed a reliable way to auto-answer incoming calls and play a specific audio file into the call — something the standard telephony APIs simply don’t allow without root. I ended up diving deep into ALSA and root-level audio routing to make it work consistently across devices.

Beyond the core automation, I added practical controls like answer delay, volume, looping, and a full call log with optional recording. The UI is straightforward but polished with Jetpack Compose, so users can configure everything quickly and see clear status feedback.

Technical Overview

A blend of modern Android practices with low-level root integration where absolutely necessary.

  • UI: Jetpack Compose with custom components and subtle animations
  • Architecture: Clean + MVVM, Koin DI, Kotlin Flows
  • Audio Core: Root shell commands + ALSA mixer control for voice uplink injection
  • Call Handling: TelephonyManager + foreground service
  • Persistence: Room for settings and logs
  • Testing: Heavy manual testing across devices due to root requirements

The Challenge

Android deliberately restricts apps from injecting audio into active voice calls for privacy and security reasons. The only reliable way to achieve this is through root access and low-level audio routing — which brings its own set of device-specific quirks and stability concerns.

  • Audio injection: No public API exists to play audio into an ongoing call — required root and ALSA manipulation.
  • Device variability: Different manufacturers handle audio routing and root privileges differently.
  • Reliability under load: Needed consistent behavior even with poor signal or background restrictions.
  • User trust: Clear status and controls so users know exactly when the app is active.
  • Battery & performance: Avoid draining resources while waiting for calls.

Approach & Key Decisions

I went all-in on root-level integration while keeping the rest of the app clean and modern. The core audio handling lives in a native module, while the UI and logic stay pure Kotlin/Compose.

Audio Routing

Used root to redirect audio output to the voice call uplink via ALSA mixer paths — the only consistent way across devices.

  • Shell commands to set correct mixer controls before playback
  • Pre-processed audio files to mono PCM to match telephony requirements
  • Fallback detection and user guidance when root or paths weren’t available

Architecture

Kept the app modular with Clean Architecture so the risky root/audio parts are isolated.

  • Foreground service for call detection and playback to survive background limits
  • Koin for DI, Flow/StateFlow for reactive state
  • Room for persisting settings and call logs

UI & Feedback

Made the interface calm and transparent — users need to trust what’s happening during calls.

  • Persistent notification with current status
  • Subtle in-call overlay with playback progress
  • Clear enable/disable toggle with confirmation
  • Detailed logs for troubleshooting

Stability

Added safeguards for real-world edge cases.

  • Graceful cleanup on errors or call end
  • Watchdog for stuck audio states
  • Configurable timeouts and retries

Results & Impact

Audio DeliveryReliable

Successfully played selected audio into calls on all tested rooted devices.

User ControlFull

Delay, volume, looping, and recording all configurable with immediate feedback.

StabilityHigh

Handled interruptions (signal loss, other calls) without crashing or leaving audio stuck.

Reflection

This app was a deep dive into Android’s underbelly — working around intentional platform restrictions to solve a very specific need. It reminded me how powerful root access can be when used carefully, but also how important clear communication and safeguards are when building something that operates at that level. In the end, the client got exactly what they needed: reliable, configurable call automation that just works.

Key Takeaways

  • Root is a last resort: But when it’s the only way, isolate it completely.
  • User trust matters most: Especially when the app does something invisible like injecting audio.
  • Feedback is everything: Clear status and logs turn a 'magic' feature into something users feel in control of.
  • Polish the basics: Even a niche tool feels professional with a clean, thoughtful UI.

Share this case study