ichigoryume programming blog

プログラミングに関する備忘録。主にHTML5, C#, Swiftなど。

Media & Apple Musicへのアクセス許可を繰り返し求める方法

概要

  • プログラムからiTnuesライブラリにアクセスしたり、MPMusicPlayerControllerを使って曲を再生したりする場合、ユーザーに「メディアとApple Music」へのアクセスを許可してもらう必要がある。
  • MPMediaLibrary.requestAuthorization()メソッドをコールすると許可を求めるダイアログが表示される。

f:id:ichigoryume:20180906092029p:plain

  • このダイアログは一度しか表示されない。同メソッドを再度コールしても、アプリを一旦再起動してコールしても何も表示されない。
  • この挙動は初回コール時に「OK」をタップしてもらえた場合はいいが、「Don't Allow」をタップされた場合厄介。
  • 一旦「Don't Allow」された場合は設定画面でアクセスを許可してもらえばいい。

f:id:ichigoryume:20180906092518p:plain

  • なので「Don't Allow」された場合は、2回目以降、設定画面へ誘導するダイアログを自前で表示すると親切。
  • ユーザがアクセスを許可しているかどうかは、MPMediaLibrary.authorizationStatus()メソッドで判定できる。

手順

まず、MPMediaLibrary.requestAuthorization()メソッド初回実行時のダイアログに表示される、アクセス理由に相当する文字列をInfo.plistに設定する。Info.plistにこの設定項目がないとダイアログが表示されることなくアプリがクラッシュする。

  • key: Privacy - Media Library Usage Description
  • Value: To Play Music(例)

f:id:ichigoryume:20180906093938p:plain

続いて、2回目以降、設定画面へ誘導するダイアログを表示するメソッドを作成する

    func displayPermissionAlertFromViewController() {
        
        let alert = UIAlertController(
            title: "This application needs to access your music library. Please allow it to access \"Meidia & Apple Music\" at Settings.",
            preferredStyle: .alert
        )
        
        alert.popoverPresentationController?.sourceView = self.view

        let cancelAction = UIAlertAction(title: "Cancel", style: .default, handler: nil)
        alert.addAction(cancelAction)
        
        let okAction = UIAlertAction(title: "GoToSettings", style: .default) { _ in
            if let url = URL(string: UIApplicationOpenSettingsURLString) {
                // 設定画面をオープン
                UIApplication.shared.open(url, options: [:], completionHandler: nil)
            }
        }
        alert.addAction(okAction)
        
        self.presentedViewController?.dismiss(animated: false, completion: nil)
        present(alert, animated: true, completion: nil)
    }

最後に、許可状況を確認したうえでクロージャーを実行するメソッドを作るとこんな感じ。

    fileprivate func checkMediaPlayerPermission(completion:@escaping () -> Void) {
        
        let status = MPMediaLibrary.authorizationStatus()
        
        switch status {

        case .authorized:
            completion()
            break

        // 初回起動時はnotDetermined
        case .notDetermined:
            MPMediaLibrary.requestAuthorization { status in
                if status == .authorized {
                    completion()
                }
            }
            break
            
         // 一度拒否されている場合
        case .denied, .restricted:
            displayPermissionAlertFromViewController()
        }
    }