iOS10.3 で MPMusicPlayerController クラスの挙動が変わった

デバイスをiOS10.3にアップデートしたら自作の音楽再生アプリでバグが発生しました。選んだ曲と別のものが再生されるバグです。

はじめに

この問題について述べる前にMPMusicPlayerControllerクラスのことを軽く書きます。
デバイスに入っている音楽を自作アプリ内で流すとき、曲のリストを取得してMPMusicPlayerControllerクラスのインスタンス(この記事ではこれをPlayerと呼ぶことにします)にセットします。その後、Playerに対して曲の再生、停止などの指令を出します。

//.h
MPMusicPlayerController  *iPodMusicPlayer;
MPMediaQuery    *albumsQuery;
MPMediaItemCollection  *selectedAlbumCollection;

//.m
iPodMusicPlayer = [MPMusicPlayerController systemMusicPlayer]; //Playerの作成
albumsQuery = [MPMediaQuery albumsQuery]; //アルバム単位で情報を取得
selectedAlbumCollection = [albumsQuery.collections objectAtIndex:6]; //6のアルバムの情報を取得
[iPodMusicPlayer setQueueWithItemCollection:selectedAlbumCollection]; //取得した6のアルバムの情報をPlayerにセット
[iPodMusicPlayer play]; //再生指令

Playerの作成するときは
  • systemMusicPlayer
  • applicationMusicPlayer
のいずれかで作成します。

ここから今回の問題についてです。
何パターンかの操作を行うことで問題の症状を細かく炙り出しました。

症状1

曲の再生を停止すると、Playerに設定した曲のリストが無効になる。(再設定が必要。)
Playerに対するstop指令で失う。pause指令では失わない。

曲のリストを失ったら、次に再生する前にリストを設定し直します。新たにMPMediaQueryから曲のリストを取得して設定すればOKです。
上の例でいうと
albumsQuery = [MPMediaQuery albumsQuery]; //アルバム単位で情報を取得
selectedAlbumCollection = [albumsQuery.collections objectAtIndex:6]; //6のアルバムの情報を取得
[iPodMusicPlayer setQueueWithItemCollection:selectedAlbumCollection]; //取得した6のアルバムの情報をPlayerにセット
[iPodMusicPlayer play]; //再生指令
の部分を毎回実行するようにします。

症状2

いちいちMPMediaQueryから取得しなくてもリストを保存しておいてそれを設定すればいいのだが、これをやろうとすると前回と同じ曲のリストを設定したときにうまくいかない。別のリストだとうまくいく。これは多分、現在値情報などがリセットされるのを避けるために同じリストを設定した場合は何もしないという処理になっていて、その機能に前回設定したリストが残っていると予想。なので、何か設定するときは、一旦空のリストを設定してからならうまくいく。
//空を設定
[iPodMusicPlayer setQueueWithItemCollection:[[MPMediaItemCollection alloc] initWithItems:[[NSArray alloc] init]]];
  
//本来設定したいものを設定 
[iPodMusicPlayer setQueueWithItemCollection:selectedAlbumCollection];
同じ曲のリストでも新たにMPMediaQueryから取得したものだとOKなのは別のリストと認識しているのだろうか?

ちなみに、曲のリストを失った後、リストの設定をしないでplay指令を送ったときの現象は
systemMusicPlayerの場合は何か勝手に選ばれた曲が再生される。
applicationMusicPlayerの場合は何も再生されない。
となる。

症状3

プレイ中にプレイ指令を送ると内部で混乱する。
これはiOS10.3より以前からあったかもしれませんが今回見つけました。

コメント

  1. この問題を解決できるコードを教えてください。

    返信削除
  2. コメントに気が付くのが遅れました。

    コードを追加しました。
    - 毎回曲のリストを取得して設定する(症状1のほう)
    - 曲のリストを保存しておいて、毎回、空リストを設定してから本来のリストを設定し直す(症状2のほう)
    の2つのやり方があります。

    返信削除

コメントを投稿

このブログの人気の投稿

Swiftのコンパイルエラー寄せ集め

コンパイルエラー覚え書き(Objective-C)

AVAudioSession細かいことまとめ(late 2014)