2525import android .app .MediaRouteButton ;
2626import android .content .Context ;
2727import android .graphics .drawable .Drawable ;
28+ import android .media .AudioManager ;
2829import android .media .MediaRouter ;
2930import android .media .MediaRouter .RouteCategory ;
3031import android .media .MediaRouter .RouteGroup ;
3132import android .media .MediaRouter .RouteInfo ;
33+ import android .media .MediaRouter .UserRouteInfo ;
34+ import android .media .RemoteControlClient ;
3235import android .os .Bundle ;
3336import android .text .TextUtils ;
37+ import android .view .KeyEvent ;
3438import android .view .LayoutInflater ;
3539import android .view .View ;
3640import android .view .ViewGroup ;
4145import android .widget .ImageButton ;
4246import android .widget .ImageView ;
4347import android .widget .ListView ;
48+ import android .widget .SeekBar ;
4449import android .widget .TextView ;
4550
4651import java .util .ArrayList ;
@@ -67,15 +72,20 @@ public class MediaRouteChooserDialogFragment extends DialogFragment {
6772 };
6873
6974 MediaRouter mRouter ;
75+ AudioManager mAudio ;
7076 private int mRouteTypes ;
7177
7278 private LayoutInflater mInflater ;
7379 private LauncherListener mLauncherListener ;
7480 private View .OnClickListener mExtendedSettingsListener ;
7581 private RouteAdapter mAdapter ;
7682 private ListView mListView ;
83+ private SeekBar mVolumeSlider ;
84+ private ImageView mVolumeIcon ;
7785
7886 final RouteComparator mComparator = new RouteComparator ();
87+ final MediaRouterCallback mCallback = new MediaRouterCallback ();
88+ private boolean mIgnoreVolumeChanges ;
7989
8090 public MediaRouteChooserDialogFragment () {
8191 setStyle (STYLE_NO_TITLE , R .style .Theme_DeviceDefault_Dialog );
@@ -89,6 +99,7 @@ public void setLauncherListener(LauncherListener listener) {
8999 public void onAttach (Activity activity ) {
90100 super .onAttach (activity );
91101 mRouter = (MediaRouter ) activity .getSystemService (Context .MEDIA_ROUTER_SERVICE );
102+ mAudio = (AudioManager ) activity .getSystemService (Context .AUDIO_SERVICE );
92103 }
93104
94105 @ Override
@@ -98,20 +109,13 @@ public void onDetach() {
98109 mLauncherListener .onDetached (this );
99110 }
100111 if (mAdapter != null ) {
101- mRouter .removeCallback (mAdapter .mCallback );
102112 mAdapter = null ;
103113 }
104114 mInflater = null ;
115+ mRouter .removeCallback (mCallback );
105116 mRouter = null ;
106117 }
107118
108- /**
109- * Implemented by the MediaRouteButton that launched this dialog
110- */
111- public interface LauncherListener {
112- public void onDetached (MediaRouteChooserDialogFragment detachedFragment );
113- }
114-
115119 public void setExtendedSettingsClickListener (View .OnClickListener listener ) {
116120 mExtendedSettingsListener = listener ;
117121 }
@@ -120,14 +124,70 @@ public void setRouteTypes(int types) {
120124 mRouteTypes = types ;
121125 }
122126
127+ void updateVolume () {
128+ final RouteInfo selectedRoute = mRouter .getSelectedRoute (mRouteTypes );
129+ final boolean defaultAudioSelected = selectedRoute == mRouter .getSystemAudioRoute ();
130+ final boolean selectedSystemRoute =
131+ selectedRoute .getCategory () == mRouter .getSystemAudioCategory ();
132+ mVolumeIcon .setImageResource (defaultAudioSelected ?
133+ R .drawable .ic_audio_vol : R .drawable .ic_media_route_on_holo_dark );
134+
135+ mIgnoreVolumeChanges = true ;
136+ mVolumeSlider .setEnabled (true );
137+ if (selectedSystemRoute ) {
138+ // Use the standard media audio stream
139+ mVolumeSlider .setMax (mAudio .getStreamMaxVolume (AudioManager .STREAM_MUSIC ));
140+ mVolumeSlider .setProgress (mAudio .getStreamVolume (AudioManager .STREAM_MUSIC ));
141+ } else {
142+ final RouteInfo firstSelected ;
143+ if (selectedRoute instanceof RouteGroup ) {
144+ firstSelected = ((RouteGroup ) selectedRoute ).getRouteAt (0 );
145+ } else {
146+ firstSelected = selectedRoute ;
147+ }
148+
149+ RemoteControlClient rcc = null ;
150+ if (firstSelected instanceof UserRouteInfo ) {
151+ rcc = ((UserRouteInfo ) firstSelected ).getRemoteControlClient ();
152+ }
153+
154+ if (rcc == null ) {
155+ // No RemoteControlClient? Assume volume can't be controlled.
156+ // Disable the slider and show it at max volume.
157+ mVolumeSlider .setMax (1 );
158+ mVolumeSlider .setProgress (1 );
159+ mVolumeSlider .setEnabled (false );
160+ } else {
161+ // TODO: Connect this to the remote control volume
162+ }
163+ }
164+ mIgnoreVolumeChanges = false ;
165+ }
166+
167+ void changeVolume (int newValue ) {
168+ if (mIgnoreVolumeChanges ) return ;
169+
170+ RouteCategory selectedCategory = mRouter .getSelectedRoute (mRouteTypes ).getCategory ();
171+ if (selectedCategory == mRouter .getSystemAudioCategory ()) {
172+ final int maxVolume = mAudio .getStreamMaxVolume (AudioManager .STREAM_MUSIC );
173+ newValue = Math .max (0 , Math .min (newValue , maxVolume ));
174+ mAudio .setStreamVolume (AudioManager .STREAM_MUSIC , newValue , 0 );
175+ }
176+ }
177+
123178 @ Override
124179 public View onCreateView (LayoutInflater inflater , ViewGroup container ,
125180 Bundle savedInstanceState ) {
126181 mInflater = inflater ;
127182 final View layout = inflater .inflate (R .layout .media_route_chooser_layout , container , false );
128- final View extendedSettingsButton = layout .findViewById (R .id .extended_settings );
183+
184+ mVolumeIcon = (ImageView ) layout .findViewById (R .id .volume_icon );
185+ mVolumeSlider = (SeekBar ) layout .findViewById (R .id .volume_slider );
186+ updateVolume ();
187+ mVolumeSlider .setOnSeekBarChangeListener (new VolumeSliderChangeListener ());
129188
130189 if (mExtendedSettingsListener != null ) {
190+ final View extendedSettingsButton = layout .findViewById (R .id .extended_settings );
131191 extendedSettingsButton .setVisibility (View .VISIBLE );
132192 extendedSettingsButton .setOnClickListener (mExtendedSettingsListener );
133193 }
@@ -138,7 +198,7 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container,
138198 list .setOnItemClickListener (mAdapter );
139199
140200 mListView = list ;
141- mRouter .addCallback (mRouteTypes , mAdapter . mCallback );
201+ mRouter .addCallback (mRouteTypes , mCallback );
142202
143203 mAdapter .scrollToSelectedItem ();
144204
@@ -174,7 +234,6 @@ private class RouteAdapter extends BaseAdapter implements ListView.OnItemClickLi
174234
175235 private int mSelectedItemPosition = -1 ;
176236 private final ArrayList <Object > mItems = new ArrayList <Object >();
177- final MediaRouterCallback mCallback = new MediaRouterCallback ();
178237
179238 private RouteCategory mCategoryEditingGroups ;
180239 private RouteGroup mEditingGroup ;
@@ -443,10 +502,6 @@ void bindHeaderView(int position, ViewHolder holder) {
443502 holder .text1 .setText (cat .getName (getActivity ()));
444503 }
445504
446- public int getSelectedRoutePosition () {
447- return mSelectedItemPosition ;
448- }
449-
450505 @ Override
451506 public void onItemClick (AdapterView <?> parent , View view , int position , long id ) {
452507 final int type = getItemViewType (position );
@@ -523,46 +578,49 @@ public void onClick(View v) {
523578 scrollToEditingGroup ();
524579 }
525580 }
581+ }
526582
527- class MediaRouterCallback extends MediaRouter .Callback {
528- @ Override
529- public void onRouteSelected (MediaRouter router , int type , RouteInfo info ) {
530- update ();
531- }
583+ class MediaRouterCallback extends MediaRouter .Callback {
584+ @ Override
585+ public void onRouteSelected (MediaRouter router , int type , RouteInfo info ) {
586+ mAdapter .update ();
587+ updateVolume ();
588+ }
532589
533- @ Override
534- public void onRouteUnselected (MediaRouter router , int type , RouteInfo info ) {
535- update ();
536- }
590+ @ Override
591+ public void onRouteUnselected (MediaRouter router , int type , RouteInfo info ) {
592+ mAdapter . update ();
593+ }
537594
538- @ Override
539- public void onRouteAdded (MediaRouter router , RouteInfo info ) {
540- update ();
541- }
595+ @ Override
596+ public void onRouteAdded (MediaRouter router , RouteInfo info ) {
597+ mAdapter .update ();
598+ updateVolume ();
599+ }
542600
543- @ Override
544- public void onRouteRemoved (MediaRouter router , RouteInfo info ) {
545- if (info == mEditingGroup ) {
546- finishGrouping ();
547- }
548- update ();
601+ @ Override
602+ public void onRouteRemoved (MediaRouter router , RouteInfo info ) {
603+ if (info == mAdapter .mEditingGroup ) {
604+ mAdapter .finishGrouping ();
549605 }
606+ mAdapter .update ();
607+ updateVolume ();
608+ }
550609
551- @ Override
552- public void onRouteChanged (MediaRouter router , RouteInfo info ) {
553- notifyDataSetChanged ();
554- }
610+ @ Override
611+ public void onRouteChanged (MediaRouter router , RouteInfo info ) {
612+ mAdapter . notifyDataSetChanged ();
613+ }
555614
556- @ Override
557- public void onRouteGrouped (MediaRouter router , RouteInfo info ,
558- RouteGroup group , int index ) {
559- update ();
560- }
615+ @ Override
616+ public void onRouteGrouped (MediaRouter router , RouteInfo info ,
617+ RouteGroup group , int index ) {
618+ mAdapter . update ();
619+ }
561620
562- @ Override
563- public void onRouteUngrouped (MediaRouter router , RouteInfo info , RouteGroup group ) {
564- update ();
565- }
621+ @ Override
622+ public void onRouteUngrouped (MediaRouter router , RouteInfo info , RouteGroup group ) {
623+ mAdapter .update ();
566624 }
567625 }
568626
@@ -587,5 +645,41 @@ public void onBackPressed() {
587645 super .onBackPressed ();
588646 }
589647 }
648+
649+ public boolean onKeyDown (int keyCode , KeyEvent event ) {
650+ if (keyCode == KeyEvent .KEYCODE_VOLUME_DOWN && mVolumeSlider .isEnabled ()) {
651+ mVolumeSlider .incrementProgressBy (-1 );
652+ return true ;
653+ } else if (keyCode == KeyEvent .KEYCODE_VOLUME_UP && mVolumeSlider .isEnabled ()) {
654+ mVolumeSlider .incrementProgressBy (1 );
655+ return true ;
656+ } else {
657+ return super .onKeyDown (keyCode , event );
658+ }
659+ }
660+ }
661+
662+ /**
663+ * Implemented by the MediaRouteButton that launched this dialog
664+ */
665+ public interface LauncherListener {
666+ public void onDetached (MediaRouteChooserDialogFragment detachedFragment );
667+ }
668+
669+ class VolumeSliderChangeListener implements SeekBar .OnSeekBarChangeListener {
670+
671+ @ Override
672+ public void onProgressChanged (SeekBar seekBar , int progress , boolean fromUser ) {
673+ changeVolume (progress );
674+ }
675+
676+ @ Override
677+ public void onStartTrackingTouch (SeekBar seekBar ) {
678+ }
679+
680+ @ Override
681+ public void onStopTrackingTouch (SeekBar seekBar ) {
682+ }
683+
590684 }
591685}
0 commit comments