← Back to Blog

Building AuraMusic: A Modern Android Music Player with YouTube Music Integration

December 15, 202412 min read
KotlinAndroidJetpack ComposeMaterial 3YouTube MusicVoice ControlOpen Source

Building AuraMusic: A Modern Android Music Player with YouTube Music Integration

AuraMusic represents my journey into modern Android development, combining cutting-edge technologies with practical user needs. This open-source music player demonstrates how to build production-quality Android applications using Kotlin, Jetpack Compose, and modern architectural patterns.

#The Vision

Music streaming has evolved significantly, but many players lack: - Seamless YouTube Music integration - Hands-free voice control - Modern Material 3 design - Cross-platform casting capabilities - Offline playback with smart caching

AuraMusic addresses these gaps while maintaining simplicity and performance.

#Technology Stack

Core Technologies: - Kotlin: Primary programming language for modern Android development - Jetpack Compose: Declarative UI framework for building native interfaces - Material 3: Latest design system with dynamic theming - Media3 ExoPlayer: Google's modern media playback library - VOSK: Offline speech recognition for voice control - Google Cast: Framework for casting to smart displays and speakers

Architecture: MVVM with Repository pattern - Data Layer: Room database, DataStore preferences - Domain Layer: Use cases and business logic - UI Layer: Jetpack Compose screens and ViewModels

#Key Features Implementation

##YouTube Music Integration

The core functionality revolves around seamless YouTube Music integration:

class YouTubeMusicRepository @Inject constructor(
    private val apiService: YouTubeMusicApiService,
    private val localDataSource: LocalMusicDataSource
) {
    
    suspend fun searchSongs(query: String): List<Song> {
        return try {
            // Try remote API first
            val remoteSongs = apiService.searchSongs(query)
            // Cache results locally
            localDataSource.saveSongs(remoteSongs)
            remoteSongs
        } catch (e: Exception) {
            // Fallback to local cache
            localDataSource.searchSongs(query)
        }
    }
}

##Voice Control with VOSK

Hands-free music control using offline speech recognition:

class VoiceController @Inject constructor(
    private val voskModel: VoskModel,
    private val musicPlayer: MusicPlayer
) {
    
    fun startListening() {
        voskModel.setListener { command ->
            when {
                command.contains("play") -> musicPlayer.play()
                command.contains("pause") -> musicPlayer.pause()
                command.contains("next") -> musicPlayer.next()
                command.contains("previous") -> musicPlayer.previous()
                command.contains("volume up") -> musicPlayer.volumeUp()
                command.contains("volume down") -> musicPlayer.volumeDown()
            }
        }
    }
}

##Material 3 Theming

Dynamic theming that adapts to system preferences:

dynamicColorScheme(
    seedColor = Color(0xFF0061A4),
    isDark = isSystemInDarkTheme()
).copy(
    primary = Color(0xFF0061A4),
    onPrimary = Color.White,
    primaryContainer = Color(0xFFD1E4FF),
    onPrimaryContainer = Color(0xFF001D35)
)

#Architecture Decisions

##Why Kotlin Over Java?

  • **Null Safety**: Eliminates null pointer exceptions
  • **Coroutines**: Simplified asynchronous programming
  • **Data Classes**: Boilerplate-free model classes
  • **Sealed Classes**: Type-safe state management
  • **Inline Functions**: Performance optimizations

##Jetpack Compose Advantages

  • **Declarative**: Describe what UI should look like, not how to build it
  • **Composable**: Reusable UI components
  • **Reactive**: Automatic UI updates when state changes
  • **Interoperable**: Works with existing View-based code
  • **Testable**: Easy unit testing of UI components

#Performance Optimizations

##Memory Management

@Composable
fun SongList(
    songs: List<Song>,
    modifier: Modifier = Modifier
) {
    LazyColumn(modifier = modifier) {
        items(
            items = songs,
            key = { it.id }
        ) { song ->
            SongItem(song = song)
        }
    }
}

##Caching Strategy

  • **Memory Cache**: Recent searches and frequently played songs
  • **Disk Cache**: Downloaded songs for offline playback
  • **Network Cache**: API responses with intelligent invalidation

#Cross-Platform Considerations

While AuraMusic is Android-focused, the architecture supports: - Android Auto: Car integration - Android TV: Leanback support - Wear OS: Companion app for smartwatches - Web: Progressive Web App version

#Testing Strategy

@Test
fun `search should return results from API`() = runTest {
    // Given
    val repository = YouTubeMusicRepository(
        FakeYouTubeApiService(),
        FakeLocalDataSource()
    )
    
    // When
    val results = repository.searchSongs("test query")
    
    // Then
    assertTrue(results.isNotEmpty())
}

#Deployment and Distribution

Build Variants: - FOSS: Free and Open Source Software (no Google services) - GMS: Full version with Google Cast and voice features

Distribution Channels: - GitHub Releases - F-Droid (FOSS variant) - Google Play Store (GMS variant)

#Lessons Learned

##Technical Lessons

1. Kotlin Coroutines: Essential for responsive Android apps 2. State Management: MVI pattern works better than MVVM for complex UIs 3. Performance: Lazy loading and pagination are crucial for media apps 4. Testing: Integration tests catch more bugs than unit tests alone

##Project Management

1. Open Source: Community contributions improve code quality 2. Documentation: Essential for complex features like voice control 3. User Feedback: Beta testing revealed unexpected use cases 4. Scalability: Modular architecture enables feature additions

#Future Roadmap

Short Term: - Lyrics synchronization improvements - Enhanced equalizer presets - Playlist collaboration features

Long Term: - Multi-platform desktop app - Social music discovery - AI-powered recommendations

#Contributing to AuraMusic

AuraMusic is open source and welcomes contributions. The project demonstrates modern Android development practices and serves as a learning resource for developers interested in media applications.

Getting Started: 1. Fork the repository 2. Set up the development environment 3. Choose an issue from the backlog 4. Submit a pull request

The codebase follows clean architecture principles and includes comprehensive documentation for new contributors.

#Conclusion

Building AuraMusic has been an incredible learning experience, combining my passion for music with modern Android development. The project showcases how open-source software can compete with commercial applications while providing users with privacy-respecting alternatives.

The journey from concept to production app involved mastering Kotlin, embracing Jetpack Compose, and understanding the complexities of media streaming. AuraMusic stands as a testament to what dedicated developers can achieve with the right tools and community support.

Have thoughts on this article? Share them with me on Facebook or GitHub.