前記事で書いたようにSportifyを使うとアルバム画像(Cover Art)が時折表示されないという問題に遭遇していました。YTube Musicを使えばちゃんと表示されるし、コミュニティの投稿を読むと他のサービスのアプリを使った場合でもちゃんと表示されているようで、Sportifyのアプリ側に問題があるようです。投稿では、アプリの接続先としてカーナビを使っている人が多いようです。
曲が変わった時に、曲名やアーティスト名は正しい情報が取得できるのに、アルバム画像だけは取得できないというのが、この問題の症状です。何度か連続して画像取得に成功することもあれば、連続して失敗することもあるのが、これまた困ったチャンです。YTube Musicの無料版ではバックグラウンド再生ができないので、やはりSportifyの無料版でちゃんとCover Art表示が安定して動くようにしたい... というわけで問題の原因調査と、その対処について検討、実装してみました。
まずは、AVRCP 1.6の仕様書から正常な画像取得シーケンスを見てみましょう。
GetElementAttributeCmd を送信して AttributeID=0x08 のDefault Cover Artの画像情報を要求します。すると、その応答として長さ7バイトのイメージハンドルが返ってきます。このハンドルを使って実際の画像イメージを GetLinkedThumnail で取得するという手順になっています。
ところが、取得に失敗した時のシーケンスを見ると、次のようになっていました。
イメージハンドルを正しく取得することができないので、実際の画像のダウンロードまで進めていないのでした。そこで、ハンドルの取得に失敗した場合には、GetElementAttributesCmd を再送してみたところ....
1回目の送信で失敗しても2回目では成功する場合があることがわかりました!! しかしながら、失敗応答を受信してからすぐに再送を行ったのでは、5回再送しても5回とも失敗することもありました。そこで失敗応答を受信したら、120ms待ってから再送し、それでも失敗したならばさらに 240ms待って送信というように、120msずつ間隔を増やして5回までの再送を試みることにしました。
結果として、多くても2回再送すれば成功応答を受信できるようになりました! 2時間以上連続してSportifyを流してみましたが、曲が切り替わると問題なくアルバム画像が更新されるようです。
このように、ちょっと待ってから再送してやることで問題が解決することが判明しました。スマホアプリ側の挙動を想像するに、タイトルやアーティスト名を取得した後で画像のハンドルを要求しても、アプリ側ではまだ画像が準備できていない場合があるのではないでしょうか? スマホアプリ側もネットワーク経由でサーバから画像を取得する必要があり、その処理が間に合わない場合に失敗応答を返していると考えれば、問題の発生状況と挙動が一致します。あらかじめタイトルやアーティスト名情報収集と共に、アルバム画像も用意してからアプリから プレーヤに対してTrack Changedイベントを通知すれば、このような問題は発生しないでしょうから、YTube Music等のアプリはそのような動作をするのに対し、Sportifyはそうなっていないのではないでしょうか? このようにプレーヤー側で対処できることはわかりましたが、既存のカーナビのプレーヤーはそう簡単にアップデートは望めないでしょうから、やはりアプリ側で対応して欲しいところですね。