MediaRouteControllerDialog.java revision 145e93b13dd025b278665494e7be0c15b8df5986
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 19bfb90b6717bb46535d747aa50045a206965542d0Jae Seoimport static android.widget.SeekBar.OnSeekBarChangeListener; 20bfb90b6717bb46535d747aa50045a206965542d0Jae Seo 21005482649154d0970693b3967241eb4d2cb22003Jaewan Kimimport android.content.ContentResolver; 2211417b1cfde8f1749905f2d735623af9214148afJeff Brownimport android.content.Context; 236e547065f21f1645b3e9d5b3a3fd9720be8aede8Jaewan Kimimport android.content.res.Configuration; 246e547065f21f1645b3e9d5b3a3fd9720be8aede8Jaewan Kimimport android.content.res.Resources; 256051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seoimport android.content.res.TypedArray; 26005482649154d0970693b3967241eb4d2cb22003Jaewan Kimimport android.graphics.Bitmap; 27005482649154d0970693b3967241eb4d2cb22003Jaewan Kimimport android.graphics.BitmapFactory; 2813d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kimimport android.graphics.drawable.BitmapDrawable; 292ef36d857302c5cd738c7c8bdec53d31feebebbaJeff Brownimport android.graphics.drawable.Drawable; 30005482649154d0970693b3967241eb4d2cb22003Jaewan Kimimport android.net.Uri; 31005482649154d0970693b3967241eb4d2cb22003Jaewan Kimimport android.os.AsyncTask; 3211417b1cfde8f1749905f2d735623af9214148afJeff Brownimport android.os.Bundle; 3394be6100218126ce6a08bf1f56209578500b361fRoboErikimport android.os.RemoteException; 3494be6100218126ce6a08bf1f56209578500b361fRoboErikimport android.support.v4.media.MediaDescriptionCompat; 3594be6100218126ce6a08bf1f56209578500b361fRoboErikimport android.support.v4.media.MediaMetadataCompat; 3694be6100218126ce6a08bf1f56209578500b361fRoboErikimport android.support.v4.media.session.MediaControllerCompat; 3794be6100218126ce6a08bf1f56209578500b361fRoboErikimport android.support.v4.media.session.MediaSessionCompat; 3894be6100218126ce6a08bf1f56209578500b361fRoboErikimport android.support.v4.media.session.PlaybackStateCompat; 39005482649154d0970693b3967241eb4d2cb22003Jaewan Kimimport android.support.v7.graphics.Palette; 4011417b1cfde8f1749905f2d735623af9214148afJeff Brownimport android.support.v7.media.MediaRouteSelector; 4111417b1cfde8f1749905f2d735623af9214148afJeff Brownimport android.support.v7.media.MediaRouter; 4211417b1cfde8f1749905f2d735623af9214148afJeff Brownimport android.support.v7.mediarouter.R; 4394be6100218126ce6a08bf1f56209578500b361fRoboErikimport android.text.TextUtils; 4413d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kimimport android.util.DisplayMetrics; 4594be6100218126ce6a08bf1f56209578500b361fRoboErikimport android.util.Log; 4611417b1cfde8f1749905f2d735623af9214148afJeff Brownimport android.view.KeyEvent; 476051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seoimport android.view.LayoutInflater; 4811417b1cfde8f1749905f2d735623af9214148afJeff Brownimport android.view.View; 496051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seoimport android.view.ViewGroup; 506051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seoimport android.widget.ArrayAdapter; 5111417b1cfde8f1749905f2d735623af9214148afJeff Brownimport android.widget.Button; 5211417b1cfde8f1749905f2d735623af9214148afJeff Brownimport android.widget.FrameLayout; 5394be6100218126ce6a08bf1f56209578500b361fRoboErikimport android.widget.ImageButton; 5494be6100218126ce6a08bf1f56209578500b361fRoboErikimport android.widget.ImageView; 55f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shahimport android.widget.LinearLayout; 566051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seoimport android.widget.ListView; 577ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Limimport android.widget.RelativeLayout; 58f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shahimport android.widget.SeekBar; 5994be6100218126ce6a08bf1f56209578500b361fRoboErikimport android.widget.TextView; 6011417b1cfde8f1749905f2d735623af9214148afJeff Brown 61005482649154d0970693b3967241eb4d2cb22003Jaewan Kimimport java.io.BufferedInputStream; 62005482649154d0970693b3967241eb4d2cb22003Jaewan Kimimport java.io.IOException; 637ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Limimport java.util.ArrayList; 646051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seoimport java.util.List; 65005482649154d0970693b3967241eb4d2cb22003Jaewan Kim 6611417b1cfde8f1749905f2d735623af9214148afJeff Brown/** 6711417b1cfde8f1749905f2d735623af9214148afJeff Brown * This class implements the route controller dialog for {@link MediaRouter}. 6811417b1cfde8f1749905f2d735623af9214148afJeff Brown * <p> 6911417b1cfde8f1749905f2d735623af9214148afJeff Brown * This dialog allows the user to control or disconnect from the currently selected route. 7011417b1cfde8f1749905f2d735623af9214148afJeff Brown * </p> 7111417b1cfde8f1749905f2d735623af9214148afJeff Brown * 7211417b1cfde8f1749905f2d735623af9214148afJeff Brown * @see MediaRouteButton 7311417b1cfde8f1749905f2d735623af9214148afJeff Brown * @see MediaRouteActionProvider 7411417b1cfde8f1749905f2d735623af9214148afJeff Brown */ 7589530d511efd566d53bedd9178454dd01d227c61Jae Seopublic class MediaRouteControllerDialog extends AlertDialog { 7611417b1cfde8f1749905f2d735623af9214148afJeff Brown private static final String TAG = "MediaRouteControllerDialog"; 7711417b1cfde8f1749905f2d735623af9214148afJeff Brown 78a4bcfe765789ebef71c36cbb2dba3f9f881fa5b4Jae Seo // STOPSHIP: Remove the flag when the group volume control implementation completes. 79a4bcfe765789ebef71c36cbb2dba3f9f881fa5b4Jae Seo private static final boolean USE_GROUP = false; 80a4bcfe765789ebef71c36cbb2dba3f9f881fa5b4Jae Seo 81f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah // Time to wait before updating the volume when the user lets go of the seek bar 82f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah // to allow the route provider time to propagate the change and publish a new 83f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah // route descriptor. 84f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah private static final int VOLUME_UPDATE_DELAY_MILLIS = 250; 85f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah 8611417b1cfde8f1749905f2d735623af9214148afJeff Brown private final MediaRouter mRouter; 8711417b1cfde8f1749905f2d735623af9214148afJeff Brown private final MediaRouterCallback mCallback; 8811417b1cfde8f1749905f2d735623af9214148afJeff Brown private final MediaRouter.RouteInfo mRoute; 8911417b1cfde8f1749905f2d735623af9214148afJeff Brown 90eff7719415542ba819054863b0995f07742a7a8aJeff Brown private boolean mCreated; 91e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik private boolean mAttachedToWindow; 926e547065f21f1645b3e9d5b3a3fd9720be8aede8Jaewan Kim private int mOrientation; 936e547065f21f1645b3e9d5b3a3fd9720be8aede8Jaewan Kim private int mDialogWidthPortrait; 946e547065f21f1645b3e9d5b3a3fd9720be8aede8Jaewan Kim private int mDialogWidthLandscape; 9513d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim private int mDialogPaddingVertical; 9611417b1cfde8f1749905f2d735623af9214148afJeff Brown 977ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim private View mCustomControlView; 9811417b1cfde8f1749905f2d735623af9214148afJeff Brown 9911417b1cfde8f1749905f2d735623af9214148afJeff Brown private Button mDisconnectButton; 10094be6100218126ce6a08bf1f56209578500b361fRoboErik private Button mStopCastingButton; 101b48ccf48b0281e69262fc643d0def898aede407bSungsoo Lim private ImageButton mCloseButton; 10294be6100218126ce6a08bf1f56209578500b361fRoboErik 1037ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim private FrameLayout mCustomControlFrame; 10494be6100218126ce6a08bf1f56209578500b361fRoboErik private ImageView mArtView; 1057ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim private TextView mRouteNameTextView; 10694be6100218126ce6a08bf1f56209578500b361fRoboErik 107f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah private boolean mVolumeControlEnabled = true; 1087ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim private MediaRouteControlAdapter mControlAdapter; 1097ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim private ListView mControlView; 1106051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo private ListView mVolumeGroupList; 111f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah 11294be6100218126ce6a08bf1f56209578500b361fRoboErik private MediaControllerCompat mMediaController; 11394be6100218126ce6a08bf1f56209578500b361fRoboErik private MediaControllerCallback mControllerCallback; 11494be6100218126ce6a08bf1f56209578500b361fRoboErik private PlaybackStateCompat mState; 11594be6100218126ce6a08bf1f56209578500b361fRoboErik private MediaDescriptionCompat mDescription; 11694be6100218126ce6a08bf1f56209578500b361fRoboErik 117005482649154d0970693b3967241eb4d2cb22003Jaewan Kim private FetchArtTask mFetchArtTask; 11811417b1cfde8f1749905f2d735623af9214148afJeff Brown 11911417b1cfde8f1749905f2d735623af9214148afJeff Brown public MediaRouteControllerDialog(Context context) { 12011417b1cfde8f1749905f2d735623af9214148afJeff Brown this(context, 0); 12111417b1cfde8f1749905f2d735623af9214148afJeff Brown } 12211417b1cfde8f1749905f2d735623af9214148afJeff Brown 12311417b1cfde8f1749905f2d735623af9214148afJeff Brown public MediaRouteControllerDialog(Context context, int theme) { 12494be6100218126ce6a08bf1f56209578500b361fRoboErik super(MediaRouterThemeHelper.createThemedContext(context), theme); 12511417b1cfde8f1749905f2d735623af9214148afJeff Brown context = getContext(); 12611417b1cfde8f1749905f2d735623af9214148afJeff Brown 12794be6100218126ce6a08bf1f56209578500b361fRoboErik mControllerCallback = new MediaControllerCallback(); 12811417b1cfde8f1749905f2d735623af9214148afJeff Brown mRouter = MediaRouter.getInstance(context); 12911417b1cfde8f1749905f2d735623af9214148afJeff Brown mCallback = new MediaRouterCallback(); 13011417b1cfde8f1749905f2d735623af9214148afJeff Brown mRoute = mRouter.getSelectedRoute(); 131e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik setMediaSession(mRouter.getMediaSessionToken()); 13211417b1cfde8f1749905f2d735623af9214148afJeff Brown } 13311417b1cfde8f1749905f2d735623af9214148afJeff Brown 13411417b1cfde8f1749905f2d735623af9214148afJeff Brown /** 13511417b1cfde8f1749905f2d735623af9214148afJeff Brown * Gets the route that this dialog is controlling. 13611417b1cfde8f1749905f2d735623af9214148afJeff Brown */ 13711417b1cfde8f1749905f2d735623af9214148afJeff Brown public MediaRouter.RouteInfo getRoute() { 13811417b1cfde8f1749905f2d735623af9214148afJeff Brown return mRoute; 13911417b1cfde8f1749905f2d735623af9214148afJeff Brown } 14011417b1cfde8f1749905f2d735623af9214148afJeff Brown 1416051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo private MediaRouter.RouteGroup getGroup() { 1426051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo if (mRoute instanceof MediaRouter.RouteGroup) { 1436051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo return (MediaRouter.RouteGroup) mRoute; 1446051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo } 1456051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo return null; 1466051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo } 1476051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo 14811417b1cfde8f1749905f2d735623af9214148afJeff Brown /** 14911417b1cfde8f1749905f2d735623af9214148afJeff Brown * Provides the subclass an opportunity to create a view that will 15011417b1cfde8f1749905f2d735623af9214148afJeff Brown * be included within the body of the dialog to offer additional media controls 15111417b1cfde8f1749905f2d735623af9214148afJeff Brown * for the currently playing content. 15211417b1cfde8f1749905f2d735623af9214148afJeff Brown * 15311417b1cfde8f1749905f2d735623af9214148afJeff Brown * @param savedInstanceState The dialog's saved instance state. 15411417b1cfde8f1749905f2d735623af9214148afJeff Brown * @return The media control view, or null if none. 15511417b1cfde8f1749905f2d735623af9214148afJeff Brown */ 15611417b1cfde8f1749905f2d735623af9214148afJeff Brown public View onCreateMediaControlView(Bundle savedInstanceState) { 15711417b1cfde8f1749905f2d735623af9214148afJeff Brown return null; 15811417b1cfde8f1749905f2d735623af9214148afJeff Brown } 15911417b1cfde8f1749905f2d735623af9214148afJeff Brown 16011417b1cfde8f1749905f2d735623af9214148afJeff Brown /** 16111417b1cfde8f1749905f2d735623af9214148afJeff Brown * Gets the media control view that was created by {@link #onCreateMediaControlView(Bundle)}. 16211417b1cfde8f1749905f2d735623af9214148afJeff Brown * 16311417b1cfde8f1749905f2d735623af9214148afJeff Brown * @return The media control view, or null if none. 16411417b1cfde8f1749905f2d735623af9214148afJeff Brown */ 16511417b1cfde8f1749905f2d735623af9214148afJeff Brown public View getMediaControlView() { 1667ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim return mCustomControlView; 16711417b1cfde8f1749905f2d735623af9214148afJeff Brown } 16811417b1cfde8f1749905f2d735623af9214148afJeff Brown 169eff7719415542ba819054863b0995f07742a7a8aJeff Brown /** 170f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah * Sets whether to enable the volume slider and volume control using the volume keys 171f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah * when the route supports it. 172f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah * <p> 173f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah * The default value is true. 174f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah * </p> 175f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah */ 176f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah public void setVolumeControlEnabled(boolean enable) { 177f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah if (mVolumeControlEnabled != enable) { 178f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah mVolumeControlEnabled = enable; 179f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah if (mCreated) { 1807ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim mControlAdapter.updateVolumeControl(); 181f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah } 182f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah } 183f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah } 184f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah 185f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah /** 186f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah * Returns whether to enable the volume slider and volume control using the volume keys 187f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah * when the route supports it. 188f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah */ 189f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah public boolean isVolumeControlEnabled() { 190f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah return mVolumeControlEnabled; 191f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah } 192f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah 193f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah /** 19494be6100218126ce6a08bf1f56209578500b361fRoboErik * Set the session to use for metadata and transport controls. The dialog 19594be6100218126ce6a08bf1f56209578500b361fRoboErik * will listen to changes on this session and update the UI automatically in 19694be6100218126ce6a08bf1f56209578500b361fRoboErik * response to changes. 19794be6100218126ce6a08bf1f56209578500b361fRoboErik * 19894be6100218126ce6a08bf1f56209578500b361fRoboErik * @param sessionToken The token for the session to use. 199eff7719415542ba819054863b0995f07742a7a8aJeff Brown */ 200e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik private void setMediaSession(MediaSessionCompat.Token sessionToken) { 20194be6100218126ce6a08bf1f56209578500b361fRoboErik if (mMediaController != null) { 20294be6100218126ce6a08bf1f56209578500b361fRoboErik mMediaController.unregisterCallback(mControllerCallback); 20394be6100218126ce6a08bf1f56209578500b361fRoboErik mMediaController = null; 20494be6100218126ce6a08bf1f56209578500b361fRoboErik } 20594be6100218126ce6a08bf1f56209578500b361fRoboErik if (sessionToken == null) { 20694be6100218126ce6a08bf1f56209578500b361fRoboErik return; 20794be6100218126ce6a08bf1f56209578500b361fRoboErik } 208e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik if (!mAttachedToWindow) { 209e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik return; 210e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } 21194be6100218126ce6a08bf1f56209578500b361fRoboErik try { 21294be6100218126ce6a08bf1f56209578500b361fRoboErik mMediaController = new MediaControllerCompat(getContext(), sessionToken); 21394be6100218126ce6a08bf1f56209578500b361fRoboErik } catch (RemoteException e) { 21494be6100218126ce6a08bf1f56209578500b361fRoboErik Log.e(TAG, "Error creating media controller in setMediaSession.", e); 21594be6100218126ce6a08bf1f56209578500b361fRoboErik } 21694be6100218126ce6a08bf1f56209578500b361fRoboErik if (mMediaController != null) { 21794be6100218126ce6a08bf1f56209578500b361fRoboErik mMediaController.registerCallback(mControllerCallback); 218eff7719415542ba819054863b0995f07742a7a8aJeff Brown } 21994be6100218126ce6a08bf1f56209578500b361fRoboErik MediaMetadataCompat metadata = mMediaController == null ? null 22094be6100218126ce6a08bf1f56209578500b361fRoboErik : mMediaController.getMetadata(); 22194be6100218126ce6a08bf1f56209578500b361fRoboErik mDescription = metadata == null ? null : metadata.getDescription(); 22294be6100218126ce6a08bf1f56209578500b361fRoboErik mState = mMediaController == null ? null : mMediaController.getPlaybackState(); 22394be6100218126ce6a08bf1f56209578500b361fRoboErik update(); 224eff7719415542ba819054863b0995f07742a7a8aJeff Brown } 225eff7719415542ba819054863b0995f07742a7a8aJeff Brown 226eff7719415542ba819054863b0995f07742a7a8aJeff Brown /** 22794be6100218126ce6a08bf1f56209578500b361fRoboErik * Gets the description being used by the default UI. 22894be6100218126ce6a08bf1f56209578500b361fRoboErik * 22994be6100218126ce6a08bf1f56209578500b361fRoboErik * @return The current description. 230eff7719415542ba819054863b0995f07742a7a8aJeff Brown */ 23194be6100218126ce6a08bf1f56209578500b361fRoboErik public MediaSessionCompat.Token getMediaSession() { 23294be6100218126ce6a08bf1f56209578500b361fRoboErik return mMediaController == null ? null : mMediaController.getSessionToken(); 233eff7719415542ba819054863b0995f07742a7a8aJeff Brown } 234eff7719415542ba819054863b0995f07742a7a8aJeff Brown 23511417b1cfde8f1749905f2d735623af9214148afJeff Brown @Override 23611417b1cfde8f1749905f2d735623af9214148afJeff Brown protected void onCreate(Bundle savedInstanceState) { 23711417b1cfde8f1749905f2d735623af9214148afJeff Brown super.onCreate(savedInstanceState); 23811417b1cfde8f1749905f2d735623af9214148afJeff Brown 239a09c7b30d3a5c53281db955eabce171e1aec6feaSungsoo Lim setContentView(R.layout.mr_controller_material_dialog_b); 2406e547065f21f1645b3e9d5b3a3fd9720be8aede8Jaewan Kim View decorView = getWindow().getDecorView(); 2416e547065f21f1645b3e9d5b3a3fd9720be8aede8Jaewan Kim int dialogHorizontalPadding = decorView.getPaddingLeft() + decorView.getPaddingRight(); 2426e547065f21f1645b3e9d5b3a3fd9720be8aede8Jaewan Kim Resources res = getContext().getResources(); 2436e547065f21f1645b3e9d5b3a3fd9720be8aede8Jaewan Kim mDialogWidthPortrait = res.getDimensionPixelSize( 2446e547065f21f1645b3e9d5b3a3fd9720be8aede8Jaewan Kim R.dimen.mr_dialog_content_width_portrait) + dialogHorizontalPadding; 2456e547065f21f1645b3e9d5b3a3fd9720be8aede8Jaewan Kim mDialogWidthLandscape = res.getDimensionPixelSize( 2466e547065f21f1645b3e9d5b3a3fd9720be8aede8Jaewan Kim R.dimen.mr_dialog_content_width_landscape) + dialogHorizontalPadding; 24713d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim mDialogPaddingVertical = decorView.getPaddingTop() + decorView.getPaddingBottom(); 24811417b1cfde8f1749905f2d735623af9214148afJeff Brown 24994be6100218126ce6a08bf1f56209578500b361fRoboErik ClickListener listener = new ClickListener(); 250d6748a7926ebb2450337f9f0ff4d445c980344e5Jeff Brown 25194be6100218126ce6a08bf1f56209578500b361fRoboErik mDisconnectButton = (Button) findViewById(R.id.disconnect); 25294be6100218126ce6a08bf1f56209578500b361fRoboErik mDisconnectButton.setOnClickListener(listener); 25311417b1cfde8f1749905f2d735623af9214148afJeff Brown 25494be6100218126ce6a08bf1f56209578500b361fRoboErik mStopCastingButton = (Button) findViewById(R.id.stop); 25594be6100218126ce6a08bf1f56209578500b361fRoboErik mStopCastingButton.setOnClickListener(listener); 25611417b1cfde8f1749905f2d735623af9214148afJeff Brown 2577ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim mRouteNameTextView = (TextView) findViewById(R.id.route_name); 258b48ccf48b0281e69262fc643d0def898aede407bSungsoo Lim mCloseButton = (ImageButton) findViewById(R.id.close); 259b48ccf48b0281e69262fc643d0def898aede407bSungsoo Lim mCloseButton.setOnClickListener(listener); 26011417b1cfde8f1749905f2d735623af9214148afJeff Brown 2617ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim mCustomControlFrame = (FrameLayout) findViewById(R.id.custom_control_frame); 2627ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim mArtView = (ImageView) findViewById(R.id.mr_art); 2636051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo 2647ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim mControlAdapter = new MediaRouteControlAdapter( 2657ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim getContext(), new ArrayList<View>(), listener); 2667ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim mControlView = (ListView) findViewById(R.id.mr_control); 2677ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim mControlView.setAdapter(mControlAdapter); 2687ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim mVolumeGroupList = (ListView)findViewById(R.id.mr_volume_group_list); 26911417b1cfde8f1749905f2d735623af9214148afJeff Brown 270eff7719415542ba819054863b0995f07742a7a8aJeff Brown mCreated = true; 2717ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim mCustomControlView = onCreateMediaControlView(savedInstanceState); 2727ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim if (mCustomControlView != null) { 2737ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim mCustomControlFrame.addView(mCustomControlView); 2747ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim mCustomControlFrame.setVisibility(View.VISIBLE); 2757ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim mArtView.setVisibility(View.GONE); 27611417b1cfde8f1749905f2d735623af9214148afJeff Brown } 2777ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim update(); 27811417b1cfde8f1749905f2d735623af9214148afJeff Brown } 27911417b1cfde8f1749905f2d735623af9214148afJeff Brown 2806e547065f21f1645b3e9d5b3a3fd9720be8aede8Jaewan Kim /** 2816e547065f21f1645b3e9d5b3a3fd9720be8aede8Jaewan Kim * Called by {@link MediaRouteControllerDialogFragment} when the device configuration 2826e547065f21f1645b3e9d5b3a3fd9720be8aede8Jaewan Kim * is changed. 2836e547065f21f1645b3e9d5b3a3fd9720be8aede8Jaewan Kim */ 2846e547065f21f1645b3e9d5b3a3fd9720be8aede8Jaewan Kim void onConfigurationChanged(Configuration newConfig) { 2856e547065f21f1645b3e9d5b3a3fd9720be8aede8Jaewan Kim onOrientationChanged(newConfig.orientation); 2866e547065f21f1645b3e9d5b3a3fd9720be8aede8Jaewan Kim } 2876e547065f21f1645b3e9d5b3a3fd9720be8aede8Jaewan Kim 2886e547065f21f1645b3e9d5b3a3fd9720be8aede8Jaewan Kim private void onOrientationChanged(int orientation) { 2896e547065f21f1645b3e9d5b3a3fd9720be8aede8Jaewan Kim if (!mAttachedToWindow || mOrientation == orientation) { 2906e547065f21f1645b3e9d5b3a3fd9720be8aede8Jaewan Kim return; 2916e547065f21f1645b3e9d5b3a3fd9720be8aede8Jaewan Kim } 2926e547065f21f1645b3e9d5b3a3fd9720be8aede8Jaewan Kim mOrientation = orientation; 2936e547065f21f1645b3e9d5b3a3fd9720be8aede8Jaewan Kim getWindow().setLayout( 2946e547065f21f1645b3e9d5b3a3fd9720be8aede8Jaewan Kim mOrientation == Configuration.ORIENTATION_LANDSCAPE 2956e547065f21f1645b3e9d5b3a3fd9720be8aede8Jaewan Kim ? mDialogWidthLandscape : mDialogWidthPortrait, 2966e547065f21f1645b3e9d5b3a3fd9720be8aede8Jaewan Kim ViewGroup.LayoutParams.WRAP_CONTENT); 29713d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim updateArtView(); 2986e547065f21f1645b3e9d5b3a3fd9720be8aede8Jaewan Kim } 2996e547065f21f1645b3e9d5b3a3fd9720be8aede8Jaewan Kim 30011417b1cfde8f1749905f2d735623af9214148afJeff Brown @Override 30111417b1cfde8f1749905f2d735623af9214148afJeff Brown public void onAttachedToWindow() { 30211417b1cfde8f1749905f2d735623af9214148afJeff Brown super.onAttachedToWindow(); 303e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik mAttachedToWindow = true; 30411417b1cfde8f1749905f2d735623af9214148afJeff Brown 30511417b1cfde8f1749905f2d735623af9214148afJeff Brown mRouter.addCallback(MediaRouteSelector.EMPTY, mCallback, 30611417b1cfde8f1749905f2d735623af9214148afJeff Brown MediaRouter.CALLBACK_FLAG_UNFILTERED_EVENTS); 307e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik setMediaSession(mRouter.getMediaSessionToken()); 3086e547065f21f1645b3e9d5b3a3fd9720be8aede8Jaewan Kim onOrientationChanged(getContext().getResources().getConfiguration().orientation); 30911417b1cfde8f1749905f2d735623af9214148afJeff Brown } 31011417b1cfde8f1749905f2d735623af9214148afJeff Brown 31111417b1cfde8f1749905f2d735623af9214148afJeff Brown @Override 31211417b1cfde8f1749905f2d735623af9214148afJeff Brown public void onDetachedFromWindow() { 31311417b1cfde8f1749905f2d735623af9214148afJeff Brown mRouter.removeCallback(mCallback); 314e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik setMediaSession(null); 315e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik mAttachedToWindow = false; 31611417b1cfde8f1749905f2d735623af9214148afJeff Brown super.onDetachedFromWindow(); 31711417b1cfde8f1749905f2d735623af9214148afJeff Brown } 31811417b1cfde8f1749905f2d735623af9214148afJeff Brown 31911417b1cfde8f1749905f2d735623af9214148afJeff Brown @Override 32011417b1cfde8f1749905f2d735623af9214148afJeff Brown public boolean onKeyDown(int keyCode, KeyEvent event) { 321ce8cbd614a64f94e54b936d66ecd14b6c1282ddfJeff Brown if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN 322ce8cbd614a64f94e54b936d66ecd14b6c1282ddfJeff Brown || keyCode == KeyEvent.KEYCODE_VOLUME_UP) { 323ce8cbd614a64f94e54b936d66ecd14b6c1282ddfJeff Brown mRoute.requestUpdateVolume(keyCode == KeyEvent.KEYCODE_VOLUME_DOWN ? -1 : 1); 324ce8cbd614a64f94e54b936d66ecd14b6c1282ddfJeff Brown return true; 32511417b1cfde8f1749905f2d735623af9214148afJeff Brown } 32611417b1cfde8f1749905f2d735623af9214148afJeff Brown return super.onKeyDown(keyCode, event); 32711417b1cfde8f1749905f2d735623af9214148afJeff Brown } 32811417b1cfde8f1749905f2d735623af9214148afJeff Brown 32911417b1cfde8f1749905f2d735623af9214148afJeff Brown @Override 33011417b1cfde8f1749905f2d735623af9214148afJeff Brown public boolean onKeyUp(int keyCode, KeyEvent event) { 331ce8cbd614a64f94e54b936d66ecd14b6c1282ddfJeff Brown if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN 332ce8cbd614a64f94e54b936d66ecd14b6c1282ddfJeff Brown || keyCode == KeyEvent.KEYCODE_VOLUME_UP) { 333ce8cbd614a64f94e54b936d66ecd14b6c1282ddfJeff Brown return true; 33411417b1cfde8f1749905f2d735623af9214148afJeff Brown } 33511417b1cfde8f1749905f2d735623af9214148afJeff Brown return super.onKeyUp(keyCode, event); 33611417b1cfde8f1749905f2d735623af9214148afJeff Brown } 33711417b1cfde8f1749905f2d735623af9214148afJeff Brown 3387ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim private void update() { 33911417b1cfde8f1749905f2d735623af9214148afJeff Brown if (!mRoute.isSelected() || mRoute.isDefault()) { 34011417b1cfde8f1749905f2d735623af9214148afJeff Brown dismiss(); 3417ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim return; 34211417b1cfde8f1749905f2d735623af9214148afJeff Brown } 34394be6100218126ce6a08bf1f56209578500b361fRoboErik if (!mCreated) { 3447ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim return; 34594be6100218126ce6a08bf1f56209578500b361fRoboErik } 3462ef36d857302c5cd738c7c8bdec53d31feebebbaJeff Brown 3477ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim mRouteNameTextView.setText(mRoute.getName()); 3487ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim mDisconnectButton.setVisibility(mRoute.canDisconnect() ? View.VISIBLE : View.GONE); 34994be6100218126ce6a08bf1f56209578500b361fRoboErik 3507ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim if (mCustomControlView == null) { 351005482649154d0970693b3967241eb4d2cb22003Jaewan Kim if (mFetchArtTask != null) { 352005482649154d0970693b3967241eb4d2cb22003Jaewan Kim mFetchArtTask.cancel(true); 35366937fc7dfe22c8c505bf735781d1f5b62f08e34Dongwon Kang } 354005482649154d0970693b3967241eb4d2cb22003Jaewan Kim mFetchArtTask = new FetchArtTask(); 355005482649154d0970693b3967241eb4d2cb22003Jaewan Kim mFetchArtTask.execute(); 356f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah } 3577ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim mControlAdapter.updateVolumeControl(); 3587ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim mControlAdapter.updatePlaybackControl(); 359f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah } 360f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah 361f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah private boolean isVolumeControlAvailable() { 362f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah return mVolumeControlEnabled && mRoute.getVolumeHandling() == 363f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah MediaRouter.RouteInfo.PLAYBACK_VOLUME_VARIABLE; 364f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah } 365f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah 36613d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim private void updateArtView() { 36713d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim if (!(mArtView.getDrawable() instanceof BitmapDrawable)) { 368bfb90b6717bb46535d747aa50045a206965542d0Jae Seo mArtView.setVisibility(View.GONE); 36913d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim return; 37013d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim } 37113d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim Bitmap art = ((BitmapDrawable) mArtView.getDrawable()).getBitmap(); 37213d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim if (art == null) { 373bfb90b6717bb46535d747aa50045a206965542d0Jae Seo mArtView.setVisibility(View.GONE); 37413d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim return; 37513d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim } 37613d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim int desiredArtHeight = getDesiredArtHeight(art.getWidth(), art.getHeight()); 37713d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim DisplayMetrics displayMetrics = getContext().getResources().getDisplayMetrics(); 37813d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim int dialogWidth = displayMetrics.widthPixels < displayMetrics.heightPixels 37913d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim ? mDialogWidthPortrait : mDialogWidthLandscape; 38013d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim View decorView = getWindow().getDecorView(); 38113d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim decorView.measure(dialogWidth, View.MeasureSpec.UNSPECIFIED); 38213d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim // Show art if and only if it fits in the screen. 38313d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim if (mArtView.getVisibility() == View.GONE) { 38413d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim if (decorView.getMeasuredHeight() + desiredArtHeight <= displayMetrics.heightPixels) { 38513d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim mArtView.setVisibility(View.VISIBLE); 38613d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim mArtView.setMaxHeight(desiredArtHeight); 38713d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim } 38813d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim } else { 38913d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim if (decorView.getMeasuredHeight() - mArtView.getMeasuredHeight() + desiredArtHeight 39013d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim <= displayMetrics.heightPixels) { 39113d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim mArtView.setMaxHeight(desiredArtHeight); 39213d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim } else { 39313d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim mArtView.setVisibility(View.GONE); 39413d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim } 39513d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim } 39613d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim } 39713d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim 39813d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim /** 39913d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim * Returns desired art height to fit into controller dialog. 40013d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim */ 40113d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim private int getDesiredArtHeight(int originalWidth, int originalHeight) { 40213d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim int dialogWidth = getWindow().getAttributes().width - mDialogPaddingVertical; 40313d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim if (originalWidth >= originalHeight) { 40413d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim // For landscape art, fit width to dialog width. 4055716b49c08ac172c06fdced848ec8ab599174970Jaewan Kim return (int) ((float) dialogWidth * originalHeight / originalWidth + 0.5f); 40613d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim } 40713d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim // For portrait art, fit height to 16:9 ratio case's height. 4085716b49c08ac172c06fdced848ec8ab599174970Jaewan Kim return (int) ((float) dialogWidth * 9 / 16 + 0.5f); 40913d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim } 41013d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim 41111417b1cfde8f1749905f2d735623af9214148afJeff Brown private final class MediaRouterCallback extends MediaRouter.Callback { 41211417b1cfde8f1749905f2d735623af9214148afJeff Brown @Override 41311417b1cfde8f1749905f2d735623af9214148afJeff Brown public void onRouteUnselected(MediaRouter router, MediaRouter.RouteInfo route) { 41411417b1cfde8f1749905f2d735623af9214148afJeff Brown update(); 41511417b1cfde8f1749905f2d735623af9214148afJeff Brown } 41611417b1cfde8f1749905f2d735623af9214148afJeff Brown 41711417b1cfde8f1749905f2d735623af9214148afJeff Brown @Override 41811417b1cfde8f1749905f2d735623af9214148afJeff Brown public void onRouteChanged(MediaRouter router, MediaRouter.RouteInfo route) { 41911417b1cfde8f1749905f2d735623af9214148afJeff Brown update(); 42011417b1cfde8f1749905f2d735623af9214148afJeff Brown } 42111417b1cfde8f1749905f2d735623af9214148afJeff Brown 42211417b1cfde8f1749905f2d735623af9214148afJeff Brown @Override 42311417b1cfde8f1749905f2d735623af9214148afJeff Brown public void onRouteVolumeChanged(MediaRouter router, MediaRouter.RouteInfo route) { 42411417b1cfde8f1749905f2d735623af9214148afJeff Brown if (route == mRoute) { 4257ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim mControlAdapter.updateVolumeControl(); 42694be6100218126ce6a08bf1f56209578500b361fRoboErik } 42794be6100218126ce6a08bf1f56209578500b361fRoboErik } 42894be6100218126ce6a08bf1f56209578500b361fRoboErik } 42994be6100218126ce6a08bf1f56209578500b361fRoboErik 43094be6100218126ce6a08bf1f56209578500b361fRoboErik private final class MediaControllerCallback extends MediaControllerCompat.Callback { 43194be6100218126ce6a08bf1f56209578500b361fRoboErik @Override 43294be6100218126ce6a08bf1f56209578500b361fRoboErik public void onSessionDestroyed() { 43394be6100218126ce6a08bf1f56209578500b361fRoboErik if (mMediaController != null) { 43494be6100218126ce6a08bf1f56209578500b361fRoboErik mMediaController.unregisterCallback(mControllerCallback); 43594be6100218126ce6a08bf1f56209578500b361fRoboErik mMediaController = null; 43694be6100218126ce6a08bf1f56209578500b361fRoboErik } 43794be6100218126ce6a08bf1f56209578500b361fRoboErik } 43894be6100218126ce6a08bf1f56209578500b361fRoboErik 43994be6100218126ce6a08bf1f56209578500b361fRoboErik @Override 44094be6100218126ce6a08bf1f56209578500b361fRoboErik public void onPlaybackStateChanged(PlaybackStateCompat state) { 44194be6100218126ce6a08bf1f56209578500b361fRoboErik mState = state; 44294be6100218126ce6a08bf1f56209578500b361fRoboErik update(); 44394be6100218126ce6a08bf1f56209578500b361fRoboErik } 44494be6100218126ce6a08bf1f56209578500b361fRoboErik 44594be6100218126ce6a08bf1f56209578500b361fRoboErik @Override 44694be6100218126ce6a08bf1f56209578500b361fRoboErik public void onMetadataChanged(MediaMetadataCompat metadata) { 44794be6100218126ce6a08bf1f56209578500b361fRoboErik mDescription = metadata == null ? null : metadata.getDescription(); 44894be6100218126ce6a08bf1f56209578500b361fRoboErik update(); 44994be6100218126ce6a08bf1f56209578500b361fRoboErik } 45094be6100218126ce6a08bf1f56209578500b361fRoboErik } 45194be6100218126ce6a08bf1f56209578500b361fRoboErik 45294be6100218126ce6a08bf1f56209578500b361fRoboErik private final class ClickListener implements View.OnClickListener { 45394be6100218126ce6a08bf1f56209578500b361fRoboErik @Override 45494be6100218126ce6a08bf1f56209578500b361fRoboErik public void onClick(View v) { 45594be6100218126ce6a08bf1f56209578500b361fRoboErik int id = v.getId(); 45694be6100218126ce6a08bf1f56209578500b361fRoboErik if (id == R.id.stop || id == R.id.disconnect) { 45794be6100218126ce6a08bf1f56209578500b361fRoboErik if (mRoute.isSelected()) { 45894be6100218126ce6a08bf1f56209578500b361fRoboErik mRouter.unselect(id == R.id.stop ? 45994be6100218126ce6a08bf1f56209578500b361fRoboErik MediaRouter.UNSELECT_REASON_STOPPED : 46094be6100218126ce6a08bf1f56209578500b361fRoboErik MediaRouter.UNSELECT_REASON_DISCONNECTED); 46194be6100218126ce6a08bf1f56209578500b361fRoboErik } 46294be6100218126ce6a08bf1f56209578500b361fRoboErik dismiss(); 4637ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim } else if (id == R.id.mr_control_play_pause) { 46494be6100218126ce6a08bf1f56209578500b361fRoboErik if (mMediaController != null && mState != null) { 46594be6100218126ce6a08bf1f56209578500b361fRoboErik if (mState.getState() == PlaybackStateCompat.STATE_PLAYING) { 46694be6100218126ce6a08bf1f56209578500b361fRoboErik mMediaController.getTransportControls().pause(); 46794be6100218126ce6a08bf1f56209578500b361fRoboErik } else { 46894be6100218126ce6a08bf1f56209578500b361fRoboErik mMediaController.getTransportControls().play(); 46994be6100218126ce6a08bf1f56209578500b361fRoboErik } 47094be6100218126ce6a08bf1f56209578500b361fRoboErik } 471b48ccf48b0281e69262fc643d0def898aede407bSungsoo Lim } else if (id == R.id.close) { 472b48ccf48b0281e69262fc643d0def898aede407bSungsoo Lim dismiss(); 47311417b1cfde8f1749905f2d735623af9214148afJeff Brown } 47411417b1cfde8f1749905f2d735623af9214148afJeff Brown } 47511417b1cfde8f1749905f2d735623af9214148afJeff Brown } 476005482649154d0970693b3967241eb4d2cb22003Jaewan Kim 4777ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim // TODO: Consider to implement the default controls using LinearLayout instead of ListView. 4787ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim private class MediaRouteControlAdapter extends ArrayAdapter<View> { 4797ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim private List<View> mItemViews; 4807ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim 4817ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim private RelativeLayout mPlaybackControl; 4827ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim private TextView mTitleView; 4837ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim private TextView mSubtitleView; 4847ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim private ImageButton mPlayPauseButton; 4857ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim 4867ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim private LinearLayout mVolumeControl; 4877ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim private SeekBar mVolumeSlider; 4887ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim private ImageButton mGroupExpandCollapseButton; 4897ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim private boolean mVolumeSliderTouched; 4907ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim 4917ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim 4927ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim public MediaRouteControlAdapter(Context context, List<View> itemViews, 4937ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim ClickListener listener) { 4947ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim super(context, 0, itemViews); 4957ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim mItemViews = itemViews; 4967ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim 4977ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim mPlaybackControl = (RelativeLayout) LayoutInflater.from(context).inflate( 4987ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim R.layout.mr_playback_control, mControlView); 4997ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim mTitleView = (TextView) mPlaybackControl.findViewById(R.id.mr_control_title); 5007ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim mSubtitleView = (TextView) mPlaybackControl.findViewById(R.id.mr_control_subtitle); 5017ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim mPlayPauseButton = (ImageButton) mPlaybackControl.findViewById( 5027ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim R.id.mr_control_play_pause); 5037ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim mPlayPauseButton.setOnClickListener(listener); 5047ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim 5057ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim mVolumeControl = (LinearLayout) LayoutInflater.from(context).inflate( 5067ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim R.layout.mr_volume_control, mControlView); 5077ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim mVolumeSlider = (SeekBar) mVolumeControl.findViewById(R.id.mr_volume_slider); 5087ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim mVolumeSlider.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { 5097ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim private final Runnable mStopTrackingTouch = new Runnable() { 5107ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim @Override 5117ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim public void run() { 5127ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim if (mVolumeSliderTouched) { 5137ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim mVolumeSliderTouched = false; 5147ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim updateVolumeControl(); 5157ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim } 5167ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim } 5177ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim }; 5187ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim 5197ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim @Override 5207ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim public void onStartTrackingTouch(SeekBar seekBar) { 5217ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim if (mVolumeSliderTouched) { 5227ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim mVolumeSlider.removeCallbacks(mStopTrackingTouch); 5237ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim } else { 5247ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim mVolumeSliderTouched = true; 5257ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim } 5267ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim } 5277ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim 5287ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim @Override 5297ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim public void onStopTrackingTouch(SeekBar seekBar) { 5307ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim // Defer resetting mVolumeSliderTouched to allow the media route provider 5317ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim // a little time to settle into its new state and publish the final 5327ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim // volume update. 5337ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim mVolumeSlider.postDelayed(mStopTrackingTouch, VOLUME_UPDATE_DELAY_MILLIS); 5347ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim } 5357ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim 5367ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim @Override 5377ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { 5387ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim if (fromUser) { 5397ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim mRoute.requestSetVolume(progress); 5407ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim } 5417ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim } 5427ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim }); 5437ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim 5447ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim TypedArray styledAttributes = context.obtainStyledAttributes(new int[] { 5457ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim R.attr.mediaRouteExpandGroupDrawable, 5467ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim R.attr.mediaRouteCollapseGroupDrawable 5477ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim }); 5487ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim final Drawable expandGroupDrawable = styledAttributes.getDrawable(0); 5497ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim final Drawable collapseGroupDrawable = styledAttributes.getDrawable(1); 5507ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim styledAttributes.recycle(); 5517ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim 5527ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim mGroupExpandCollapseButton = (ImageButton) mVolumeControl.findViewById( 5537ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim R.id.mr_group_expand_collapse); 5547ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim mGroupExpandCollapseButton.setOnClickListener(new View.OnClickListener() { 5557ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim private boolean mIsExpanded; 5567ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim 5577ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim @Override 5587ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim public void onClick(View v) { 5597ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim mIsExpanded = !mIsExpanded; 5607ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim if (mIsExpanded) { 5617ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim mGroupExpandCollapseButton.setImageDrawable(collapseGroupDrawable); 5627ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim mVolumeGroupList.setVisibility(View.VISIBLE); 5637ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim mVolumeGroupList.setAdapter( 5647ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim new VolumeGroupAdapter(getContext(), getGroup().getRoutes())); 5657ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim } else { 5667ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim mGroupExpandCollapseButton.setImageDrawable(expandGroupDrawable); 5677ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim mVolumeGroupList.setVisibility(View.GONE); 5687ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim } 5697ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim } 5707ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim }); 5717ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim } 5727ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim 5737ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim @Override 5747ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim public View getView(final int position, View convertView, ViewGroup parent) { 5757ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim return mItemViews.get(position); 5767ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim } 5777ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim 5787ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim public void updateVolumeControl() { 5797ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim if (!mVolumeSliderTouched) { 5807ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim if (isVolumeControlAvailable()) { 5817ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim if (!mItemViews.contains(mVolumeControl)) { 5827ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim mItemViews.add(mVolumeControl); 5837ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim 5847ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim notifyDataSetChanged(); 5857ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim } 5867ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim mVolumeSlider.setMax(mRoute.getVolumeMax()); 5877ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim mVolumeSlider.setProgress(mRoute.getVolume()); 5887ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim if (USE_GROUP) { 5897ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim if (getGroup() == null) { 5907ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim mGroupExpandCollapseButton.setVisibility(View.GONE); 5917ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim } else { 5927ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim mGroupExpandCollapseButton.setVisibility(View.VISIBLE); 5937ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim VolumeGroupAdapter adapter = 5947ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim (VolumeGroupAdapter) mVolumeGroupList.getAdapter(); 5957ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim if (adapter != null) { 5967ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim adapter.notifyDataSetChanged(); 5977ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim } 5987ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim } 5997ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim } 6007ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim } else if (mItemViews.contains(mVolumeControl)) { 6017ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim mItemViews.remove(mVolumeControl); 6027ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim notifyDataSetChanged(); 6037ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim } 6044bae6b7e7005d631aed69b13cf0abb5dbff64802Dongwon Kang mControlView.setVisibility(mItemViews.isEmpty() ? View.GONE : View.VISIBLE); 6057ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim } 6067ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim } 6077ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim 6087ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim public void updatePlaybackControl() { 6094bae6b7e7005d631aed69b13cf0abb5dbff64802Dongwon Kang if (mCustomControlView == null && (mDescription != null || mState != null)) { 6107ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim if (!mItemViews.contains(mPlaybackControl)) { 6117ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim mItemViews.add(0, mPlaybackControl); 6127ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim notifyDataSetChanged(); 6137ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim } 6147ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim CharSequence title = mDescription == null ? null : mDescription.getTitle(); 6157ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim boolean hasTitle = !TextUtils.isEmpty(title); 6167ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim 6177ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim CharSequence subtitle = mDescription == null ? null : mDescription.getSubtitle(); 6187ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim boolean hasSubtitle = !TextUtils.isEmpty(subtitle); 6197ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim 6207ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim if (!hasTitle && !hasSubtitle) { 62177367b4a1871417198d0399d9ad074314c758567Jae Seo if (mRoute.getPresentationDisplayId() 62277367b4a1871417198d0399d9ad074314c758567Jae Seo != MediaRouter.RouteInfo.PRESENTATION_DISPLAY_ID_NONE) { 62377367b4a1871417198d0399d9ad074314c758567Jae Seo // The user is currently casting screen. 62477367b4a1871417198d0399d9ad074314c758567Jae Seo mTitleView.setText(R.string.mr_controller_casting_screen); 62577367b4a1871417198d0399d9ad074314c758567Jae Seo } else { 62677367b4a1871417198d0399d9ad074314c758567Jae Seo mTitleView.setText(R.string.mr_controller_no_info_available); 62777367b4a1871417198d0399d9ad074314c758567Jae Seo } 6287ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim mTitleView.setEnabled(false); 6297ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim mTitleView.setVisibility(View.VISIBLE); 6307ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim mSubtitleView.setVisibility(View.GONE); 6317ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim } else { 6327ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim mTitleView.setText(title); 6337ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim mTitleView.setEnabled(hasTitle); 6347ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim mTitleView.setVisibility(hasTitle ? View.VISIBLE : View.GONE); 6357ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim mSubtitleView.setText(subtitle); 6367ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim mSubtitleView.setVisibility(hasSubtitle ? View.VISIBLE : View.GONE); 6377ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim } 6387ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim if (mState != null) { 6397ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim boolean isPlaying = mState.getState() == PlaybackStateCompat.STATE_BUFFERING 6407ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim || mState.getState() == PlaybackStateCompat.STATE_PLAYING; 6417ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim boolean supportsPlay = (mState.getActions() & (PlaybackStateCompat.ACTION_PLAY 6427ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim | PlaybackStateCompat.ACTION_PLAY_PAUSE)) != 0; 6437ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim boolean supportsPause = (mState.getActions() & (PlaybackStateCompat.ACTION_PAUSE 6447ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim | PlaybackStateCompat.ACTION_PLAY_PAUSE)) != 0; 6457ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim if (isPlaying && supportsPause) { 6467ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim mPlayPauseButton.setVisibility(View.VISIBLE); 6477ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim mPlayPauseButton.setImageResource(MediaRouterThemeHelper.getThemeResource( 6487ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim getContext(), R.attr.mediaRoutePauseDrawable)); 6497ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim mPlayPauseButton.setContentDescription(getContext().getResources() 6507ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim .getText(R.string.mr_controller_pause)); 6517ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim } else if (!isPlaying && supportsPlay) { 6527ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim mPlayPauseButton.setVisibility(View.VISIBLE); 6537ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim mPlayPauseButton.setImageResource(MediaRouterThemeHelper.getThemeResource( 6547ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim getContext(), R.attr.mediaRoutePlayDrawable)); 6557ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim mPlayPauseButton.setContentDescription(getContext().getResources() 6567ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim .getText(R.string.mr_controller_play)); 6577ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim } else { 6587ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim mPlayPauseButton.setVisibility(View.GONE); 6597ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim } 6607ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim } 6617ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim } else if (mItemViews.contains(mPlaybackControl)) { 6627ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim mItemViews.remove(mPlaybackControl); 6637ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim notifyDataSetChanged(); 6647ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim } 6654bae6b7e7005d631aed69b13cf0abb5dbff64802Dongwon Kang mControlView.setVisibility(mItemViews.isEmpty() ? View.GONE : View.VISIBLE); 6667ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim } 6677ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim } 6687ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim 6696051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo private class VolumeGroupAdapter extends ArrayAdapter<MediaRouter.RouteInfo> { 6700e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo final static float DISABLED_ALPHA = .3f; 6710e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo 6726051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo final OnSeekBarChangeListener mOnSeekBarChangeListener = new OnSeekBarChangeListener() { 6736051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo @Override 6746051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { 6756051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo if (fromUser) { 6766051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo int position = (int) seekBar.getTag(); 6776051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo getGroup().getRouteAt(position).requestSetVolume(progress); 6786051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo } 6796051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo } 6806051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo 6816051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo @Override 6826051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo public void onStartTrackingTouch(SeekBar seekBar) { 6836051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo // TODO: Implement 6846051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo } 6856051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo 6866051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo @Override 6876051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo public void onStopTrackingTouch(SeekBar seekBar) { 6886051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo // TODO: Implement 6896051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo } 6906051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo }; 6916051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo 6926051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo public VolumeGroupAdapter(Context context, List<MediaRouter.RouteInfo> objects) { 6936051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo super(context, 0, objects); 6946051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo } 6956051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo 6966051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo @Override 6976051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo public View getView(final int position, View convertView, ViewGroup parent) { 6986051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo View v = convertView; 6996051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo if (v == null) { 7006051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo v = LayoutInflater.from(getContext()).inflate( 701a09c7b30d3a5c53281db955eabce171e1aec6feaSungsoo Lim R.layout.mr_controller_volume_item, null); 7026051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo } 7036051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo MediaRouter.RouteInfo route = getItem(position); 7046051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo if (route != null) { 7050e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo boolean isEnabled = route.isEnabled(); 7060e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo 7077ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim TextView routeName = (TextView) v.findViewById(R.id.mr_name); 7080e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo routeName.setEnabled(isEnabled); 7090e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo routeName.setText(route.getName()); 7106051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo 7117ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim SeekBar volumeSlider = (SeekBar) v.findViewById(R.id.mr_volume_slider); 7120e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo volumeSlider.setEnabled(isEnabled); 7136051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo volumeSlider.setTag(position); 7140e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo if (isEnabled) { 7150e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo if (route.getVolumeHandling() 7160e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo == MediaRouter.RouteInfo.PLAYBACK_VOLUME_VARIABLE) { 7170e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo volumeSlider.setMax(route.getVolumeMax()); 7180e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo volumeSlider.setProgress(route.getVolume()); 7190e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo volumeSlider.setOnSeekBarChangeListener(mOnSeekBarChangeListener); 7200e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo } else { 7210e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo volumeSlider.setMax(100); 7220e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo volumeSlider.setProgress(100); 7230e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo volumeSlider.setEnabled(false); 7240e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo } 7250e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo } 7260e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo // TODO: Find a way to hide the scroll thumb. 7270e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo // if (Build.VERSION.SDK_INT >= 16) { 7280e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo // volumeSlider.getThumb().setAlpha(isEnabled ? 255 : 0); 7290e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo // } 7300e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo 7310e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo ImageView volumeItemIcon = 7327ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim (ImageView) v.findViewById(R.id.mr_volume_item_icon); 73377367b4a1871417198d0399d9ad074314c758567Jae Seo volumeItemIcon.setAlpha(isEnabled ? 255 : (int) (255 * DISABLED_ALPHA)); 7346051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo } 7356051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo return v; 7366051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo } 7376051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo } 7386051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo 739005482649154d0970693b3967241eb4d2cb22003Jaewan Kim private class FetchArtTask extends AsyncTask<Void, Void, Bitmap> { 740005482649154d0970693b3967241eb4d2cb22003Jaewan Kim private int mBackgroundColor; 741005482649154d0970693b3967241eb4d2cb22003Jaewan Kim 742005482649154d0970693b3967241eb4d2cb22003Jaewan Kim @Override 743005482649154d0970693b3967241eb4d2cb22003Jaewan Kim protected Bitmap doInBackground(Void... arg) { 74413d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim Bitmap art = null; 745005482649154d0970693b3967241eb4d2cb22003Jaewan Kim if (mDescription == null) { 746005482649154d0970693b3967241eb4d2cb22003Jaewan Kim return null; 747005482649154d0970693b3967241eb4d2cb22003Jaewan Kim } 748005482649154d0970693b3967241eb4d2cb22003Jaewan Kim if (mDescription.getIconBitmap() != null) { 74913d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim art = mDescription.getIconBitmap(); 750005482649154d0970693b3967241eb4d2cb22003Jaewan Kim } else if (mDescription.getIconUri() != null) { 751005482649154d0970693b3967241eb4d2cb22003Jaewan Kim Uri iconUri = mDescription.getIconUri(); 752005482649154d0970693b3967241eb4d2cb22003Jaewan Kim String scheme = iconUri.getScheme(); 753005482649154d0970693b3967241eb4d2cb22003Jaewan Kim if (!(ContentResolver.SCHEME_ANDROID_RESOURCE.equals(scheme) 754005482649154d0970693b3967241eb4d2cb22003Jaewan Kim || ContentResolver.SCHEME_CONTENT.equals(scheme) 755005482649154d0970693b3967241eb4d2cb22003Jaewan Kim || ContentResolver.SCHEME_FILE.equals(scheme))) { 756005482649154d0970693b3967241eb4d2cb22003Jaewan Kim Log.w(TAG, "Icon Uri should point to local resources."); 757005482649154d0970693b3967241eb4d2cb22003Jaewan Kim return null; 758005482649154d0970693b3967241eb4d2cb22003Jaewan Kim } 759005482649154d0970693b3967241eb4d2cb22003Jaewan Kim BufferedInputStream stream = null; 760005482649154d0970693b3967241eb4d2cb22003Jaewan Kim try { 761005482649154d0970693b3967241eb4d2cb22003Jaewan Kim stream = new BufferedInputStream( 762005482649154d0970693b3967241eb4d2cb22003Jaewan Kim getContext().getContentResolver().openInputStream(iconUri)); 763005482649154d0970693b3967241eb4d2cb22003Jaewan Kim 76413d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim // Query art size. 765005482649154d0970693b3967241eb4d2cb22003Jaewan Kim BitmapFactory.Options options = new BitmapFactory.Options(); 766005482649154d0970693b3967241eb4d2cb22003Jaewan Kim options.inJustDecodeBounds = true; 767005482649154d0970693b3967241eb4d2cb22003Jaewan Kim BitmapFactory.decodeStream(stream, null, options); 76813d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim if (options.outWidth == 0 || options.outHeight == 0) { 76913d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim return null; 77013d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim } 77113d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim // Rewind the stream in order to restart art decoding. 772005482649154d0970693b3967241eb4d2cb22003Jaewan Kim try { 773005482649154d0970693b3967241eb4d2cb22003Jaewan Kim stream.reset(); 774005482649154d0970693b3967241eb4d2cb22003Jaewan Kim } catch (IOException e) { 775005482649154d0970693b3967241eb4d2cb22003Jaewan Kim // Failed to rewind the stream, try to reopen it. 776005482649154d0970693b3967241eb4d2cb22003Jaewan Kim stream.close(); 777005482649154d0970693b3967241eb4d2cb22003Jaewan Kim stream = new BufferedInputStream(getContext().getContentResolver() 778005482649154d0970693b3967241eb4d2cb22003Jaewan Kim .openInputStream(iconUri)); 779005482649154d0970693b3967241eb4d2cb22003Jaewan Kim } 78013d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim // Calculate required size to decode the art and possibly resize it. 781005482649154d0970693b3967241eb4d2cb22003Jaewan Kim options.inJustDecodeBounds = false; 78213d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim int reqHeight = getDesiredArtHeight(options.outWidth, options.outHeight); 78313d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim int ratio = options.outHeight / reqHeight; 784005482649154d0970693b3967241eb4d2cb22003Jaewan Kim options.inSampleSize = Math.max(1, Integer.highestOneBit(ratio)); 785005482649154d0970693b3967241eb4d2cb22003Jaewan Kim if (isCancelled()) { 786005482649154d0970693b3967241eb4d2cb22003Jaewan Kim return null; 787005482649154d0970693b3967241eb4d2cb22003Jaewan Kim } 78813d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim art = BitmapFactory.decodeStream(stream, null, options); 789005482649154d0970693b3967241eb4d2cb22003Jaewan Kim } catch (IOException e){ 790005482649154d0970693b3967241eb4d2cb22003Jaewan Kim Log.w(TAG, "Unable to open content: " + iconUri, e); 791005482649154d0970693b3967241eb4d2cb22003Jaewan Kim } finally { 792005482649154d0970693b3967241eb4d2cb22003Jaewan Kim if (stream != null) { 793005482649154d0970693b3967241eb4d2cb22003Jaewan Kim try { 794005482649154d0970693b3967241eb4d2cb22003Jaewan Kim stream.close(); 795005482649154d0970693b3967241eb4d2cb22003Jaewan Kim } catch (IOException e) { 796005482649154d0970693b3967241eb4d2cb22003Jaewan Kim } 797005482649154d0970693b3967241eb4d2cb22003Jaewan Kim } 798005482649154d0970693b3967241eb4d2cb22003Jaewan Kim } 799005482649154d0970693b3967241eb4d2cb22003Jaewan Kim } 800145e93b13dd025b278665494e7be0c15b8df5986Jaewan Kim if (art != null && art.getWidth() < art.getHeight()) { 801145e93b13dd025b278665494e7be0c15b8df5986Jaewan Kim // Portrait art requires background color. 802145e93b13dd025b278665494e7be0c15b8df5986Jaewan Kim Palette palette = new Palette.Builder(art).maximumColorCount(1).generate(); 803145e93b13dd025b278665494e7be0c15b8df5986Jaewan Kim mBackgroundColor = (palette.getSwatches() == null) 804145e93b13dd025b278665494e7be0c15b8df5986Jaewan Kim ? 0 : palette.getSwatches().get(0).getRgb(); 805005482649154d0970693b3967241eb4d2cb22003Jaewan Kim } 80613d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim return art; 807005482649154d0970693b3967241eb4d2cb22003Jaewan Kim } 808005482649154d0970693b3967241eb4d2cb22003Jaewan Kim 809005482649154d0970693b3967241eb4d2cb22003Jaewan Kim @Override 810005482649154d0970693b3967241eb4d2cb22003Jaewan Kim protected void onCancelled() { 811005482649154d0970693b3967241eb4d2cb22003Jaewan Kim mFetchArtTask = null; 812005482649154d0970693b3967241eb4d2cb22003Jaewan Kim } 813005482649154d0970693b3967241eb4d2cb22003Jaewan Kim 814005482649154d0970693b3967241eb4d2cb22003Jaewan Kim @Override 81513d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim protected void onPostExecute(Bitmap art) { 816005482649154d0970693b3967241eb4d2cb22003Jaewan Kim mFetchArtTask = null; 81713d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim mArtView.setImageBitmap(art); 81813d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim mArtView.setBackgroundColor(mBackgroundColor); 81913d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim updateArtView(); 820005482649154d0970693b3967241eb4d2cb22003Jaewan Kim } 821005482649154d0970693b3967241eb4d2cb22003Jaewan Kim } 8226051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo} 823