質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.52%

  • Swift

    8728questions

    Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

Swift バックグラウンドで自動ロック(スリープ)状態になっても、mp3を再生し続ける方法

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 281

torkia

score 14

バックグラウンド再生を、iPhoneのロック状態(スリープ)になっても継続させたいのですが、うまくいきません。
解る方がいらっしゃいましたら教えて頂けると助かります。宜しくお願い致します。

 仕様

各mp3を割り当てたボタンをタップしたら、AVAudioPlayerでmp3データを再生させています。
各ページにmp3は10コ〜30コほど割り当てています
自動再生するように設定すると、AVAudioPlayerDelegateの[audioPlayerDidFinishPlaying] メソッドで再生終了したら次のmp3を再生するように条件分岐させ、連続で再生し続け、そのページの最後のmp3を再生すると、次ページの頭から自動再生するようにしています。

 試したこと

バックグラウンド再生させるために、以下のコードをmp3を再生させるメソッド内の audioPlayer.play()の手前で記述。

try?AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback, 
with: .mixWithOthers)
try? AVAudioSession.sharedInstance().setActive(true)

(「capabilities」で「Background Modes」をONにして、「Audio,AirPlay, and Picture in Picture」にチェック済み)

 できていること・できないこと

アプリをバックグラウンドにした時点では、再生は継続されているのですが、自動ロック(スリープ状態)に入ると、スリープ状態に入ったときのページのデータ分が再生し終えたら、次ページにいかず、終了してしまいます。
どうやら、スリープ状態にならなければ、バックグラウンド再生は継続されるみたいなのですが、スリープ状態でも再生を継続させたいです。

import UIKit
import AVFoundation

class PageContentViewController: UIViewController, UIScrollViewDelegate, AVAudioPlayerDelegate {

    (略)
    override func viewDidLoad() {
        super.viewDidLoad()
        (略)
        soundArray = csvSoundArray[pageIndex].components(separatedBy: ";")
        soundArray = soundArray.filter {$0 != ""}
        for index in 0..<soundArray.count {
            ・
            ・
            soundButton.tag = index // ボタン識別用ID
            soundButton.addTarget(self, action: #selector(buttonEventSound(sender:)), for: .touchDown)
            soundButtons.append(soundButton)
            scrollView.addSubview(soundButton)
        }
    }

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        backgroundSetting = userDefaults.integer(forKey: "backgroundSetting")
        autoPlaySetting = userDefaults.integer(forKey: "autoPlaySetting")
        autoPlayNextSetting = userDefaults.integer(forKey: "autoPlayNextSetting")
        autoPlayNext = userDefaults.integer(forKey: "autoPlayNext")
            ・
            ・
        // 自動連続再生
        if autoPlayNext == 1 {
            if autoPlaySetting == 1 {
                let index = 0
                soundPlay(index: index)  // mp3再生メソッド呼出し
                userDefaults.set(0, forKey: "autoPlayNext")
            }
        }
    }

    // ボタンタップイベント
    func buttonEventSound(sender: UIButton) {
        let index = sender.tag
        soundPlay(index: index)
    }

    // mp3再生メソッド
    func soundPlay(index: Int) {
        let audioPath = Bundle.main.path(forResource: "\(soundArray[index])", ofType:"mp3")!
        let audioUrl = URL(fileURLWithPath: audioPath)

        do {
            audioPlayer = try AVAudioPlayer(contentsOf: audioUrl)
            audioPlayer.delegate = self
            // バックグラウンド再生
            try?AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback, with: .mixWithOthers)
            try? AVAudioSession.sharedInstance().setActive(true)
            audioPlayer.prepareToPlay()
            audioPlayer.enableRate = true
            audioPlayer.rate = soundRate
        } catch {
            print("エラー")
        }
        (略)
        audioPlayer.play()
        currentPlayer = audioPlayer
        currentButtonIndex = index
    }


    // 音楽再生が成功した時に呼ばれるメソッド
    func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) {
        currentPlayer = nil
        if autoPlaySetting == 1 {  // 自動再生するとき
            let index = currentButtonIndex! + 1
            if index < soundArray.count { 
                soundPlay(index: index)
                if autoPlayScrollSetting == 1 {  // 自動スクロールするとき
                (略)
                }
            if autoPlayNextSetting == 1 {  // 全ページ自動再生するなら
                if index >= soundArray.count {  // 最後のボタンの再生が終わったら
                    if pageIndex < 19 {  // 19までは次ページも自動連続再生する
                        let pvc = self.parent as! PageViewController
                        let nextIndex = pageIndex + 1
                        pvc.setViewControllers([pvc.contentVCs[nextIndex]], direction: .forward, animated: true, completion: nil)
                        pvc.currentIndex += 1
                        autoPlayNext = 1       // 次ページも自動再生させる
                        userDefaults.set(autoPlayNext, forKey: "autoPlayNext")
                    } else if pageIndex == 19 {
                       print("音終了")
                    }
                }
            }
        }
    }
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

check解決した方法

0

自動ロック(スリープ状態)にならなければ、バックグラウンド再生中でも次ページのデータ再生はできていたのですが、スリープ状態になると、次ページを呼び出せても更新(再生メソッドの呼出)ができていないようだったので、「次ページのviewWillAppear」を、次ページの呼出しと同時に行うようにしました。

// 「audioPlayerDidFinishPlaying」のメソッド内にコードを1行追加

if autoPlayNextSetting == 1 {  // 全ページ自動再生するなら
                if index >= soundArray.count {  
                    if pageIndex < 19 {  
                        let pvc = self.parent as! PageViewController
                        let nextIndex = pageIndex + 1
                        pvc.setViewControllers([pvc.contentVCs[nextIndex]], direction: .forward, animated: true, completion: nil)
                        pvc.currentIndex += 1
                        autoPlayNext = 1       
                        userDefaults.set(autoPlayNext, forKey: "autoPlayNext")
                        pvc.contentVCs[nextIndex].viewWillAppear(true)  // コードを追加
                    } else if pageIndex == 19 {
                       print("全ページ音終了")
                    }
                  ・
                  ・
                  ・

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

同じタグがついた質問を見る

  • Swift

    8728questions

    Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています