lost-my-phone/README.md
avi 6b6f242edb refactor: rename package to lostmyphone.app
Move off the reserved com.example placeholder namespace to the app's own
package identifier.
2026-08-14 16:19:54 -05:00

5.8 KiB
Raw Permalink Blame History

Lost My Phone

An Android app that listens for SMS commands to trigger a loud ring — overriding "Do Not Disturb" (DND) — so you can find your phone.

  • Package: lostmyphone.app
  • No Google Play Services. Pure Android SDK.
  • Languages: Kotlin, Material Components (AndroidX).

SMS Trigger

The app listens for a configurable trigger phrase. When an incoming SMS body matches it exactly (case-insensitive, trimmed), the app rings.

Both the phrase, the sound it plays, and the duration are configurable from the in-app Ring Settings screen (launched from the "Ring Settings" button). Send the configured phrase to your phone from any other phone to trigger it.

Trigger Phrase (default: RING_NOW)

Configured in Settings. Any SMS whose body equals the phrase triggers the ring.

Sound

Choose between:

  • System ringtone (or pick a specific one), or
  • Custom song — pick any audio file on the device.

Duration

Playback runs for the configured number of seconds (5300, default 30), then the previous volume is restored.

Volume

The ring plays at a configurable percentage (1100%) of the alarm-stream volume.


How Do Not Disturb Override Works (read this)

Android does not allow any app to silently bypass DND. The only supported path is the "Do Not Disturb access" special app setting. Without it the app will refuse to play any sound. This is enforced at two points:

  1. SmsReceiver passes whether access is granted to the service.
  2. RingService.onStartCommand re-verifies NotificationManager.isNotificationPolicyAccessGranted as the source of truth. If it is false the service:
    • does not start playback,
    • shows an ongoing "Action Required: DND Access" notification,
    • and launches the system DND-access settings screen.

Only after the user flips that toggle will a trigger actually ring.

When access is granted, RingService:

  • saves the current alarm-stream volume,
  • sets AudioManager.STREAM_ALARM to the configured volume percentage,
  • requests AUDIOFOCUS_GAIN_TRANSIENT using AudioAttributes.USAGE_ALARM,
  • plays on the alarm stream — the one stream Do Not Disturb does not silence by default (media/music is silenced), which is what lets the ring cut through DND,
  • plays for the configured number of seconds, then restores the volume and abandons focus.

Build & Install

Prerequisites

  • JDK 17
  • Android SDK with compileSdk = 34 (platform 34 + build tools) — see app/build.gradle.kts.

Steps

cd /path/to/Lost_My_Phone

# 1) Point Gradle at your Android SDK (if not already in $ANDROID_HOME)
#    create a local.properties file:
#    echo "sdk.dir=/path/to/Android/Sdk" > local.properties

# 2) Generate the Gradle wrapper (optional if you already have gradle 8.6)
gradle wrapper

# 3) Build the debug APK
./gradlew :app:assembleDebug

# 4) The APK is at app/build/outputs/apk/debug/app-debug.apk

# 5) Install with adb
adb install app/build/outputs/apk/debug/app-debug.apk

First-Launch Permission Setup

On install you must grant four things, in this order:

1. SMS permission (required — SMS receiver will not fire without it)

Launch the app → tap "Grant SMS & Media Permissions"Allow.

  • On Android 13+ this also asks for READ_MEDIA_AUDIO (needed for PLAY_SONG).

2. Notification permission (Android 13+)

Tap "Grant Notification Permission"Allow. (Needed so the foreground-service notification shows.)

3. Do Not Disturb Access (CRITICAL)

The only way the app can legally override DND. Do one of:

  • (A) Tap "Open Do Not Disturb Access Settings" in the app, or
  • (B) Navigate manually:
Settings  >  Apps  >  (All / See all N apps)  >  Lost My Phone
     >  Special access  >  "Do Not Disturb access"  >  ALLOW / turn ON

Some OEMs label it "Do Not Disturb access", some "Notification policy access". Older Android versions: Settings > Apps > Advanced > Special app access. Exact wording varies by manufacturer/Android version; search Settings for "Do Not Disturb access".

Once enabled, return to the app — the status card should read "Do Not Disturb Access: GRANTED".

4. (Optional) Manual test

Tap "Test Ring Now (30s)". Must have completed step 3 or it will warn and open settings instead.


Architecture

app/src/main/java/lostmyphone/app/
├── MainActivity.kt   # UI: status, permission requests, DND-access launcher, manual test
├── SmsReceiver.kt    # BroadcastReceiver: parses SMS -> detects RING_NOW / PLAY_SONG
└── RingService.kt    # ForegroundService: DND gate, volume override, focus + playback, 30s timer
  • SmsReceiver listens for android.provider.Telephony.SMS_RECEIVED and starts RingService as a foreground service (foregroundServiceType="mediaPlayback").
  • RingService encapsulates all playback and DND logic so the ring continues with the screen off.

Permissions declared (AndroidManifest.xml)

  • ACCESS_NOTIFICATION_POLICY — enables DND override once user grants special access.
  • RECEIVE_SMS — to detect the trigger commands.
  • FOREGROUND_SERVICE + FOREGROUND_SERVICE_MEDIA_PLAYBACK — media foreground service.
  • READ_MEDIA_AUDIO (13+) / READ_EXTERNAL_STORAGE (≤ 12) — MediaStore song search.
  • POST_NOTIFICATIONS (13+) — foreground / status notifications.
  • WAKE_LOCK, VIBRATE — ensure the ring is audible/prominent.

Privacy & Safety

  • The app never plays audio unless (a) the user has granted DND access and (b) a valid trigger was sent or the manual test was tapped.
  • Permit to Media and SMS are only used for the described purpose. No data leaves the device, no analytics, no network calls, no GMS/Firebase.