Audio, playlists and Spotify¶
ApkPy provides the building blocks for music and podcast applications: foreground playback, queues, player bindings, favourites, user playlists, downloads and OAuth.
Play audio¶
Use background playback when audio should continue while the user changes screen or leaves the app:
audio.play_background(
"https://cdn.example.com/midnight-drive.mp3",
title="Midnight Drive",
artist="Nova",
art="https://cdn.example.com/midnight-drive.jpg",
)
Android uses a foreground media service. The notification and system media controls are maintained by the generated native project.
Queues¶
sources = [
"https://cdn.example.com/track-1.mp3",
"https://cdn.example.com/track-2.mp3",
]
audio.play_playlist(
sources,
titles=["First Light", "Midnight Drive"],
artists=["Nova", "Nova"],
arts=["cover-1.jpg", "cover-2.jpg"],
start=0,
)
audio.next()
audio.previous()
audio.shuffle()
audio.repeat()
The start value can be an index or the selected source URL.
Bind a player screen¶
progress = inputs("", type="range", screen=player)
elapsed = label("0:00 / 0:00", screen=player)
cover = image("", screen=player)
title = label("", screen=player)
artist = label("", screen=player)
play_pause = button("Play", variant="icon", icon="play_arrow", screen=player)
shuffle = button("Shuffle", variant="icon", icon="shuffle", screen=player)
repeat = button("Repeat", variant="icon", icon="repeat", screen=player)
audio.now_playing(
progress=progress,
time=elapsed,
cover=cover,
title=title,
artist=artist,
)
audio.controls(
play_pause=play_pause,
shuffle=shuffle,
repeat=repeat,
)
Moving the bound range seeks through the track. The labels, artwork and buttons stay synchronized with playback.
Favourites¶
The binding watches the current track and refreshes the button/list automatically.
User playlists¶
audio.add_to_playlist("Focus")
audio.play_saved_playlist("Focus")
audio.playlists_list(playlist_list)
audio.edit_playlist("Focus")
audio.playlist_editor(playlist_tracks)
audio.remove_from_playlist("Focus")
audio.delete_playlist("Focus")
When add_to_playlist or remove_from_playlist receives no explicit item, it uses the current track. You may also pass an item dictionary containing src, title, artist and art.
Playlist lists and editors refresh when their screen resumes, keeping the Previewer and generated Android app aligned.
Offline downloads¶
def downloaded(success, path):
if success:
audio.play(path)
else:
toast("Download failed")
files.download(
"https://cdn.example.com/midnight-drive.mp3",
"midnight-drive.mp3",
on_result=downloaded,
)
if files.exists("midnight-drive.mp3"):
audio.play(files.path("midnight-drive.mp3"))
files.delete("midnight-drive.mp3")
Files are stored in app-private storage, so broad storage permission is not required.
Spotify OAuth¶
def signed_in(user):
account_name.set_value(user["name"])
auth.login(
provider="spotify",
client_id="YOUR_SPOTIFY_CLIENT_ID",
scopes=["user-read-email", "user-read-private"],
then=home,
)
auth.user(on_result=signed_in)
token = auth.token()
logged_in = auth.is_logged_in()
auth.logout()
Register both redirect styles with the provider:
- Android:
apkpy://auth - Previewer: the loopback callback shown by the login flow, normally
http://127.0.0.1:8888/callback
OAuth uses Authorization Code with PKCE, avoiding an embedded client secret in the APK.
What ApkPy does not include
ApkPy provides playback, interface, download, playlist and authentication primitives. It does not provide Spotify catalogue rights or bypass provider rules. Only access media and APIs that your application is authorized to use.