checkpoint: Lost My Phone app - SMS triggers, DND override, mediaPlayback FGS
This commit is contained in:
commit
220dd85ed3
16 changed files with 1147 additions and 0 deletions
150
README.md
Normal file
150
README.md
Normal file
|
|
@ -0,0 +1,150 @@
|
|||
# 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:** `com.example.lostmyphone`
|
||||
- **No Google Play Services.** Pure Android SDK.
|
||||
- **Languages:** Kotlin, Material Components (AndroidX).
|
||||
|
||||
---
|
||||
|
||||
## SMS Trigger Commands
|
||||
|
||||
| Command | Behaviour |
|
||||
|--------------------|----------------------------------------------------------------------------------|
|
||||
| `RING_NOW` | Plays the default system ringtone at max volume. |
|
||||
| `PLAY_SONG <name>` | Searches local `MediaStore` for a matching song. Plays it, or falls back to the default ringtone if not found. |
|
||||
|
||||
Playback always runs for exactly **30 seconds**, then the previous volume is
|
||||
restored.
|
||||
|
||||
> Send the SMS to your phone from any other phone. The command is matched
|
||||
> case-insensitively.
|
||||
|
||||
---
|
||||
|
||||
## 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 music volume,
|
||||
- forces `AudioManager.STREAM_MUSIC` to max,
|
||||
- requests `AUDIOFOCUS_GAIN_TRANSIENT` using `USAGE_NOTIFICATION_RINGTONE` and
|
||||
sets `AudioManager.mode = MODE_RINGTONE` so the sound cuts through DND,
|
||||
- plays for 30 s, 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
|
||||
```bash
|
||||
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/com/example/lostmyphone/
|
||||
├── 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.
|
||||
Loading…
Add table
Add a link
Reference in a new issue