Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/FUNDING.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ko_fi: sphildreth
14 changes: 8 additions & 6 deletions .github/workflows/android.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@ jobs:
- name: Checkout
uses: actions/checkout@v4

- name: Set up JDK 17
- name: Set up JDK 21
uses: actions/setup-java@v4
with:
distribution: temurin
java-version: '17'
java-version: '21'

- name: Cache Gradle
uses: actions/cache@v4
Expand All @@ -34,6 +34,9 @@ jobs:
- name: Set up Android SDK
uses: android-actions/setup-android@v3

- name: Install Android SDK packages
run: sdkmanager "platforms;android-36" "build-tools;36.0.0" "platform-tools"

- name: Grant execute permission for gradlew
working-directory: src
run: chmod +x gradlew
Expand All @@ -44,12 +47,12 @@ jobs:

- name: Run Unit Tests
working-directory: src
run: ./gradlew testDebugUnitTest --stacktrace
run: ./gradlew :app:testDebugUnitTest --stacktrace

- name: Run Instrumented Tests (emulator)
if: false # enable when emulator is set up
working-directory: src
run: ./gradlew connectedDebugAndroidTest --stacktrace
run: ./gradlew :app:connectedDebugAndroidTest --stacktrace

- name: Benchmark (connected)
if: false # enable when device/emulator available
Expand All @@ -58,5 +61,4 @@ jobs:

- name: Coverage Report
working-directory: src
run: ./gradlew jacocoTestReport --stacktrace

run: ./gradlew :app:jacocoTestReport --stacktrace
118 changes: 118 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
# Coding Agent Instructions

These instructions apply to coding agents working in this repository.

## Project Shape

- The Git repository root is `melodee-player/`, but the Android Gradle project
root is `melodee-player/src/`.
- Run Gradle from `src/`, not from the repository root.
- The app module is `src/app`; the macrobenchmark module is `src/benchmark`.
- The app targets Melodee API v1 and Android SDK 36, with minSdk 23.
- The local Android SDK path used in this workspace is
`/home/steven/Android/Sdk`.

## Change Discipline

- Keep edits scoped to the requested behavior and existing architecture.
- Do not revert user changes or unrelated workspace changes.
- Prefer the existing Kotlin, Compose, Retrofit, Media3, coroutine, and
SharedPreferences patterns before introducing new frameworks.
- Treat authentication, Android Auto, media playback, API models, and Gradle
configuration as high-risk areas. Add or update tests when touching them.
- Do not add local app-data SQLite/Room persistence unless explicitly requested.
Media3 already uses its own SQLite-backed cache metadata internally.

## Changelog

- Update `CHANGELOG.md` for every notable change before finishing work.
- Add new entries under `## [Unreleased]` by default. If the user says the
current version has not been released yet, or the task is explicitly part of
an in-progress release section such as `## [1.8.0]`, update that active
version section instead.
- Follow the existing Keep a Changelog categories: `Added`, `Changed`,
`Deprecated`, `Removed`, `Fixed`, and `Security`.
- Include user-visible behavior changes, API compatibility changes,
authentication/session changes, Android Auto changes, dependency/toolchain
changes, security hardening, and important test coverage additions.
- Do not add changelog entries for purely mechanical formatting changes unless
they materially affect users, maintainers, CI, or release behavior.
- Keep entries concise and factual. Mention the affected subsystem when useful.
- If a task intentionally skips a changelog update, state why in the final
response.

## README And Docs

- Keep `README.md` accurate when setup, build commands, API behavior,
authentication behavior, Android Auto behavior, or project layout changes.
- Some files under `docs/` are historical review/planning artifacts. Do not
treat them as more authoritative than current source, Gradle files,
`README.md`, and `CHANGELOG.md`.
- If docs contradict source code, verify against source before editing.

## Authentication And API

- Preserve refresh tokens when API responses omit rotated refresh-token values.
- Android Auto must be able to restore existing stored authentication without
requiring the user to open the handheld UI again.
- Invalid/rejected refresh tokens may clear authentication; transient refresh
failures should keep stored credentials available for retry.
- API contract changes should be covered by tests under
`src/app/src/test/java/com/melodee/autoplayer/api` or related model tests.
- The current OpenAPI reference used during this work was
`/home/steven/Downloads/v1.json`; verify with the user before assuming that
path is still current in future sessions.

## Android Auto And Playback

- `MusicService` is exported for Android Auto discovery; caller validation must
remain strict before returning browse content.
- Do not trust Android Auto callers by substring package-name checks. Use exact
trusted packages and package/UID ownership checks.
- UI playback state should be driven by service/manager flows where possible,
not by UI-owned polling loops.
- When changing playback state, verify handheld UI and Android Auto behavior:
current song, play/pause, queue, metadata, notification controls, and auth
restoration.

## Validation

- Always run:

```bash
git diff --check
```

- For Markdown-only changes, `git diff --check` is usually enough.
- For test-only changes, run the targeted test class and preferably the full
unit suite:

```bash
cd src
ANDROID_HOME=/home/steven/Android/Sdk ./gradlew testDebugUnitTest --stacktrace
```

- For production Android code, build logic, shared models, authentication,
Android Auto, networking, or playback changes, run the full build:

```bash
cd src
ANDROID_HOME=/home/steven/Android/Sdk ./gradlew build --stacktrace
```

- Connected tests and benchmarks require a device or emulator:

```bash
cd src
ANDROID_HOME=/home/steven/Android/Sdk ./gradlew connectedDebugAndroidTest
ANDROID_HOME=/home/steven/Android/Sdk ./gradlew :benchmark:connectedCheck
```

- If a validation command cannot be run, explain why and report what was run
instead.

## Final Response Expectations

- Summarize what changed, what was verified, and any residual risk.
- Mention skipped validations explicitly.
- Keep file references precise for important source or documentation changes.
115 changes: 115 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
# Changelog

This file records notable project changes. It follows the
[Keep a Changelog](https://keepachangelog.com/en/1.0.0/) format and uses
[Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [1.8.0] - 2026-06-17

### Added

- Added encrypted SharedPreferences storage for authentication tokens, including
migration of existing access-token, refresh-token, and refresh-token-expiry
values out of the regular settings file.
- Added refresh-token expiry persistence so refreshed authentication state can
be saved alongside rotated access and refresh tokens.
- Added an OkHttp `Authenticator`-based token refresh flow that retries 401
responses with a refreshed access token and distinguishes invalid credentials
from transient network or server failures.
- Added a separate unauthenticated Retrofit/OkHttp client for refresh-token
requests to avoid recursive authorization handling.
- Added service-side playlist and search queue APIs so bound UI ViewModels can
hand queues directly to `MusicService` without large Parcelable intent
payloads.
- Added playlist page-size tracking, in-flight next-page fetch reuse, and
proactive page prefetching when playback nears the end of the current queue.
- Added MediaBrowser caller validation for the exported Android Auto media
service before exposing browse content.
- Added debug-symbol keep rules for native libraries used by AndroidX graphics,
benchmark, DataStore, and tracing dependencies.
- Added focused authentication persistence tests for omitted refresh-token
responses, refresh-token expiry retention, transient refresh failures, invalid
refresh failures, and Android Auto service-side authentication restoration.
- Added OpenAPI v1 contract tests covering authentication, refresh-token
requests, playlist and favorite route placeholders, scrobble payloads and
error responses, nullable refresh-token fields, and artist genre arrays.
- Added repository instructions for coding agents requiring changelog updates
for notable code, behavior, dependency, security, and documentation changes.
- Added project-specific coding-agent guidance for nested Gradle usage,
validation, authentication, API contracts, Android Auto, playback, and
documentation expectations.

### Changed

- Updated the Android project version from `1.7.3` to `1.8.0`.
- Raised the Android platform requirements from min SDK 21 / target SDK 35 to
min SDK 23 / target SDK 36.
- Updated the build toolchain to Gradle 9.5.1, Android Gradle Plugin 9.2.1, and
JDK 21 in CI.
- Updated Kotlin plugin usage for Kotlin 2.3.21 and Compose compiler plugin
integration.
- Updated major Android and Kotlin dependencies, including Compose BOM
2026.05.01, Media3 1.10.1, Retrofit 3.0.0, OkHttp 5.3.2, Coroutines 1.11.0,
Lifecycle 2.10.0, AndroidX media 1.8.0, Firebase BOM 34.13.0, and current
test libraries.
- Reduced HTTP logging in app and image-loading clients, redacted authorization
headers, and disabled verbose request logging for non-debuggable builds.
- Changed authentication failure handling so only non-recoverable refresh
failures clear stored credentials, while transient refresh failures leave
credentials available for later retries.
- Changed single-song, playlist, search-result, and album playback setup to use
service methods when the playback service is already bound.
- Changed playlist playback intents to send playlist references and start
metadata instead of serializing full song lists through intent extras.
- Aligned the Retrofit v1 API contract with the current OpenAPI spec, including
refresh-token authentication, playlist pagination query names, album-song
browsing, scrobble requests, and v1 error payload parsing.
- Updated README, documentation, review notes, and prompt artifacts for the
SDK 36, JDK 21, Gradle 9.5.1, and dependency-version changes.
- Updated the benchmark module to compile and target SDK 36 with the same JDK
21 toolchain configuration as the app module.
- Updated `HomeViewModel` and `PlaylistViewModel` to collect playback state,
current song, playback context, duration, and position from service-backed
flows instead of running UI-owned polling loops.
- Updated `MusicService` and `MusicPlaybackManager` to expose and maintain
flow-backed playback progress for bound UI consumers.
- Updated the README to document current setup, API v1 authentication behavior,
Android Auto behavior, testing commands, and repository layout.
- Cleaned Android Studio commit-inspection warnings in playback, playlist,
home, service, and model serialization code by removing dead helpers,
simplifying redundant conditions, and keeping only intentional Android
lifecycle suppressions.
- Updated Android CI to explicitly install Android SDK 36 and run app-qualified
unit-test and JaCoCo tasks from the nested Gradle project.

### Fixed

- Fixed token value leakage in logs by logging token presence instead of token
prefixes.
- Fixed refresh-token rotation persistence by saving new refresh tokens and
refresh-token expiry values from network refresh callbacks.
- Fixed Android Auto playlist continuation to avoid starting duplicate next-page
fetches when playback reaches a queue boundary during an active prefetch.
- Fixed queue navigation state updates by separating next/previous queue
movement from immediate playback commands in the consolidated playback
manager.
- Fixed logout flow to route through `AuthenticationManager` when available so
stored settings, network authentication state, and UI authentication state stay
synchronized.
- Fixed nullable refresh-token response handling so login and token refresh
persistence tolerate v1 responses that omit rotated refresh-token values.
- Fixed the JaCoCo report task so CI coverage uses debug unit-test execution
data and non-instrumented app classes instead of requiring connected Android
coverage.

### Security

- Moved sensitive authentication tokens from regular SharedPreferences to
encrypted SharedPreferences when the platform keystore-backed implementation
is available.
- Reduced sensitive network logging by redacting authorization headers and
disabling OkHttp body logging.
- Kept the media browser service exported for Android Auto discovery while
adding caller checks before returning a browser root.
- Tightened Android Auto media browser caller classification by replacing
package-name substring trust with exact trusted package matching.
Loading
Loading