Home | History | Annotate | Download | only in app
      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 
     17 package com.android.internal.app;
     18 
     19 import com.android.internal.R;
     20 
     21 import android.app.Dialog;
     22 import android.content.Context;
     23 import android.media.MediaRouter;
     24 import android.media.MediaRouter.RouteInfo;
     25 import android.os.Bundle;
     26 import android.text.TextUtils;
     27 import android.view.LayoutInflater;
     28 import android.view.View;
     29 import android.view.ViewGroup;
     30 import android.view.Window;
     31 import android.widget.AdapterView;
     32 import android.widget.ArrayAdapter;
     33 import android.widget.Button;
     34 import android.widget.ListView;
     35 import android.widget.TextView;
     36 
     37 import java.util.Comparator;
     38 
     39 /**
     40  * This class implements the route chooser dialog for {@link MediaRouter}.
     41  * <p>
     42  * This dialog allows the user to choose a route that matches a given selector.
     43  * </p>
     44  *
     45  * @see MediaRouteButton
     46  * @see MediaRouteActionProvider
     47  *
     48  * TODO: Move this back into the API, as in the support library media router.
     49  */
     50 public class MediaRouteChooserDialog extends Dialog {
     51     private final MediaRouter mRouter;
     52     private final MediaRouterCallback mCallback;
     53 
     54     private int mRouteTypes;
     55     private View.OnClickListener mExtendedSettingsClickListener;
     56     private RouteAdapter mAdapter;
     57     private ListView mListView;
     58     private Button mExtendedSettingsButton;
     59     private boolean mAttachedToWindow;
     60 
     61     public MediaRouteChooserDialog(Context context, int theme) {
     62         super(context, theme);
     63 
     64         mRouter = (MediaRouter) context.getSystemService(Context.MEDIA_ROUTER_SERVICE);
     65         mCallback = new MediaRouterCallback();
     66     }
     67 
     68     /**
     69      * Gets the media route types for filtering the routes that the user can
     70      * select using the media route chooser dialog.
     71      *
     72      * @return The route types.
     73      */
     74     public int getRouteTypes() {
     75         return mRouteTypes;
     76     }
     77 
     78     /**
     79      * Sets the types of routes that will be shown in the media route chooser dialog
     80      * launched by this button.
     81      *
     82      * @param types The route types to match.
     83      */
     84     public void setRouteTypes(int types) {
     85         if (mRouteTypes != types) {
     86             mRouteTypes = types;
     87 
     88             if (mAttachedToWindow) {
     89                 mRouter.removeCallback(mCallback);
     90                 mRouter.addCallback(types, mCallback,
     91                         MediaRouter.CALLBACK_FLAG_PERFORM_ACTIVE_SCAN);
     92             }
     93 
     94             refreshRoutes();
     95         }
     96     }
     97 
     98     public void setExtendedSettingsClickListener(View.OnClickListener listener) {
     99         if (listener != mExtendedSettingsClickListener) {
    100             mExtendedSettingsClickListener = listener;
    101             updateExtendedSettingsButton();
    102         }
    103     }
    104 
    105     /**
    106      * Returns true if the route should be included in the list.
    107      * <p>
    108      * The default implementation returns true for enabled non-default routes that
    109      * match the route types.  Subclasses can override this method to filter routes
    110      * differently.
    111      * </p>
    112      *
    113      * @param route The route to consider, never null.
    114      * @return True if the route should be included in the chooser dialog.
    115      */
    116     public boolean onFilterRoute(MediaRouter.RouteInfo route) {
    117         return !route.isDefault() && route.isEnabled() && route.matchesTypes(mRouteTypes);
    118     }
    119 
    120     @Override
    121     protected void onCreate(Bundle savedInstanceState) {
    122         super.onCreate(savedInstanceState);
    123 
    124         getWindow().requestFeature(Window.FEATURE_LEFT_ICON);
    125 
    126         setContentView(R.layout.media_route_chooser_dialog);
    127         setTitle(mRouteTypes == MediaRouter.ROUTE_TYPE_REMOTE_DISPLAY
    128                 ? R.string.media_route_chooser_title_for_remote_display
    129                 : R.string.media_route_chooser_title);
    130 
    131         // Must be called after setContentView.
    132         getWindow().setFeatureDrawableResource(Window.FEATURE_LEFT_ICON,
    133                 R.drawable.ic_media_route_off_holo_dark);
    134 
    135         mAdapter = new RouteAdapter(getContext());
    136         mListView = (ListView)findViewById(R.id.media_route_list);
    137         mListView.setAdapter(mAdapter);
    138         mListView.setOnItemClickListener(mAdapter);
    139         mListView.setEmptyView(findViewById(android.R.id.empty));
    140 
    141         mExtendedSettingsButton = (Button)findViewById(R.id.media_route_extended_settings_button);
    142         updateExtendedSettingsButton();
    143     }
    144 
    145     private void updateExtendedSettingsButton() {
    146         if (mExtendedSettingsButton != null) {
    147             mExtendedSettingsButton.setOnClickListener(mExtendedSettingsClickListener);
    148             mExtendedSettingsButton.setVisibility(
    149                     mExtendedSettingsClickListener != null ? View.VISIBLE : View.GONE);
    150         }
    151     }
    152 
    153     @Override
    154     public void onAttachedToWindow() {
    155         super.onAttachedToWindow();
    156 
    157         mAttachedToWindow = true;
    158         mRouter.addCallback(mRouteTypes, mCallback, MediaRouter.CALLBACK_FLAG_PERFORM_ACTIVE_SCAN);
    159         refreshRoutes();
    160     }
    161 
    162     @Override
    163     public void onDetachedFromWindow() {
    164         mAttachedToWindow = false;
    165         mRouter.removeCallback(mCallback);
    166 
    167         super.onDetachedFromWindow();
    168     }
    169 
    170     /**
    171      * Refreshes the list of routes that are shown in the chooser dialog.
    172      */
    173     public void refreshRoutes() {
    174         if (mAttachedToWindow) {
    175             mAdapter.update();
    176         }
    177     }
    178 
    179     private final class RouteAdapter extends ArrayAdapter<MediaRouter.RouteInfo>
    180             implements ListView.OnItemClickListener {
    181         private final LayoutInflater mInflater;
    182 
    183         public RouteAdapter(Context context) {
    184             super(context, 0);
    185             mInflater = LayoutInflater.from(context);
    186         }
    187 
    188         public void update() {
    189             clear();
    190             final int count = mRouter.getRouteCount();
    191             for (int i = 0; i < count; i++) {
    192                 MediaRouter.RouteInfo route = mRouter.getRouteAt(i);
    193                 if (onFilterRoute(route)) {
    194                     add(route);
    195                 }
    196             }
    197             sort(RouteComparator.sInstance);
    198             notifyDataSetChanged();
    199         }
    200 
    201         @Override
    202         public boolean areAllItemsEnabled() {
    203             return false;
    204         }
    205 
    206         @Override
    207         public boolean isEnabled(int position) {
    208             return getItem(position).isEnabled();
    209         }
    210 
    211         @Override
    212         public View getView(int position, View convertView, ViewGroup parent) {
    213             View view = convertView;
    214             if (view == null) {
    215                 view = mInflater.inflate(R.layout.media_route_list_item, parent, false);
    216             }
    217             MediaRouter.RouteInfo route = getItem(position);
    218             TextView text1 = (TextView)view.findViewById(android.R.id.text1);
    219             TextView text2 = (TextView)view.findViewById(android.R.id.text2);
    220             text1.setText(route.getName());
    221             CharSequence description = route.getDescription();
    222             if (TextUtils.isEmpty(description)) {
    223                 text2.setVisibility(View.GONE);
    224                 text2.setText("");
    225             } else {
    226                 text2.setVisibility(View.VISIBLE);
    227                 text2.setText(description);
    228             }
    229             view.setEnabled(route.isEnabled());
    230             return view;
    231         }
    232 
    233         @Override
    234         public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
    235             MediaRouter.RouteInfo route = getItem(position);
    236             if (route.isEnabled()) {
    237                 route.select();
    238                 dismiss();
    239             }
    240         }
    241     }
    242 
    243     private final class MediaRouterCallback extends MediaRouter.SimpleCallback {
    244         @Override
    245         public void onRouteAdded(MediaRouter router, MediaRouter.RouteInfo info) {
    246             refreshRoutes();
    247         }
    248 
    249         @Override
    250         public void onRouteRemoved(MediaRouter router, MediaRouter.RouteInfo info) {
    251             refreshRoutes();
    252         }
    253 
    254         @Override
    255         public void onRouteChanged(MediaRouter router, MediaRouter.RouteInfo info) {
    256             refreshRoutes();
    257         }
    258 
    259         @Override
    260         public void onRouteSelected(MediaRouter router, int type, RouteInfo info) {
    261             dismiss();
    262         }
    263     }
    264 
    265     private static final class RouteComparator implements Comparator<MediaRouter.RouteInfo> {
    266         public static final RouteComparator sInstance = new RouteComparator();
    267 
    268         @Override
    269         public int compare(MediaRouter.RouteInfo lhs, MediaRouter.RouteInfo rhs) {
    270             return lhs.getName().toString().compareTo(rhs.getName().toString());
    271         }
    272     }
    273 }
    274