MediaRouteChooserDialog.java revision a86bd0f39b38411d915670c5bc46d859d02a2c0e
1/* 2 * Copyright (C) 2013 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package android.support.v7.app; 18 19import android.app.Dialog; 20import android.content.Context; 21import android.os.Bundle; 22import android.support.v7.media.MediaRouter; 23import android.support.v7.media.MediaRouteSelector; 24import android.support.v7.mediarouter.R; 25import android.text.TextUtils; 26import android.view.LayoutInflater; 27import android.view.View; 28import android.view.ViewGroup; 29import android.view.Window; 30import android.widget.AdapterView; 31import android.widget.ArrayAdapter; 32import android.widget.ListView; 33import android.widget.TextView; 34 35import java.util.ArrayList; 36import java.util.Collections; 37import java.util.Comparator; 38import java.util.List; 39 40/** 41 * This class implements the route chooser dialog for {@link MediaRouter}. 42 * <p> 43 * This dialog allows the user to choose a route that matches a given selector. 44 * </p> 45 * 46 * @see MediaRouteButton 47 * @see MediaRouteActionProvider 48 */ 49public class MediaRouteChooserDialog extends Dialog { 50 private final MediaRouter mRouter; 51 private final MediaRouterCallback mCallback; 52 53 private MediaRouteSelector mSelector = MediaRouteSelector.EMPTY; 54 private ArrayList<MediaRouter.RouteInfo> mRoutes; 55 private RouteAdapter mAdapter; 56 private ListView mListView; 57 private boolean mAttachedToWindow; 58 59 public MediaRouteChooserDialog(Context context) { 60 this(context, 0); 61 } 62 63 public MediaRouteChooserDialog(Context context, int theme) { 64 super(MediaRouterThemeHelper.createThemedContext(context, true), theme); 65 context = getContext(); 66 67 mRouter = MediaRouter.getInstance(context); 68 mCallback = new MediaRouterCallback(); 69 } 70 71 /** 72 * Gets the media route selector for filtering the routes that the user can select. 73 * 74 * @return The selector, never null. 75 */ 76 public MediaRouteSelector getRouteSelector() { 77 return mSelector; 78 } 79 80 /** 81 * Sets the media route selector for filtering the routes that the user can select. 82 * 83 * @param selector The selector, must not be null. 84 */ 85 public void setRouteSelector(MediaRouteSelector selector) { 86 if (selector == null) { 87 throw new IllegalArgumentException("selector must not be null"); 88 } 89 90 if (!mSelector.equals(selector)) { 91 mSelector = selector; 92 93 if (mAttachedToWindow) { 94 mRouter.removeCallback(mCallback); 95 mRouter.addCallback(selector, mCallback, 96 MediaRouter.CALLBACK_FLAG_PERFORM_ACTIVE_SCAN); 97 } 98 99 refreshRoutes(); 100 } 101 } 102 103 /** 104 * Called to filter the set of routes that should be included in the list. 105 * <p> 106 * The default implementation iterates over all routes in the provided list and 107 * removes those for which {@link #onFilterRoute} returns false. 108 * </p> 109 * 110 * @param routes The list of routes to filter in-place, never null. 111 */ 112 public void onFilterRoutes(List<MediaRouter.RouteInfo> routes) { 113 for (int i = routes.size(); i-- > 0; ) { 114 if (!onFilterRoute(routes.get(i))) { 115 routes.remove(i); 116 } 117 } 118 } 119 120 /** 121 * Returns true if the route should be included in the list. 122 * <p> 123 * The default implementation returns true for enabled non-default routes that 124 * match the selector. Subclasses can override this method to filter routes 125 * differently. 126 * </p> 127 * 128 * @param route The route to consider, never null. 129 * @return True if the route should be included in the chooser dialog. 130 */ 131 public boolean onFilterRoute(MediaRouter.RouteInfo route) { 132 return !route.isDefault() && route.isEnabled() && route.matchesSelector(mSelector); 133 } 134 135 @Override 136 protected void onCreate(Bundle savedInstanceState) { 137 super.onCreate(savedInstanceState); 138 139 getWindow().requestFeature(Window.FEATURE_LEFT_ICON); 140 141 setContentView(R.layout.mr_media_route_chooser_dialog); 142 setTitle(R.string.mr_media_route_chooser_title); 143 144 // Must be called after setContentView. 145 getWindow().setFeatureDrawableResource(Window.FEATURE_LEFT_ICON, 146 MediaRouterThemeHelper.getThemeResource( 147 getContext(), R.attr.mediaRouteOffDrawable)); 148 149 mRoutes = new ArrayList<MediaRouter.RouteInfo>(); 150 mAdapter = new RouteAdapter(getContext(), mRoutes); 151 mListView = (ListView)findViewById(R.id.media_route_list); 152 mListView.setAdapter(mAdapter); 153 mListView.setOnItemClickListener(mAdapter); 154 mListView.setEmptyView(findViewById(android.R.id.empty)); 155 } 156 157 @Override 158 public void onAttachedToWindow() { 159 super.onAttachedToWindow(); 160 161 mAttachedToWindow = true; 162 mRouter.addCallback(mSelector, mCallback, MediaRouter.CALLBACK_FLAG_PERFORM_ACTIVE_SCAN); 163 refreshRoutes(); 164 } 165 166 @Override 167 public void onDetachedFromWindow() { 168 mAttachedToWindow = false; 169 mRouter.removeCallback(mCallback); 170 171 super.onDetachedFromWindow(); 172 } 173 174 /** 175 * Refreshes the list of routes that are shown in the chooser dialog. 176 */ 177 public void refreshRoutes() { 178 if (mAttachedToWindow) { 179 mRoutes.clear(); 180 mRoutes.addAll(mRouter.getRoutes()); 181 onFilterRoutes(mRoutes); 182 Collections.sort(mRoutes, RouteComparator.sInstance); 183 mAdapter.notifyDataSetChanged(); 184 } 185 } 186 187 private final class RouteAdapter extends ArrayAdapter<MediaRouter.RouteInfo> 188 implements ListView.OnItemClickListener { 189 private final LayoutInflater mInflater; 190 191 public RouteAdapter(Context context, List<MediaRouter.RouteInfo> routes) { 192 super(context, 0, routes); 193 mInflater = LayoutInflater.from(context); 194 } 195 196 @Override 197 public boolean areAllItemsEnabled() { 198 return false; 199 } 200 201 @Override 202 public boolean isEnabled(int position) { 203 return getItem(position).isEnabled(); 204 } 205 206 @Override 207 public View getView(int position, View convertView, ViewGroup parent) { 208 View view = convertView; 209 if (view == null) { 210 view = mInflater.inflate(R.layout.mr_media_route_list_item, parent, false); 211 } 212 MediaRouter.RouteInfo route = getItem(position); 213 TextView text1 = (TextView)view.findViewById(android.R.id.text1); 214 TextView text2 = (TextView)view.findViewById(android.R.id.text2); 215 text1.setText(route.getName()); 216 String description = route.getDescription(); 217 if (TextUtils.isEmpty(description)) { 218 text2.setVisibility(View.GONE); 219 text2.setText(""); 220 } else { 221 text2.setVisibility(View.VISIBLE); 222 text2.setText(description); 223 } 224 view.setEnabled(route.isEnabled()); 225 return view; 226 } 227 228 @Override 229 public void onItemClick(AdapterView<?> parent, View view, int position, long id) { 230 MediaRouter.RouteInfo route = getItem(position); 231 if (route.isEnabled()) { 232 route.select(); 233 dismiss(); 234 } 235 } 236 } 237 238 private final class MediaRouterCallback extends MediaRouter.Callback { 239 @Override 240 public void onRouteAdded(MediaRouter router, MediaRouter.RouteInfo info) { 241 refreshRoutes(); 242 } 243 244 @Override 245 public void onRouteRemoved(MediaRouter router, MediaRouter.RouteInfo info) { 246 refreshRoutes(); 247 } 248 249 @Override 250 public void onRouteChanged(MediaRouter router, MediaRouter.RouteInfo info) { 251 refreshRoutes(); 252 } 253 254 @Override 255 public void onRouteSelected(MediaRouter router, MediaRouter.RouteInfo route) { 256 dismiss(); 257 } 258 } 259 260 private static final class RouteComparator implements Comparator<MediaRouter.RouteInfo> { 261 public static final RouteComparator sInstance = new RouteComparator(); 262 263 @Override 264 public int compare(MediaRouter.RouteInfo lhs, MediaRouter.RouteInfo rhs) { 265 return lhs.getName().compareTo(rhs.getName()); 266 } 267 } 268} 269