SPTSessionManager does not initialize or fail

别说谁变了你拦得住时间么 提交于 2021-02-11 01:11:06

问题


When I try to call sessionManager.initialize() neither func sessionManager(manager: SPTSessionManager, didFailWith error: Error) nor func sessionManager(manager: SPTSessionManager, didInitiate session: SPTSession) are called.

I have a nodeJS server running on AWS for token access and refresh and I have also tried running a local Ruby server to get the token. No matter what, calling initialize() does nothing. It does fail or succeed and nothing is output to console. I have tried running the XCode debugger and it seems as if the program just skips past initialize. Here is my complete ViewController.swift file with the unrelated/private parts deleted:

import UIKit
import Firebase

class LobbyAdminViewController: UIViewController, SPTSessionManagerDelegate, SPTAppRemoteDelegate, SPTAppRemotePlayerStateDelegate  {
    fileprivate let SpotifyClientID = "client_id"
    fileprivate let SpotifyRedirectURI = URL(string: "redirect_url")!
    fileprivate var lastPlayerState: SPTAppRemotePlayerState?
    var refreshAPI = "token_server/refresh_token"
    var tokenAPI = "token_server/token"

    lazy var configuration: SPTConfiguration = {
           let configuration = SPTConfiguration(clientID: SpotifyClientID, redirectURL: SpotifyRedirectURI)
           configuration.playURI = ""
           configuration.tokenSwapURL = URL(string: tokenAPI)
           configuration.tokenRefreshURL = URL(string: refreshAPI)
           return configuration
       }()

       lazy var sessionManager: SPTSessionManager = {
           let manager = SPTSessionManager(configuration: configuration, delegate: self)
           return manager
       }()

       lazy var appRemote: SPTAppRemote = {
           let appRemote = SPTAppRemote(configuration: configuration, logLevel: .debug)
           appRemote.delegate = self
           return appRemote
       }()

    override func viewDidLoad() {
        super.viewDidLoad()
        let random = Int(arc4random_uniform(900000) + 100000)
        lobbyCode = String(random)
        lobbyCodeLabel.text = lobbyCode
        var ref: DatabaseReference!
        ref = Database.database().reference()
        ref.child(lobbyCode).child("null").setValue("null")
        let scope: SPTScope = [.appRemoteControl]
        if #available(iOS 11, *) {
            print("ios 11+")
            sessionManager.initiateSession(with: scope, options: .clientOnly)
        } else {
            print("ios 11-")
            sessionManager.initiateSession(with: scope, options: .clientOnly, presenting: self)
        }
    }

    func update(playerState: SPTAppRemotePlayerState) {
        print("Updating")
        lastPlayerState = playerState
        currentSongLabel.text = playerState.track.name
        currentArtistLabel.text = playerState.track.artist.name
        if playerState.isPaused {
            pausePlayButton.setBackgroundImage(UIImage(named: "play"), for: .normal)
        } else {
            pausePlayButton.setBackgroundImage(UIImage(named: "pause"), for: .normal)
        }
    }

    func fetchPlayerState() {
        print("Getting player state")
        appRemote.playerAPI?.getPlayerState({ [weak self] (playerState, error) in
            if let error = error {
                print("Error getting player state:" + error.localizedDescription)
            } else if let playerState = playerState as? SPTAppRemotePlayerState {
                self?.update(playerState: playerState)
            }
        })
    }

    @IBAction func onTap_pausePlayButton(_ sender: UIButton) {
        print("tapped")
        if let lastPlayerState = lastPlayerState, lastPlayerState.isPaused {
            appRemote.playerAPI?.resume(nil)
            print("Resuming")
        } else {
            appRemote.playerAPI?.pause(nil)
            print("Pausing")
        }
    }

    func sessionManager(manager: SPTSessionManager, didFailWith error: Error) {
        print("Bad init")
        print(error.localizedDescription)
    }

    func sessionManager(manager: SPTSessionManager, didRenew session: SPTSession) {
        print("Renewed")
    }

    func sessionManager(manager: SPTSessionManager, didInitiate session: SPTSession) {
        print("Trying to connect")
        appRemote.connectionParameters.accessToken = session.accessToken
        print(session.accessToken)
        appRemote.connect()
    }

    // MARK: - SPTAppRemoteDelegate

    func appRemoteDidEstablishConnection(_ appRemote: SPTAppRemote) {
        print("App Remote Connected")
        appRemote.playerAPI?.delegate = self
        appRemote.playerAPI?.subscribe(toPlayerState: { (success, error) in
            if let error = error {
                print("Error subscribing to player state:" + error.localizedDescription)
            }
        })
        fetchPlayerState()
    }

    func appRemote(_ appRemote: SPTAppRemote, didDisconnectWithError error: Error?) {
        lastPlayerState = nil
        print("Error connecting to app remote")
    }

    func appRemote(_ appRemote: SPTAppRemote, didFailConnectionAttemptWithError error: Error?) {
        lastPlayerState = nil
        print("Another error connectiong to app remote")
    }

    // MARK: - SPTAppRemotePlayerAPIDelegate

    func playerStateDidChange(_ playerState: SPTAppRemotePlayerState) {
        print("Player state changed")
        update(playerState: playerState)
    }

    // MARK: - Private Helpers

    fileprivate func presentAlertController(title: String, message: String, buttonTitle: String) {
        let controller = UIAlertController(title: title, message: message, preferredStyle: .alert)
        let action = UIAlertAction(title: buttonTitle, style: .default, handler: nil)
        controller.addAction(action)
        present(controller, animated: true)
    }

}

The only print() statement that fires is "ios 11" in viewDidLoad() I have scoured the internet for anyone with the same issue and have come up empty. The only thing I can think of that could be causing this issue is a known runtime issue with iOS 13. This error:

Can't end BackgroundTask: no background task exists with identifier 8 (0x8), or it may have already been ended. Break in UIApplicationEndBackgroundTaskError() to debug.

fires every time the app is sent to the background (ie when the app redirects to spotify to authenticate). However, this issue exists with even a blank app in XCode and does not halt execution.


回答1:


I just figured that out now. In the scene delegate class you have to implement the

func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {

}

method and you have to access the sessionManager that you have in your LobbyAdminViewController and create an instance of it and add these lines of code into the method

func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {

    print("Opened url")
    guard let url = URLContexts.first?.url else {
        return
    }
    lobbyAdminVC.sessionManager.application(UIApplication.shared, open: url, options: [:])
}

After doing this, the app remote connected and all the print statements printed and said app remote was connected.




回答2:


I was having the same issue, kept getting the exact same Can't end BackgroundTask error and was stumped for quite a while. Until I figured out the issue (in my case). It has to do with your AppDelegate.swift file. This error code doesn't actually have to do with the issue I don't think, this is just the last thing logged to the console before the session initialization abruptly stops.

With the introduction of scene delegates, the default App Delegate file has changed in recent months. What you need to do is make sure that you are not using this newer App Delegate that works with the scene delegate, but rather, you need to convert your App Delegate to the way it looked in the past.

For me, removing scene delegate completely from my app involved two steps:

1. Revert your AppDelegate.swift file

Mine looks something like this:

import UIKit

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
    var window: UIWindow?
    var application: UIApplication!

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        // Override point for customization after application launch.
        return true
    }

    func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {

        return true
    }

    func applicationWillResignActive(_ application: UIApplication) {
        //SpotifyManager.shared.appRemote is of type SPTAppRemote
        if SpotifyManager.shared.appRemote.isConnected {
            SpotifyManager.shared.appRemote.disconnect()
        }
    }

    func applicationDidBecomeActive(_ application: UIApplication) {
        //SpotifyManager.shared.appRemote is of type SPTAppRemote
        if let _ = SpotifyManager.shared.appRemote.connectionParameters.accessToken {
            SpotifyManager.shared.appRemote.connect()
        }
    }
}

2. Remove Application Scene Manifest from your info.plist

In your info.plist file, there is a property that tells your app that you are using the scene delegate. We need to delete this from the plist. It should look something like this:

<key>UIApplicationSceneManifest</key>
    <dict>
        <key>New item</key>
        <string></string>
        <key>UIApplicationSupportsMultipleScenes</key>
        <false/>
        <key>UISceneConfigurations</key>
        <dict>
            <key>UIWindowSceneSessionRoleApplication</key>
            <array>
                <dict>
                    <key>UISceneConfigurationName</key>
                    <string>Default Configuration</string>
                    <key>UISceneDelegateClassName</key>
                    <string>$(PRODUCT_MODULE_NAME).SceneDelegate</string>
                    <key>UISceneStoryboardFile</key>
                    <string>Main</string>
                </dict>
            </array>
        </dict>
    </dict>

If you update your app delegate and remove this property from the plist, it should work for you (or, at least, it worked for me).

P.S. if you want to use scene delegate and use the Spotify SDK, I believe you have to do it in the way outlined in this resource. Notably, look for the part of the authorization guide that mentions "If you are using UIScene then you need to use appropriate method in your scene delegate."



来源:https://stackoverflow.com/questions/58784552/sptsessionmanager-does-not-initialize-or-fail

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!