Spotify iOS SDKのチュートリアルをSwiftでやってみた

本日、音楽ストリーミング[Spotify](https://www.spotify.com/jp/)のサービスが日本でも使えるようになりました。
Spotifyはデベロッパーに対してWeb APIやSDKを提供しています。今回は早速[Spotify Developer]([Home](https://developer.spotify.com/))のiOS SDKのチュートリアルをやってみたので、その概要とSwift版のコードを公開したいと思います。

【追記】
本記事執筆時点では、Spotifyのサービスは招待制となっているようです。ハッカソン等で以前にSpotifyにアカウントを作成してもらっていた人はそのアカウントが使えるみたいです。

【追記2】
2016年11月10日に日本でもSpotifyが一般公開されました。


## Web API
SpotifyはRESTに基づいた[Web API](https://developer.spotify.com/web-api/)を公開しています。Spotifyのカタログデータを取得したり、ユーザーのプレイリストを管理したりといったことができます。
ライブラリとしては、RubyやPythonなど主要言語のラッパーがあります。


## iOS SDK
今回の記事で組み込むSDKです。以下のようなことができます。詳しくは公式の[iOS SDK](https://developer.spotify.com/technologies/spotify-ios-sdk/)のページをご覧ください。

- ユーザー認証
- オーディオ再生とストリームの管理
- アートワークを含むメタデータ（アーティスト、アルバム、トラック）のルックアップ
- プレイリストの管理
- ユーザーのYour Musicライブラリの管理

現時点ではベータとなっています。前身のLibspotify SDKもありましたが、現在はiOS SDKを利用することが推奨されています。

## チュートリアル
### チュートリアルの内容
iOS SDKの[Beginner’s Tutorial](https://developer.spotify.com/technologies/spotify-ios-sdk/tutorial/)では以下を学ぶことができます。  

- Xcodeプロジェクトのセットアップ
- ユーザー認証
- オーディオストリームの再生（Spotify Premiumアカウントのみ）

チュートリアルでコードを書くのはAppDelegateだけで、UIの作成は不要です。

### アプリケーション登録

Spotify Developerの[My Applications](https://developer.spotify.com/my-applications/)から、今回のサンプルアプリの名前を入力します。
Application NameとDescriptionを入力し、アプリケーションを作成します。  
アプリが作成できたら、Client IDとClient Secretを控えます。  
Redirect URIsやBundle IDsはiOS側の設定と合わせます。

![spotify_xcode_1_1.png](https://qiita-image-store.s3.amazonaws.com/0/17330/05602372-dbcd-cd92-9931-618133f5f965.png)

※Client IDとClient Secretは伏せています

### Xcodeプロジェクト設定
Info.plistのURL Typesで、Identifier とURL Schemesを設定します。

<img width="760" alt="spotify_xcode_1.png" src="https://qiita-image-store.s3.amazonaws.com/0/17330/0f247644-222f-673b-ef53-19d2b1cd46ff.png">

Githubの[spotify/ios-sdk](https://github.com/spotify/ios-sdk)をダウンロードし、Spotify.frameworkをXcodeプロジェクトに追加します。（Carthageは未対応で、CocoaPodsで対応しているSDKは旧バージョンでした。）

Spotify.frameworkはObjective-Cで書かれているので、Bridging-Header を追加してフレームワークをインポートします。

### コード
公式のサンプルをSwiftで書いたコードです。内容は基本的に同じです。
プロジェクトファイル一式は[Github](https://github.com/ariiyu/SpotifyPlayerSample-Swift)に置きました。
 
```swift:AppDelagate.swift
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, SPTAudioStreamingDelegate {
    
    var window: UIWindow?
    
    let kClientId = "YOUR_CLIENT_ID"
    let kRedirectUrl = NSURL(string: "YOUR_REDIRECT_URL")
    
    var session: SPTSession?
    var player: SPTAudioStreamingController?
    
    
    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
        // set up Spotofy
        SPTAuth.defaultInstance().clientID = kClientId
        SPTAuth.defaultInstance().redirectURL = kRedirectUrl
        SPTAuth.defaultInstance().requestedScopes = [SPTAuthStreamingScope] as [AnyObject]
        let loginUrl = SPTAuth.defaultInstance().loginURL
        application.openURL(loginUrl)
        
        return true
    }
    
    // handle auth
    func application(application: UIApplication, openURL url: NSURL, sourceApplication: String?, annotation: AnyObject) -> Bool {
        if SPTAuth.defaultInstance().canHandleURL(url) {
            SPTAuth.defaultInstance().handleAuthCallbackWithTriggeredAuthURL(url, callback: { error, session in
                if error != nil {
                    print("*** Auth error: \(error)")
                }                
                // Call the -loginUsingSession: method to login SDK
                self.loginUsingSession(session)
            })
            return true
        }
        
        return false
    }
    
    func loginUsingSession(session: SPTSession) {
        // Get the player Instance
        player = SPTAudioStreamingController.sharedInstance()
        if let player = player {
            player.delegate = self
            // start the player (will start a thread)
            try! player.startWithClientId(kClientId)
            // Login SDK before we can start playback
            player.loginWithAccessToken(session.accessToken)
        }
    }
    
    // MARK: SPTAudioStreamingDelegate.
    
    func audioStreamingDidLogin(audioStreaming: SPTAudioStreamingController!) {
        let urlStr = "spotify:track:6ZSvhLZRJredt15aJiBQqv" // track available in Japan
        player!.playSpotifyURI(urlStr, startingWithIndex: 0, startingWithPosition: 0, callback: { error in
            if error != nil {
                print("*** failed to play: \(error)")
                return
            } else {
                print("play")
            }
        })
    }
}
```

ちなみに公式サンプルで使われているトラックはおそらく日本では再生できないようなので、上記のサンプルコードでは別のトラックを指定しました。


### 実行

アプリ起動後、Safariが開き、アカウント接続を促すダイアログが表示されます。
OKを押すとアプリに戻り、楽曲が再生されます。

# まとめ
ほぼ公式ページの手順通りに作業を進めて、Spotify SDKをSwiftのアプリで利用することができました。実際のアプリ開発ではさらに、ログインセッションの管理や、トラック情報の取得などの機能が必要になってくるでしょう。
他の大手音楽ストリーミングサービスと比較してSpotifyは情報がオープンで開発コミュニティも充実しており、今回のように公開APIを使うことが出来るのも音楽好きエンジニアにとっては嬉しいですね。ライバルであるApple MusicもAPIを公開しています。また機会があれば記事を書きたいと思います。