From 0b7907146dca15e7e9e5d6019f91c910e4f69c8d Mon Sep 17 00:00:00 2001 From: chris Date: Sat, 3 Oct 2026 17:37:30 -0400 Subject: [PATCH] Document the Android reader, pause sharing and dev builds Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01MzFywujuH9TiuXbr9vjoX8 --- README.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 862ebd0..f05e73b 100644 --- a/README.md +++ b/README.md @@ -57,7 +57,8 @@ npm run mobile # starts Metro; scan the QR code with a dev build or Expo ``` - The app talks to the API on the same host as Metro (your LAN IP, port 4000), so phone and computer must be on the same network. Set `EXPO_PUBLIC_API_URL` for other environments. -- Native tabs and some native modules need a **development build** for full fidelity: `npx expo run:ios` / `npx expo run:android` locally, or `npx eas-cli@latest build --profile development`. +- The app includes custom native code (the Android now-playing reader), so it needs a **development build**, not Expo Go: `npm run android -w @musicshare/mobile` (needs the Android SDK and JDK 17) or `npx eas-cli@latest build --profile development`. In Expo Go the reader is simply hidden. +- `android/` and `ios/` are generated by `expo prebuild` and gitignored; configure native settings in `app.json` and `modules/`. - **Spotify/Plex sign-in from a phone:** the OAuth callback goes to `API_PUBLIC_URL`, which defaults to `127.0.0.1` — that's the phone itself. Expose the API with a tunnel (`cloudflared tunnel --url http://localhost:4000`) and set `API_PUBLIC_URL` to the https URL (and add it as a redirect URI in the Spotify dashboard). - Bundle IDs are `tech.chrisedwards.musicshare` (in `apps/mobile/app.json`); change before your first store build, they're permanent after. @@ -115,10 +116,12 @@ Links are https universal links, so on phones they open the native app. Missing | Jellyfin | ✅ | Server URL + login; only the issued access token is stored and it's revoked on disconnect. Optional Webhook-plugin URL for instant updates. | | Apple Music | ⏳ | No server-side now-playing API. MusicKit gives recently-played only; the iOS app can read the device player while open. | | YouTube Music | via Last.fm | No official history API | -| Android (any app) | ⏳ | The mobile app reads the system media session (`NotificationListenerService`) | +| Android (any music app) | ✅ | One toggle in the app. `modules/now-playing-reader` listens to system media sessions (via notification access, never reading notification contents), filters to known music apps, and reports changes plus a 4-minute heartbeat through WorkManager with a per-phone revocable token. Testing with apps outside the allowlist: `EXPO_PUBLIC_EXTRA_MEDIA_APPS=com.android.chrome` (dev only). | ## SaaS readiness +- **Pause sharing:** `PUT /me/sharing` pauses for 1h, 8h or indefinitely. While paused, connections aren't polled, phone reports are dropped, and nothing is added to history. +- **Google Play:** notification access needs the in-app disclosure (`share-setup` screen) and a matching Data safety entry (listening activity, shared with friends). - **Pinned friends:** followers can pin friends to the top of their feed (`PUT/DELETE /users/:username/pin`); the limit comes from `maxPinnedFriends` in the plan. - **Plans:** `users.plan` plus `PLAN_ENTITLEMENTS` in `packages/shared/src/plans.ts` are the single place feature gates live. The API enforces them (e.g. connection limits return `402`), and `/me` returns them so clients can show upsells. - **Billing (next):** RevenueCat is recommended. It unifies App Store, Play Store and Stripe (web) subscriptions, and a webhook sets `plan`/`plan_expires_at`. App Store and Play rules require in-app purchase for digital features bought in-app.