Skip to content

About

No description, website, or topics provided.

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

Earpiece Router

Route your phone's audio to the earpiece speaker — automatically when you bring the phone to your ear, or manually on demand. Useful for listening to voice messages, podcasts, or any media privately without headphones.

  • Auto mode — bring the phone to your ear while audio is playing and it switches to the earpiece; pull away and it switches back. The screen turns off at your ear, just like during a phone call.
  • Manual mode — force earpiece routing on/off from the notification or the app.
  • Quick Settings tile — start/stop the service from the notification shade.
  • Headphone-aware — automatically disengages when wired, Bluetooth, or USB audio is connected, and refuses to engage while headphones are attached.
  • Survives reboots — restarts itself after boot if it was running.

Why this app exists

Android offers no public API to route other apps' audio to the earpiece on demand. Apps that own their player (e.g. WhatsApp voice messages) can recreate their AudioTrack on STREAM_VOICE_CALL, but third-party audio can't be touched that way without root. The only mechanism available to a normal app is MODE_IN_COMMUNICATION + AudioManager.setCommunicationDevice() — which is what this app uses, with several device-specific workarounds described below.

How it works

The core is a foreground service (AudioRouterService):

  • Routing: sets AudioManager.mode = MODE_IN_COMMUNICATION and calls setCommunicationDevice(earpiece) (API 31+; falls back to isSpeakerphoneOn = false on older versions). In communication mode the system routes media streams to the earpiece.
  • Silent comm-path track: several devices (observed on Vivo) reset MODE_IN_COMMUNICATION back to MODE_NORMAL every few seconds when no app is actually using the communication path, causing an audible glitch on every reset. The service plays a silent AudioTrack with USAGE_VOICE_COMMUNICATION while routing is active, which keeps the mode legitimately held. No audio focus is requested — requesting focus would make media apps pause.
  • Proximity: a SensorEventListener on the proximity sensor with a 150 ms debounce. Some devices do not deliver proximity events at all unless a PROXIMITY_SCREEN_OFF_WAKE_LOCK is held, so the wakelock is held for the entire time auto mode is active (it also turns the screen off at your ear, which is the desired behavior anyway).
  • Playback detection: AudioPlaybackCallback watches AudioPlaybackConfigurations. isActive() was removed from the public SDK in API 34, so it is reached via reflection with a presence-based fallback. Configs with USAGE_VOICE_COMMUNICATION are ignored so the app doesn't trigger on its own silent track.
  • Device changes: AudioDeviceCallback (not the deprecated ACTION_HEADSET_PLUG broadcast) detects wired/Bluetooth/USB output changes.
  • Call safety: the routing watchdog backs off during MODE_IN_CALL and MODE_RINGTONE so it never fights telephony.
  • State is persisted across process restarts and reboots (SharedPreferences + BOOT_COMPLETED receiver).

Permissions

Permission Why
FOREGROUND_SERVICE / FOREGROUND_SERVICE_SPECIAL_USE The routing service must run persistently
POST_NOTIFICATIONS Status + controls notification (Android 13+)
MODIFY_AUDIO_SETTINGS Required to change audio mode and routing
WAKE_LOCK Proximity screen-off wakelock (ear detection + sensor delivery)
RECEIVE_BOOT_COMPLETED Restart the service after reboot

No internet permission. No analytics, no ads, no data collection.

Requirements

  • Android 8.0 (API 26) or newer; best experience on Android 12+ (API 31), where setCommunicationDevice is available.
  • A device with a proximity sensor (for auto mode) and an earpiece speaker.

Build

Standard Gradle build, no extra setup:

./gradlew assembleDebug      # debug APK in app/build/outputs/apk/debug/
./gradlew assembleRelease    # release (minified) — add your signing config

Requirements: JDK 17, Android SDK 34. Gradle wrapper included (Gradle 8.5, AGP 8.2.2, Kotlin 1.9.22).

Install

adb install -r app/build/outputs/apk/debug/app-debug.apk

Then launch the app, tap Start Service, and (Android 13+) grant the notification permission. Add the Earpiece Quick Settings tile for quick access.

Known limitations

  • The earpiece is a small speaker — expect phone-call quality, not media quality. That is the point (privacy), not a bug.
  • Auto mode reacts in ~150–300 ms on the app side, but the proximity sensor hardware itself adds ~1–2 s of latency on most devices. This is a hardware floor; the stock Phone app has the same delay.
  • Some OEMs (e.g. Vivo) aggressively manage audio modes; the silent comm-path track exists specifically to keep routing stable on those devices.
  • On API 34+, true play/pause state of other apps is hidden by the platform, so playback detection falls back to a presence heuristic in rare cases.

Project structure

app/src/main/java/com/earpiece/router/
├── AudioRouterService.kt   # Core: routing, proximity, wakelock, silent track
├── EarpieceTileService.kt  # Quick Settings tile
├── MainActivity.kt         # Start/stop UI + notification permission
└── BootReceiver.kt         # Restart after reboot

Contributing

Issues and PRs are welcome — see CONTRIBUTING.md. Device-specific routing behavior reports (with adb logcat -s EarpieceRouter) are especially valuable.

License

MIT

About

No description, website, or topics provided.

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages