am 9678ee60: am c1eb2306: Add sample code to customize the MediaRouteControllerDialog

* commit '9678ee604ba5bfe1810b5773b1739af5919e7249':
  Add sample code to customize the MediaRouteControllerDialog
This commit is contained in:
Chong Zhang
2013-11-08 13:02:18 -08:00
committed by Android Git Automerger
10 changed files with 299 additions and 64 deletions

View File

@@ -0,0 +1,58 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2012 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<!-- Layout for the customized MediaRouteControllerDialog -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout android:id="@+id/media_route_info"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1">
<ImageView
android:id="@+id/snapshot"
android:layout_width="100dp"
android:layout_height="100dp"
android:scaleType="centerCrop"/>
<TextView android:id="@+id/track_info"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:padding="4dp"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="0"
android:gravity="center">
<ImageButton android:id="@+id/pause_resume_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:minWidth="48dp"
android:minHeight="48dp"
android:background="@null"
android:src="@drawable/ic_media_pause" />
<ImageButton android:id="@+id/stop_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:minWidth="48dp"
android:minHeight="48dp"
android:background="@null"
android:src="@drawable/ic_media_stop" />
</LinearLayout>
</LinearLayout>

View File

@@ -28,7 +28,7 @@
<string name="library_tab_text">Library</string> <string name="library_tab_text">Library</string>
<string name="playlist_tab_text">Playlist</string> <string name="playlist_tab_text">Playlist</string>
<string name="statistics_tab_text">Statistics</string> <string name="info_tab_text">Route Info</string>
<string name="sample_media_route_provider_service">Media Route Provider Service Support Library Sample</string> <string name="sample_media_route_provider_service">Media Route Provider Service Support Library Sample</string>
<string name="fixed_volume_route_name">Fixed Volume Remote Playback Route</string> <string name="fixed_volume_route_name">Fixed Volume Remote Playback Route</string>

View File

@@ -21,6 +21,7 @@ import android.app.Presentation;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.res.Resources; import android.content.res.Resources;
import android.graphics.Bitmap;
import android.media.MediaPlayer; import android.media.MediaPlayer;
import android.net.Uri; import android.net.Uri;
import android.os.Build; import android.os.Build;
@@ -628,5 +629,10 @@ public abstract class LocalPlayer extends Player implements
public void onWindowDestroyed() { public void onWindowDestroyed() {
setSurface((SurfaceHolder)null); setSurface((SurfaceHolder)null);
} }
@Override
public Bitmap getSnapshot() {
return mOverlay.getSnapshot();
}
} }
} }

View File

@@ -18,6 +18,7 @@ package com.example.android.supportv7.media;
import com.example.android.supportv7.R; import com.example.android.supportv7.R;
import android.content.Context; import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Point; import android.graphics.Point;
import android.graphics.SurfaceTexture; import android.graphics.SurfaceTexture;
import android.hardware.display.DisplayManager; import android.hardware.display.DisplayManager;
@@ -90,6 +91,8 @@ public abstract class OverlayDisplayWindow {
public abstract void updateAspectRatio(int width, int height); public abstract void updateAspectRatio(int width, int height);
public abstract Bitmap getSnapshot();
// Watches for significant changes in the overlay display window lifecycle. // Watches for significant changes in the overlay display window lifecycle.
public interface OverlayWindowListener { public interface OverlayWindowListener {
public void onWindowCreated(Surface surface); public void onWindowCreated(Surface surface);
@@ -164,6 +167,11 @@ public abstract class OverlayDisplayWindow {
@Override @Override
public void updateAspectRatio(int width, int height) { public void updateAspectRatio(int width, int height) {
} }
@Override
public Bitmap getSnapshot() {
return null;
}
} }
/** /**
@@ -250,6 +258,11 @@ public abstract class OverlayDisplayWindow {
relayout(); relayout();
} }
@Override
public Bitmap getSnapshot() {
return mTextureView.getBitmap();
}
private void relayout() { private void relayout() {
if (mWindowVisible) { if (mWindowVisible) {
updateWindowParams(); updateWindowParams();

View File

@@ -18,6 +18,7 @@ package com.example.android.supportv7.media;
import android.net.Uri; import android.net.Uri;
import android.content.Context; import android.content.Context;
import android.graphics.Bitmap;
import android.support.v7.media.MediaControlIntent; import android.support.v7.media.MediaControlIntent;
import android.support.v7.media.MediaRouter.RouteInfo; import android.support.v7.media.MediaRouter.RouteInfo;
@@ -48,9 +49,10 @@ public abstract class Player {
public abstract void enqueue(final PlaylistItem item); public abstract void enqueue(final PlaylistItem item);
public abstract PlaylistItem remove(String iid); public abstract PlaylistItem remove(String iid);
// route statistics // track info for current media item
public void updateStatistics() {} public void updateTrackInfo() {}
public String getStatistics() { return ""; } public String getDescription() { return ""; }
public Bitmap getSnapshot() { return null; }
// presentation display // presentation display
public void updatePresentation() {} public void updatePresentation() {}

View File

@@ -18,6 +18,7 @@ package com.example.android.supportv7.media;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.graphics.Bitmap;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.support.v7.media.MediaItemStatus; import android.support.v7.media.MediaItemStatus;
@@ -47,7 +48,8 @@ public class RemotePlayer extends Player {
private Context mContext; private Context mContext;
private RouteInfo mRoute; private RouteInfo mRoute;
private boolean mEnqueuePending; private boolean mEnqueuePending;
private String mStatsInfo = ""; private String mTrackInfo = "";
private Bitmap mSnapshot;
private List<PlaylistItem> mTempQueue = new ArrayList<PlaylistItem>(); private List<PlaylistItem> mTempQueue = new ArrayList<PlaylistItem>();
private RemotePlaybackClient mClient; private RemotePlaybackClient mClient;
@@ -318,11 +320,12 @@ public class RemotePlayer extends Player {
} }
@Override @Override
public void updateStatistics() { public void updateTrackInfo() {
// clear stats info first // clear stats info first
mStatsInfo = ""; mTrackInfo = "";
mSnapshot = null;
Intent intent = new Intent(SampleMediaRouteProvider.ACTION_GET_STATISTICS); Intent intent = new Intent(SampleMediaRouteProvider.ACTION_GET_TRACK_INFO);
intent.addCategory(SampleMediaRouteProvider.CATEGORY_SAMPLE_ROUTE); intent.addCategory(SampleMediaRouteProvider.CATEGORY_SAMPLE_ROUTE);
if (mRoute != null && mRoute.supportsControlRequest(intent)) { if (mRoute != null && mRoute.supportsControlRequest(intent)) {
@@ -333,9 +336,9 @@ public class RemotePlayer extends Player {
Log.d(TAG, "getStatistics: succeeded: data=" + data); Log.d(TAG, "getStatistics: succeeded: data=" + data);
} }
if (data != null) { if (data != null) {
int playbackCount = data.getInt( mTrackInfo = data.getString(SampleMediaRouteProvider.TRACK_INFO_DESC);
SampleMediaRouteProvider.DATA_PLAYBACK_COUNT, -1); mSnapshot = data.getParcelable(
mStatsInfo = "Total playback count: " + playbackCount; SampleMediaRouteProvider.TRACK_INFO_SNAPSHOT);
} }
} }
@@ -350,8 +353,13 @@ public class RemotePlayer extends Player {
} }
@Override @Override
public String getStatistics() { public String getDescription() {
return mStatsInfo; return mTrackInfo;
}
@Override
public Bitmap getSnapshot() {
return mSnapshot;
} }
private void enqueueInternal(final PlaylistItem item) { private void enqueueInternal(final PlaylistItem item) {

View File

@@ -0,0 +1,121 @@
/*
* Copyright (C) 2013 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.android.supportv7.media;
import com.example.android.supportv7.R;
import android.app.Dialog;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.support.v7.app.MediaRouteControllerDialog;
import android.support.v7.media.MediaRouteSelector;
import android.support.v7.media.MediaRouter;
import android.util.Log;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
/**
* This class serves as an example on how to customize the media router control
* dialog. It is derived from the standard MediaRouteControllerDialog with the
* following overrides:
*
* 1. Shows thumbnail/snapshot of the current item
*
* 2. For variable volume routes, only allow volume control via Volume Up/Down
* keys (to prevent accidental tapping on the volume adjust seekbar that sets
* volume to maximum)
*
* 3. Provides transport control buttons (play/pause, stop)
*/
public class SampleMediaRouteControllerDialog extends MediaRouteControllerDialog {
private static final String TAG = "SampleMediaRouteControllerDialog";
private final SampleMediaRouterActivity mActivity;
private final SessionManager mSessionManager;
private final Player mPlayer;
private ImageButton mPauseResumeButton;
private ImageButton mStopButton;
private ImageView mThumbnail;
private TextView mTextView;
private LinearLayout mInfoLayout;
private LinearLayout mVolumeLayout;
public SampleMediaRouteControllerDialog(Context context,
SessionManager manager, Player player) {
super(context);
mActivity = (SampleMediaRouterActivity) context;
mSessionManager = manager;
mPlayer = player;
}
@Override
public View onCreateMediaControlView(Bundle savedInstanceState) {
// Thumbnail and Track info
View v = getLayoutInflater().inflate(R.layout.sample_media_controller, null);
mInfoLayout = (LinearLayout)v.findViewById(R.id.media_route_info);
mTextView = (TextView)v.findViewById(R.id.track_info);
mThumbnail = (ImageView)v.findViewById(R.id.snapshot);
// Transport controls
mPauseResumeButton = (ImageButton)v.findViewById(R.id.pause_resume_button);
mPauseResumeButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (mActivity != null) {
mActivity.handleMediaKey(new KeyEvent(KeyEvent.ACTION_DOWN,
KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE));
}
}
});
mStopButton = (ImageButton)v.findViewById(R.id.stop_button);
mStopButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (mActivity != null) {
mActivity.handleMediaKey(new KeyEvent(KeyEvent.ACTION_DOWN,
KeyEvent.KEYCODE_MEDIA_STOP));
}
}
});
// update session status (will callback to updateUi at the end)
mSessionManager.updateStatus();
return v;
}
public void updateUi() {
String trackInfo = mPlayer.getDescription();
Bitmap snapshot = mPlayer.getSnapshot();
if (mPlayer.isRemotePlayback() && !trackInfo.isEmpty() && snapshot != null) {
mInfoLayout.setVisibility(View.VISIBLE);
mThumbnail.setImageBitmap(snapshot);
mTextView.setText(trackInfo);
} else {
mInfoLayout.setVisibility(View.GONE);
}
// show pause or resume icon depending on current state
mPauseResumeButton.setImageResource(mSessionManager.isPaused() ?
R.drawable.ic_media_play : R.drawable.ic_media_pause);
}
}

View File

@@ -23,6 +23,7 @@ import android.content.Intent;
import android.content.IntentFilter; import android.content.IntentFilter;
import android.content.IntentFilter.MalformedMimeTypeException; import android.content.IntentFilter.MalformedMimeTypeException;
import android.content.res.Resources; import android.content.res.Resources;
import android.graphics.Bitmap;
import android.media.AudioManager; import android.media.AudioManager;
import android.media.MediaRouter; import android.media.MediaRouter;
import android.net.Uri; import android.net.Uri;
@@ -66,22 +67,27 @@ final class SampleMediaRouteProvider extends MediaRouteProvider {
/** /**
* A custom media control intent action for special requests that are * A custom media control intent action for special requests that are
* supported by this provider's routes. * supported by this provider's routes.
* <p>
* This particular request is designed to return a bundle of not very
* interesting statistics for demonstration purposes.
* </p> * </p>
* *
* @see #DATA_PLAYBACK_COUNT * @see #TRACK_INFO_DESC
* @see #TRACK_INFO_SNAPSHOT
*/ */
public static final String ACTION_GET_STATISTICS = public static final String ACTION_GET_TRACK_INFO =
"com.example.android.supportv7.media.ACTION_GET_STATISTICS"; "com.example.android.supportv7.media.ACTION_GET_TRACK_INFO";
/** /**
* {@link #ACTION_GET_STATISTICS} result data: Number of times the * {@link #ACTION_GET_TRACK_INFO} result data: a string of information about
* playback action was invoked. * the currently playing media item
*/ */
public static final String DATA_PLAYBACK_COUNT = public static final String TRACK_INFO_DESC =
"com.example.android.supportv7.media.EXTRA_PLAYBACK_COUNT"; "com.example.android.supportv7.media.EXTRA_TRACK_INFO_DESC";
/**
* {@link #ACTION_GET_TRACK_INFO} result data: a bitmap containing a snapshot
* of the currently playing media item
*/
public static final String TRACK_INFO_SNAPSHOT =
"com.example.android.supportv7.media.EXTRA_TRACK_INFO_SNAPSHOT";
private static final ArrayList<IntentFilter> CONTROL_FILTERS_BASIC; private static final ArrayList<IntentFilter> CONTROL_FILTERS_BASIC;
private static final ArrayList<IntentFilter> CONTROL_FILTERS_QUEUING; private static final ArrayList<IntentFilter> CONTROL_FILTERS_QUEUING;
@@ -90,7 +96,7 @@ final class SampleMediaRouteProvider extends MediaRouteProvider {
static { static {
IntentFilter f1 = new IntentFilter(); IntentFilter f1 = new IntentFilter();
f1.addCategory(CATEGORY_SAMPLE_ROUTE); f1.addCategory(CATEGORY_SAMPLE_ROUTE);
f1.addAction(ACTION_GET_STATISTICS); f1.addAction(ACTION_GET_TRACK_INFO);
IntentFilter f2 = new IntentFilter(); IntentFilter f2 = new IntentFilter();
f2.addCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK); f2.addCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK);
@@ -245,6 +251,7 @@ final class SampleMediaRouteProvider extends MediaRouteProvider {
handleStatusChange(item); handleStatusChange(item);
} }
}); });
setVolumeInternal(mVolume);
Log.d(TAG, mRouteId + ": Controller created"); Log.d(TAG, mRouteId + ": Controller created");
} }
@@ -315,10 +322,14 @@ final class SampleMediaRouteProvider extends MediaRouteProvider {
return success; return success;
} }
if (action.equals(ACTION_GET_STATISTICS) if (action.equals(ACTION_GET_TRACK_INFO)
&& intent.hasCategory(CATEGORY_SAMPLE_ROUTE)) { && intent.hasCategory(CATEGORY_SAMPLE_ROUTE)) {
Bundle data = new Bundle(); Bundle data = new Bundle();
data.putInt(DATA_PLAYBACK_COUNT, mEnqueueCount); PlaylistItem item = mSessionManager.getCurrentItem();
if (item != null) {
data.putString(TRACK_INFO_DESC, item.toString());
data.putParcelable(TRACK_INFO_SNAPSHOT, mPlayer.getSnapshot());
}
if (callback != null) { if (callback != null) {
callback.onResult(data); callback.onResult(data);
} }

View File

@@ -37,7 +37,10 @@ import android.support.v4.app.FragmentManager;
import android.support.v4.view.MenuItemCompat; import android.support.v4.view.MenuItemCompat;
import android.support.v7.app.ActionBarActivity; import android.support.v7.app.ActionBarActivity;
import android.support.v7.app.MediaRouteActionProvider; import android.support.v7.app.MediaRouteActionProvider;
import android.support.v7.app.MediaRouteControllerDialog;
import android.support.v7.app.MediaRouteControllerDialogFragment;
import android.support.v7.app.MediaRouteDiscoveryFragment; import android.support.v7.app.MediaRouteDiscoveryFragment;
import android.support.v7.app.MediaRouteDialogFactory;
import android.support.v7.media.MediaControlIntent; import android.support.v7.media.MediaControlIntent;
import android.support.v7.media.MediaRouter; import android.support.v7.media.MediaRouter;
import android.support.v7.media.MediaRouter.Callback; import android.support.v7.media.MediaRouter.Callback;
@@ -88,9 +91,9 @@ public class SampleMediaRouterActivity extends ActionBarActivity {
private ImageButton mPauseResumeButton; private ImageButton mPauseResumeButton;
private ImageButton mStopButton; private ImageButton mStopButton;
private SeekBar mSeekBar; private SeekBar mSeekBar;
private boolean mPaused;
private boolean mNeedResume; private boolean mNeedResume;
private boolean mSeeking; private boolean mSeeking;
private SampleMediaRouteControllerDialog mControllerDialog;
private final Handler mHandler = new Handler(); private final Handler mHandler = new Handler();
private final Runnable mUpdateSeekRunnable = new Runnable() { private final Runnable mUpdateSeekRunnable = new Runnable() {
@@ -143,12 +146,13 @@ public class SampleMediaRouterActivity extends ActionBarActivity {
PlaylistItem item = getCheckedPlaylistItem(); PlaylistItem item = getCheckedPlaylistItem();
if (item != null) { if (item != null) {
long pos = item.getPosition() + (mPaused ? long pos = item.getPosition() + (mSessionManager.isPaused() ?
0 : (SystemClock.elapsedRealtime() - item.getTimestamp())); 0 : (SystemClock.elapsedRealtime() - item.getTimestamp()));
mSessionManager.suspend(pos); mSessionManager.suspend(pos);
} }
mPlayer.updatePresentation(); mPlayer.updatePresentation();
mPlayer.release(); mPlayer.release();
mControllerDialog = null;
} }
@Override @Override
@@ -271,7 +275,7 @@ public class SampleMediaRouterActivity extends ActionBarActivity {
spec2.setIndicator(tabName); spec2.setIndicator(tabName);
spec2.setContent(R.id.tab2); spec2.setContent(R.id.tab2);
tabName = getResources().getString(R.string.statistics_tab_text); tabName = getResources().getString(R.string.info_tab_text);
TabSpec spec3=tabHost.newTabSpec(tabName); TabSpec spec3=tabHost.newTabSpec(tabName);
spec3.setIndicator(tabName); spec3.setIndicator(tabName);
spec3.setContent(R.id.tab3); spec3.setContent(R.id.tab3);
@@ -312,11 +316,10 @@ public class SampleMediaRouterActivity extends ActionBarActivity {
mPauseResumeButton.setOnClickListener(new OnClickListener() { mPauseResumeButton.setOnClickListener(new OnClickListener() {
@Override @Override
public void onClick(View v) { public void onClick(View v) {
mPaused = !mPaused; if (mSessionManager.isPaused()) {
if (mPaused) {
mSessionManager.pause();
} else {
mSessionManager.resume(); mSessionManager.resume();
} else {
mSessionManager.pause();
} }
} }
}); });
@@ -325,7 +328,6 @@ public class SampleMediaRouterActivity extends ActionBarActivity {
mStopButton.setOnClickListener(new OnClickListener() { mStopButton.setOnClickListener(new OnClickListener() {
@Override @Override
public void onClick(View v) { public void onClick(View v) {
mPaused = false;
mSessionManager.stop(); mSessionManager.stop();
} }
}); });
@@ -421,19 +423,17 @@ public class SampleMediaRouterActivity extends ActionBarActivity {
case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE: case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
{ {
Log.d(TAG, "Received Play/Pause event from RemoteControlClient"); Log.d(TAG, "Received Play/Pause event from RemoteControlClient");
mPaused = !mPaused; if (mSessionManager.isPaused()) {
if (mPaused) {
mSessionManager.pause();
} else {
mSessionManager.resume(); mSessionManager.resume();
} else {
mSessionManager.pause();
} }
return true; return true;
} }
case KeyEvent.KEYCODE_MEDIA_PLAY: case KeyEvent.KEYCODE_MEDIA_PLAY:
{ {
Log.d(TAG, "Received Play event from RemoteControlClient"); Log.d(TAG, "Received Play event from RemoteControlClient");
if (mPaused) { if (mSessionManager.isPaused()) {
mPaused = false;
mSessionManager.resume(); mSessionManager.resume();
} }
return true; return true;
@@ -441,8 +441,7 @@ public class SampleMediaRouterActivity extends ActionBarActivity {
case KeyEvent.KEYCODE_MEDIA_PAUSE: case KeyEvent.KEYCODE_MEDIA_PAUSE:
{ {
Log.d(TAG, "Received Pause event from RemoteControlClient"); Log.d(TAG, "Received Pause event from RemoteControlClient");
if (!mPaused) { if (!mSessionManager.isPaused()) {
mPaused = true;
mSessionManager.pause(); mSessionManager.pause();
} }
return true; return true;
@@ -450,7 +449,6 @@ public class SampleMediaRouterActivity extends ActionBarActivity {
case KeyEvent.KEYCODE_MEDIA_STOP: case KeyEvent.KEYCODE_MEDIA_STOP:
{ {
Log.d(TAG, "Received Stop event from RemoteControlClient"); Log.d(TAG, "Received Stop event from RemoteControlClient");
mPaused = false;
mSessionManager.stop(); mSessionManager.stop();
return true; return true;
} }
@@ -480,7 +478,7 @@ public class SampleMediaRouterActivity extends ActionBarActivity {
@Override @Override
public void onPause() { public void onPause() {
// pause media player for local playback case only // pause media player for local playback case only
if (!mPlayer.isRemotePlayback() && !mPaused) { if (!mPlayer.isRemotePlayback() && !mSessionManager.isPaused()) {
mNeedResume = true; mNeedResume = true;
mSessionManager.pause(); mSessionManager.pause();
} }
@@ -502,7 +500,6 @@ public class SampleMediaRouterActivity extends ActionBarActivity {
// Unregister the remote control client // Unregister the remote control client
unregisterRCC(); unregisterRCC();
mPaused = false;
mSessionManager.stop(); mSessionManager.stop();
mPlayer.release(); mPlayer.release();
super.onDestroy(); super.onDestroy();
@@ -520,6 +517,20 @@ public class SampleMediaRouterActivity extends ActionBarActivity {
MediaRouteActionProvider mediaRouteActionProvider = MediaRouteActionProvider mediaRouteActionProvider =
(MediaRouteActionProvider)MenuItemCompat.getActionProvider(mediaRouteMenuItem); (MediaRouteActionProvider)MenuItemCompat.getActionProvider(mediaRouteMenuItem);
mediaRouteActionProvider.setRouteSelector(mSelector); mediaRouteActionProvider.setRouteSelector(mSelector);
mediaRouteActionProvider.setDialogFactory(new MediaRouteDialogFactory() {
@Override
public MediaRouteControllerDialogFragment onCreateControllerDialogFragment() {
return new MediaRouteControllerDialogFragment() {
@Override
public MediaRouteControllerDialog onCreateControllerDialog(
Context context, Bundle savedInstanceState) {
mControllerDialog = new SampleMediaRouteControllerDialog(
context, mSessionManager, mPlayer);
return mControllerDialog;
}
};
}
});
// Return true to show the menu. // Return true to show the menu.
return true; return true;
@@ -541,7 +552,7 @@ public class SampleMediaRouterActivity extends ActionBarActivity {
} }
} else { } else {
long position = item.getPosition(); long position = item.getPosition();
long timeDelta = mPaused ? 0 : long timeDelta = mSessionManager.isPaused() ? 0 :
(SystemClock.elapsedRealtime() - item.getTimestamp()); (SystemClock.elapsedRealtime() - item.getTimestamp());
progress = (int)(100.0 * (position + timeDelta) / duration); progress = (int)(100.0 * (position + timeDelta) / duration);
} }
@@ -553,6 +564,9 @@ public class SampleMediaRouterActivity extends ActionBarActivity {
updatePlaylist(); updatePlaylist();
updateRouteDescription(); updateRouteDescription();
updateButtons(); updateButtons();
if (mControllerDialog != null) {
mControllerDialog.updateUi();
}
} }
private void updatePlaylist() { private void updatePlaylist() {
@@ -563,29 +577,24 @@ public class SampleMediaRouterActivity extends ActionBarActivity {
mPlayListView.invalidate(); mPlayListView.invalidate();
} }
private void updateRouteDescription() { private void updateRouteDescription() {
RouteInfo route = mMediaRouter.getSelectedRoute(); RouteInfo route = mMediaRouter.getSelectedRoute();
mInfoTextView.setText("Currently selected route:" mInfoTextView.setText("Currently selected route:"
+ "\nName: " + route.getName() + "\nName: " + route.getName()
+ "\nProvider: " + route.getProvider().getPackageName() + "\nProvider: " + route.getProvider().getPackageName()
+ "\nDescription: " + route.getDescription() + "\nDescription: " + route.getDescription());
+ "\nStatistics: " + mSessionManager.getStatistics());
} }
private void updateButtons() { private void updateButtons() {
MediaRouter.RouteInfo route = mMediaRouter.getSelectedRoute(); MediaRouter.RouteInfo route = mMediaRouter.getSelectedRoute();
// show pause or resume icon depending on current state // show pause or resume icon depending on current state
mPauseResumeButton.setImageResource(mPaused ? mPauseResumeButton.setImageResource(mSessionManager.isPaused() ?
R.drawable.ic_media_play : R.drawable.ic_media_pause); R.drawable.ic_media_play : R.drawable.ic_media_pause);
// disable pause/resume/stop if no session
mPauseResumeButton.setEnabled(mSessionManager.hasSession());
mStopButton.setEnabled(mSessionManager.hasSession());
// only enable seek bar when duration is known // only enable seek bar when duration is known
PlaylistItem item = getCheckedPlaylistItem(); PlaylistItem item = getCheckedPlaylistItem();
mSeekBar.setEnabled(item != null && item.getDuration() > 0); mSeekBar.setEnabled(item != null && item.getDuration() > 0);
if (mRemoteControlClient != null) { if (mRemoteControlClient != null) {
mRemoteControlClient.setPlaybackState(mPaused ? mRemoteControlClient.setPlaybackState(mSessionManager.isPaused() ?
RemoteControlClient.PLAYSTATE_PAUSED : RemoteControlClient.PLAYSTATE_PAUSED :
RemoteControlClient.PLAYSTATE_PLAYING); RemoteControlClient.PLAYSTATE_PLAYING);
} }

View File

@@ -50,6 +50,10 @@ public class SessionManager implements Player.Callback {
mName = name; mName = name;
} }
public boolean isPaused() {
return hasSession() && mPaused;
}
public boolean hasSession() { public boolean hasSession() {
return mSessionValid; return mSessionValid;
} }
@@ -62,12 +66,6 @@ public class SessionManager implements Player.Callback {
return mPlaylist.isEmpty() ? null : mPlaylist.get(0); return mPlaylist.isEmpty() ? null : mPlaylist.get(0);
} }
// Get the cached statistic info from the player (will not update it)
public String getStatistics() {
checkPlayer();
return mPlayer.getStatistics();
}
// Returns the cached playlist (note this is not responsible for updating it) // Returns the cached playlist (note this is not responsible for updating it)
public List<PlaylistItem> getPlaylist() { public List<PlaylistItem> getPlaylist() {
return mPlaylist; return mPlaylist;
@@ -81,7 +79,7 @@ public class SessionManager implements Player.Callback {
checkPlayer(); checkPlayer();
// update the statistics first, so that the stats string is valid when // update the statistics first, so that the stats string is valid when
// onPlaylistReady() gets called in the end // onPlaylistReady() gets called in the end
mPlayer.updateStatistics(); mPlayer.updateTrackInfo();
if (mPlaylist.isEmpty()) { if (mPlaylist.isEmpty()) {
// If queue is empty, don't forget to call onPlaylistReady()! // If queue is empty, don't forget to call onPlaylistReady()!
@@ -179,7 +177,10 @@ public class SessionManager implements Player.Callback {
if (DEBUG) { if (DEBUG) {
log("pause"); log("pause");
} }
checkPlayerAndSession(); if (!mSessionValid) {
return;
}
checkPlayer();
mPaused = true; mPaused = true;
updatePlaybackState(); updatePlaybackState();
} }
@@ -188,7 +189,10 @@ public class SessionManager implements Player.Callback {
if (DEBUG) { if (DEBUG) {
log("resume"); log("resume");
} }
checkPlayerAndSession(); if (!mSessionValid) {
return;
}
checkPlayer();
mPaused = false; mPaused = false;
updatePlaybackState(); updatePlaybackState();
} }
@@ -197,7 +201,10 @@ public class SessionManager implements Player.Callback {
if (DEBUG) { if (DEBUG) {
log("stop"); log("stop");
} }
checkPlayerAndSession(); if (!mSessionValid) {
return;
}
checkPlayer();
mPlayer.stop(); mPlayer.stop();
mPlaylist.clear(); mPlaylist.clear();
mPaused = false; mPaused = false;