Chromecastがいよいよ日本で発売されました。
スマホやChromeブラウザから、画面出力するだけでしょ?と思っている人が結構多いと思うのですが、それは、Miracastの役割でして、Chromecastは、Chromecastがインターネットにアクセスして、コンテンツを表示するのが、本来の役割です。
Android端末から、Chromecastに命令を出して、Web上のコンテンツを表示するサンプルコードを作ってみました。(エラー処理とか基本無視ですwww)
ここでは、自由にカスタマイズできるCustom Receiverを使ったものです。
試す為には、Google Cast SDK Developer契約(5ドル)払わなくてはなりませんのであしからず。
Receiverのアプリケーションは、HTML5(HTML,CSS,Javascript)で作ります。ここでは、下記のような簡単なHTMLをWebサーバにアップロードしておきます。
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8"/>
  <style type="text/css">
	body {
      overflow:hidden;
	}
    
    div {
	  height:720PX;
	  width:1280PX;
	  text-align:center;
	  border:0px solid silver;
	  display: table-cell;
	  vertical-align:middle;
	  color:#FFFFFF;
	  background-color:#000000;
	  font-weight:bold;
	  font-family:Verdana, Geneva, sans-serif;
	  font-size:40px;
	}
  </style>
  <title>Chromecastテストページ</title>
  <script src="//www.gstatic.com/cast/sdk/libs/receiver/2.0.0/cast_receiver.js"></script>
  <script type="text/javascript">
      window.onload = function() {
        cast.receiver.logger.setLevelValue(0);
        window.castReceiverManager = cast.receiver.CastReceiverManager.getInstance();
        console.log('Starting Receiver Manager');
        
        // handler for the 'ready' event
        castReceiverManager.onReady = function(event) {
          console.log('Received Ready event: ' + JSON.stringify(event.data));
          window.castReceiverManager.setApplicationState("Application status is ready...");
        };
        
        // handler for 'senderconnected' event
        castReceiverManager.onSenderConnected = function(event) {
          console.log('Received Sender Connected event: ' + event.data);
          console.log(window.castReceiverManager.getSender(event.data).userAgent);
        };
        
        // handler for 'senderdisconnected' event
        castReceiverManager.onSenderDisconnected = function(event) {
          console.log('Received Sender Disconnected event: ' + event.data);
          if (window.castReceiverManager.getSenders().length == 0) {
	        window.close();
	      }
        };
        
        // handler for 'systemvolumechanged' event
        castReceiverManager.onSystemVolumeChanged = function(event) {
          console.log('Received System Volume Changed event: ' + event.data['level'] + ' ' +
              event.data['muted']);
        };
        // initialize the CastReceiverManager with an application status message
        window.castReceiverManager.start({statusText: "Application is starting"});
        console.log('Receiver Manager started');
      };
  </script>
</head>
<body>
<div>Chromecastテストぺーじだよ〜〜〜ん</div>
</body>
</html>
Google Cast SDK Developer Console上では、mini.htmlを置いたサイトのURLを記述します。
ここで、Custom Receiverを選択して
Applecation IDが発行されるので、Android側のソースコードにこのApplication IDを記述することになります。
コンテンツの準備ができたということで、次は、Android側の準備をすることになります。
Android SDK Managerで、ライブラリを追加します。
必要なのは
Android Support Library
Google Play Services
の2つです。
インストールすると、Android SDKのフォルダのextrasにインストールされるので、Eclipseでインポートします!
importするライブラリは2つです。
android-support-v7-mediarouter
google-play-services_lib
android-support-v7-mediarouterをインポートした際にエラーが出る場合がありますので、その時は、プロジェクトのプロバティで、app_compact_v7のライブラリのパスを修正してください。
これで、新規にプロジェクトを作って開発を始められます。
新規プロジェクトを作ったら、そのプロジェクトにライブラリーを追加します。
これが終わったら、今度は、Manifestファイルの設定を変更します。
Applicationタグで、Google ServiceのAPIを使うので、metaタグを追加します。
次に、Parmissionです。
Wifiで通信しますので、INTERNETのパーミッションを追加します。
Google Playにアップするなら、もっと必要ですが、動作確認には、これで十分でしょう。
package com.example.castcast;
import com.google.android.gms.cast.CastMediaControlIntent;
import android.app.Activity;
import android.os.Bundle;
import android.support.v7.media.MediaRouteSelector;
import android.support.v7.media.MediaRouter;
import android.support.v7.media.MediaRouter.RouteInfo;
import android.util.Log;
public class MainActivity extends Activity
{
	private String TAG = "test";
	
	// Google Cast SDK Developer Consoleから取得した Application IDを設定してください
	private static String APPLICATION_ID = "hogehoge";
		
	// Chromecastを探索するのに使う変数類
	private MediaRouter mRouter;
	private MediaRouteSelector mMediaRouteSelector;
	private MediaRouter.Callback mCB;
	
	@Override
	protected void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		
		// Chromecastを探す準備
		mRouter = MediaRouter.getInstance(this);
		mMediaRouteSelector = new MediaRouteSelector.Builder().addControlCategory(CastMediaControlIntent.categoryForCast(APPLICATION_ID)).build();
		mCB = new MediaRouter.Callback()
		{
			@Override
			public void onRouteAdded(MediaRouter router, RouteInfo route)
			{
				Log.d(TAG,"onRouteAdded=" + route.getName());
			}
			@Override
			public void onRouteRemoved(MediaRouter router, RouteInfo route)
			{
				Log.d(TAG,"onRouteRemoved" + route.getName());
			}
		};
	}
	
	@Override
	protected void onResume()
	{
		super.onResume();
		// Chromecastを探す
		mRouter.addCallback(mMediaRouteSelector, mCB,MediaRouter.CALLBACK_FLAG_PERFORM_ACTIVE_SCAN);
	}
	@Override
	protected void onPause()
	{
		if (isFinishing())
		{
		    mRouter.removeCallback(mCB);
		}
		super.onPause();
	}
}
これだけのソースで、同一ネットワークに接続されているChromecastのリストを取得することができます。
デバイスが見つかったら、接続を行います。
// 最初に見つけたデバイスに接続を行う。
if(mSelectedDevice == null)
{
    mSelectedDevice = CastDevice.getFromBundle(route.getExtras());
    
    Cast.CastOptions.Builder apiOptionsBuilder = Cast.CastOptions.builder(mSelectedDevice, mCastClientListener);
    apiOptionsBuilder.setVerboseLoggingEnabled(true);
    
    mApiClient = new GoogleApiClient.Builder(getBaseContext())
    .addApi(Cast.API, apiOptionsBuilder.build())
    .addConnectionCallbacks(mConnectionCallbacks)
    .addOnConnectionFailedListener(mConnectionFailedListener)
    .build();
    
    mApiClient.connect();
}
その他必要なコードは下記の通りです。
	// Chromecastに接続確認用コールバック
	private GoogleApiClient.ConnectionCallbacks mConnectionCallbacks = new GoogleApiClient.ConnectionCallbacks()
	{
		@Override
		public void onConnected(Bundle connectionHint)
		{
			Log.d(TAG,"onConnected");
			
			try
			{
				Cast.CastApi.launchApplication(mApiClient, APPLICATION_ID, false)
				 .setResultCallback(new ResultCallback<Cast.ApplicationConnectionResult>()
				{
					@Override
					public void onResult(ApplicationConnectionResult result)
					{
						Status status = result.getStatus();
		                if (status.isSuccess())
		                {
		                	mSessionId = result.getSessionId();
		                	Log.d(TAG,"mSessionID=" + mSessionId);
		                }
					}
				});
			}
			catch(Exception ex)
			{
				Log.d(TAG,ex.toString());
			}			
		}
		@Override
		public void onConnectionSuspended(int cause)
		{
		}
	};
	// Chromecastに接続失敗した場合に呼ばれる
	private GoogleApiClient.OnConnectionFailedListener mConnectionFailedListener = new GoogleApiClient.OnConnectionFailedListener()
	{
		@Override
		public void onConnectionFailed(ConnectionResult result)
		{
		}
	};
	
	// Chromecastとの接続を解除する
	private void peardown()
	{		
		if (mApiClient != null)
		{
			if (mApiClient.isConnected())
			{
				try
				{
		            Cast.CastApi.stopApplication(mApiClient, mSessionId);
		        }
				catch (Exception e)
		        {
		        	Log.e(TAG, "Exception while removing channel", e);
		        }
				
				mApiClient.disconnect();
		    }
			
		    mApiClient = null;
		    mSelectedDevice = null;
		    mSessionId = null;
		}
	}
GitHubに動くプロジェクトファイル一式(SampleCast)をアップデートしてありますので、必要に応じてご利用ください。
以上、ハッピーキャスティング!










