1690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell/* 2690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell * Copyright (C) 2012 The Android Open Source Project 3690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell * 4690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell * Licensed under the Apache License, Version 2.0 (the "License"); 5690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell * you may not use this file except in compliance with the License. 6690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell * You may obtain a copy of the License at 7690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell * 8690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell * http://www.apache.org/licenses/LICENSE-2.0 9690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell * 10690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell * Unless required by applicable law or agreed to in writing, software 11690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell * distributed under the License is distributed on an "AS IS" BASIS, 12690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell * See the License for the specific language governing permissions and 14690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell * limitations under the License. 15690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell */ 16690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell 17690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powellpackage android.app; 18690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell 1970e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powellimport com.android.internal.app.MediaRouteChooserDialogFragment; 2070e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell 21690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powellimport android.content.Context; 2270e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powellimport android.content.ContextWrapper; 23690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powellimport android.media.MediaRouter; 2439d5c6172503620ac3761148adac5fd7fa20d02dAdam Powellimport android.media.MediaRouter.RouteInfo; 25690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powellimport android.util.Log; 26690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powellimport android.view.ActionProvider; 27690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powellimport android.view.MenuItem; 28690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powellimport android.view.View; 298c1b02e7592dd02f30750c56bf88c65f8acbd3c9Adam Powellimport android.view.ViewGroup; 30690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell 3139d5c6172503620ac3761148adac5fd7fa20d02dAdam Powellimport java.lang.ref.WeakReference; 3239d5c6172503620ac3761148adac5fd7fa20d02dAdam Powell 33690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powellpublic class MediaRouteActionProvider extends ActionProvider { 34690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell private static final String TAG = "MediaRouteActionProvider"; 35690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell 36690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell private Context mContext; 37690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell private MediaRouter mRouter; 38690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell private MenuItem mMenuItem; 39690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell private MediaRouteButton mView; 40690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell private int mRouteTypes; 41b35c445f34e1a18e17aef3e3dfbc1c39b4d1815cAdam Powell private View.OnClickListener mExtendedSettingsListener; 4239d5c6172503620ac3761148adac5fd7fa20d02dAdam Powell private RouterCallback mCallback; 43690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell 44690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell public MediaRouteActionProvider(Context context) { 45690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell super(context); 46690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell mContext = context; 47b35c445f34e1a18e17aef3e3dfbc1c39b4d1815cAdam Powell mRouter = (MediaRouter) context.getSystemService(Context.MEDIA_ROUTER_SERVICE); 4839d5c6172503620ac3761148adac5fd7fa20d02dAdam Powell mCallback = new RouterCallback(this); 49690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell 50690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell // Start with live audio by default. 51690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell // TODO Update this when new route types are added; segment by API level 52690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell // when different route types were added. 53690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell setRouteTypes(MediaRouter.ROUTE_TYPE_LIVE_AUDIO); 54690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell } 55690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell 56690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell public void setRouteTypes(int types) { 5739d5c6172503620ac3761148adac5fd7fa20d02dAdam Powell if (mRouteTypes == types) return; 5839d5c6172503620ac3761148adac5fd7fa20d02dAdam Powell if (mRouteTypes != 0) { 5939d5c6172503620ac3761148adac5fd7fa20d02dAdam Powell mRouter.removeCallback(mCallback); 6039d5c6172503620ac3761148adac5fd7fa20d02dAdam Powell } 61690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell mRouteTypes = types; 6239d5c6172503620ac3761148adac5fd7fa20d02dAdam Powell if (types != 0) { 6339d5c6172503620ac3761148adac5fd7fa20d02dAdam Powell mRouter.addCallback(types, mCallback); 6439d5c6172503620ac3761148adac5fd7fa20d02dAdam Powell } 65690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell if (mView != null) { 66690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell mView.setRouteTypes(mRouteTypes); 67690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell } 68690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell } 69690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell 70690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell @Override 71690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell public View onCreateActionView() { 72690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell throw new UnsupportedOperationException("Use onCreateActionView(MenuItem) instead."); 73690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell } 74690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell 75690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell @Override 76690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell public View onCreateActionView(MenuItem item) { 77690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell if (mMenuItem != null || mView != null) { 78690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell Log.e(TAG, "onCreateActionView: this ActionProvider is already associated " + 79690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell "with a menu item. Don't reuse MediaRouteActionProvider instances! " + 80690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell "Abandoning the old one..."); 81690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell } 82690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell mMenuItem = item; 83690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell mView = new MediaRouteButton(mContext); 84e4681878702edaf0833294b3f1ce835705d3ad04Adam Powell mView.setCheatSheetEnabled(true); 85690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell mView.setRouteTypes(mRouteTypes); 86b35c445f34e1a18e17aef3e3dfbc1c39b4d1815cAdam Powell mView.setExtendedSettingsClickListener(mExtendedSettingsListener); 878c1b02e7592dd02f30750c56bf88c65f8acbd3c9Adam Powell mView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, 888c1b02e7592dd02f30750c56bf88c65f8acbd3c9Adam Powell ViewGroup.LayoutParams.MATCH_PARENT)); 89690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell return mView; 90690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell } 91690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell 92690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell @Override 93690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell public boolean onPerformDefaultAction() { 9470e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell final FragmentManager fm = getActivity().getFragmentManager(); 9570e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell // See if one is already attached to this activity. 9670e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell MediaRouteChooserDialogFragment dialogFragment = 9770e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell (MediaRouteChooserDialogFragment) fm.findFragmentByTag( 9870e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell MediaRouteChooserDialogFragment.FRAGMENT_TAG); 9970e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell if (dialogFragment != null) { 10070e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell Log.w(TAG, "onPerformDefaultAction(): Chooser dialog already showing!"); 10170e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell return false; 10270e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell } 10370e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell 10470e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell dialogFragment = new MediaRouteChooserDialogFragment(); 10570e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell dialogFragment.setExtendedSettingsClickListener(mExtendedSettingsListener); 10670e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell dialogFragment.setRouteTypes(mRouteTypes); 10770e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell dialogFragment.show(fm, MediaRouteChooserDialogFragment.FRAGMENT_TAG); 108690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell return true; 109690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell } 110690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell 11170e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell private Activity getActivity() { 11270e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell // Gross way of unwrapping the Activity so we can get the FragmentManager 11370e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell Context context = mContext; 11470e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell while (context instanceof ContextWrapper && !(context instanceof Activity)) { 11570e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell context = ((ContextWrapper) context).getBaseContext(); 11670e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell } 11770e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell if (!(context instanceof Activity)) { 11870e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell throw new IllegalStateException("The MediaRouteActionProvider's Context " + 11970e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell "is not an Activity."); 12070e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell } 12170e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell 12270e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell return (Activity) context; 12370e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell } 12470e11e50eecfc8f1dfb76316d099e4331ebd28f7Adam Powell 125b35c445f34e1a18e17aef3e3dfbc1c39b4d1815cAdam Powell public void setExtendedSettingsClickListener(View.OnClickListener listener) { 126b35c445f34e1a18e17aef3e3dfbc1c39b4d1815cAdam Powell mExtendedSettingsListener = listener; 127b35c445f34e1a18e17aef3e3dfbc1c39b4d1815cAdam Powell if (mView != null) { 128b35c445f34e1a18e17aef3e3dfbc1c39b4d1815cAdam Powell mView.setExtendedSettingsClickListener(listener); 129b35c445f34e1a18e17aef3e3dfbc1c39b4d1815cAdam Powell } 130b35c445f34e1a18e17aef3e3dfbc1c39b4d1815cAdam Powell } 131b35c445f34e1a18e17aef3e3dfbc1c39b4d1815cAdam Powell 132130b4572d1f3df702e5b296a655d15a41f6d4c66Adam Powell @Override 133130b4572d1f3df702e5b296a655d15a41f6d4c66Adam Powell public boolean overridesItemVisibility() { 134130b4572d1f3df702e5b296a655d15a41f6d4c66Adam Powell return true; 135130b4572d1f3df702e5b296a655d15a41f6d4c66Adam Powell } 136690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell 137130b4572d1f3df702e5b296a655d15a41f6d4c66Adam Powell @Override 138130b4572d1f3df702e5b296a655d15a41f6d4c66Adam Powell public boolean isVisible() { 139130b4572d1f3df702e5b296a655d15a41f6d4c66Adam Powell return mRouter.getRouteCount() > 1; 140690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell } 14139d5c6172503620ac3761148adac5fd7fa20d02dAdam Powell 14239d5c6172503620ac3761148adac5fd7fa20d02dAdam Powell private static class RouterCallback extends MediaRouter.SimpleCallback { 14339d5c6172503620ac3761148adac5fd7fa20d02dAdam Powell private WeakReference<MediaRouteActionProvider> mAp; 14439d5c6172503620ac3761148adac5fd7fa20d02dAdam Powell 14539d5c6172503620ac3761148adac5fd7fa20d02dAdam Powell RouterCallback(MediaRouteActionProvider ap) { 14639d5c6172503620ac3761148adac5fd7fa20d02dAdam Powell mAp = new WeakReference<MediaRouteActionProvider>(ap); 14739d5c6172503620ac3761148adac5fd7fa20d02dAdam Powell } 14839d5c6172503620ac3761148adac5fd7fa20d02dAdam Powell 14939d5c6172503620ac3761148adac5fd7fa20d02dAdam Powell @Override 15039d5c6172503620ac3761148adac5fd7fa20d02dAdam Powell public void onRouteAdded(MediaRouter router, RouteInfo info) { 15139d5c6172503620ac3761148adac5fd7fa20d02dAdam Powell final MediaRouteActionProvider ap = mAp.get(); 15239d5c6172503620ac3761148adac5fd7fa20d02dAdam Powell if (ap == null) { 15339d5c6172503620ac3761148adac5fd7fa20d02dAdam Powell router.removeCallback(this); 15439d5c6172503620ac3761148adac5fd7fa20d02dAdam Powell return; 15539d5c6172503620ac3761148adac5fd7fa20d02dAdam Powell } 15639d5c6172503620ac3761148adac5fd7fa20d02dAdam Powell 15739d5c6172503620ac3761148adac5fd7fa20d02dAdam Powell ap.refreshVisibility(); 15839d5c6172503620ac3761148adac5fd7fa20d02dAdam Powell } 15939d5c6172503620ac3761148adac5fd7fa20d02dAdam Powell 16039d5c6172503620ac3761148adac5fd7fa20d02dAdam Powell @Override 16139d5c6172503620ac3761148adac5fd7fa20d02dAdam Powell public void onRouteRemoved(MediaRouter router, RouteInfo info) { 16239d5c6172503620ac3761148adac5fd7fa20d02dAdam Powell final MediaRouteActionProvider ap = mAp.get(); 16339d5c6172503620ac3761148adac5fd7fa20d02dAdam Powell if (ap == null) { 16439d5c6172503620ac3761148adac5fd7fa20d02dAdam Powell router.removeCallback(this); 16539d5c6172503620ac3761148adac5fd7fa20d02dAdam Powell return; 16639d5c6172503620ac3761148adac5fd7fa20d02dAdam Powell } 16739d5c6172503620ac3761148adac5fd7fa20d02dAdam Powell 16839d5c6172503620ac3761148adac5fd7fa20d02dAdam Powell ap.refreshVisibility(); 16939d5c6172503620ac3761148adac5fd7fa20d02dAdam Powell } 17039d5c6172503620ac3761148adac5fd7fa20d02dAdam Powell } 171690ffb4e1f735148a15f2036d9a3c1962fba188cAdam Powell} 172