Skip to content

Getting Started

NuGet package Shiny.Music

GitHub

Shiny.Music provides a unified API for accessing the device music library on Android and iOS. It supports permission management, querying track metadata, playing music files, and copying tracks (where platform restrictions allow).

  • Request and check music library permissions on both platforms
  • Query all music tracks or search by title, artist, or album
  • Browse by genre, year, or decade — each with track counts
  • Browse playlists and their tracks
  • Filter tracks by any combination of genre, year, decade, and search query via MusicFilter
  • Cross-dimensional browsing — genres by decade, years by genre, etc.
  • Play, pause, resume, stop, and seek within tracks
  • Stream Apple Music subscription tracks via MPMusicPlayerController on iOS
  • Check for active streaming subscriptions
  • Copy music files to app storage (non-DRM content only on iOS)
  • Event-driven playback state changes and completion notifications
FeatureAndroidiOS
Permission Request
Query Tracks
Search Tracks
Browse by Genre
Browse by Year / Decade
Browse Playlists
Filter by Genre + Year/Decade
Local Playback✅ (AVAudioPlayer)
Streaming Playback✅ (MPMusicPlayerController via StoreId)
Copy Track✅ (non-DRM only)
Streaming Subscription Check❌ (always false)✅ (SKCloudServiceController)
Album Art URI❌ (use MPMediaItem.Artwork)
Explicit Flag✅ (via MPMediaItem.IsExplicitItem)

Add a project reference to Shiny.Music in your .NET MAUI or platform-specific project.

Register the services in your MauiProgram.cs:

using Shiny.Music;
public static class MauiProgram
{
public static MauiApp CreateMauiApp()
{
var builder = MauiApp.CreateBuilder();
builder.UseMauiApp<App>();
builder.Services.AddShinyMusic();
return builder.Build();
}
}
public class MyPage
{
readonly IMediaLibrary _library;
readonly IMusicPlayer _player;
public MyPage(IMediaLibrary library, IMusicPlayer player)
{
_library = library;
_player = player;
}
async Task PlayFirstTrack()
{
// 1. Request permission
var status = await _library.RequestPermissionAsync();
if (status != PermissionStatus.Granted)
return;
// 2. Get all tracks
var tracks = await _library.GetAllTracksAsync();
if (tracks.Count == 0)
return;
// 3. Play the first track
await _player.PlayAsync(tracks[0]);
// 4. Listen for completion
_player.PlaybackCompleted += (s, e) =>
{
Console.WriteLine("Track finished!");
};
}
async Task BrowseAndFilter()
{
// Browse genres with track counts
var genres = await _library.GetGenresAsync();
foreach (var g in genres)
Console.WriteLine($"{g.Value} ({g.Count} tracks)");
// Browse decades
var decades = await _library.GetDecadesAsync();
foreach (var d in decades)
Console.WriteLine($"{d.Value}s ({d.Count} tracks)");
// Get rock tracks from the 1990s
var tracks = await _library.GetTracksAsync(new MusicFilter
{
Genre = "Rock",
Decade = 1990
});
// Get genres within the 2000s
var genresIn2000s = await _library.GetGenresAsync(new MusicFilter { Decade = 2000 });
// Browse playlists
var playlists = await _library.GetPlaylistsAsync();
foreach (var p in playlists)
Console.WriteLine($"{p.Name} ({p.SongCount} songs)");
// Get tracks in a playlist
var playlistTracks = await _library.GetPlaylistTracksAsync(playlists[0].Id);
}
}

An AI skill is available for Shiny Music to help generate music library code, configure permissions, and follow best practices directly in your IDE.

Claude Code

Terminal window
claude plugin add github:shinyorg/skills

GitHub Copilot — Copy the shiny-music skill file into your repository’s custom instructions.