読者です 読者をやめる 読者になる 読者になる

酢ろぐ!

カレーが嫌いなスマートフォンアプリプログラマのブログ。

AndroidでChromecast対応アプリを作る

先日のGoogleの新製品イベントでChromecast 2とChromecast audioが発表されました。Chromecast 2はドングル型からペンダント型へのデザイン変更と次の動画を先読みするFast Play機能対応や5GHz対応がメインでしたね。過去モデルとは基本的にあまり変わらなさそうで少し安心しました。

Google ChromecastはテレビHDMI端子に刺して使うタイプのガジェットです。テレビの大きな画面でhuluやYoutubeをみることができます。Chromecastには操作するためのボタンやリモコンは付属しておらず、操作するのにはスマートフォンを使います。

操作するために必要なChromecast SDKはiOSとAndroid向けに提供されています。本記事ではAndroidでChromecast対応のアプリを作るための方法をメモを残しておきます。

実装上のサンプルとしてAndroidデバイスでhuluアプリとYouTubeアプリを使った際のスクリーンショットを貼りました。

以下、目次です。

アプリとChromecastのザックリとした概念

Androidデバイス側がReceiverに「このビデオとか音楽を再生してください」と指示を出します。テレビのリモコンの感覚ですね。

Androidデバイスはリモコン(Sender)。Chromecastデバイスはテレビ(Receiver)となります。SenderとReceiverの関係はコード上でも出てくるので覚えておいてください。

実装的には、公式ライブラリにもあるCastCompanionLibrary-android(以下、CCL)を使うことになるでしょう。後述しているのですがChromecast対応には要求される項目が多く、イチから実装をするのはかなり大変です。

すべてCCL側でよしなにしてくれます。Receiverからの応答を受診してUI側にほぼ自動で反映してくれたりします。ただし、president controlやnotification を 自前のカスタムUIにしたいようなやむを得ない事情がある場合には、CCLのUI周りは使えないので適切にコールバックを受けてUIへ状態を反映する必要があります。

UI周りが流用できないとしてもChromecastとの通信周りはCCLを使ったほうが数段楽だと思いますので、このあたりは必要に応じて検討してみてください。

デザインガイドライン

Chromecast対応のアプリを作るために、まず調べないといけないのが公式のデザインチェックリストのページです。

Androidはお膝もと(?)ということもあってか、iOSに比べるとかなり厳しい実装が要求されています。まぁ厳しいといっても先ほど紹介したライブラリを使えば(ライブラリが提供している標準機能の範疇であれば)簡単に実装できると思います。

デザインチェックリスト上、実装しないといけないものは以下の通りです。

  • Introduce Cast to users
  • Sender volume controls
  • Sender expanded controls
  • Sender persistent controls
  • Sender notification
  • Sender lock screen
  • Sender resumes cast
  • Sender stops cast

英語が並んでいますが、huluとYoutubeのアプリを使って実例を出しながら説明を書いておきます。

初回Chromecast認識時ガイド(Introduce Cast to users)

アプリがChromecastを初めて認識したときには操作ガイドを表示する必要があります。

YouTubeアプリ

f:id:ch3cooh393:20150910153142p:plain

ツールバーにある「Chromecastのマークのボタンを押して接続しよう」てのが伝われば良いらしいです。

ミニコントローラー(Sender persistent controls)

すべての画面に必要最低限のコントローラーを表示する必要があります。

huluアプリ

f:id:ch3cooh393:20150910153515p:plain

再生・一時停止ボタンとタップされた場合にexpanded controlsを表示させるボタンをつけます。

リモート再生コントローラー(Sender expanded controls)

詳細な操作が可能なコントローラーが必要です。音量調整のハードウェアキーを使ってChromecastの音量調整をする必要があるのも気付きにくいポイントです。

huluアプリ

f:id:ch3cooh393:20150910153445p:plain

huluアプリでは、再生・一時停止、シークバー、字幕・吹替の切り替えボタンが実装されています。

通知センター上のコントローラー(Sender notification)

notificationとして、アートワーク、タイトル、再生・一時停止あたりを表示させる必要があります。

huluアプリ

f:id:ch3cooh393:20150908173036p:plain

YouTubeアプリ

f:id:ch3cooh393:20150908173115p:plain

ロック画面(Sender lock screen)

後述しますがAndroid 5.0からはRemoteControlClient APIが使えなくなっているためロック画面上での表示が異なります。Android 5.0未満と5.0以上での表示の仕方の違いを紹介します。

Android 5.0未満

Android 5.0未満の場合は、RemoteControlClient APIがそのまま使えるので表示を任せることができます。このAPIを使って、再生中のメディアのタイトルやアートワークを表示します。同じ端末であればアプリに関係なく同じように表示されます。RemoteControlClient APIは機種依存が強いので必ずしも以下のスクリーンショットと同じにならないということを気をつける必要があります。

huluアプリ

f:id:ch3cooh393:20150910153233p:plain

YouTubeアプリ

f:id:ch3cooh393:20150910153251p:plain

Android 5.0以降

Android 5.0以降はnotificationがロック画面に表示されます。huluはnotificationと同じものを、Youtubeもほぼ同じですがChromecastデバイスとのコネクションを切断するためのxボタンが付いています。

huluアプリ

f:id:ch3cooh393:20150908173015p:plain

YouTubeアプリ

f:id:ch3cooh393:20150908172953p:plain

トラブルシューティング

RemoteControlClient APIが使えない

デザインガイドラインに含まれているロック画面(Sender lock screen)はRemoteControlClient APIを使って実装するのですが、Android 5.0からはRemoteControlClientが使えないのでロック画面にコントローラーが表示できません。

Android 5.0 LollipopでのNotificationについて - Qiita」に記載があります。

新しいMediaのNotificationでは、Thumbs upの様なカスタムコントロールを最大6つのActionボタンと一貫性のあるメディアコントロールを提供する。 もうRemoteViewで頑張らなくていい。
※多分MediaStyleのこと言ってるんだけど、Actionボタンは最大5つだった。
※MediaControlClientを動かなくしたから、ロックスクリーン上のNotificationでメディア再生のコントロールを提供するようにしろよ。便利なMediaStyleも用意したぞ。という意味。

Android 5.0のロックスクリーンにはもうメディアコントロールは表示されません。

との記載です。RemoteControlClient APIは機種依存が強いから無くなるのは良いよね……

GenymotionでChromecastのテストができない

  • GenymotionにGoogle Playストアをインストールする
  • Google Play開発者サービス(アプリ)をインストールする
  • Virtual PCの設定でネットワークをWiFiに

RemoteControlClientが表示されたままになる(消えない)

ロック画面に表示したRemoteControlClientが非表示にならない問題に行き当たって、検索したらまず出てくるのは以下の記事です。

この記事の内容でも不十分で、RemoteControlClientはregisterRemoteControlClientregisterMediaButtonEventReceiverをしたオブジェクトすべてをregisterしないと消えてくれません。

remoteControlClient.setPlaybackState(RemoteControlClient.PLAYSTATE_STOPPED);
audioManager.unregisterRemoteControlClient(remoteControlClient);
audioManager.unregisterMediaButtonEventReceiver(mediaEventReceiver);

ハードウェアボタンで音量調整ってどうするの

ActivityにdispatchKeyEvent(KeyEvent)を実装して、KeyEvent.ACTION_DOWNかつKeyEvent.KEYCODE_VOLUME_UPもしくはKeyEvent.KEYCODE_VOLUME_DOWNだったら音量調整する。

実装中にお世話になったライブラリ/記事リンク

Chromecast対応をしている人はそんなにいないのか、CastCompanionLibrary(以下、CCL)を使っているので詳細を書く必要ないのか、ネット上にChromeCast対応をした!という解説記事はものすごく少ないです。僕がChromecast対応中にお世話になったリンクをピックアップしてみました。

公式の実装方法のページです。CCLを使うのであればあまり必要ないかもしれませんがCCLに頼っているといざというときにハマってしまうので、押さえておきたいところです。

CCLについては少し触れました。なんて紹介するのが良いのかわかりませんが、実装の難しいChromeCast対応の処理をラッピングしてくれるライブラリです。やむを得ない事情がなければこのライブラリを使うことで前述したガイドラインを網羅することができます。

上の「CastCompanionLibrary」を使って実際にChromeCast対応ビデオ再生プレイヤーアプリを作った実装サンプルのプロジェクトです。やむを得ない事情がなければ、この通り実装すれば良いと思います。

「CastVideos-android」のソースコードを見てわからないことがあればこの記事で補完しましょう。CCLについて書かれた日本語の記事では一番だと思います。

Receiverを実装するのであればこの記事が役に立つかもしれません。

あまり見てないけれど。