Skip to content

Instantly share code, notes, and snippets.

@kkarayannis
Created October 2, 2019 11:50
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save kkarayannis/65f8927ecc6444515c6525db72c7544a to your computer and use it in GitHub Desktop.
Save kkarayannis/65f8927ecc6444515c6525db72c7544a to your computer and use it in GitHub Desktop.
import UIKit
class SceneDelegate: UIResponder, UIWindowSceneDelegate,
SPTAppRemoteDelegate {
static private let kAccessTokenKey = "access-token-key"
private let redirectUri = URL(string:"comspotifytestsdk://")!
private let clientIdentifier = "089d841ccc194c10a77afad9e1c11d54"
var window: UIWindow?
lazy var appRemote: SPTAppRemote = {
let configuration = SPTConfiguration(clientID: self.clientIdentifier, redirectURL: self.redirectUri)
let appRemote = SPTAppRemote(configuration: configuration, logLevel: .debug)
appRemote.connectionParameters.accessToken = self.accessToken
appRemote.delegate = self
return appRemote
}()
var accessToken = UserDefaults.standard.string(forKey: kAccessTokenKey) {
didSet {
let defaults = UserDefaults.standard
defaults.set(accessToken, forKey: SceneDelegate.kAccessTokenKey)
}
}
func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
guard let url = URLContexts.first?.url else {
return
}
let parameters = appRemote.authorizationParameters(from: url);
if let access_token = parameters?[SPTAppRemoteAccessTokenKey] {
appRemote.connectionParameters.accessToken = access_token
self.accessToken = access_token
} else if let _ = parameters?[SPTAppRemoteErrorDescriptionKey] {
// Show the error
}
}
func sceneDidBecomeActive(_ scene: UIScene) {
connect();
}
func sceneWillResignActive(_ scene: UIScene) {
playerViewController.appRemoteDisconnect()
appRemote.disconnect()
}
func connect() {
playerViewController.appRemoteConnecting()
appRemote.connect()
}
// MARK: AppRemoteDelegate
func appRemoteDidEstablishConnection(_ appRemote: SPTAppRemote) {
self.appRemote = appRemote
playerViewController.appRemoteConnected()
}
func appRemote(_ appRemote: SPTAppRemote, didFailConnectionAttemptWithError error: Error?) {
print("didFailConnectionAttemptWithError")
playerViewController.appRemoteDisconnect()
}
func appRemote(_ appRemote: SPTAppRemote, didDisconnectWithError error: Error?) {
print("didDisconnectWithError")
playerViewController.appRemoteDisconnect()
}
var playerViewController: ViewController {
get {
let navController = self.window?.rootViewController?.children[0] as! UINavigationController
return navController.topViewController as! ViewController
}
}
}
@Bradysm
Copy link

Bradysm commented Mar 21, 2020

If you're using SwiftUI, move the connect function to the line windowScene is instantiated. This will ensure that connect is only called once and will make it so the applications do not keep switchback

@Samuel-IH
Copy link

Samuel-IH commented Apr 27, 2020

I had a similar problem.
Calling appRemote.connect() would open Spotify but would not return a valid access token.
I was able to get Spotify to generate an access token by using appRemote.authorizeAndPlayURI("") however I still had to call appRemote.connect() afterward to connect the session.

Lastly, I removed appRemote.disconnect() from sceneWillResignActive(...) as this was causing an endless loop where connecting swaps over to Spotify, and swapping over causes us to disconnect... and then swapping back tries to reconnect.. you get the point.

I'll have to dig into the API a bit more, and maybe make a gist. But for now, here's the corrected working code:

    func sceneWillResignActive(_ scene: UIScene) {
        //Stop the never-ending loop!
        //"connecting" will cause us to call this very function when it changes over to Spotify, therefore we need a better way to decide when to disconnect
        //appRemote.disconnect()
    }

    func connect() {
        //attempt a connection
        appRemote.connect()
        
        //if it failed, aka we dont have a valid access token
        if (!appRemote.isConnected) {//ultimately access token issues aren't the only thing that will cause this the connection to fail
            //make spotify authorize and create an access token for us
            appRemote.authorizeAndPlayURI("")
        }
    }

My best guess is that perhaps in a previous version of the API, calling connect() didn't switch over to Spotify.
¯\_(ツ)_/¯

@kendalleasterly
Copy link

From a previous thread I saw that I need to use UIScene to get this to work on iOS13. I am using this code for my SceneDelegate but seem to get the error that ViewController has no appRemoteDisconnect method. If I comment those lines out, it fails Spotify authentication (goes into Spotify gets an X and returns to my app). Could you try to help?

I am having the same issue... Any help?

Hello! Have you tried updating all necessary information in your developer app? I had the same issue recently and doing this helped.

@raqssr
Copy link

raqssr commented Apr 25, 2021

Does anyone here has the code for the playerViewController? All the demo examples doesn't work for me, I have been reading Spotify's documentation since yesterday and there is different code for the same functions everywhere, I'm lost in this lack of consistency. I was currently trying the code of this SceneDelegate.swift but I don't even know what functions like appRemoteConnecting(), appRemoteConnected() and appRemoteDisconnected() in the view controller are doing 🤷🏼‍♀️

@Erikjimenez314
Copy link

Does anyone know how to implement this on a specific view controller after everything is done on the Scene delegate?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment