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
}
}
}
@jstn455
Copy link

jstn455 commented Feb 22, 2020

How do I call sessionManager.application(app, open: url, options: options) from SceneDelegate?

@sean-williams24
Copy link

Hey. I'm trying to setup my app using the iOS quick start guide, implementing the methods in my view controller and not the App Delegate or scene Delegate: when calling the appRemote.authorizeAndPlayURI(self.playURI) method, it switches to Spotify, attempts to authorise - but gives me a big fat X every time and then that's that.... is someone able to let me know what I might be missing please?

Copy link

ghost commented Feb 24, 2020

Hey. I'm trying to setup my app using the iOS quick start guide, implementing the methods in my view controller and not the App Delegate or scene Delegate: when calling the appRemote.authorizeAndPlayURI(self.playURI) method, it switches to Spotify, attempts to authorise - but gives me a big fat X every time and then that's that.... is someone able to let me know what I might be missing please?

You might want to make sure that your client ID, URL types, and bundle IDs all match. That is what failed it for me. Client ID

@sean-williams24
Copy link

They are all the same just double checked. The play URI might have been what's was deucing it up, I changed to an empty string - it now switches to Spotify, authorises successfully and plays my last playing song. But, that's it, it won't switch back to my app with a lovely, much needed access token. 😩

Copy link

ghost commented Feb 26, 2020

Awesome. I am also stuck with you at the same point. No token and switchback.......

@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