package com.ptrprograms.chromecast;
import android.os.Bundle;
import android.support.v4.view.MenuItemCompat;
import android.support.v7.app.ActionBarActivity;
import android.support.v7.app.MediaRouteActionProvider;
import android.support.v7.media.MediaRouteSelector;
import android.support.v7.media.MediaRouter;
import android.support.v7.media.MediaRouter.RouteInfo;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import com.google.android.gms.cast.ApplicationMetadata;
import com.google.android.gms.cast.Cast;
import com.google.android.gms.cast.CastDevice;
import com.google.android.gms.cast.CastMediaControlIntent;
import com.google.android.gms.cast.MediaInfo;
import com.google.android.gms.cast.MediaMetadata;
import com.google.android.gms.cast.MediaStatus;
import com.google.android.gms.cast.RemoteMediaPlayer;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.ResultCallback;
import com.google.android.gms.common.api.Status;
import java.io.IOException;
public class MainActivity extends ActionBarActivity {
private Button mButton;
private MediaRouter mMediaRouter;
private MediaRouteSelector mMediaRouteSelector;
private MediaRouter.Callback mMediaRouterCallback;
private CastDevice mSelectedDevice;
private GoogleApiClient mApiClient;
private RemoteMediaPlayer mRemoteMediaPlayer;
private Cast.Listener mCastClientListener;
private boolean mWaitingForReconnect = false;
private boolean mApplicationStarted = false;
private boolean mVideoIsLoaded;
private boolean mIsPlaying;
@Override
protected void onCreate( Bundle savedInstanceState ) {
super.onCreate( savedInstanceState );
setContentView( R.layout.activity_main );
mButton = (Button) findViewById( R.id.button );
mButton.setOnClickListener( new OnClickListener() {
@Override
public void onClick( View v ) {
if( !mVideoIsLoaded )
startVideo();
else
controlVideo();
}
});
initMediaRouter();
}
private void initMediaRouter() {
// Configure Cast device discovery
mMediaRouter = MediaRouter.getInstance( getApplicationContext() );
mMediaRouteSelector = new MediaRouteSelector.Builder()
.addControlCategory( CastMediaControlIntent.categoryForCast( getString( R.string.app_id ) ) )
.build();
mMediaRouterCallback = new MediaRouterCallback();
}
private void initCastClientListener() {
mCastClientListener = new Cast.Listener() {
@Override
public void onApplicationStatusChanged() {
}
@Override
public void onVolumeChanged() {
}
@Override
public void onApplicationDisconnected( int statusCode ) {
teardown();
}
};
}
private void initRemoteMediaPlayer() {
mRemoteMediaPlayer = new RemoteMediaPlayer();
mRemoteMediaPlayer.setOnStatusUpdatedListener( new RemoteMediaPlayer.OnStatusUpdatedListener() {
@Override
public void onStatusUpdated() {
MediaStatus mediaStatus = mRemoteMediaPlayer.getMediaStatus();
mIsPlaying = mediaStatus.getPlayerState() == MediaStatus.PLAYER_STATE_PLAYING;
}
});
mRemoteMediaPlayer.setOnMetadataUpdatedListener( new RemoteMediaPlayer.OnMetadataUpdatedListener() {
@Override
public void onMetadataUpdated() {
}
});
}
private void controlVideo() {
if( mRemoteMediaPlayer == null || !mVideoIsLoaded )
return;
if( mIsPlaying ) {
mRemoteMediaPlayer.pause( mApiClient );
mButton.setText( getString( R.string.resume_video ) );
} else {
mRemoteMediaPlayer.play( mApiClient );
mButton.setText( getString( R.string.pause_video ) );
}
}
private void startVideo() {
MediaMetadata mediaMetadata = new MediaMetadata( MediaMetadata.MEDIA_TYPE_MOVIE );
mediaMetadata.putString( MediaMetadata.KEY_TITLE, getString( R.string.video_title ) );
MediaInfo mediaInfo = new MediaInfo.Builder( getString( R.string.video_url ) )
.setContentType( getString( R.string.content_type_mp4 ) )
.setStreamType( MediaInfo.STREAM_TYPE_BUFFERED )
.setMetadata( mediaMetadata )
.build();
try {
mRemoteMediaPlayer.load( mApiClient, mediaInfo, true )
.setResultCallback( new ResultCallback<RemoteMediaPlayer.MediaChannelResult>() {
@Override
public void onResult( RemoteMediaPlayer.MediaChannelResult mediaChannelResult ) {
if( mediaChannelResult.getStatus().isSuccess() ) {
mVideoIsLoaded = true;
mButton.setText( getString( R.string.pause_video ) );
}
}
} );
} catch( Exception e ) {
}
}
@Override
protected void onResume() {
super.onResume();
// Start media router discovery
mMediaRouter.addCallback( mMediaRouteSelector, mMediaRouterCallback, MediaRouter.CALLBACK_FLAG_PERFORM_ACTIVE_SCAN );
}
@Override
protected void onPause() {
if ( isFinishing() ) {
// End media router discovery
mMediaRouter.removeCallback( mMediaRouterCallback );
}
super.onPause();
}
private class MediaRouterCallback extends MediaRouter.Callback {
@Override
public void onRouteSelected(MediaRouter router, RouteInfo info) {
initCastClientListener();
initRemoteMediaPlayer();
mSelectedDevice = CastDevice.getFromBundle( info.getExtras() );
launchReceiver();
}
@Override
public void onRouteUnselected( MediaRouter router, RouteInfo info ) {
teardown();
mSelectedDevice = null;
mButton.setText( getString( R.string.play_video ) );
mVideoIsLoaded = false;
}
}
private void launchReceiver() {
Cast.CastOptions.Builder apiOptionsBuilder = Cast.CastOptions
.builder( mSelectedDevice, mCastClientListener );
ConnectionCallbacks mConnectionCallbacks = new ConnectionCallbacks();
ConnectionFailedListener mConnectionFailedListener = new ConnectionFailedListener();
mApiClient = new GoogleApiClient.Builder( this )
.addApi( Cast.API, apiOptionsBuilder.build() )
.addConnectionCallbacks( mConnectionCallbacks )
.addOnConnectionFailedListener( mConnectionFailedListener )
.build();
mApiClient.connect();
}
private class ConnectionCallbacks implements GoogleApiClient.ConnectionCallbacks {
@Override
public void onConnected( Bundle hint ) {
if( mWaitingForReconnect ) {
mWaitingForReconnect = false;
reconnectChannels( hint );
} else {
try {
Cast.CastApi.launchApplication( mApiClient, getString( R.string.app_id ), false )
.setResultCallback( new ResultCallback<Cast.ApplicationConnectionResult>() {
@Override
public void onResult(Cast.ApplicationConnectionResult applicationConnectionResult) {
Status status = applicationConnectionResult.getStatus();
if( status.isSuccess() ) {
//Values that can be useful for storing/logic
ApplicationMetadata applicationMetadata = applicationConnectionResult.getApplicationMetadata();
String sessionId = applicationConnectionResult.getSessionId();
String applicationStatus = applicationConnectionResult.getApplicationStatus();
boolean wasLaunched = applicationConnectionResult.getWasLaunched();
mApplicationStarted = true;
reconnectChannels( null );
}
}
}
);
} catch ( Exception e ) {
}
}
}
@Override
public void onConnectionSuspended(int i) {
mWaitingForReconnect = true;
}
}
private void reconnectChannels( Bundle hint ) {
if( ( hint != null ) && hint.getBoolean( Cast.EXTRA_APP_NO_LONGER_RUNNING ) ) {
//Log.e( TAG, "App is no longer running" );
teardown();
} else {
try {
Cast.CastApi.setMessageReceivedCallbacks( mApiClient, mRemoteMediaPlayer.getNamespace(), mRemoteMediaPlayer );
} catch( IOException e ) {
//Log.e( TAG, "Exception while creating media channel ", e );
} catch( NullPointerException e ) {
//Log.e( TAG, "Something wasn't reinitialized for reconnectChannels" );
}
}
}
private class ConnectionFailedListener implements GoogleApiClient.OnConnectionFailedListener {
@Override
public void onConnectionFailed( ConnectionResult connectionResult ) {
teardown();
}
}
@Override
public boolean onCreateOptionsMenu( Menu menu ) {
super.onCreateOptionsMenu( menu );
getMenuInflater().inflate( R.menu.main, menu );
MenuItem mediaRouteMenuItem = menu.findItem( R.id.media_route_menu_item );
MediaRouteActionProvider mediaRouteActionProvider = (MediaRouteActionProvider) MenuItemCompat.getActionProvider( mediaRouteMenuItem );
mediaRouteActionProvider.setRouteSelector( mMediaRouteSelector );
return true;
}
private void teardown() {
if( mApiClient != null ) {
if( mApplicationStarted ) {
try {
Cast.CastApi.stopApplication( mApiClient );
if( mRemoteMediaPlayer != null ) {
Cast.CastApi.removeMessageReceivedCallbacks( mApiClient, mRemoteMediaPlayer.getNamespace() );
mRemoteMediaPlayer = null;
}
} catch( IOException e ) {
//Log.e( TAG, "Exception while removing application " + e );
}
mApplicationStarted = false;
}
if( mApiClient.isConnected() )
mApiClient.disconnect();
mApiClient = null;
}
mSelectedDevice = null;
mVideoIsLoaded = false;
}
@Override
public void onDestroy() {
teardown();
super.onDestroy();
}
}