* commit '9678ee604ba5bfe1810b5773b1739af5919e7249': Add sample code to customize the MediaRouteControllerDialog
This commit is contained in:
58
samples/Support7Demos/res/layout/sample_media_controller.xml
Normal file
58
samples/Support7Demos/res/layout/sample_media_controller.xml
Normal 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>
|
||||||
@@ -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>
|
||||||
|
|||||||
@@ -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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -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() {}
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user