/* * Copyright (C) 2013 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.internal.app; import com.android.internal.R; import android.app.Dialog; import android.content.Context; import android.media.MediaRouter; import android.media.MediaRouter.RouteInfo; import android.os.Bundle; import android.text.TextUtils; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.view.Window; import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.Button; import android.widget.ListView; import android.widget.TextView; import java.util.Comparator; /** * This class implements the route chooser dialog for {@link MediaRouter}. * <p> * This dialog allows the user to choose a route that matches a given selector. * </p> * * @see MediaRouteButton * @see MediaRouteActionProvider * * TODO: Move this back into the API, as in the support library media router. */ public class MediaRouteChooserDialog extends Dialog { private final MediaRouter mRouter; private final MediaRouterCallback mCallback; private int mRouteTypes; private View.OnClickListener mExtendedSettingsClickListener; private RouteAdapter mAdapter; private ListView mListView; private Button mExtendedSettingsButton; private boolean mAttachedToWindow; public MediaRouteChooserDialog(Context context, int theme) { super(context, theme); mRouter = (MediaRouter) context.getSystemService(Context.MEDIA_ROUTER_SERVICE); mCallback = new MediaRouterCallback(); } /** * Gets the media route types for filtering the routes that the user can * select using the media route chooser dialog. * * @return The route types. */ public int getRouteTypes() { return mRouteTypes; } /** * Sets the types of routes that will be shown in the media route chooser dialog * launched by this button. * * @param types The route types to match. */ public void setRouteTypes(int types) { if (mRouteTypes != types) { mRouteTypes = types; if (mAttachedToWindow) { mRouter.removeCallback(mCallback); mRouter.addCallback(types, mCallback, MediaRouter.CALLBACK_FLAG_PERFORM_ACTIVE_SCAN); } refreshRoutes(); } } public void setExtendedSettingsClickListener(View.OnClickListener listener) { if (listener != mExtendedSettingsClickListener) { mExtendedSettingsClickListener = listener; updateExtendedSettingsButton(); } } /** * Returns true if the route should be included in the list. * <p> * The default implementation returns true for enabled non-default routes that * match the route types. Subclasses can override this method to filter routes * differently. * </p> * * @param route The route to consider, never null. * @return True if the route should be included in the chooser dialog. */ public boolean onFilterRoute(MediaRouter.RouteInfo route) { return !route.isDefault() && route.isEnabled() && route.matchesTypes(mRouteTypes); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); getWindow().requestFeature(Window.FEATURE_LEFT_ICON); setContentView(R.layout.media_route_chooser_dialog); setTitle(mRouteTypes == MediaRouter.ROUTE_TYPE_REMOTE_DISPLAY ? R.string.media_route_chooser_title_for_remote_display : R.string.media_route_chooser_title); // Must be called after setContentView. getWindow().setFeatureDrawableResource(Window.FEATURE_LEFT_ICON, R.drawable.ic_media_route_off_holo_dark); mAdapter = new RouteAdapter(getContext()); mListView = (ListView)findViewById(R.id.media_route_list); mListView.setAdapter(mAdapter); mListView.setOnItemClickListener(mAdapter); mListView.setEmptyView(findViewById(android.R.id.empty)); mExtendedSettingsButton = (Button)findViewById(R.id.media_route_extended_settings_button); updateExtendedSettingsButton(); } private void updateExtendedSettingsButton() { if (mExtendedSettingsButton != null) { mExtendedSettingsButton.setOnClickListener(mExtendedSettingsClickListener); mExtendedSettingsButton.setVisibility( mExtendedSettingsClickListener != null ? View.VISIBLE : View.GONE); } } @Override public void onAttachedToWindow() { super.onAttachedToWindow(); mAttachedToWindow = true; mRouter.addCallback(mRouteTypes, mCallback, MediaRouter.CALLBACK_FLAG_PERFORM_ACTIVE_SCAN); refreshRoutes(); } @Override public void onDetachedFromWindow() { mAttachedToWindow = false; mRouter.removeCallback(mCallback); super.onDetachedFromWindow(); } /** * Refreshes the list of routes that are shown in the chooser dialog. */ public void refreshRoutes() { if (mAttachedToWindow) { mAdapter.update(); } } private final class RouteAdapter extends ArrayAdapter<MediaRouter.RouteInfo> implements ListView.OnItemClickListener { private final LayoutInflater mInflater; public RouteAdapter(Context context) { super(context, 0); mInflater = LayoutInflater.from(context); } public void update() { clear(); final int count = mRouter.getRouteCount(); for (int i = 0; i < count; i++) { MediaRouter.RouteInfo route = mRouter.getRouteAt(i); if (onFilterRoute(route)) { add(route); } } sort(RouteComparator.sInstance); notifyDataSetChanged(); } @Override public boolean areAllItemsEnabled() { return false; } @Override public boolean isEnabled(int position) { return getItem(position).isEnabled(); } @Override public View getView(int position, View convertView, ViewGroup parent) { View view = convertView; if (view == null) { view = mInflater.inflate(R.layout.media_route_list_item, parent, false); } MediaRouter.RouteInfo route = getItem(position); TextView text1 = (TextView)view.findViewById(android.R.id.text1); TextView text2 = (TextView)view.findViewById(android.R.id.text2); text1.setText(route.getName()); CharSequence description = route.getDescription(); if (TextUtils.isEmpty(description)) { text2.setVisibility(View.GONE); text2.setText(""); } else { text2.setVisibility(View.VISIBLE); text2.setText(description); } view.setEnabled(route.isEnabled()); return view; } @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { MediaRouter.RouteInfo route = getItem(position); if (route.isEnabled()) { route.select(); dismiss(); } } } private final class MediaRouterCallback extends MediaRouter.SimpleCallback { @Override public void onRouteAdded(MediaRouter router, MediaRouter.RouteInfo info) { refreshRoutes(); } @Override public void onRouteRemoved(MediaRouter router, MediaRouter.RouteInfo info) { refreshRoutes(); } @Override public void onRouteChanged(MediaRouter router, MediaRouter.RouteInfo info) { refreshRoutes(); } @Override public void onRouteSelected(MediaRouter router, int type, RouteInfo info) { dismiss(); } } private static final class RouteComparator implements Comparator<MediaRouter.RouteInfo> { public static final RouteComparator sInstance = new RouteComparator(); @Override public int compare(MediaRouter.RouteInfo lhs, MediaRouter.RouteInfo rhs) { return lhs.getName().toString().compareTo(rhs.getName().toString()); } } }