2012年7月22日日曜日

[Android]Android向けDMRアプリに挑戦 その1

残念ながら未完成ではあるのですがこれまでの足跡を残しておこうかと思う。
思いの外情報が転がってないんだよねぇ。探し方が悪いというのはあるんだろうけど。

ということで、現在の開発状況。

  • Intel Opensource Developer ToolsのDevice Builderより作成したAndroid用Stackを使用
  • デバイスやサービスはONKYO TX-NA579をコピー
  • DMCからSetAVTransportURIを叩かれると、MediaPlayerインスタンスで再生
  • GetPositionInfoにてシーク位置を返しているつもり
  • Seek、Pause、Playコマンドを実装済み
  • 一部のアプリからはうまく再生できない
  • MediaPlayerの状態遷移の理解が甘くて次の曲へ遷移するときに落ちることが多々
てな感じでしょうか。

MediaPlayerが落ちるバグについては大体どこが悪いのかは雰囲気つかめているのでそこはなんとかなりそう。
再生状態がPAUSED_PLAYBACKになってるときはGetPosition呼ばれるんだね。再生が終了した段階で再生状態をSTOPPEDに変えていなかったかもしれないからそこは要チェックだわ。
イベントを受け取らずにポーリングにしてるとかいう場合はそもそも再生してない時にMediaPlayer.GetDurationを呼ばないように処理を変えないといけないかな・・・。 けどMediaPlayer.isPlayingだと一時停止なのか再生停止状態なのか分からんのだよな。 確かMediaPlayerの状態遷移は自分で管理しておかないといけないとかいうのをどこかでちらっと見た気がするからなんぞ状態管理の変数を用意しておくか。Enumにでもすっかなー。それくらい用意しておいてくれてもいいような気もしなくはない。

で。このIntelのライブラリ、非常に良くできているんだけど悲しいほどにドキュメントがない。C#なんかは割とドキュメントコメントが入ってるから使いやすいんだけど、Android向けのJavaコードにはほっとんどコメントすら無い。
とりあえずC#のサンプルコードでもって挙動を確かめつつ、Javaの方にも同じ挙動をするようにコードを追記していくような感じで進めています。

ほんと、そこで感じることはC#の素晴らしさとJava嫌いっていうことばかりなんですがね・・・!w まぁ愚痴はさておき。
ちょいと実装の話を進めて行きましょう。

Device BuilderにてTX-NA579をコピーしたのがこちら。
Device Builderを起動し、File→Open from Networkを選ぶと自身のネットワーク内にあるUPnPデバイスが表示されるので、選べばそれの設定がさくっとコピーできます。

適当なデバイスがないって場合は、Device Builderをインストールした先にサンプルデバイスやサンプルサービスのファイルが置いてあるのでそこから作りたいデバイスを選びます。 DMSやDMRは標準で用意されているのでそちらを選べばよろしいかと。

そしてDescriptionにある各項目を好きに修正。このまんま使ってもいいですが、私の場合本物のTX-NA579と見分けつかなくなりますからね・・・。

ちなみに、Configurationにてデバイスタイプを「Device」から「ControlPoint」に変更すると、その名の通りDMCを作ることができます。ただ、このツールではDMCとして制御できるデバイスタイプは1種類のみだと思われます(多分)。DMRとDMS両方を制御するようなDMCの雛形を作るにはどうしたらいいかよく分かってません。

まぁ、それ自体はちょちょっとコードを追記したら済むので、さほど気にしなくても良いとは思います。
今回はDMCの話はさておきますが。

で、適当にデバイスの設定を記述し終えたら、一旦ファイルを保存しておきます。このツールに限らず、Intel(以下略)のツールはやたらめったらクラッシュするので注意。これ以外は特に保存すべきデータがないのでクラッシュしても困りはしませんが、こいつはクラッシュされると再度記述しないといけないので面倒です。

ファイルを保存したら、Generate Stackにてひな形プログラムを生成します。
Windows用に作りたいのであればC#かC用のWinSock2を選んでおくのが無難でしょう。ただ、先述しましたがドキュメントが一切無いのでCは正直つらいとは思います。一応C++のコードも吐き出せますが基本はCでそれをちょろっとラップしてあるだけなのでよほどUPnPに詳しい人でないと使えない気がします。。。

で、私はAndroid用が作りたかったのでJavaを選択。Cで作ってAndroidにポーティングするという意識もあるのか、CのスタックのところにもAndroidと書いてありますが上記の理由でお勧めしません。

ちなみにGenerate Stackにて生成されるファイル群は指定したフォルダ以下にそのまま展開されるので、C:\とかに配置すると悲しいことになります。プロジェクト用に1個フォルダを作っておくのが吉です。
例:C:\UPnPDevice

※ このIntel(略)のツール群はOSSであり、サイトからソースをダウンロードしてビルドすることができます。C#で書かれているのでLinuxでもビルドできます(レンダラーについてはWMPコンポーネントを使っているためにビルドに失敗します)。Device Builderももちろんビルドできますが、当然Windows向けに開発されているので、Generate Stackしようとするとファイルパスが不正ですと言って怒られます。パス区切り文字を「\」前提で作ってあるわけですね。 そこを環境に依存しないように(変数忘れちゃいましたが)適切に書き換えてやればLinuxでも使えるようになるはずです。そこまではやってませんが・・・w

で、Android用のプロジェクトが作成されたらEclipseからプロジェクトのインポートで取り込みます。
UPnP.jarがプロジェクトの直下におかれているので、libsに配置するなりBuildオプションにてライブラリを追加するなりしておきます。

そんでもってビルドして実機に転送して、「Start Device」ボタンをぽちっとなすればDMRとしてDMCから認識されます。
中身空っぽなのでデバイスとして認識されるだけで再生も何も出来ませんが、認識されるまでの通信部分はすべてよきに計らってくれます。素晴らしい!

ということで、あとはAPIをそそくさと埋めて逝きましょう。
それがわかれば苦労しないんだけどね・・・! でもひな形コード自体は非常に良く出来ていて、あとは仕様に従い粛々と埋めていけばOKです。

ということで続きはその2へ・・・。