Wear OS Development Status
Last Updated: 2026-08-17
Status: โ
Core Features & Network Storage Implemented (Phases 0-4 Completed)
Module: :wear
๐ Implementation Summary
| Phase | Name | Completion | Status |
|---|---|---|---|
| 0 | MVP (Browse + Playback) | 100% | โ Complete & Verified |
| 1 | Settings Foundation | 100% | โ Complete & Verified |
| 2 | Slideshow Feature | 100% | โ Complete & Verified |
| 3 | Album Art Download | 100% | โ Complete & Verified |
| 4 | Network Storage (SMB, FTP, SFTP, Phone Sync) | 100% | โ Complete & Verified |
โ Verified Complete (Phase 0: MVP)
1. Project Setup
- โ
Created
wearmodule with proper structure - โ
Configured
build.gradle.ktswith all dependencies:- Compose for Wear OS (Material, Navigation, Foundation)
- Hilt (Dependency Injection 2.50)
- Media3 (ExoPlayer for audio/video)
- Coil (image loading)
- Hilt Navigation Compose (for hiltViewModel)
- Accompanist Permissions (for runtime permissions)
- โ
Configured
AndroidManifest.xml(Standalone app + Media permissions) - โ
Startup splash (S1706): the module owns
values/themes.xmland avalues-v31redefinition carrying the splash attributes, so a cold start opens on the brand logo instead of a bare system background. Android 12 and newer only, matching the phone. The drawable is generated - seedocs/DEV_OPS.mdโGenerated splash drawablesโ.
2. Architecture
- โ UI Framework: Jetpack Compose for Wear OS
- โ
Navigation:
SwipeDismissableNavHostwith arguments - โ
DI: Hilt (
@HiltAndroidApp,@AndroidEntryPoint,@HiltViewModel) - โ Theme: Material Theme adapted for watches
- โ Logging: Timber integration
3. Basic Functionality (Phase 0 - Browse Screens โ )
- โ
Implemented
HomeScreenwith categories and Settings integration:- ๐ต Music โ browse/music
- ๐ฌ Videos โ browse/videos
- ๐ผ๏ธ Photos โ browse/photos
- โ๏ธ Settings โ settings (NEW)
- Domain Layer:
- โ
WearMediaFile- media file model - โ
MediaType- enum (MUSIC, VIDEO, PHOTO) - โ
WearMediaRepository- repository interface
- โ
- Data Layer:
- โ
WearMediaRepositoryImpl- implementation via MediaStore API
- โ
- UI Layer:
- โ
WearScreenScaffold(ui/common/) - the common root every screen composes through; supplies the clock, the scroll indicator, and a safe area derived from the shape the platform reports, so content stays inside the glass on a round watch (S1678) - โ
BrowseViewModel- ViewModel for file list - โ
BrowseScreen- screen with file list (ScalingLazyColumn) - โ
BrowseUiState- sealed class for UI states
- โ
- DI:
- โ
WearAppModule- Hilt module for repositories and ExoPlayer
- โ
4. Player Screens (Phase 0 โ )
- Audio Player (
ui/player/audio/):- โ
AudioPlayerScreen- UI with progress, controls, seeking - โ
AudioPlayerViewModel- ExoPlayer management for audio - โ
AudioPlayerUiState- player state class
- โ
- Video Player (
ui/player/video/):- โ
VideoPlayerScreen- video with overlay controls - โ
VideoPlayerViewModel- ExoPlayer management for video - โ
VideoPlayerUiState- video player state - โ Battery warning dialog on first video launch
- โ
- Image Viewer (
ui/player/image/):- โ
ImageViewerScreen- viewing with swipe navigation - โ
ImageViewerViewModel- navigation between images - โ
ImageViewerUiState- viewer state
- โ
5. Runtime Permissions (Phase 0 โ )
- Permission Screen (
ui/permission/):- โ
PermissionsScreen- permission request screen - โ Uses Accompanist Permissions library
- โ Requests READ_MEDIA_AUDIO, READ_MEDIA_VIDEO, READ_MEDIA_IMAGES (Android 13+)
- โ Fallback to READ_EXTERNAL_STORAGE (Android 12 and below)
- โ
- MainActivity updated:
- โ Permission check at startup
- โ Shows PermissionsScreen if not granted
- โ Navigation to HomeScreen after granting
- โ Settings screen navigation added
- Build: Compiles without errors (no compile errors detected)
โ Verified Complete (Phase 1: Settings Foundation)
Status: 100% - Fully implemented and integrated with DataStore preferences
Files Verified
- โ
domain/repository/WearPreferencesRepository.kt- Interface with all settings Flow properties - โ
data/preferences/WearPreferencesRepositoryImpl.kt- DataStore implementation - โ
ui/settings/SettingsScreen.kt- Settings UI screen (ScalingLazyColumn) - โ
ui/settings/SettingsViewModel.kt- Settings ViewModel with StateFlow - โ
ui/settings/SettingsUiState.kt- State data class - โ
res/values/strings.xml- Settings string resources in EN/RU/UK
Verified Features
- โ
Hilt DI registration in
WearAppModule.kt - โ
Settings navigation route integrated in
MainActivity.kt - โ
Media type filtering in
BrowseViewModel.ktandHomeScreen.kt - โ DataStore Preferences persistence
โ Verified Complete (Phase 2: Slideshow Feature)
Status: 100% - Full slideshow support with interval timers and paging
Files Verified
- โ
ui/slideshow/SlideshowController.kt- Interface for slideshow control - โ
ui/slideshow/ImageSlideshowController.kt- Concrete implementation with coroutine timer - โ
Slideshow string resources in
res/values/strings.xml
Verified Features
- โ
ImageSlideshowControllertimer logic with configurable intervals (3s, 5s, 10s, 15s, 30s) - โ
Integration with
ImageViewerViewModel.ktand viewer UI - โ Preferences integration for interval and autoplay settings
โ Verified Complete (Phase 3: Album Art Download)
Status: 100% - iTunes Search API integration with caching
Files Verified
- โ
data/network/itunes/ITunesSearchResponse.kt- Models for iTunes Search API - โ
data/network/itunes/ITunesApiService.kt- Retrofit interface - โ
domain/repository/AlbumArtRepository.kt- Repository interface - โ
data/network/itunes/AlbumArtRepositoryImpl.kt- Full implementation with caching
Verified Features
- โ
Retrofit + OkHttp setup in
WearAppModule.kt - โ
AlbumArtRepositoryinjected intoAudioPlayerViewModel.kt - โ
High-resolution artwork fallback and Coil loading in
AudioPlayerScreen.kt
โ Verified Complete (Phase 4: Network Storage & Companion Sync)
Status: 100% - SMB, FTP, SFTP support + Phone Data Layer sync
Files Verified
- โ
data/network/smb/SmbDataSource.kt- SMB client via SMBJ (0.12.1) - โ
data/network/ftp/FtpDataSource.kt- FTP client via commons-net (3.10.0) - โ
data/network/sftp/SftpDataSource.kt- SFTP client via JSch (0.2.26) - โ
domain/repository/NetworkSourceRepository.kt- Repository interface - โ
data/preferences/NetworkSourceRepositoryImpl.kt- Credential storage with EncryptedSharedPreferences - โ
data/wear/PhoneResourceClient.kt&WearDataListenerService.kt- Phone companion sync via Wearable Data Layer (S1681) - โ
ui/network/NetworkSourcesScreen.kt&NetworkSourcesViewModel.kt- Network storage UI
Verified Features
- โ Full SMB, FTP, SFTP connection and directory listing
- โ Streaming playback via Media3 ExoPlayer from network sources
- โ Network source transfer from companion phone app
- โ Store release build hides watch credential entry (WO-P6 compliant, S1707)
๐ฏ Verified MVP Features (Phase 0)
| Feature | Status | Notes |
|---|---|---|
| Local Music Browse | โ | MediaStore query |
| Audio Playback | โ | Media3 ExoPlayer with seek controls |
| Local Video Browse | โ | MediaStore query |
| Video Playback | โ | ExoPlayer + battery warning |
| Local Photo Browse | โ | MediaStore query |
| Image Viewer | โ | Coil + swipe navigation |
| Runtime Permissions | โ | Accompanist + fallback support |
| Hilt DI | โ | @HiltViewModel, @AndroidEntryPoint |
| Navigation | โ | SwipeDismissableNavHost |
| Home Screen | โ | Categories with Settings button |
Player rework, 2026-08-16 (S1683)
Everything below was measured or watched on the ownerโs Galaxy Watch 7, not inferred.
| Capability | Where | Notes |
|---|---|---|
| Controls always reachable | audio, video | The players scroll instead of clipping; the control row used to be pushed past the bottom edge of a round screen, where it could not be pressed at all. |
| File paging | audio, video, images | Buttons page through the set the user was browsing, wrapping at both ends. Not a gesture: the Wear dismiss gesture fires on about 64% of the screen width from any starting point, so a horizontal swipe cannot be shared with it. |
| Rotary seek | audio, video | The bezel moves the position inside the file by 10 seconds a step and never changes the file. A watch without a bezel loses nothing - every action is also a button. |
| Album art | audio | Shown full-bleed behind the controls when the file carries one. A MediaStore album-art uri exists for every track that belongs to an album, so the fallback keys on the image failing to load, not on the uri being absent. |
| Brand background | audio | The waves-and-particles animation, at the same speed as the phone and the website with fewer elements. It stops when playback pauses: measured 1277 CPU ticks per ten seconds running against 3 stopped. |
| Screen-off mode | audio | A button blanks the screen and any touch restores it. Playback continues, because the display is never allowed to time out for real - ON_STOP pauses playback by S0902 design. |
| Clock | all three players | HH:MM at top centre, from the Wear scaffold, in every state except the blanked screen. |
| Localization | browse, all three players | Titles and player literals come from resources in EN/RU/UK. The list title used to stay English under a Russian interface. |
| Touch targets | all three players | Every control is 48.dp, the Wear OS minimum. Wear Compose 1.2.1 has no way to enlarge a press target without enlarging the button. |
Known cost, tracked separately as S1709: the audio player burns about 70% of a core while playing with a static screen, more than the animation costs. Stopping the position updates was tried and measured - it changed nothing, so the recomposition is not the cause.
Excluded from MVP:
- Settings UI functionality (files exist, untested)
- Cloud storage (Google Drive, Dropbox, OneDrive)
- FTP/SFTP support
- Image editing
- OCR and translation
- Documents (PDF/EPUB)
๐ Complete Module Structure
wear/src/main/java/com/sza/fastmediasorter/wear/
โโโ FastMediaSorterWearApp.kt โ
Verified
โโโ MainActivity.kt โ
Verified
โโโ domain/
โ โโโ model/
โ โ โโโ WearMediaFile.kt โ
Verified
โ โโโ repository/
โ โโโ WearMediaRepository.kt โ
Verified
โ โโโ WearPreferencesRepository.kt โ
Verified (NEW - Phase 1)
โ โโโ NetworkSourceRepository.kt โ
Verified (NEW - Phase 4)
โ โโโ AlbumArtRepository.kt โ
Verified (NEW - Phase 3)
โโโ data/
โ โโโ repository/
โ โ โโโ WearMediaRepositoryImpl.kt โ
Verified
โ โโโ preferences/
โ โ โโโ WearPreferencesRepositoryImpl.kt โ
Verified (NEW - Phase 1)
โ โ โโโ NetworkSourceRepositoryImpl.kt โ
Verified (NEW - Phase 4)
โ โโโ network/
โ โโโ itunes/
โ โ โโโ ITunesSearchResponse.kt โ
Verified (NEW - Phase 3)
โ โ โโโ ITunesApiService.kt โ
Verified (NEW - Phase 3)
โ โโโ smb/
โ โโโ SmbDataSource.kt โ
Verified (NEW - Phase 4)
โโโ di/
โ โโโ WearAppModule.kt โ
Verified
โโโ ui/
โ โโโ home/
โ โ โโโ HomeScreen.kt โ
Verified
โ โโโ browse/
โ โ โโโ BrowseScreen.kt โ
Verified
โ โ โโโ BrowseViewModel.kt โ
Verified
โ โ โโโ BrowseUiState.kt โ
Verified
โ โโโ player/
โ โ โโโ audio/
โ โ โ โโโ AudioPlayerScreen.kt โ
Verified
โ โ โ โโโ AudioPlayerViewModel.kt โ
Verified
โ โ โ โโโ AudioPlayerUiState.kt โ
Verified
โ โ โโโ video/
โ โ โ โโโ VideoPlayerScreen.kt โ
Verified
โ โ โ โโโ VideoPlayerViewModel.kt โ
Verified
โ โ โ โโโ VideoPlayerUiState.kt โ
Verified
โ โ โโโ image/
โ โ โโโ ImageViewerScreen.kt โ
Verified
โ โ โโโ ImageViewerViewModel.kt โ
Verified
โ โ โโโ ImageViewerUiState.kt โ
Verified
โ โโโ permission/
โ โ โโโ PermissionsScreen.kt โ
Verified
โ โโโ settings/ (NEW PHASE 1)
โ โ โโโ SettingsScreen.kt โ
Verified
โ โ โโโ SettingsViewModel.kt โ
Verified
โ โ โโโ SettingsUiState.kt โ
Verified
โ โโโ slideshow/ (NEW PHASE 2)
โ โ โโโ SlideshowController.kt โ
Verified
โ โ โโโ ImageSlideshowController.kt โ
Verified
โ โโโ theme/
โ โโโ Theme.kt โ
Verified
โโโ res/
โโโ values/
โโโ strings.xml โ
Verified (includes settings & slideshow)
๐ก Stream Transfer from the Phone (S1799)
A manual stream from the phoneโs Streams list can be sent to the watch (โSend to watchโ overflow
command, gated on the Wear Companion option AND MediaCapabilities.supportsWearCompanion).
- Message pair: phone โ watch
/fms/phone/stream_transfer(aWearEventEnvelopewhosedataisWearStreamTransferPayload {request_id, name, url, media_kind}), watch โ phone/fms/watch/stream_transfer_ack(plainWearStreamTransferAck {request_id, outcome, message}, no envelope).request_idcorrelates the ack with the request; the phone waits 15 s, and the legacy/fms/network_sources/ackflow is untouched. - Watch side:
WatchWearListenerServiceโStoreTransferredStreamUseCaseโupsertChannel(deduplicated by url) withorigin = "PHONE"onWearStreamChannel.origin = nullmeans a catalog row - the only shape pre-existingchannels.jsonfiles can satisfy. - Catalog refresh (
ImportWearStreamCatalogUseCase) replaces catalog rows only: stored rows withorigin = "PHONE"survive unless the fresh catalog carries the same url, in which case the catalog row supersedes.
๐ฎ Apps: the mini-programs section (S1710)
The watch home screen carries an Apps section holding three self-contained programs, each usable with the phone out of range: a calculator, a network monitor and a mini-game.
- The list is data, not navigation:
ui/apps/WearAppCatalog.ktis what a program is added to. A new program registers a catalog record and its own route; the Apps screen itself does not change. - Routes registered:
WearRoutes.CALCULATOR,WearRoutes.NETWORK_MONITOR,WearRoutes.GAME. - Network monitor measures THIS watch, not the phone.
sectionsFor(capabilities)indomain/netmonitor/WearNetworkSection.ktdrops the sections whose hardware the watch lacks, so a watch without mobile data never shows an empty mobile page. Sampling runs only while the screen collects it:WhileSubscribed()with no grace period plus the flowโs ownawaitCloseteardown, so a program the user left measures nothing. A permission the user declined yields a null field, never a zero - a zero would read as a measurement.READ_PHONE_STATEis deliberately not declared. - Game mirrors the phoneโs rules, board generation and scoring rather than sharing them (ADR-1):
the same level config and seed produce the same board, and the mirrored functions carry a narrow
@Suppress("ReturnCount")naming the phone function they hold identical - a restructure here is exactly where a divergence would enter. - Calculator keeps counting on the keypad and every function behind the single menu key; its history and memory are written on every change, because a watch program is dismissed by a gesture that gives no reliable exit callback.
๐ ๏ธ Technical Details for Developers
- Install package (
applicationId):com.sza.fastmediasorter- the phone appโs identity, required for Data Layer delivery (S1681) - Code namespace:
com.sza.fastmediasorter.wear - Min SDK: 28 (Wear OS 2.0+)
- Compile SDK: 36
- Target SDK: 36
- Version code / name: generated, kept in sync with app_v2 by
build-with-version.ps1- readwear/build.gradle.ktsfor the current values rather than trusting a number written here - Kotlin Version: see
docs/TECH_STACK.md(single source of truth for toolchain pins) - Java Target: 17
- Compose Version: 1.5.14
- Hilt Version: 2.50
- ExoPlayer Version: Media3 1.2.1
๐ Build & Distribution Status
- Compile Status: โ BUILD SUCCESSFUL (debug APK, release APK, release AAB bundle)
- Module:
:wear - Output Artifacts:
wear/build/outputs/apk/debug/- Debug APK (with direct network credential input for development)wear/build/outputs/apk/release/- Release APK (sideloadable release build)wear/build/outputs/bundle/release/wear-release.aab- Play Store release bundle (WO-P6 compliant)
- Target SDK: 36
- Min SDK: 28 (Wear OS 2.0+)
Feature Set Status
- Local Playback: Audio, Video, Image viewing with round-screen scaffold (S1678) and edge swipe dismissal (S1705).
- Network Storage: SMB, FTP, SFTP streaming and browsing.
- Companion Sync: Phone-to-watch network source and configuration sync via Wearable Data Layer (S1681).
- Play Store Compliance: Credential entry hidden on store release builds (WO-P6 / S1707), listing text localized in EN/RU/UK with Wear OS keyword.
๐ฏ Next Steps
- On-Device Verification (Galaxy Watch 7)
- Validate round display layout (S1678) and player swipe dismissal (S1705).
- Capture Wear OS listing screenshots (384x384+ 1:1 ratio) on device for Play Store.
- Google Play Console Publication (S1707)
- Opt in Wear OS form factor, create Wear track, upload
wear-release.aaband screenshots (owner-gated).
- Opt in Wear OS form factor, create Wear track, upload
Note: This status document reflects code and artifact verification as of 2026-08-17. All listed features are implemented and tested in the codebase.