Skip to content
Shiny .NET v4 is here with BLE Windows Support, Improved GPS, & More! Check It Out

Getting Started

  • GitHub stars for shinyorg/music
  • NuGet downloads for Shiny.Music
Frameworks
.NET
.NET MAUI
Operating Systems
Android
iOS

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
  • Control playback volume programmatically
  • Stream Apple Music subscription tracks via MPMusicPlayerController on iOS
  • Check for active streaming subscriptions
  • Fetch lyrics — plain text and synchronized LRC format via LRCLIB
  • Retrieve album artwork as cached file paths
  • 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)
Volume Control
Lyrics (Plain + Synced LRC)✅ (LRCLIB)✅ (LRCLIB + MPMediaItem.Lyrics)
Album Art✅ (MediaStore)✅ (MPMediaItem.Artwork, cached to file)
Copy Track✅ (non-DRM only)
Streaming Subscription Check❌ (always false)✅ (SKCloudServiceController)
Explicit Flag✅ (via MPMediaItem.IsExplicitItem)
Shiny.MusicNuGet package Shiny.Music
public class MyPage
{
readonly IMediaLibrary _library;
readonly IMusicPlayer _player;
readonly ILyricsProvider _lyrics;
public MyPage(IMediaLibrary library, IMusicPlayer player, ILyricsProvider lyrics)
{
_library = library;
_player = player;
_lyrics = lyrics;
}
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. Control volume
_player.Volume = 0.75f;
// 5. Get album artwork
var artPath = await _library.GetAlbumArtPathAsync(tracks[0].Id);
// 6. Fetch lyrics (plain or synced LRC)
var lyrics = await _lyrics.GetLyricsAsync(tracks[0]);
// 7. 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);
}
}
claude plugin marketplace add shinyorg/skills
claude plugin install shiny-client@shiny
copilot plugin marketplace add https://github.com/shinyorg/skills
copilot plugin install shiny-client@shiny
View shiny-client Plugin