How to integrate SoundCloud into project in Swift
Recently we have published an article about a popular music streaming service Spotify. In this article we will describe how to connect to and use another well-known service - SoundCloud.
ADVANTAGES AND DISADVANTAGES (COMPARED TO SPOTIFY):
Advantages
- free of charge (one of the main advantages, as price is a key factor for many users)
- good documentation (of course, Spotify’s one is also quite good, but in “volume-declared functionality” estimation SoundCheck is a bit ahead of its rival)
- realization opportunity with the help of standard components (AVPlayer, in particular, is more accustomed for work)
Disadvantage
- absence of SDK (the whole functionality is realised on a quite good WEB_API, however a library-like design would be more convenient)
Creation of SoundCloud application
- Register in soundcloud.com
- Enter developers.soundcloud.com. Here is documentation on demand.
We are interested in creation of an application for SoundCloud API access. Move to “Your Apps” and click “Register a new application”. Enter the name of our application - Register - done!
In the article we will not use redirect URL, that is why we copy only ClientID and ClientSecret in to the project.
Integration of SoundCloud in our application
If you use users’ personal information maliciously (or, SoundCloud authorization is used in your application), we recommend to use classes, given at this address. SoundCloudLoginViewController - UIView with incorporated UIWebView, which appeals to SoundCloud server.
SoundCloudAuthenticator - a wrap-manager for configuration and SoundCloud data receiving. It is a cirrected version of SoundCloud official demo application.
The use of the given classes:
extension LoginManager : SoundCloudLoginResultsDelegate {
func getSoundcloudToken(fromController controller: UIViewController, success: (soundcloudToken: String, soundcloudId: String) -> Void, failure: (error: NSError?) -> Void) {
loginSuccessBlock = success
loginFailureBlock = failure
let soundCloudLoginController = UIStoryboard(name: "Login", bundle: nil).instantiateViewControllerWithIdentifier(String(SoundCloudLoginViewController)) as! SoundCloudLoginViewController
soundCloudLoginController.delegate = self
controller.navigationController?.presentViewController(soundCloudLoginController, animated: true, completion: nil)
}
internal func didSucceed(loginViewController: SoundCloudLoginViewController, authResult: AuthenticationResult) {
if let successBlock = loginSuccessBlock {
let meUrl = "https://api.soundcloud.com/me?oauth_token=" + authResult.value
APIManager.request(.GET, url: meUrl, params: nil, success: { (responseJSON) -> Void in
if let id = responseJSON.first![IdKey] as? Int {
successBlock(token: authResult.value, id: String(id))
} else {
self.loginFailureBlock!(error: Error("Failed to connect SoundCloud"))
}
}, failure: loginFailureBlock!)
}
reset()
}
internal func didFail(loginViewController: SoundCloudLoginViewController, error: NSError?) {
if let failBlock = loginFailureBlock {
reset()
failBlock(error: error)
}
}
}
This time we carry out the server’s answer processing via saved loginSuccessBlock and loginFailureBlock, which get nulled without fail in reset method:
private func reset() {
loginSuccessBlock = nil
loginFailureBlock = nil
}
Save clientID and Token wherever it is convenient. For this purpose we use statistical variables of TokenManager class:
static var soundCloudClientId: String?
static var soundCloudToken: String?
Aaand... That’s it! :) As you can see, authorization in SoundCloud is much easier, than in Spotify. The situation is similar with streaming.
Songs stream
For playback we only need a track’s ID. The link is formed out of it for AVPlayer. We use the following wrap.
private var trackUrl: String? {
get {
return "http://api.soundcloud.com/tracks/" + String(track!.sourceId!) + "/stream?\(ClientId)=\(SoundCloudClientID)"
}
}
Make a usual AVPlayer
let url = NSURL(string: trackUrl)!
player = AVPlayer(URL: url)
###Player’s main methods:
- Check of the state (play/pause):
```swift
private func isPlaying() -> Bool {
return player?.rate != nil && player?.rate != 0
}
- Play/pause:
if isPlaying {
player!.pause()
} else {
player!.play()
}
- Current state:
Float(CMTimeGetSeconds(player!.currentItem!.currentTime()))
- General duration:
Float(CMTimeGetSeconds(player!.currentItem!.duration))
- Time rewind:
player.seekToTime(CMTimeMake(Int64(newPosition), 1))
Thank you for your time. We hope you have found it useful.
P.S. Don’t forget to logout by simply deleting ClientID and Token and visit our Github page and our Blog.