MediaRouteControllerDialog.java revision a09c7b30d3a5c53281db955eabce171e1aec6fea
111417b1cfde8f1749905f2d735623af9214148afJeff Brown/* 211417b1cfde8f1749905f2d735623af9214148afJeff Brown * Copyright (C) 2013 The Android Open Source Project 311417b1cfde8f1749905f2d735623af9214148afJeff Brown * 411417b1cfde8f1749905f2d735623af9214148afJeff Brown * Licensed under the Apache License, Version 2.0 (the "License"); 511417b1cfde8f1749905f2d735623af9214148afJeff Brown * you may not use this file except in compliance with the License. 611417b1cfde8f1749905f2d735623af9214148afJeff Brown * You may obtain a copy of the License at 711417b1cfde8f1749905f2d735623af9214148afJeff Brown * 811417b1cfde8f1749905f2d735623af9214148afJeff Brown * http://www.apache.org/licenses/LICENSE-2.0 911417b1cfde8f1749905f2d735623af9214148afJeff Brown * 1011417b1cfde8f1749905f2d735623af9214148afJeff Brown * Unless required by applicable law or agreed to in writing, software 1111417b1cfde8f1749905f2d735623af9214148afJeff Brown * distributed under the License is distributed on an "AS IS" BASIS, 1211417b1cfde8f1749905f2d735623af9214148afJeff Brown * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1311417b1cfde8f1749905f2d735623af9214148afJeff Brown * See the License for the specific language governing permissions and 1411417b1cfde8f1749905f2d735623af9214148afJeff Brown * limitations under the License. 1511417b1cfde8f1749905f2d735623af9214148afJeff Brown */ 1611417b1cfde8f1749905f2d735623af9214148afJeff Brown 1711417b1cfde8f1749905f2d735623af9214148afJeff Brownpackage android.support.v7.app; 1811417b1cfde8f1749905f2d735623af9214148afJeff Brown 196051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seoimport static android.widget.SeekBar.OnSeekBarChangeListener; 206051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo 21005482649154d0970693b3967241eb4d2cb22003Jaewan Kimimport android.content.ContentResolver; 2211417b1cfde8f1749905f2d735623af9214148afJeff Brownimport android.content.Context; 236051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seoimport android.content.res.TypedArray; 24005482649154d0970693b3967241eb4d2cb22003Jaewan Kimimport android.graphics.Bitmap; 25005482649154d0970693b3967241eb4d2cb22003Jaewan Kimimport android.graphics.BitmapFactory; 262ef36d857302c5cd738c7c8bdec53d31feebebbaJeff Brownimport android.graphics.drawable.Drawable; 27005482649154d0970693b3967241eb4d2cb22003Jaewan Kimimport android.net.Uri; 28005482649154d0970693b3967241eb4d2cb22003Jaewan Kimimport android.os.AsyncTask; 2911417b1cfde8f1749905f2d735623af9214148afJeff Brownimport android.os.Bundle; 3094be6100218126ce6a08bf1f56209578500b361fRoboErikimport android.os.RemoteException; 3194be6100218126ce6a08bf1f56209578500b361fRoboErikimport android.support.v4.media.MediaDescriptionCompat; 3294be6100218126ce6a08bf1f56209578500b361fRoboErikimport android.support.v4.media.MediaMetadataCompat; 3394be6100218126ce6a08bf1f56209578500b361fRoboErikimport android.support.v4.media.session.MediaControllerCompat; 3494be6100218126ce6a08bf1f56209578500b361fRoboErikimport android.support.v4.media.session.MediaSessionCompat; 3594be6100218126ce6a08bf1f56209578500b361fRoboErikimport android.support.v4.media.session.PlaybackStateCompat; 36005482649154d0970693b3967241eb4d2cb22003Jaewan Kimimport android.support.v7.graphics.Palette; 3711417b1cfde8f1749905f2d735623af9214148afJeff Brownimport android.support.v7.media.MediaRouteSelector; 3811417b1cfde8f1749905f2d735623af9214148afJeff Brownimport android.support.v7.media.MediaRouter; 3911417b1cfde8f1749905f2d735623af9214148afJeff Brownimport android.support.v7.mediarouter.R; 4094be6100218126ce6a08bf1f56209578500b361fRoboErikimport android.text.TextUtils; 4194be6100218126ce6a08bf1f56209578500b361fRoboErikimport android.util.Log; 4211417b1cfde8f1749905f2d735623af9214148afJeff Brownimport android.view.KeyEvent; 436051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seoimport android.view.LayoutInflater; 4411417b1cfde8f1749905f2d735623af9214148afJeff Brownimport android.view.View; 456051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seoimport android.view.ViewGroup; 466051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seoimport android.widget.ArrayAdapter; 4711417b1cfde8f1749905f2d735623af9214148afJeff Brownimport android.widget.Button; 4811417b1cfde8f1749905f2d735623af9214148afJeff Brownimport android.widget.FrameLayout; 4994be6100218126ce6a08bf1f56209578500b361fRoboErikimport android.widget.ImageButton; 5094be6100218126ce6a08bf1f56209578500b361fRoboErikimport android.widget.ImageView; 51f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shahimport android.widget.LinearLayout; 526051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seoimport android.widget.ListView; 53f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shahimport android.widget.SeekBar; 5494be6100218126ce6a08bf1f56209578500b361fRoboErikimport android.widget.TextView; 5511417b1cfde8f1749905f2d735623af9214148afJeff Brown 56005482649154d0970693b3967241eb4d2cb22003Jaewan Kimimport java.io.BufferedInputStream; 57005482649154d0970693b3967241eb4d2cb22003Jaewan Kimimport java.io.IOException; 586051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seoimport java.util.List; 59005482649154d0970693b3967241eb4d2cb22003Jaewan Kim 6011417b1cfde8f1749905f2d735623af9214148afJeff Brown/** 6111417b1cfde8f1749905f2d735623af9214148afJeff Brown * This class implements the route controller dialog for {@link MediaRouter}. 6211417b1cfde8f1749905f2d735623af9214148afJeff Brown * <p> 6311417b1cfde8f1749905f2d735623af9214148afJeff Brown * This dialog allows the user to control or disconnect from the currently selected route. 6411417b1cfde8f1749905f2d735623af9214148afJeff Brown * </p> 6511417b1cfde8f1749905f2d735623af9214148afJeff Brown * 6611417b1cfde8f1749905f2d735623af9214148afJeff Brown * @see MediaRouteButton 6711417b1cfde8f1749905f2d735623af9214148afJeff Brown * @see MediaRouteActionProvider 6811417b1cfde8f1749905f2d735623af9214148afJeff Brown */ 6989530d511efd566d53bedd9178454dd01d227c61Jae Seopublic class MediaRouteControllerDialog extends AlertDialog { 7011417b1cfde8f1749905f2d735623af9214148afJeff Brown private static final String TAG = "MediaRouteControllerDialog"; 7111417b1cfde8f1749905f2d735623af9214148afJeff Brown 72a4bcfe765789ebef71c36cbb2dba3f9f881fa5b4Jae Seo // STOPSHIP: Remove the flag when the group volume control implementation completes. 73a4bcfe765789ebef71c36cbb2dba3f9f881fa5b4Jae Seo private static final boolean USE_GROUP = false; 74a4bcfe765789ebef71c36cbb2dba3f9f881fa5b4Jae Seo 75f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah // Time to wait before updating the volume when the user lets go of the seek bar 76f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah // to allow the route provider time to propagate the change and publish a new 77f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah // route descriptor. 78f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah private static final int VOLUME_UPDATE_DELAY_MILLIS = 250; 79f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah 8011417b1cfde8f1749905f2d735623af9214148afJeff Brown private final MediaRouter mRouter; 8111417b1cfde8f1749905f2d735623af9214148afJeff Brown private final MediaRouterCallback mCallback; 8211417b1cfde8f1749905f2d735623af9214148afJeff Brown private final MediaRouter.RouteInfo mRoute; 8311417b1cfde8f1749905f2d735623af9214148afJeff Brown 84eff7719415542ba819054863b0995f07742a7a8aJeff Brown private boolean mCreated; 85e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik private boolean mAttachedToWindow; 8611417b1cfde8f1749905f2d735623af9214148afJeff Brown 8711417b1cfde8f1749905f2d735623af9214148afJeff Brown private View mControlView; 8811417b1cfde8f1749905f2d735623af9214148afJeff Brown 8911417b1cfde8f1749905f2d735623af9214148afJeff Brown private Button mDisconnectButton; 9094be6100218126ce6a08bf1f56209578500b361fRoboErik private Button mStopCastingButton; 9194be6100218126ce6a08bf1f56209578500b361fRoboErik private ImageButton mPlayPauseButton; 92b48ccf48b0281e69262fc643d0def898aede407bSungsoo Lim private ImageButton mCloseButton; 9310433d5f7b77f5453fb9a10e8e1c1a58c0f08e7bDongwon Kang private ImageButton mGroupExpandCollapseButton; 9494be6100218126ce6a08bf1f56209578500b361fRoboErik 9594be6100218126ce6a08bf1f56209578500b361fRoboErik private ImageView mArtView; 9694be6100218126ce6a08bf1f56209578500b361fRoboErik private TextView mTitleView; 9794be6100218126ce6a08bf1f56209578500b361fRoboErik private TextView mSubtitleView; 9894be6100218126ce6a08bf1f56209578500b361fRoboErik private TextView mRouteNameView; 9994be6100218126ce6a08bf1f56209578500b361fRoboErik 100f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah private boolean mVolumeControlEnabled = true; 101f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah private LinearLayout mVolumeLayout; 1026051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo private ListView mVolumeGroupList; 103f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah private SeekBar mVolumeSlider; 104f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah private boolean mVolumeSliderTouched; 105f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah 10694be6100218126ce6a08bf1f56209578500b361fRoboErik private MediaControllerCompat mMediaController; 10794be6100218126ce6a08bf1f56209578500b361fRoboErik private MediaControllerCallback mControllerCallback; 10894be6100218126ce6a08bf1f56209578500b361fRoboErik private PlaybackStateCompat mState; 10994be6100218126ce6a08bf1f56209578500b361fRoboErik private MediaDescriptionCompat mDescription; 11094be6100218126ce6a08bf1f56209578500b361fRoboErik 111005482649154d0970693b3967241eb4d2cb22003Jaewan Kim private FetchArtTask mFetchArtTask; 11211417b1cfde8f1749905f2d735623af9214148afJeff Brown 11311417b1cfde8f1749905f2d735623af9214148afJeff Brown public MediaRouteControllerDialog(Context context) { 11411417b1cfde8f1749905f2d735623af9214148afJeff Brown this(context, 0); 11511417b1cfde8f1749905f2d735623af9214148afJeff Brown } 11611417b1cfde8f1749905f2d735623af9214148afJeff Brown 11711417b1cfde8f1749905f2d735623af9214148afJeff Brown public MediaRouteControllerDialog(Context context, int theme) { 11894be6100218126ce6a08bf1f56209578500b361fRoboErik super(MediaRouterThemeHelper.createThemedContext(context), theme); 11911417b1cfde8f1749905f2d735623af9214148afJeff Brown context = getContext(); 12011417b1cfde8f1749905f2d735623af9214148afJeff Brown 12194be6100218126ce6a08bf1f56209578500b361fRoboErik mControllerCallback = new MediaControllerCallback(); 12211417b1cfde8f1749905f2d735623af9214148afJeff Brown mRouter = MediaRouter.getInstance(context); 12311417b1cfde8f1749905f2d735623af9214148afJeff Brown mCallback = new MediaRouterCallback(); 12411417b1cfde8f1749905f2d735623af9214148afJeff Brown mRoute = mRouter.getSelectedRoute(); 125e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik setMediaSession(mRouter.getMediaSessionToken()); 12611417b1cfde8f1749905f2d735623af9214148afJeff Brown } 12711417b1cfde8f1749905f2d735623af9214148afJeff Brown 12811417b1cfde8f1749905f2d735623af9214148afJeff Brown /** 12911417b1cfde8f1749905f2d735623af9214148afJeff Brown * Gets the route that this dialog is controlling. 13011417b1cfde8f1749905f2d735623af9214148afJeff Brown */ 13111417b1cfde8f1749905f2d735623af9214148afJeff Brown public MediaRouter.RouteInfo getRoute() { 13211417b1cfde8f1749905f2d735623af9214148afJeff Brown return mRoute; 13311417b1cfde8f1749905f2d735623af9214148afJeff Brown } 13411417b1cfde8f1749905f2d735623af9214148afJeff Brown 1356051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo private MediaRouter.RouteGroup getGroup() { 1366051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo if (mRoute instanceof MediaRouter.RouteGroup) { 1376051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo return (MediaRouter.RouteGroup) mRoute; 1386051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo } 1396051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo return null; 1406051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo } 1416051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo 14211417b1cfde8f1749905f2d735623af9214148afJeff Brown /** 14311417b1cfde8f1749905f2d735623af9214148afJeff Brown * Provides the subclass an opportunity to create a view that will 14411417b1cfde8f1749905f2d735623af9214148afJeff Brown * be included within the body of the dialog to offer additional media controls 14511417b1cfde8f1749905f2d735623af9214148afJeff Brown * for the currently playing content. 14611417b1cfde8f1749905f2d735623af9214148afJeff Brown * 14711417b1cfde8f1749905f2d735623af9214148afJeff Brown * @param savedInstanceState The dialog's saved instance state. 14811417b1cfde8f1749905f2d735623af9214148afJeff Brown * @return The media control view, or null if none. 14911417b1cfde8f1749905f2d735623af9214148afJeff Brown */ 15011417b1cfde8f1749905f2d735623af9214148afJeff Brown public View onCreateMediaControlView(Bundle savedInstanceState) { 15111417b1cfde8f1749905f2d735623af9214148afJeff Brown return null; 15211417b1cfde8f1749905f2d735623af9214148afJeff Brown } 15311417b1cfde8f1749905f2d735623af9214148afJeff Brown 15411417b1cfde8f1749905f2d735623af9214148afJeff Brown /** 15511417b1cfde8f1749905f2d735623af9214148afJeff Brown * Gets the media control view that was created by {@link #onCreateMediaControlView(Bundle)}. 15611417b1cfde8f1749905f2d735623af9214148afJeff Brown * 15711417b1cfde8f1749905f2d735623af9214148afJeff Brown * @return The media control view, or null if none. 15811417b1cfde8f1749905f2d735623af9214148afJeff Brown */ 15911417b1cfde8f1749905f2d735623af9214148afJeff Brown public View getMediaControlView() { 16011417b1cfde8f1749905f2d735623af9214148afJeff Brown return mControlView; 16111417b1cfde8f1749905f2d735623af9214148afJeff Brown } 16211417b1cfde8f1749905f2d735623af9214148afJeff Brown 163eff7719415542ba819054863b0995f07742a7a8aJeff Brown /** 164f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah * Sets whether to enable the volume slider and volume control using the volume keys 165f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah * when the route supports it. 166f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah * <p> 167f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah * The default value is true. 168f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah * </p> 169f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah */ 170f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah public void setVolumeControlEnabled(boolean enable) { 171f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah if (mVolumeControlEnabled != enable) { 172f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah mVolumeControlEnabled = enable; 173f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah if (mCreated) { 174f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah updateVolume(); 175f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah } 176f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah } 177f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah } 178f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah 179f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah /** 180f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah * Returns whether to enable the volume slider and volume control using the volume keys 181f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah * when the route supports it. 182f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah */ 183f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah public boolean isVolumeControlEnabled() { 184f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah return mVolumeControlEnabled; 185f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah } 186f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah 187f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah /** 18894be6100218126ce6a08bf1f56209578500b361fRoboErik * Set the session to use for metadata and transport controls. The dialog 18994be6100218126ce6a08bf1f56209578500b361fRoboErik * will listen to changes on this session and update the UI automatically in 19094be6100218126ce6a08bf1f56209578500b361fRoboErik * response to changes. 19194be6100218126ce6a08bf1f56209578500b361fRoboErik * 19294be6100218126ce6a08bf1f56209578500b361fRoboErik * @param sessionToken The token for the session to use. 193eff7719415542ba819054863b0995f07742a7a8aJeff Brown */ 194e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik private void setMediaSession(MediaSessionCompat.Token sessionToken) { 19594be6100218126ce6a08bf1f56209578500b361fRoboErik if (mMediaController != null) { 19694be6100218126ce6a08bf1f56209578500b361fRoboErik mMediaController.unregisterCallback(mControllerCallback); 19794be6100218126ce6a08bf1f56209578500b361fRoboErik mMediaController = null; 19894be6100218126ce6a08bf1f56209578500b361fRoboErik } 19994be6100218126ce6a08bf1f56209578500b361fRoboErik if (sessionToken == null) { 20094be6100218126ce6a08bf1f56209578500b361fRoboErik return; 20194be6100218126ce6a08bf1f56209578500b361fRoboErik } 202e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik if (!mAttachedToWindow) { 203e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik return; 204e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } 20594be6100218126ce6a08bf1f56209578500b361fRoboErik try { 20694be6100218126ce6a08bf1f56209578500b361fRoboErik mMediaController = new MediaControllerCompat(getContext(), sessionToken); 20794be6100218126ce6a08bf1f56209578500b361fRoboErik } catch (RemoteException e) { 20894be6100218126ce6a08bf1f56209578500b361fRoboErik Log.e(TAG, "Error creating media controller in setMediaSession.", e); 20994be6100218126ce6a08bf1f56209578500b361fRoboErik } 21094be6100218126ce6a08bf1f56209578500b361fRoboErik if (mMediaController != null) { 21194be6100218126ce6a08bf1f56209578500b361fRoboErik mMediaController.registerCallback(mControllerCallback); 212eff7719415542ba819054863b0995f07742a7a8aJeff Brown } 21394be6100218126ce6a08bf1f56209578500b361fRoboErik MediaMetadataCompat metadata = mMediaController == null ? null 21494be6100218126ce6a08bf1f56209578500b361fRoboErik : mMediaController.getMetadata(); 21594be6100218126ce6a08bf1f56209578500b361fRoboErik mDescription = metadata == null ? null : metadata.getDescription(); 21694be6100218126ce6a08bf1f56209578500b361fRoboErik mState = mMediaController == null ? null : mMediaController.getPlaybackState(); 21794be6100218126ce6a08bf1f56209578500b361fRoboErik update(); 218eff7719415542ba819054863b0995f07742a7a8aJeff Brown } 219eff7719415542ba819054863b0995f07742a7a8aJeff Brown 220eff7719415542ba819054863b0995f07742a7a8aJeff Brown /** 22194be6100218126ce6a08bf1f56209578500b361fRoboErik * Gets the description being used by the default UI. 22294be6100218126ce6a08bf1f56209578500b361fRoboErik * 22394be6100218126ce6a08bf1f56209578500b361fRoboErik * @return The current description. 224eff7719415542ba819054863b0995f07742a7a8aJeff Brown */ 22594be6100218126ce6a08bf1f56209578500b361fRoboErik public MediaSessionCompat.Token getMediaSession() { 22694be6100218126ce6a08bf1f56209578500b361fRoboErik return mMediaController == null ? null : mMediaController.getSessionToken(); 227eff7719415542ba819054863b0995f07742a7a8aJeff Brown } 228eff7719415542ba819054863b0995f07742a7a8aJeff Brown 22911417b1cfde8f1749905f2d735623af9214148afJeff Brown @Override 23011417b1cfde8f1749905f2d735623af9214148afJeff Brown protected void onCreate(Bundle savedInstanceState) { 23111417b1cfde8f1749905f2d735623af9214148afJeff Brown super.onCreate(savedInstanceState); 23211417b1cfde8f1749905f2d735623af9214148afJeff Brown 233a09c7b30d3a5c53281db955eabce171e1aec6feaSungsoo Lim setContentView(R.layout.mr_controller_material_dialog_b); 23411417b1cfde8f1749905f2d735623af9214148afJeff Brown 23594be6100218126ce6a08bf1f56209578500b361fRoboErik ClickListener listener = new ClickListener(); 236d6748a7926ebb2450337f9f0ff4d445c980344e5Jeff Brown 23794be6100218126ce6a08bf1f56209578500b361fRoboErik mDisconnectButton = (Button) findViewById(R.id.disconnect); 23894be6100218126ce6a08bf1f56209578500b361fRoboErik mDisconnectButton.setOnClickListener(listener); 23911417b1cfde8f1749905f2d735623af9214148afJeff Brown 24094be6100218126ce6a08bf1f56209578500b361fRoboErik mStopCastingButton = (Button) findViewById(R.id.stop); 24194be6100218126ce6a08bf1f56209578500b361fRoboErik mStopCastingButton.setOnClickListener(listener); 24211417b1cfde8f1749905f2d735623af9214148afJeff Brown 243b48ccf48b0281e69262fc643d0def898aede407bSungsoo Lim mCloseButton = (ImageButton) findViewById(R.id.close); 244b48ccf48b0281e69262fc643d0def898aede407bSungsoo Lim mCloseButton.setOnClickListener(listener); 24511417b1cfde8f1749905f2d735623af9214148afJeff Brown 24694be6100218126ce6a08bf1f56209578500b361fRoboErik mArtView = (ImageView) findViewById(R.id.art); 24794be6100218126ce6a08bf1f56209578500b361fRoboErik mTitleView = (TextView) findViewById(R.id.title); 24894be6100218126ce6a08bf1f56209578500b361fRoboErik mSubtitleView = (TextView) findViewById(R.id.subtitle); 24994be6100218126ce6a08bf1f56209578500b361fRoboErik mPlayPauseButton = (ImageButton) findViewById(R.id.play_pause); 25094be6100218126ce6a08bf1f56209578500b361fRoboErik mPlayPauseButton.setOnClickListener(listener); 25194be6100218126ce6a08bf1f56209578500b361fRoboErik mRouteNameView = (TextView) findViewById(R.id.route_name); 252f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah mVolumeLayout = (LinearLayout)findViewById(R.id.media_route_volume_layout); 2536051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo mVolumeGroupList = (ListView)findViewById(R.id.media_route_volume_group_list); 2546051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo 2556051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo TypedArray styledAttributes = getContext().obtainStyledAttributes(new int[] { 2566051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo R.attr.mediaRouteExpandGroupDrawable, 257a09c7b30d3a5c53281db955eabce171e1aec6feaSungsoo Lim R.attr.mediaRouteCollapseGroupDrawable 258a09c7b30d3a5c53281db955eabce171e1aec6feaSungsoo Lim }); 2596051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo final Drawable expandGroupDrawable = styledAttributes.getDrawable(0); 2606051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo final Drawable collapseGroupDrawable = styledAttributes.getDrawable(1); 2616051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo styledAttributes.recycle(); 2626051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo 26310433d5f7b77f5453fb9a10e8e1c1a58c0f08e7bDongwon Kang mGroupExpandCollapseButton = (ImageButton)findViewById( 26410433d5f7b77f5453fb9a10e8e1c1a58c0f08e7bDongwon Kang R.id.media_route_group_expand_collapse); 2656051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo mGroupExpandCollapseButton.setOnClickListener(new View.OnClickListener() { 2666051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo private boolean mIsExpanded; 2676051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo 2686051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo @Override 2696051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo public void onClick(View v) { 2706051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo mIsExpanded = !mIsExpanded; 2716051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo if (mIsExpanded) { 2726051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo mGroupExpandCollapseButton.setImageDrawable(collapseGroupDrawable); 2736051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo mVolumeGroupList.setVisibility(View.VISIBLE); 2746051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo mVolumeGroupList.setAdapter( 2756051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo new VolumeGroupAdapter(getContext(), getGroup().getRoutes())); 2766051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo } else { 2776051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo mGroupExpandCollapseButton.setImageDrawable(expandGroupDrawable); 2786051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo mVolumeGroupList.setVisibility(View.GONE); 2796051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo } 2806051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo } 2816051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo }); 282f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah mVolumeSlider = (SeekBar)findViewById(R.id.media_route_volume_slider); 283f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah mVolumeSlider.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { 284f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah private final Runnable mStopTrackingTouch = new Runnable() { 285f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah @Override 286f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah public void run() { 287f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah if (mVolumeSliderTouched) { 288f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah mVolumeSliderTouched = false; 289f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah updateVolume(); 290f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah } 291f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah } 292f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah }; 293f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah 294f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah @Override 295f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah public void onStartTrackingTouch(SeekBar seekBar) { 296f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah if (mVolumeSliderTouched) { 297f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah mVolumeSlider.removeCallbacks(mStopTrackingTouch); 298f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah } else { 299f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah mVolumeSliderTouched = true; 300f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah } 301f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah } 302f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah 303f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah @Override 304f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah public void onStopTrackingTouch(SeekBar seekBar) { 305f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah // Defer resetting mVolumeSliderTouched to allow the media route provider 306f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah // a little time to settle into its new state and publish the final 307f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah // volume update. 308f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah mVolumeSlider.postDelayed(mStopTrackingTouch, VOLUME_UPDATE_DELAY_MILLIS); 309f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah } 310f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah 311f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah @Override 312f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { 313f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah if (fromUser) { 314f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah mRoute.requestSetVolume(progress); 315f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah } 316f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah } 317f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah }); 31811417b1cfde8f1749905f2d735623af9214148afJeff Brown 319eff7719415542ba819054863b0995f07742a7a8aJeff Brown mCreated = true; 32011417b1cfde8f1749905f2d735623af9214148afJeff Brown if (update()) { 32111417b1cfde8f1749905f2d735623af9214148afJeff Brown mControlView = onCreateMediaControlView(savedInstanceState); 322697ff1cbd5efee431fb10c74b31071cf95341203Prameet Shah FrameLayout controlFrame = 323697ff1cbd5efee431fb10c74b31071cf95341203Prameet Shah (FrameLayout)findViewById(R.id.media_route_control_frame); 32411417b1cfde8f1749905f2d735623af9214148afJeff Brown if (mControlView != null) { 32594be6100218126ce6a08bf1f56209578500b361fRoboErik controlFrame.findViewById(R.id.default_control_frame).setVisibility(View.GONE); 326697ff1cbd5efee431fb10c74b31071cf95341203Prameet Shah controlFrame.addView(mControlView); 32711417b1cfde8f1749905f2d735623af9214148afJeff Brown } 32811417b1cfde8f1749905f2d735623af9214148afJeff Brown } 32911417b1cfde8f1749905f2d735623af9214148afJeff Brown } 33011417b1cfde8f1749905f2d735623af9214148afJeff Brown 33111417b1cfde8f1749905f2d735623af9214148afJeff Brown @Override 33211417b1cfde8f1749905f2d735623af9214148afJeff Brown public void onAttachedToWindow() { 33311417b1cfde8f1749905f2d735623af9214148afJeff Brown super.onAttachedToWindow(); 334e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik mAttachedToWindow = true; 33511417b1cfde8f1749905f2d735623af9214148afJeff Brown 33611417b1cfde8f1749905f2d735623af9214148afJeff Brown mRouter.addCallback(MediaRouteSelector.EMPTY, mCallback, 33711417b1cfde8f1749905f2d735623af9214148afJeff Brown MediaRouter.CALLBACK_FLAG_UNFILTERED_EVENTS); 338e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik setMediaSession(mRouter.getMediaSessionToken()); 33911417b1cfde8f1749905f2d735623af9214148afJeff Brown } 34011417b1cfde8f1749905f2d735623af9214148afJeff Brown 34111417b1cfde8f1749905f2d735623af9214148afJeff Brown @Override 34211417b1cfde8f1749905f2d735623af9214148afJeff Brown public void onDetachedFromWindow() { 34311417b1cfde8f1749905f2d735623af9214148afJeff Brown mRouter.removeCallback(mCallback); 344e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik setMediaSession(null); 345e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik mAttachedToWindow = false; 34611417b1cfde8f1749905f2d735623af9214148afJeff Brown super.onDetachedFromWindow(); 34711417b1cfde8f1749905f2d735623af9214148afJeff Brown } 34811417b1cfde8f1749905f2d735623af9214148afJeff Brown 34911417b1cfde8f1749905f2d735623af9214148afJeff Brown @Override 35011417b1cfde8f1749905f2d735623af9214148afJeff Brown public boolean onKeyDown(int keyCode, KeyEvent event) { 351ce8cbd614a64f94e54b936d66ecd14b6c1282ddfJeff Brown if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN 352ce8cbd614a64f94e54b936d66ecd14b6c1282ddfJeff Brown || keyCode == KeyEvent.KEYCODE_VOLUME_UP) { 353ce8cbd614a64f94e54b936d66ecd14b6c1282ddfJeff Brown mRoute.requestUpdateVolume(keyCode == KeyEvent.KEYCODE_VOLUME_DOWN ? -1 : 1); 354ce8cbd614a64f94e54b936d66ecd14b6c1282ddfJeff Brown return true; 35511417b1cfde8f1749905f2d735623af9214148afJeff Brown } 35611417b1cfde8f1749905f2d735623af9214148afJeff Brown return super.onKeyDown(keyCode, event); 35711417b1cfde8f1749905f2d735623af9214148afJeff Brown } 35811417b1cfde8f1749905f2d735623af9214148afJeff Brown 35911417b1cfde8f1749905f2d735623af9214148afJeff Brown @Override 36011417b1cfde8f1749905f2d735623af9214148afJeff Brown public boolean onKeyUp(int keyCode, KeyEvent event) { 361ce8cbd614a64f94e54b936d66ecd14b6c1282ddfJeff Brown if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN 362ce8cbd614a64f94e54b936d66ecd14b6c1282ddfJeff Brown || keyCode == KeyEvent.KEYCODE_VOLUME_UP) { 363ce8cbd614a64f94e54b936d66ecd14b6c1282ddfJeff Brown return true; 36411417b1cfde8f1749905f2d735623af9214148afJeff Brown } 36511417b1cfde8f1749905f2d735623af9214148afJeff Brown return super.onKeyUp(keyCode, event); 36611417b1cfde8f1749905f2d735623af9214148afJeff Brown } 36711417b1cfde8f1749905f2d735623af9214148afJeff Brown 36811417b1cfde8f1749905f2d735623af9214148afJeff Brown private boolean update() { 36911417b1cfde8f1749905f2d735623af9214148afJeff Brown if (!mRoute.isSelected() || mRoute.isDefault()) { 37011417b1cfde8f1749905f2d735623af9214148afJeff Brown dismiss(); 37111417b1cfde8f1749905f2d735623af9214148afJeff Brown return false; 37211417b1cfde8f1749905f2d735623af9214148afJeff Brown } 37394be6100218126ce6a08bf1f56209578500b361fRoboErik if (!mCreated) { 37494be6100218126ce6a08bf1f56209578500b361fRoboErik return false; 37594be6100218126ce6a08bf1f56209578500b361fRoboErik } 37611417b1cfde8f1749905f2d735623af9214148afJeff Brown 377f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah updateVolume(); 378f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah 37994be6100218126ce6a08bf1f56209578500b361fRoboErik mRouteNameView.setText(mRoute.getName()); 38011417b1cfde8f1749905f2d735623af9214148afJeff Brown 38194be6100218126ce6a08bf1f56209578500b361fRoboErik if (mRoute.canDisconnect()) { 38294be6100218126ce6a08bf1f56209578500b361fRoboErik mDisconnectButton.setVisibility(View.VISIBLE); 38394be6100218126ce6a08bf1f56209578500b361fRoboErik } else { 38494be6100218126ce6a08bf1f56209578500b361fRoboErik mDisconnectButton.setVisibility(View.GONE); 38594be6100218126ce6a08bf1f56209578500b361fRoboErik } 3862ef36d857302c5cd738c7c8bdec53d31feebebbaJeff Brown 38794be6100218126ce6a08bf1f56209578500b361fRoboErik if (mRoute.getSettingsIntent() != null) { 388b48ccf48b0281e69262fc643d0def898aede407bSungsoo Lim mCloseButton.setVisibility(View.VISIBLE); 38994be6100218126ce6a08bf1f56209578500b361fRoboErik } else { 390b48ccf48b0281e69262fc643d0def898aede407bSungsoo Lim mCloseButton.setVisibility(View.GONE); 39194be6100218126ce6a08bf1f56209578500b361fRoboErik } 39294be6100218126ce6a08bf1f56209578500b361fRoboErik 39394be6100218126ce6a08bf1f56209578500b361fRoboErik if (mControlView == null) { 394005482649154d0970693b3967241eb4d2cb22003Jaewan Kim if (mFetchArtTask != null) { 395005482649154d0970693b3967241eb4d2cb22003Jaewan Kim mFetchArtTask.cancel(true); 39666937fc7dfe22c8c505bf735781d1f5b62f08e34Dongwon Kang } 397005482649154d0970693b3967241eb4d2cb22003Jaewan Kim mArtView.setVisibility(View.GONE); 398005482649154d0970693b3967241eb4d2cb22003Jaewan Kim mFetchArtTask = new FetchArtTask(); 399005482649154d0970693b3967241eb4d2cb22003Jaewan Kim mFetchArtTask.execute(); 4005db1d51338a41b1dab537a5a37a0de8f5f0cc5b9Jae Seo 40166937fc7dfe22c8c505bf735781d1f5b62f08e34Dongwon Kang CharSequence title = mDescription == null ? null : mDescription.getTitle(); 40266937fc7dfe22c8c505bf735781d1f5b62f08e34Dongwon Kang boolean hasTitle = !TextUtils.isEmpty(title); 40366937fc7dfe22c8c505bf735781d1f5b62f08e34Dongwon Kang 40466937fc7dfe22c8c505bf735781d1f5b62f08e34Dongwon Kang CharSequence subtitle = mDescription == null ? null : mDescription.getSubtitle(); 40566937fc7dfe22c8c505bf735781d1f5b62f08e34Dongwon Kang boolean hasSubtitle = !TextUtils.isEmpty(subtitle); 40666937fc7dfe22c8c505bf735781d1f5b62f08e34Dongwon Kang 40766937fc7dfe22c8c505bf735781d1f5b62f08e34Dongwon Kang if (!hasTitle && !hasSubtitle) { 408a09c7b30d3a5c53281db955eabce171e1aec6feaSungsoo Lim mTitleView.setText(R.string.mr_controller_no_info_available); 40966937fc7dfe22c8c505bf735781d1f5b62f08e34Dongwon Kang mTitleView.setEnabled(false); 41066937fc7dfe22c8c505bf735781d1f5b62f08e34Dongwon Kang mTitleView.setVisibility(View.VISIBLE); 41166937fc7dfe22c8c505bf735781d1f5b62f08e34Dongwon Kang mSubtitleView.setVisibility(View.GONE); 41266937fc7dfe22c8c505bf735781d1f5b62f08e34Dongwon Kang } else { 41366937fc7dfe22c8c505bf735781d1f5b62f08e34Dongwon Kang mTitleView.setText(title); 41466937fc7dfe22c8c505bf735781d1f5b62f08e34Dongwon Kang mTitleView.setEnabled(hasTitle); 41566937fc7dfe22c8c505bf735781d1f5b62f08e34Dongwon Kang mTitleView.setVisibility(hasTitle ? View.VISIBLE : View.GONE); 41666937fc7dfe22c8c505bf735781d1f5b62f08e34Dongwon Kang mSubtitleView.setText(subtitle); 41766937fc7dfe22c8c505bf735781d1f5b62f08e34Dongwon Kang mSubtitleView.setVisibility(hasSubtitle ? View.VISIBLE : View.GONE); 41894be6100218126ce6a08bf1f56209578500b361fRoboErik } 41994be6100218126ce6a08bf1f56209578500b361fRoboErik if (mState != null) { 42094be6100218126ce6a08bf1f56209578500b361fRoboErik boolean isPlaying = mState.getState() == PlaybackStateCompat.STATE_BUFFERING 42194be6100218126ce6a08bf1f56209578500b361fRoboErik || mState.getState() == PlaybackStateCompat.STATE_PLAYING; 42294be6100218126ce6a08bf1f56209578500b361fRoboErik boolean supportsPlay = (mState.getActions() & (PlaybackStateCompat.ACTION_PLAY 42394be6100218126ce6a08bf1f56209578500b361fRoboErik | PlaybackStateCompat.ACTION_PLAY_PAUSE)) != 0; 42494be6100218126ce6a08bf1f56209578500b361fRoboErik boolean supportsPause = (mState.getActions() & (PlaybackStateCompat.ACTION_PAUSE 42594be6100218126ce6a08bf1f56209578500b361fRoboErik | PlaybackStateCompat.ACTION_PLAY_PAUSE)) != 0; 42694be6100218126ce6a08bf1f56209578500b361fRoboErik if (isPlaying && supportsPause) { 42794be6100218126ce6a08bf1f56209578500b361fRoboErik mPlayPauseButton.setVisibility(View.VISIBLE); 42892badabc6a274e3bf8ea2a0072e8a6371f252722RoboErik mPlayPauseButton.setImageResource(MediaRouterThemeHelper.getThemeResource( 42992badabc6a274e3bf8ea2a0072e8a6371f252722RoboErik getContext(), R.attr.mediaRoutePauseDrawable)); 43094be6100218126ce6a08bf1f56209578500b361fRoboErik mPlayPauseButton.setContentDescription(getContext().getResources() 431a09c7b30d3a5c53281db955eabce171e1aec6feaSungsoo Lim .getText(R.string.mr_controller_pause)); 43294be6100218126ce6a08bf1f56209578500b361fRoboErik } else if (!isPlaying && supportsPlay) { 43394be6100218126ce6a08bf1f56209578500b361fRoboErik mPlayPauseButton.setVisibility(View.VISIBLE); 43492badabc6a274e3bf8ea2a0072e8a6371f252722RoboErik mPlayPauseButton.setImageResource(MediaRouterThemeHelper.getThemeResource( 43592badabc6a274e3bf8ea2a0072e8a6371f252722RoboErik getContext(), R.attr.mediaRoutePlayDrawable)); 43694be6100218126ce6a08bf1f56209578500b361fRoboErik mPlayPauseButton.setContentDescription(getContext().getResources() 437a09c7b30d3a5c53281db955eabce171e1aec6feaSungsoo Lim .getText(R.string.mr_controller_play)); 43894be6100218126ce6a08bf1f56209578500b361fRoboErik } else { 43994be6100218126ce6a08bf1f56209578500b361fRoboErik mPlayPauseButton.setVisibility(View.GONE); 44094be6100218126ce6a08bf1f56209578500b361fRoboErik } 44194be6100218126ce6a08bf1f56209578500b361fRoboErik } else { 44294be6100218126ce6a08bf1f56209578500b361fRoboErik mPlayPauseButton.setVisibility(View.GONE); 44394be6100218126ce6a08bf1f56209578500b361fRoboErik } 4442ef36d857302c5cd738c7c8bdec53d31feebebbaJeff Brown } 44511417b1cfde8f1749905f2d735623af9214148afJeff Brown return true; 44611417b1cfde8f1749905f2d735623af9214148afJeff Brown } 44711417b1cfde8f1749905f2d735623af9214148afJeff Brown 448f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah private void updateVolume() { 449f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah if (!mVolumeSliderTouched) { 450f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah if (isVolumeControlAvailable()) { 451f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah mVolumeLayout.setVisibility(View.VISIBLE); 452f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah mVolumeSlider.setMax(mRoute.getVolumeMax()); 453f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah mVolumeSlider.setProgress(mRoute.getVolume()); 454a4bcfe765789ebef71c36cbb2dba3f9f881fa5b4Jae Seo if (USE_GROUP) { 455a4bcfe765789ebef71c36cbb2dba3f9f881fa5b4Jae Seo mGroupExpandCollapseButton.setVisibility( 4566051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo getGroup() != null ? View.VISIBLE : View.GONE); 457a4bcfe765789ebef71c36cbb2dba3f9f881fa5b4Jae Seo } 458f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah } else { 459f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah mVolumeLayout.setVisibility(View.GONE); 460f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah } 461f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah } 462f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah } 463f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah 464f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah private boolean isVolumeControlAvailable() { 465f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah return mVolumeControlEnabled && mRoute.getVolumeHandling() == 466f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah MediaRouter.RouteInfo.PLAYBACK_VOLUME_VARIABLE; 467f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah } 468f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah 46911417b1cfde8f1749905f2d735623af9214148afJeff Brown private final class MediaRouterCallback extends MediaRouter.Callback { 47011417b1cfde8f1749905f2d735623af9214148afJeff Brown @Override 47111417b1cfde8f1749905f2d735623af9214148afJeff Brown public void onRouteUnselected(MediaRouter router, MediaRouter.RouteInfo route) { 47211417b1cfde8f1749905f2d735623af9214148afJeff Brown update(); 47311417b1cfde8f1749905f2d735623af9214148afJeff Brown } 47411417b1cfde8f1749905f2d735623af9214148afJeff Brown 47511417b1cfde8f1749905f2d735623af9214148afJeff Brown @Override 47611417b1cfde8f1749905f2d735623af9214148afJeff Brown public void onRouteChanged(MediaRouter router, MediaRouter.RouteInfo route) { 47711417b1cfde8f1749905f2d735623af9214148afJeff Brown update(); 47811417b1cfde8f1749905f2d735623af9214148afJeff Brown } 47911417b1cfde8f1749905f2d735623af9214148afJeff Brown 48011417b1cfde8f1749905f2d735623af9214148afJeff Brown @Override 48111417b1cfde8f1749905f2d735623af9214148afJeff Brown public void onRouteVolumeChanged(MediaRouter router, MediaRouter.RouteInfo route) { 48211417b1cfde8f1749905f2d735623af9214148afJeff Brown if (route == mRoute) { 483f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah updateVolume(); 48494be6100218126ce6a08bf1f56209578500b361fRoboErik } 48594be6100218126ce6a08bf1f56209578500b361fRoboErik } 48694be6100218126ce6a08bf1f56209578500b361fRoboErik } 48794be6100218126ce6a08bf1f56209578500b361fRoboErik 48894be6100218126ce6a08bf1f56209578500b361fRoboErik private final class MediaControllerCallback extends MediaControllerCompat.Callback { 48994be6100218126ce6a08bf1f56209578500b361fRoboErik @Override 49094be6100218126ce6a08bf1f56209578500b361fRoboErik public void onSessionDestroyed() { 49194be6100218126ce6a08bf1f56209578500b361fRoboErik if (mMediaController != null) { 49294be6100218126ce6a08bf1f56209578500b361fRoboErik mMediaController.unregisterCallback(mControllerCallback); 49394be6100218126ce6a08bf1f56209578500b361fRoboErik mMediaController = null; 49494be6100218126ce6a08bf1f56209578500b361fRoboErik } 49594be6100218126ce6a08bf1f56209578500b361fRoboErik } 49694be6100218126ce6a08bf1f56209578500b361fRoboErik 49794be6100218126ce6a08bf1f56209578500b361fRoboErik @Override 49894be6100218126ce6a08bf1f56209578500b361fRoboErik public void onPlaybackStateChanged(PlaybackStateCompat state) { 49994be6100218126ce6a08bf1f56209578500b361fRoboErik mState = state; 50094be6100218126ce6a08bf1f56209578500b361fRoboErik update(); 50194be6100218126ce6a08bf1f56209578500b361fRoboErik } 50294be6100218126ce6a08bf1f56209578500b361fRoboErik 50394be6100218126ce6a08bf1f56209578500b361fRoboErik @Override 50494be6100218126ce6a08bf1f56209578500b361fRoboErik public void onMetadataChanged(MediaMetadataCompat metadata) { 50594be6100218126ce6a08bf1f56209578500b361fRoboErik mDescription = metadata == null ? null : metadata.getDescription(); 50694be6100218126ce6a08bf1f56209578500b361fRoboErik update(); 50794be6100218126ce6a08bf1f56209578500b361fRoboErik } 50894be6100218126ce6a08bf1f56209578500b361fRoboErik } 50994be6100218126ce6a08bf1f56209578500b361fRoboErik 51094be6100218126ce6a08bf1f56209578500b361fRoboErik private final class ClickListener implements View.OnClickListener { 51194be6100218126ce6a08bf1f56209578500b361fRoboErik @Override 51294be6100218126ce6a08bf1f56209578500b361fRoboErik public void onClick(View v) { 51394be6100218126ce6a08bf1f56209578500b361fRoboErik int id = v.getId(); 51494be6100218126ce6a08bf1f56209578500b361fRoboErik if (id == R.id.stop || id == R.id.disconnect) { 51594be6100218126ce6a08bf1f56209578500b361fRoboErik if (mRoute.isSelected()) { 51694be6100218126ce6a08bf1f56209578500b361fRoboErik mRouter.unselect(id == R.id.stop ? 51794be6100218126ce6a08bf1f56209578500b361fRoboErik MediaRouter.UNSELECT_REASON_STOPPED : 51894be6100218126ce6a08bf1f56209578500b361fRoboErik MediaRouter.UNSELECT_REASON_DISCONNECTED); 51994be6100218126ce6a08bf1f56209578500b361fRoboErik } 52094be6100218126ce6a08bf1f56209578500b361fRoboErik dismiss(); 52194be6100218126ce6a08bf1f56209578500b361fRoboErik } else if (id == R.id.play_pause) { 52294be6100218126ce6a08bf1f56209578500b361fRoboErik if (mMediaController != null && mState != null) { 52394be6100218126ce6a08bf1f56209578500b361fRoboErik if (mState.getState() == PlaybackStateCompat.STATE_PLAYING) { 52494be6100218126ce6a08bf1f56209578500b361fRoboErik mMediaController.getTransportControls().pause(); 52594be6100218126ce6a08bf1f56209578500b361fRoboErik } else { 52694be6100218126ce6a08bf1f56209578500b361fRoboErik mMediaController.getTransportControls().play(); 52794be6100218126ce6a08bf1f56209578500b361fRoboErik } 52894be6100218126ce6a08bf1f56209578500b361fRoboErik } 529b48ccf48b0281e69262fc643d0def898aede407bSungsoo Lim } else if (id == R.id.close) { 530b48ccf48b0281e69262fc643d0def898aede407bSungsoo Lim dismiss(); 53111417b1cfde8f1749905f2d735623af9214148afJeff Brown } 53211417b1cfde8f1749905f2d735623af9214148afJeff Brown } 53311417b1cfde8f1749905f2d735623af9214148afJeff Brown } 534005482649154d0970693b3967241eb4d2cb22003Jaewan Kim 5356051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo private class VolumeGroupAdapter extends ArrayAdapter<MediaRouter.RouteInfo> { 5366051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo final OnSeekBarChangeListener mOnSeekBarChangeListener = new OnSeekBarChangeListener() { 5376051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo @Override 5386051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { 5396051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo if (fromUser) { 5406051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo int position = (int) seekBar.getTag(); 5416051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo getGroup().getRouteAt(position).requestSetVolume(progress); 5426051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo } 5436051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo } 5446051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo 5456051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo @Override 5466051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo public void onStartTrackingTouch(SeekBar seekBar) { 5476051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo // TODO: Implement 5486051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo } 5496051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo 5506051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo @Override 5516051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo public void onStopTrackingTouch(SeekBar seekBar) { 5526051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo // TODO: Implement 5536051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo } 5546051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo }; 5556051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo 5566051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo public VolumeGroupAdapter(Context context, List<MediaRouter.RouteInfo> objects) { 5576051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo super(context, 0, objects); 5586051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo } 5596051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo 5606051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo @Override 5616051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo public View getView(final int position, View convertView, ViewGroup parent) { 5626051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo View v = convertView; 5636051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo if (v == null) { 5646051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo v = LayoutInflater.from(getContext()).inflate( 565a09c7b30d3a5c53281db955eabce171e1aec6feaSungsoo Lim R.layout.mr_controller_volume_item, null); 5666051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo } 5676051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo MediaRouter.RouteInfo route = getItem(position); 5686051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo if (route != null) { 5696051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo TextView textView = (TextView) v.findViewById(R.id.media_route_name); 5706051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo textView.setText(route.getName()); 5716051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo 5726051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo SeekBar volumeSlider = (SeekBar) v.findViewById(R.id.media_route_volume_slider); 573480052774a9fb375d68b7a0373a5bd8d733f8dc0Jae Seo if (route.getVolumeHandling() == MediaRouter.RouteInfo.PLAYBACK_VOLUME_VARIABLE) { 574480052774a9fb375d68b7a0373a5bd8d733f8dc0Jae Seo volumeSlider.setMax(route.getVolumeMax()); 575480052774a9fb375d68b7a0373a5bd8d733f8dc0Jae Seo volumeSlider.setProgress(route.getVolume()); 576480052774a9fb375d68b7a0373a5bd8d733f8dc0Jae Seo volumeSlider.setOnSeekBarChangeListener(mOnSeekBarChangeListener); 577480052774a9fb375d68b7a0373a5bd8d733f8dc0Jae Seo } else { 578480052774a9fb375d68b7a0373a5bd8d733f8dc0Jae Seo volumeSlider.setMax(100); 579480052774a9fb375d68b7a0373a5bd8d733f8dc0Jae Seo volumeSlider.setProgress(100); 580480052774a9fb375d68b7a0373a5bd8d733f8dc0Jae Seo volumeSlider.setEnabled(false); 581480052774a9fb375d68b7a0373a5bd8d733f8dc0Jae Seo } 5826051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo volumeSlider.setTag(position); 5836051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo } 5846051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo return v; 5856051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo } 5866051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo } 5876051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo 588005482649154d0970693b3967241eb4d2cb22003Jaewan Kim private class FetchArtTask extends AsyncTask<Void, Void, Bitmap> { 589005482649154d0970693b3967241eb4d2cb22003Jaewan Kim private int mBackgroundColor; 590005482649154d0970693b3967241eb4d2cb22003Jaewan Kim 591005482649154d0970693b3967241eb4d2cb22003Jaewan Kim @Override 592005482649154d0970693b3967241eb4d2cb22003Jaewan Kim protected Bitmap doInBackground(Void... arg) { 593005482649154d0970693b3967241eb4d2cb22003Jaewan Kim Bitmap bitmap = null; 594005482649154d0970693b3967241eb4d2cb22003Jaewan Kim if (mDescription == null) { 595005482649154d0970693b3967241eb4d2cb22003Jaewan Kim return null; 596005482649154d0970693b3967241eb4d2cb22003Jaewan Kim } 597005482649154d0970693b3967241eb4d2cb22003Jaewan Kim if (mDescription.getIconBitmap() != null) { 598005482649154d0970693b3967241eb4d2cb22003Jaewan Kim bitmap = mDescription.getIconBitmap(); 599005482649154d0970693b3967241eb4d2cb22003Jaewan Kim } else if (mDescription.getIconUri() != null) { 600005482649154d0970693b3967241eb4d2cb22003Jaewan Kim Uri iconUri = mDescription.getIconUri(); 601005482649154d0970693b3967241eb4d2cb22003Jaewan Kim String scheme = iconUri.getScheme(); 602005482649154d0970693b3967241eb4d2cb22003Jaewan Kim if (!(ContentResolver.SCHEME_ANDROID_RESOURCE.equals(scheme) 603005482649154d0970693b3967241eb4d2cb22003Jaewan Kim || ContentResolver.SCHEME_CONTENT.equals(scheme) 604005482649154d0970693b3967241eb4d2cb22003Jaewan Kim || ContentResolver.SCHEME_FILE.equals(scheme))) { 605005482649154d0970693b3967241eb4d2cb22003Jaewan Kim Log.w(TAG, "Icon Uri should point to local resources."); 606005482649154d0970693b3967241eb4d2cb22003Jaewan Kim return null; 607005482649154d0970693b3967241eb4d2cb22003Jaewan Kim } 608005482649154d0970693b3967241eb4d2cb22003Jaewan Kim BufferedInputStream stream = null; 609005482649154d0970693b3967241eb4d2cb22003Jaewan Kim try { 610005482649154d0970693b3967241eb4d2cb22003Jaewan Kim stream = new BufferedInputStream( 611005482649154d0970693b3967241eb4d2cb22003Jaewan Kim getContext().getContentResolver().openInputStream(iconUri)); 612005482649154d0970693b3967241eb4d2cb22003Jaewan Kim 613005482649154d0970693b3967241eb4d2cb22003Jaewan Kim // Query bitmap size. 614005482649154d0970693b3967241eb4d2cb22003Jaewan Kim BitmapFactory.Options options = new BitmapFactory.Options(); 615005482649154d0970693b3967241eb4d2cb22003Jaewan Kim options.inJustDecodeBounds = true; 616005482649154d0970693b3967241eb4d2cb22003Jaewan Kim BitmapFactory.decodeStream(stream, null, options); 617005482649154d0970693b3967241eb4d2cb22003Jaewan Kim 618005482649154d0970693b3967241eb4d2cb22003Jaewan Kim // Rewind the stream in order to restart bitmap decoding. 619005482649154d0970693b3967241eb4d2cb22003Jaewan Kim try { 620005482649154d0970693b3967241eb4d2cb22003Jaewan Kim stream.reset(); 621005482649154d0970693b3967241eb4d2cb22003Jaewan Kim } catch (IOException e) { 622005482649154d0970693b3967241eb4d2cb22003Jaewan Kim // Failed to rewind the stream, try to reopen it. 623005482649154d0970693b3967241eb4d2cb22003Jaewan Kim stream.close(); 624005482649154d0970693b3967241eb4d2cb22003Jaewan Kim stream = new BufferedInputStream(getContext().getContentResolver() 625005482649154d0970693b3967241eb4d2cb22003Jaewan Kim .openInputStream(iconUri)); 626005482649154d0970693b3967241eb4d2cb22003Jaewan Kim } 627005482649154d0970693b3967241eb4d2cb22003Jaewan Kim 628005482649154d0970693b3967241eb4d2cb22003Jaewan Kim // Caculate required size to decode the bitmap and possibly resize it. 629005482649154d0970693b3967241eb4d2cb22003Jaewan Kim options.inJustDecodeBounds = false; 630005482649154d0970693b3967241eb4d2cb22003Jaewan Kim int reqWidth; 631005482649154d0970693b3967241eb4d2cb22003Jaewan Kim int reqHeight; 632005482649154d0970693b3967241eb4d2cb22003Jaewan Kim if (options.outWidth >= options.outHeight) { 633005482649154d0970693b3967241eb4d2cb22003Jaewan Kim // For landscape image, fit width to dialog width. 634005482649154d0970693b3967241eb4d2cb22003Jaewan Kim reqWidth = getWindow().getDecorView().getWidth(); 635005482649154d0970693b3967241eb4d2cb22003Jaewan Kim reqHeight = reqWidth * (options.outHeight / options.outWidth); 636005482649154d0970693b3967241eb4d2cb22003Jaewan Kim } else { 637005482649154d0970693b3967241eb4d2cb22003Jaewan Kim // For portrait image, fit height to 16:9 ratio case's height. 638005482649154d0970693b3967241eb4d2cb22003Jaewan Kim reqHeight = getWindow().getDecorView().getWidth() * 9 / 16; 639005482649154d0970693b3967241eb4d2cb22003Jaewan Kim reqWidth = reqHeight * (options.outWidth / options.outHeight); 640005482649154d0970693b3967241eb4d2cb22003Jaewan Kim } 641005482649154d0970693b3967241eb4d2cb22003Jaewan Kim int ratio = Math.max( 642005482649154d0970693b3967241eb4d2cb22003Jaewan Kim options.outWidth / reqWidth, options.outHeight / reqHeight); 643005482649154d0970693b3967241eb4d2cb22003Jaewan Kim options.inSampleSize = Math.max(1, Integer.highestOneBit(ratio)); 644005482649154d0970693b3967241eb4d2cb22003Jaewan Kim if (isCancelled()) { 645005482649154d0970693b3967241eb4d2cb22003Jaewan Kim return null; 646005482649154d0970693b3967241eb4d2cb22003Jaewan Kim } 647005482649154d0970693b3967241eb4d2cb22003Jaewan Kim bitmap = BitmapFactory.decodeStream(stream, null, options); 648005482649154d0970693b3967241eb4d2cb22003Jaewan Kim } catch (IOException e){ 649005482649154d0970693b3967241eb4d2cb22003Jaewan Kim Log.w(TAG, "Unable to open content: " + iconUri, e); 650005482649154d0970693b3967241eb4d2cb22003Jaewan Kim } finally { 651005482649154d0970693b3967241eb4d2cb22003Jaewan Kim if (stream != null) { 652005482649154d0970693b3967241eb4d2cb22003Jaewan Kim try { 653005482649154d0970693b3967241eb4d2cb22003Jaewan Kim stream.close(); 654005482649154d0970693b3967241eb4d2cb22003Jaewan Kim } catch (IOException e) { 655005482649154d0970693b3967241eb4d2cb22003Jaewan Kim } 656005482649154d0970693b3967241eb4d2cb22003Jaewan Kim } 657005482649154d0970693b3967241eb4d2cb22003Jaewan Kim } 658005482649154d0970693b3967241eb4d2cb22003Jaewan Kim } 659005482649154d0970693b3967241eb4d2cb22003Jaewan Kim if (bitmap != null) { 660005482649154d0970693b3967241eb4d2cb22003Jaewan Kim if (bitmap.getWidth() < bitmap.getHeight()) { 661005482649154d0970693b3967241eb4d2cb22003Jaewan Kim // Portrait image requires background color. 662005482649154d0970693b3967241eb4d2cb22003Jaewan Kim mBackgroundColor = 663005482649154d0970693b3967241eb4d2cb22003Jaewan Kim new Palette.Builder(bitmap).generate().getDarkVibrantColor(0); 664005482649154d0970693b3967241eb4d2cb22003Jaewan Kim } 665005482649154d0970693b3967241eb4d2cb22003Jaewan Kim } 666005482649154d0970693b3967241eb4d2cb22003Jaewan Kim return bitmap; 667005482649154d0970693b3967241eb4d2cb22003Jaewan Kim } 668005482649154d0970693b3967241eb4d2cb22003Jaewan Kim 669005482649154d0970693b3967241eb4d2cb22003Jaewan Kim @Override 670005482649154d0970693b3967241eb4d2cb22003Jaewan Kim protected void onCancelled() { 671005482649154d0970693b3967241eb4d2cb22003Jaewan Kim mFetchArtTask = null; 672005482649154d0970693b3967241eb4d2cb22003Jaewan Kim } 673005482649154d0970693b3967241eb4d2cb22003Jaewan Kim 674005482649154d0970693b3967241eb4d2cb22003Jaewan Kim @Override 675005482649154d0970693b3967241eb4d2cb22003Jaewan Kim protected void onPostExecute(Bitmap bitmap) { 676005482649154d0970693b3967241eb4d2cb22003Jaewan Kim mFetchArtTask = null; 677005482649154d0970693b3967241eb4d2cb22003Jaewan Kim mArtView.setImageBitmap(bitmap); 678005482649154d0970693b3967241eb4d2cb22003Jaewan Kim if (bitmap != null) { 679005482649154d0970693b3967241eb4d2cb22003Jaewan Kim mArtView.setVisibility(View.VISIBLE); 680005482649154d0970693b3967241eb4d2cb22003Jaewan Kim if (bitmap.getWidth() < bitmap.getHeight()) { 681005482649154d0970693b3967241eb4d2cb22003Jaewan Kim mArtView.setMaxHeight(getWindow().getDecorView().getWidth() * 9 / 16); 682005482649154d0970693b3967241eb4d2cb22003Jaewan Kim mArtView.setBackgroundColor(mBackgroundColor); 683005482649154d0970693b3967241eb4d2cb22003Jaewan Kim } else { 684005482649154d0970693b3967241eb4d2cb22003Jaewan Kim mArtView.setMaxHeight(Integer.MAX_VALUE); 685005482649154d0970693b3967241eb4d2cb22003Jaewan Kim } 686005482649154d0970693b3967241eb4d2cb22003Jaewan Kim } else { 687005482649154d0970693b3967241eb4d2cb22003Jaewan Kim mArtView.setVisibility(View.GONE); 688005482649154d0970693b3967241eb4d2cb22003Jaewan Kim } 689005482649154d0970693b3967241eb4d2cb22003Jaewan Kim } 690005482649154d0970693b3967241eb4d2cb22003Jaewan Kim } 6916051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo} 692