Advanced coroutine-based Spotify API wrapper for Kotlin.

Overview

Kotify Maven Central GitHub release (latest by date)

Advanced coroutine-based Spotify API wrapper for Kotlin.

Contens

TODO

  • Rate limits handling.
  • Kotify Http Proxy.
  • Better documentation.

Authentication

  • Backend Application Login.
  • User Login.
  • Token Refresh.

Albums

  • Get Album. Used by HUGE
  • Get Several Albums.
  • Get Album Tracks. Used by HUGE
  • Get Saved Albums.
  • Save Albums.
  • Remove Albums.
  • Check Saved Albums.
  • Get New Releases.

Artists

  • Get Artist. Used by HUGE
  • Get Several Artists.
  • Get Artist's Albums.
  • Get Artist's Top Tracks. Used by HUGE
  • Get Artist's Related Artists.

Shows

  • Get Shows.
  • Get Several Shows.
  • Get Show Episodes.
  • Get User's Saved Shows.
  • Save Shows for Current User.
  • Remove User's Saved Shows.
  • Check User's Saved Shows.

Episodes

  • Get Episode.
  • Get Several Episodes.
  • Get User's Saved Episodes.
  • Save Episodes for User.
  • Remove User's Saved Episodes.
  • Check User's Saved Episodes.

Tracks

  • Get Track. Used by HUGE
  • Get Several Tracks.
  • Get User's Saved Tracks.
  • Save Tracks for Current User.
  • Remove Tracks for Current User.
  • Check User's Saved Tracks.
  • Get Track's Audio Features.
  • Get Track's Audio Analysis.
  • Get Recommendations.

Search

  • Search for Item.

Users:

  • Get Current User's Profile.
  • Get User's Top Items.
  • Get User's Profile
  • Follow Playlist.
  • Unfollow Playlist.
  • Get Followed Artists.
  • Follow Artists or Users.
  • Unfollow Artists or Users.
  • Check If User Follows Artists or Users.
  • Check if Users Follow Playlist.

Playlists:

  • Get Playlist. Used by HUGE
  • Change Playlist Details.
  • Get Playlist Items. Used by HUGE
  • Add Items to Playlist.
  • Update Playlist Items.
  • Remove Playlist Items.
  • Get Current User's Playlists. Used by HUGE
  • Get User's Playlist.
  • Create Playlist.
  • Get Featured Playlists. Used by HUGE
  • Get Category's Playlists.
  • Get Playlist Cover Image.
  • Add Custom Playlist Cover Image.

Categories

  • Get Several Brows Categories.
  • Get Single Brows Category.

Genres

  • Get Available Genre Seeds.

Player

  • Get Playback State.
  • Transfer Playback.
  • Get Available Devices.
  • Get Currently Playing Track.
  • Start/Resume Playback.
  • Pause Playback.
  • Skip To Next.
  • Skip To Previous.
  • Seek To Position.
  • Set Repeat Mode.
  • Set Playback Volume.
  • Toggle Playback Shuffle.
  • Get Recently Played Tracks.
  • Add Item to Playback Queue.

Markets

  • Get Available Markets.

Getting started

Configure the Kotify instance and execute requests:

suspend fun main() {

    val kotify = Kotify(
        clientId = "Spotify Client ID",
        clientSecret = "Spotify Client Secret"
    )

    // Fetch "This Is Arcane" playlist.
    val playlist: Playlist = kotify.playlists.get("37i9dQZF1DZ06evO30uMeI")
    
    // This will retrieve all the items inside the playlist
    // If the playlist have less than 100 tracks this is not required.
    val items: List<Item> = kotify.playlists.retrieveAllTracks(playlist)
    val tracks: List<Track> = items.map { it.track }
    
    // Fetch "Burn It All Down" track
    val track = kotify.tracks.get("0ked784BOZ1JtRVHux98jE")
}

Download

repositories {
    mavenCentral()
}

dependencies {
    implementation("tv.blademaker:kotify:${VERSION}")
}
You might also like...
🎞 A demo movie app using Jetpack Compose and Hilt based on modern Android tech stacks.
🎞 A demo movie app using Jetpack Compose and Hilt based on modern Android tech stacks.

MovieCompose is a small demo application based on modern Android tech-stacks especially focus on Jetpack Compose UI using The Movie DB API.

A 2FA android client based on Jetpack Compose

EzLogin A 2FA android client based on Jetpack Compose Features Material Design Import via QR Code Technology stack Jetpack Compose Hilt Navigation Roo

A 2FA android client based on Jetpack Compose

EzLogin A 2FA android client based on Jetpack Compose Features Material Design Import via QR Code Technology stack Jetpack Compose Hilt Navigation Roo

android project based on declarative UI  (jetpack compose)
android project based on declarative UI (jetpack compose)

jetpack_compose_mvvm jetpack compose Coroutines and flows Dependency Injection with Koin Library. Model View Intent Architecture - MVI. Clean Architec

Jetpack Compose based project, used to stress-testing compose features / integrations and explore non-trivial functionality

Project containing Jetpack Compose samples For pagination & network images it uses CATAAS. Known issues Navigation-Compose Issue with fast tapping on

Jetpack Compose-based chess app with visualisation layers.
Jetpack Compose-based chess app with visualisation layers.

Chesso Chesso is an animated, Jetpack Compose-based chess app aimed at beginners and intermediate players for studying purposes. Its distinctive key f

Android weather app using Hilt, Coroutines, Retrofit, Jetpack (Compose, Room, ViewModel) based on MVVM architecture
Android weather app using Hilt, Coroutines, Retrofit, Jetpack (Compose, Room, ViewModel) based on MVVM architecture

Atmostate A weather app written with Jetpack Compose using OpenWeatherMap Get the APK Features offline caching fetching data for current user location

CoinList is a simple app based on Jetpack Compose, modern tech-stack and Clean Architecture.
CoinList is a simple app based on Jetpack Compose, modern tech-stack and Clean Architecture.

CoinList is a simple app based on Jetpack Compose, modern tech-stack and Clean Architecture. The project is quite simple which shows the list of crypto currencies and their general info details gets from API.

Jet-CoinList is a simple app based on Jetpack Compose, modern tech-stack and Clean Architecture.
Jet-CoinList is a simple app based on Jetpack Compose, modern tech-stack and Clean Architecture.

Jet-CoinList is a simple app based on Jetpack Compose, modern tech-stack and Clean Architecture. The project is quite simple which shows the list of crypto currencies and their general info details gets from API.

Comments
  • JsonDecodingException when decoding playlist with id 0nXKVLwZ7yk7hkU6OWsFcw

    JsonDecodingException when decoding playlist with id 0nXKVLwZ7yk7hkU6OWsFcw

    When Kotify try to decode https://open.spotify.com/playlist/0nXKVLwZ7yk7hkU6OWsFcw?si=4eddfe0f414d4550 throw a KotifyException with the following log:

    Caused by: tv.blademaker.kotify.exceptions.KotifyException: Unexpected JSON token at offset 338133: Expected string literal but 'null' literal was found.
    Use 'coerceInputValues = true' in 'Json {}` builder to coerce nulls to default values.
    JSON input: ..... : {
              "album_type" : null,
              "artists" : [ .....
            at tv.blademaker.kotify.request.Request$execute$2.invokeSuspend(Request.kt:77)
            at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
            at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
            at kotlinx.coroutines.EventLoopImplBase.processNextEvent(EventLoop.common.kt:279)
            at kotlinx.coroutines.BlockingCoroutine.joinBlocking(Builders.kt:85)
            at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking(Builders.kt:59)
            at kotlinx.coroutines.BuildersKt.runBlocking(Unknown Source)
            at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking$default(Builders.kt:38)
            at kotlinx.coroutines.BuildersKt.runBlocking$default(Unknown Source)
            at net.hugebot.audio.sources.spotify.providers.SpotifyPlaylistProvider.load(SpotifyPlaylistProvider.kt:22)
            at net.hugebot.audio.sources.spotify.SpotifyAudioSourceManager.loadItemOnce(SpotifyAudioSourceManager.kt:59)
            at net.hugebot.audio.sources.spotify.SpotifyAudioSourceManager.loadItem(SpotifyAudioSourceManager.kt:44)
            at com.sedmelluq.discord.lavaplayer.player.DefaultAudioPlayerManager.checkSourcesForItemOnce(DefaultAudioPlayerManager.java:436)
            at com.sedmelluq.discord.lavaplayer.player.DefaultAudioPlayerManager.checkSourcesForItem(DefaultAudioPlayerManager.java:418)
            at com.sedmelluq.discord.lavaplayer.player.DefaultAudioPlayerManager.lambda$createItemLoader$0(DefaultAudioPlayerManager.java:217)
            ... 6 common frames omitted
    Caused by: kotlinx.serialization.json.internal.JsonDecodingException: Unexpected JSON token at offset 338133: Expected string literal but 'null' literal was found.
    Use 'coerceInputValues = true' in 'Json {}` builder to coerce nulls to default values.
    JSON input: ..... : {
              "album_type" : null,
              "artists" : [ .....
            at kotlinx.serialization.json.internal.JsonExceptionsKt.JsonDecodingException(JsonExceptions.kt:24)
            at kotlinx.serialization.json.internal.JsonExceptionsKt.JsonDecodingException(JsonExceptions.kt:32)
            at kotlinx.serialization.json.internal.AbstractJsonLexer.fail(AbstractJsonLexer.kt:524)
            at kotlinx.serialization.json.internal.AbstractJsonLexer.unexpectedToken(AbstractJsonLexer.kt:202)
            at kotlinx.serialization.json.internal.StringJsonLexer.consumeNextToken(StringJsonLexer.kt:74)
            at kotlinx.serialization.json.internal.StringJsonLexer.consumeKeyString(StringJsonLexer.kt:85)
            at kotlinx.serialization.json.internal.AbstractJsonLexer.consumeString(AbstractJsonLexer.kt:310)
            at kotlinx.serialization.json.internal.StreamingJsonDecoder.decodeString(StreamingJsonDecoder.kt:256)
            at kotlinx.serialization.encoding.AbstractDecoder.decodeStringElement(AbstractDecoder.kt:58)
            at tv.blademaker.kotify.models.PartialAlbum$$serializer.deserialize(Album.kt:24)
            at tv.blademaker.kotify.models.PartialAlbum$$serializer.deserialize(Album.kt:24)
            at kotlinx.serialization.json.internal.PolymorphicKt.decodeSerializableValuePolymorphic(Polymorphic.kt:59)
            at kotlinx.serialization.json.internal.StreamingJsonDecoder.decodeSerializableValue(StreamingJsonDecoder.kt:36)
            at kotlinx.serialization.encoding.AbstractDecoder.decodeSerializableValue(AbstractDecoder.kt:43)
            at kotlinx.serialization.encoding.AbstractDecoder.decodeNullableSerializableElement(AbstractDecoder.kt:79)
            at tv.blademaker.kotify.models.Track$$serializer.deserialize(Track.kt:6)
            at tv.blademaker.kotify.models.Track$$serializer.deserialize(Track.kt:6)
            at kotlinx.serialization.json.internal.PolymorphicKt.decodeSerializableValuePolymorphic(Polymorphic.kt:59)
            at kotlinx.serialization.json.internal.StreamingJsonDecoder.decodeSerializableValue(StreamingJsonDecoder.kt:36)
            at kotlinx.serialization.encoding.AbstractDecoder.decodeSerializableValue(AbstractDecoder.kt:43)
            at kotlinx.serialization.encoding.AbstractDecoder.decodeSerializableElement(AbstractDecoder.kt:70)
            at tv.blademaker.kotify.models.PlaylistPagination$Item$$serializer.deserialize(PlaylistPagination.kt:19)
            at tv.blademaker.kotify.models.PlaylistPagination$Item$$serializer.deserialize(PlaylistPagination.kt:19)
            at kotlinx.serialization.json.internal.PolymorphicKt.decodeSerializableValuePolymorphic(Polymorphic.kt:59)
            at kotlinx.serialization.json.internal.StreamingJsonDecoder.decodeSerializableValue(StreamingJsonDecoder.kt:36)
            at kotlinx.serialization.encoding.AbstractDecoder.decodeSerializableValue(AbstractDecoder.kt:43)
            at kotlinx.serialization.encoding.AbstractDecoder.decodeSerializableElement(AbstractDecoder.kt:70)
            at kotlinx.serialization.encoding.CompositeDecoder$DefaultImpls.decodeSerializableElement$default(Decoding.kt:535)
            at kotlinx.serialization.internal.ListLikeSerializer.readElement(CollectionSerializers.kt:80)
            at kotlinx.serialization.internal.AbstractCollectionSerializer.readElement$default(CollectionSerializers.kt:51)
            at kotlinx.serialization.internal.AbstractCollectionSerializer.merge(CollectionSerializers.kt:36)
            at kotlinx.serialization.internal.AbstractCollectionSerializer.deserialize(CollectionSerializers.kt:43)
            at kotlinx.serialization.json.internal.PolymorphicKt.decodeSerializableValuePolymorphic(Polymorphic.kt:59)
            at kotlinx.serialization.json.internal.StreamingJsonDecoder.decodeSerializableValue(StreamingJsonDecoder.kt:36)
            at kotlinx.serialization.encoding.AbstractDecoder.decodeSerializableValue(AbstractDecoder.kt:43)
            at kotlinx.serialization.encoding.AbstractDecoder.decodeSerializableElement(AbstractDecoder.kt:70)
            at tv.blademaker.kotify.models.PlaylistPagination$$serializer.deserialize(PlaylistPagination.kt:7)
            at tv.blademaker.kotify.models.PlaylistPagination$$serializer.deserialize(PlaylistPagination.kt:7)
            at kotlinx.serialization.json.internal.PolymorphicKt.decodeSerializableValuePolymorphic(Polymorphic.kt:59)
            at kotlinx.serialization.json.internal.StreamingJsonDecoder.decodeSerializableValue(StreamingJsonDecoder.kt:36)
            at kotlinx.serialization.encoding.AbstractDecoder.decodeSerializableValue(AbstractDecoder.kt:43)
            at kotlinx.serialization.encoding.AbstractDecoder.decodeSerializableElement(AbstractDecoder.kt:70)
            at tv.blademaker.kotify.models.Playlist$$serializer.deserialize(Playlist.kt:6)
            at tv.blademaker.kotify.models.Playlist$$serializer.deserialize(Playlist.kt:6)
            at kotlinx.serialization.json.internal.PolymorphicKt.decodeSerializableValuePolymorphic(Polymorphic.kt:59)
            at kotlinx.serialization.json.internal.StreamingJsonDecoder.decodeSerializableValue(StreamingJsonDecoder.kt:36)
            at kotlinx.serialization.json.Json.decodeFromString(Json.kt:100)
            at tv.blademaker.kotify.request.Request$execute$2.invokeSuspend(Request.kt:56)
            ... 20 common frames omitted
    

    External urls

    bug 
    opened by Blad3Mak3r 0
  • Kotify not working on RELEASE MODE

    Kotify not working on RELEASE MODE

    I was implementing Kotify in an app and everything workedd correctly in debug mode. When i switched to release mode, it does not work. I have a try/catch that tris to do the code and then with an adapter i put it on the app and the catch returns another view in the app. In debug mode everything works correctly and the TRY is triggered. But in release, it triggers the CATCH meaning thatt the code has failed (api call) CODE TRY CATCH

      lifecycleScope.launch {
            try {
    
                    val kotify = Kotify(
                        clientID = "5ef1e8a612cb4f12b3343ad26427ec93",
                        clientSecret = "6752b38c773741ea8e15404e613bea83"
                    )
    
                    val playlist: List<PlaylistPagination.Item> =
                        kotify.playlists.get("37i9dQZEVXbMDoHDwVN2tF").tracks.items
    
    
                    val tracks: ArrayList<Track> = playlist.map { it.track } as ArrayList<Track>
    
                    for (i in 0 until tracks.count()) {
    
    
                        val SEVERALartistsname: ArrayList<Artist> =
                            tracks[i].artists as ArrayList<Artist>
                        for (o in 0 until SEVERALartistsname.count()) {
                            if (artistname == null) {
                                artistname = SEVERALartistsname[o].name
                            } else {
                                artistname = artistname + ", " + SEVERALartistsname[o].name
                            }
                        }
    
    
                        val SEVERALalbumimg: ArrayList<Image> =
                            tracks[i].album?.images as ArrayList<Image>
                        val artworkTrack = SEVERALalbumimg[2].url
    
    
                        val songname = tracks[i].name ?: "N/A"
                        val nameartist = songname + System.lineSeparator() + artistname
    
    
                        courseList2.add(namespoty(i + 1, nameartist, artworkTrack))
                        SEVERALartistsname.clear()
                        artistname = null
    
    
                    }
    
                val courseRVAdapter2 = CourseRVAdapter2(courseList2, true)
                courseRV.adapter = courseRVAdapter2
    
                loadingPB.visibility = View.GONE
    
            } catch(e:Exception){
                Log.i("HELLO", "CATCH")
                loadingPB.visibility = View.GONE
                Log.i("HELLO", "CATCH2")
                courseList2.add(namespoty(null,"",""))
                val courseRVAdapter2 = CourseRVAdapter2(courseList2, false)
                Log.i("HELLO", "CATCH3")
                courseRV.adapter = courseRVAdapter2
                Log.i("HELLO", "CATCHEND")
            }
    

    it has to do with the relase mode and a thing to mention is that i have the proguard rules activated and i dont now if i have to add a rule excluding and which one! I would help a lot! Your work is awesome! (take into account that is release mode and i dont have the logcat to see wheres the error so im stuck)

    opened by Gerizard 0
Releases(1.0.0-alpha.5)
Owner
Juan Luis Caro
Java, Kotlin, TypeScript, Rust.
Juan Luis Caro
Scrobble is a wip music tracking and browsing app. It uses the Lastf.fm and spotify APIs to deliver data. The whole UI is created using Jetpack compose.

Scrobble (WIP, name not final) Scrobble is a wip music tracking and browsing app. It uses the Lastf.fm API to realize music tracking and browsing and

Niklas Schnettler 55 Oct 31, 2022
Spotify Demo Desktop app using Jetpack compose

Compose Spotify Desktop Declarative UI A Spotify demo app for desktop using Jetpack Compose UI toolkit Demo Home Search & Detail Jetpack Compose Jetpa

Gurupreet Singh 619 Dec 31, 2022
SpotifyCompose - Spotify UI written on Jetpack Compose

SpotifyCompose - Spotify UI written on Jetpack Compose

Ivan Gospodarik 36 Dec 28, 2022
very unstable UNOFFICIAL Spotify client for Android built on librespot-java + Compose

Jetispot not so broken UNOFFICIAL Spotify client for Android Note that this client will NEVER offer any kind of a downloader/offline caching. Don't as

iTaysonLab 192 Jan 2, 2023
Instagraph is an Instagram Clone which I am practicing on a new concepts and other advanced Jetpack compose specific concepts.

Instagraph Instagraph is an Instagram Clone which I am practicing on a new concepts and other advanced Jetpack compose specific concepts. The clone on

Mustafa Ibrahim 117 Nov 25, 2022
GraphQL based Jetpack Compose and SwiftUI Kotlin Multiplatform project

MortyComposeKMM Kotlin Multiplatform sample that demonstrates use of GraphQL + Jetpack Compose and SwiftUI

John O'Reilly 293 Dec 24, 2022
Formula 1 app to show current Standings from a REST API.Built using jetpack compose and kotlin.

Formula1 Formula 1 app to show Standings fetching data from REST API ?? Screenshots Tech Stack. Kotlin - Kotlin is a programming language that can run

Ezra Kanake 5 Oct 28, 2022
😇Translation tool based on Jetpack Compose

?? Screenshots   License Copyright 2020 The Android Open Source Project Licensed under the Apache License, Version 2.0 (the "License"); you may not u

Ruger 7 May 16, 2022
📝 Note List app based on MVVM architecture (ViewModel, LiveData, Coroutines, Room and Jetpack Compose)

Note list app built with Jetpack Compose Download Go to the releases page to download the latest available apk. Screenshots Architecture Features Home

Marcos Paulo Farias 45 Dec 25, 2022
🔦 Showkase is an annotation-processor based Android library that helps you organize, discover, search and visualize Jetpack Compose UI elements

Showkase is an annotation-processor based Android library that helps you organize, discover, search and visualize Jetpack Compose UI elements. With minimal configuration it generates a UI browser that helps you easily find your components, colors & typography. It also renders your components in common situations like dark mode, right-to-left layouts, and scaled fonts which help in finding issues early.

Airbnb 1.7k Jan 2, 2023