MediaRouteChooserDialog.java revision 55b361aea868e53e848bc45af3a55ae43e7871c3
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.Comparator;
36import java.util.List;
37
38/**
39 * This class implements the route chooser dialog for {@link MediaRouter}.
40 * <p>
41 * This dialog allows the user to choose a route that matches a given selector.
42 * </p>
43 *
44 * @see MediaRouteButton
45 * @see MediaRouteActionProvider
46 */
47public class MediaRouteChooserDialog extends Dialog {
48    private final MediaRouter mRouter;
49    private final MediaRouterCallback mCallback;
50
51    private final int mMediaRouteOffDrawableRes;
52
53    private MediaRouteSelector mSelector = MediaRouteSelector.EMPTY;
54    private RouteAdapter mAdapter;
55    private ListView mListView;
56    private boolean mAttachedToWindow;
57
58    public MediaRouteChooserDialog(Context context) {
59        this(context, 0);
60    }
61
62    public MediaRouteChooserDialog(Context context, int theme) {
63        super(MediaRouterThemeHelper.createThemedContext(context), theme);
64        context = getContext();
65
66        mRouter = MediaRouter.getInstance(context);
67        mCallback = new MediaRouterCallback();
68
69        mMediaRouteOffDrawableRes = MediaRouterThemeHelper.getThemeResource(
70                context, R.attr.mediaRouteOffDrawable);
71    }
72
73    /**
74     * Gets the media route selector for filtering the routes that the user can select.
75     *
76     * @return The selector, never null.
77     */
78    public MediaRouteSelector getRouteSelector() {
79        return mSelector;
80    }
81
82    /**
83     * Sets the media route selector for filtering the routes that the user can select.
84     *
85     * @param selector The selector, must not be null.
86     */
87    public void setRouteSelector(MediaRouteSelector selector) {
88        if (selector == null) {
89            throw new IllegalArgumentException("selector must not be null");
90        }
91
92        if (!mSelector.equals(selector)) {
93            mSelector = selector;
94
95            if (mAttachedToWindow) {
96                mRouter.removeCallback(mCallback);
97                mRouter.addCallback(selector, mCallback);
98            }
99
100            refreshRoutes();
101        }
102    }
103
104    @Override
105    protected void onCreate(Bundle savedInstanceState) {
106        super.onCreate(savedInstanceState);
107
108        getWindow().requestFeature(Window.FEATURE_LEFT_ICON);
109
110        setContentView(R.layout.media_route_chooser_dialog);
111        setTitle(R.string.media_route_chooser_title);
112
113        getWindow().setFeatureDrawableResource(Window.FEATURE_LEFT_ICON,
114                mMediaRouteOffDrawableRes); // must happen after setContentView
115
116        mAdapter = new RouteAdapter(getContext());
117        mListView = (ListView)findViewById(R.id.media_route_list);
118        mListView.setAdapter(mAdapter);
119        mListView.setOnItemClickListener(mAdapter);
120    }
121
122    @Override
123    public void onAttachedToWindow() {
124        super.onAttachedToWindow();
125
126        mAttachedToWindow = true;
127        mRouter.addCallback(mSelector, mCallback, MediaRouter.CALLBACK_FLAG_ACTIVE_SCAN);
128        refreshRoutes();
129    }
130
131    @Override
132    public void onDetachedFromWindow() {
133        mAttachedToWindow = false;
134        mRouter.removeCallback(mCallback);
135
136        super.onDetachedFromWindow();
137    }
138
139    private void refreshRoutes() {
140        if (mAttachedToWindow) {
141            mAdapter.update();
142        }
143    }
144
145    private final class RouteAdapter extends ArrayAdapter<MediaRouter.RouteInfo>
146            implements ListView.OnItemClickListener {
147        private final LayoutInflater mInflater;
148
149        public RouteAdapter(Context context) {
150            super(context, 0);
151            mInflater = LayoutInflater.from(context);
152        }
153
154        public void update() {
155            clear();
156            final List<MediaRouter.RouteInfo> routes = mRouter.getRoutes();
157            final int count = routes.size();
158            for (int i = 0; i < count; i++) {
159                MediaRouter.RouteInfo route = routes.get(i);
160                if (!route.isDefault() && route.matchesSelector(mSelector)) {
161                    add(route);
162                }
163            }
164            sort(RouteComparator.sInstance);
165            notifyDataSetChanged();
166        }
167
168        @Override
169        public boolean areAllItemsEnabled() {
170            return false;
171        }
172
173        @Override
174        public boolean isEnabled(int position) {
175            return getItem(position).isEnabled();
176        }
177
178        @Override
179        public View getView(int position, View convertView, ViewGroup parent) {
180            View view = convertView;
181            if (view == null) {
182                view = mInflater.inflate(R.layout.media_route_list_item, parent, false);
183            }
184            MediaRouter.RouteInfo route = getItem(position);
185            TextView text1 = (TextView)view.findViewById(android.R.id.text1);
186            TextView text2 = (TextView)view.findViewById(android.R.id.text2);
187            text1.setText(route.getName());
188            String status = route.getStatus();
189            if (TextUtils.isEmpty(status)) {
190                text2.setVisibility(View.GONE);
191            } else {
192                text2.setVisibility(View.VISIBLE);
193                text2.setText(status);
194            }
195            view.setEnabled(route.isEnabled());
196            return view;
197        }
198
199        @Override
200        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
201            MediaRouter.RouteInfo route = getItem(position);
202            if (route.isEnabled()) {
203                route.select();
204                dismiss();
205            }
206        }
207    }
208
209    private final class MediaRouterCallback extends MediaRouter.Callback {
210        @Override
211        public void onRouteAdded(MediaRouter router, MediaRouter.RouteInfo info) {
212            refreshRoutes();
213        }
214
215        @Override
216        public void onRouteRemoved(MediaRouter router, MediaRouter.RouteInfo info) {
217            refreshRoutes();
218        }
219
220        @Override
221        public void onRouteChanged(MediaRouter router, MediaRouter.RouteInfo info) {
222            refreshRoutes();
223        }
224
225        @Override
226        public void onRouteSelected(MediaRouter router, MediaRouter.RouteInfo route) {
227            dismiss();
228        }
229    }
230
231    private static final class RouteComparator implements Comparator<MediaRouter.RouteInfo> {
232        public static final RouteComparator sInstance = new RouteComparator();
233
234        @Override
235        public int compare(MediaRouter.RouteInfo lhs, MediaRouter.RouteInfo rhs) {
236            return lhs.getName().compareTo(rhs.getName());
237        }
238    }
239}
240