私のスレッドとMediaPlayerスレッド(ルーパーを介してメッセージを送信する)の2つのスレッドを想定します。私のゲームスレッドはユーザー入力に反応します。ユーザーがゲームプレイを一時停止した場合は、MediaPlayer.pause()も呼び出します。
次のイベントの順序を検討してください。
- MediaPlayerオーディオストリームが終了したため、OnCompletionメッセージがキューに入れられます
- 私のスレッド:MediaPlayer.pause()がユーザーアクションのために呼び出されました
- OnCompletion呼び出しを受け取りました(遅すぎます、pause()はすでに上記で呼び出されています)
これに伴う問題は、MediaPlayer.pause()がPAUSEDおよびSTARTED状態でのみ許可されることですが、ステップ1により、pause()が呼び出されたときにMediaPlayerはすでにPlaybackCompleted状態になっています。私は2つの解決策を見ます:
- 例外をキャッチ
- pause()を呼び出す前にMediaPlayer.isPlaying()に尋ねる
しかし、2番目の解決策には、次のシナリオで問題があります。
- ゲームが開始され、MediaPlayer.start()が呼び出されましたが、メディアプレーヤーの状態は まだ開始されていません
- ユーザーはゲームプレイを終了し、コードを呼び出します。if(isPlaying())pause();
- MediaPlayerがSTARTED状態になります(現在、isPlayingはtrueを返しますが、遅すぎます)
ここでの問題は、isPlaying()が(ドキュメントにもあるように)falseを返すため、手順3のためにMediaPlayerが引き続き起動することです。
どちらの場合も正しく、例外を回避する解決策はありますか?(または、上記の一連の思考に間違いはありますか?)
アップデート
Geobitsの回答に反応する(Androidドキュメントから引用するのでここで行います):
はい、私もローカル再生を行っており、あなたと同じようにテストしましたが、すべて問題なく見えました。しかし、ドキュメントは少し自己矛盾しています。最初の部分(これはOKです):
start()を呼び出して、一時停止したMediaPlayerオブジェクトの再生を再開します。再開された再生位置は、一時停止した場所と同じです。start()の呼び出しが戻ると、一時停止したMediaPlayerオブジェクトはStarted状態に戻ります。
そして同じページからの別の引用:
再生を一時停止および停止したり、現在の再生位置を調整したりできます。pause()を使用して再生を一時停止できます。pause()の呼び出しが戻ると、MediaPlayerオブジェクトは一時停止状態になります。開始状態から一時停止状態への遷移、およびその逆の遷移は、プレーヤーエンジンで非同期に発生することに注意してください。isPlaying()の呼び出しで状態が更新されるまでに時間がかかる場合があり、ストリーミングコンテンツの場合は数秒かかる場合があります。
この後者は、一時停止したプレーヤーを起動するときにも、状態の変更に時間がかかる場合があることを示しています(「その逆」)。これまでのところ、これは内部プレーヤーエンジンにのみ適用されるためですが、「isPlaying()の呼び出しで状態が更新されるまでに時間がかかる場合があります」というクレイジーな部分があります。これは、isPlaying()がOBSERVABLE状態を返さず、代わりに内部状態に依存することを意味します。これは紛らわしいです。