I am using registerMediaRouteProvider and it gives you a volume bar to update the tv's volume. I implemented MediaRouteAdapter
and when I scrub the volume bar, the volume changes, but the volume bar's ui always resets back to 0. How do I update the ui of the volume bar when the volume changes?
@Override
public void onCreate(Bundle savedInstanceState) {
mCastContext = new CastContext(getApplicationContext());
MediaRouteHelper.registerMinimalMediaRouteProvider(mCastContext, this);
mMediaRouter = MediaRouter.getInstance(getApplicationContext());
mMediaRouteSelector = MediaRouteHelper.buildMediaRouteSelector(MediaRouteHelper.CATEGORY_CAST);
mMetaData = new ContentMetadata();
mMediaRouterCallback = new MyMediaRouterCallback();
mMediaRouteButton.setRouteSelector(mMediaRouteSelector);
}
private class MyMediaRouterCallback extends MediaRouter.Callback {
@Override
public void onRouteSelected(MediaRouter router, RouteInfo route) {
MediaRouteHelper.requestCastDeviceForRoute(route);
}
@Override
public void onRouteUnselected(MediaRouter router, RouteInfo route) {
try {
if (mSession != null) {
Log.e(TAG, "Ending session and stopping application");
mSession.setStopApplicationWhenEnding(true);
mSession.endSession();
} else {
Log.e(TAG, "onRouteUnselected: mSession is null");
}
} catch (IllegalStateException e) {
Log.e(TAG, "onRouteUnselected:");
e.printStackTrace();
} catch (IOException e) {
Log.e(TAG, "onRouteUnselected:");
e.printStackTrace();
}
mSelectedDevice = null;
}
}
@Override
public void onDeviceAvailable(CastDevice device, String arg1, MediaRouteStateChangeListener listener) {
mSelectedDevice = device;
openSession();
}
@Override
public void onSetVolume(double volume) {
try {
if (mMessageStream != null) {
mMessageStream.setVolume(volume);
}
} catch (IllegalStateException e) {
Log.e(TAG, "Problem sending Set Volume", e);
} catch (IOException e) {
Log.e(TAG, "Problem sending Set Volume", e);
}
}
@Override
public void onUpdateVolume(double volumeChange) {
try {
if (mCurrentRoute != null) {
mCurrentRoute.requestUpdateVolume((int) (volumeChange * 20));
}
} catch (IllegalStateException e) {
Log.e(TAG, "Problem sending Update Volume", e);
}
}
EDIT - added where I initialize mMessageStream
private void openSession() {
mSession = new ApplicationSession(mCastContext, mSelectedDevice);
int flags = 0;
flags |= ApplicationSession.FLAG_DISABLE_NOTIFICATION;
flags |= ApplicationSession.FLAG_DISABLE_LOCK_SCREEN_REMOTE_CONTROL;
mSession.setApplicationOptions(flags);
Log.d(TAG, "Beginning session with context: " + mCastContext);
Log.d(TAG, "The session to begin: " + mSession);
mSession.setListener(new com.google.cast.ApplicationSession.Listener() {
@Override
public void onSessionStarted(ApplicationMetadata appMetadata) {
Log.d(TAG, "Getting channel after session start");
ApplicationChannel channel = mSession.getChannel();
if (channel == null) {
Log.e(TAG, "channel = null");
return;
}
Log.d(TAG, "Creating and attaching Message Stream");
mMessageStream = new MediaProtocolMessageStream();
channel.attachMessageStream(mMessageStream);
if (mMessageStream.getPlayerState() == null) {
if (vastVideoView.getPlayingPlaylistItem() != null) {
loadMedia();
}
} else {
Log.e(TAG, "Found player already running; updating status");
}
}
@Override
public void onSessionStartFailed(SessionError error) {
Log.e(TAG, "onStartFailed " + error + " code " + error.getCode());
nowifi.setVisibility(View.GONE);
}
@Override
public void onSessionEnded(SessionError error) {
Log.i(TAG, "onEnded " + error);
controller.removeChromeCastListener();
controller.setChromeCast(false);
nowifi.setVisibility(View.GONE);
}
});
try {
Log.e(TAG, "Starting session with app name " + getString(R.string.app_id));
mSession.startSession(getString(R.string.app_id));
vastVideoView.stopPlayback();
controller = vastVideoView.getMediaController();
controller.setChromeCast(true);
controller.setPausePlayListener(pausePlayListener);
seekBar = controller.getSeekBar();
seekBar.setProgress(0);
mPlayButtonShowsPlay = true;
} catch (IOException e) {
Log.e(TAG, "Failed to open session", e);
controller.removeChromeCastListener();
controller.setChromeCast(false);
nowifi.setVisibility(View.GONE);
}
}
I've been looking for this for days and I suddenly found the solution by myself :P
First, You will need a MediaRouteStateChangeListener
to handle this.
MediaRouteStateChangeListener mRouteStateListener;
Second, assign the listener in onDeviceAvailable
.
@Override
public void onDeviceAvailable(CastDevice device, String arg1, MediaRouteStateChangeListener listener) {
mSelectedDevice = device;
mRouteStateListener = listener;
openSession();
}
Last, call MediaRouteStateListener.onVolumeChanged()
in onSetVolume
or onUpdateVolume
.
@Override
public void onSetVolume(double volume) {
try {
if (mMessageStream != null) {
mMessageStream.setVolume(volume);
mRouteStateListener.onVolumeChanged(volume);
}
} catch (IllegalStateException e) {
Log.e(TAG, "Problem sending Set Volume", e);
} catch (IOException e) {
Log.e(TAG, "Problem sending Set Volume", e);
}
}
This should help your volume seekbar to act normally. :)
At the Receiver level, there are two ways to set the volume:
cast.Receiver.Platform.setVolume([0.0,1.0]) This will set the volume and show the blue bar. This is what is usually called by the onVolume message.
mediaElement.volume = [0.0, 1.0]; This will set the volume without showing the blue bar. You can use this for fade in / fade out, and for equalization.
Now on to your Java code: I don't see how you are getting your messageStream in what you've posted, but since it's likely to be the right thing. Here's the lines from the reference docs:
public final MediaProtocolCommand setVolume (double volume)
Sets the audio volume. Parameters volume The volume, in the range 0.0 (0%) to 1.0 (100%). Returns The command object for this request Throws IOException If an I/O error occurs while sending the message. IllegalStateException If this stream is not attached to a connected channel.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With