1 /* 2 * Copyright (C) 2012 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 android.app; 18 19 import com.android.internal.app.MediaRouteChooserDialogFragment; 20 21 import android.content.Context; 22 import android.content.ContextWrapper; 23 import android.media.MediaRouter; 24 import android.media.MediaRouter.RouteInfo; 25 import android.util.Log; 26 import android.view.ActionProvider; 27 import android.view.MenuItem; 28 import android.view.View; 29 30 import java.lang.ref.WeakReference; 31 32 public class MediaRouteActionProvider extends ActionProvider { 33 private static final String TAG = "MediaRouteActionProvider"; 34 35 private Context mContext; 36 private MediaRouter mRouter; 37 private MenuItem mMenuItem; 38 private MediaRouteButton mView; 39 private int mRouteTypes; 40 private View.OnClickListener mExtendedSettingsListener; 41 private RouterCallback mCallback; 42 MediaRouteActionProvider(Context context)43 public MediaRouteActionProvider(Context context) { 44 super(context); 45 mContext = context; 46 mRouter = (MediaRouter) context.getSystemService(Context.MEDIA_ROUTER_SERVICE); 47 mCallback = new RouterCallback(this); 48 49 // Start with live audio by default. 50 // TODO Update this when new route types are added; segment by API level 51 // when different route types were added. 52 setRouteTypes(MediaRouter.ROUTE_TYPE_LIVE_AUDIO); 53 } 54 setRouteTypes(int types)55 public void setRouteTypes(int types) { 56 if (mRouteTypes == types) return; 57 if (mRouteTypes != 0) { 58 mRouter.removeCallback(mCallback); 59 } 60 mRouteTypes = types; 61 if (types != 0) { 62 mRouter.addCallback(types, mCallback); 63 } 64 if (mView != null) { 65 mView.setRouteTypes(mRouteTypes); 66 } 67 } 68 69 @Override onCreateActionView()70 public View onCreateActionView() { 71 throw new UnsupportedOperationException("Use onCreateActionView(MenuItem) instead."); 72 } 73 74 @Override onCreateActionView(MenuItem item)75 public View onCreateActionView(MenuItem item) { 76 if (mMenuItem != null || mView != null) { 77 Log.e(TAG, "onCreateActionView: this ActionProvider is already associated " + 78 "with a menu item. Don't reuse MediaRouteActionProvider instances! " + 79 "Abandoning the old one..."); 80 } 81 mMenuItem = item; 82 mView = new MediaRouteButton(mContext); 83 mView.setRouteTypes(mRouteTypes); 84 mView.setExtendedSettingsClickListener(mExtendedSettingsListener); 85 return mView; 86 } 87 88 @Override onPerformDefaultAction()89 public boolean onPerformDefaultAction() { 90 final FragmentManager fm = getActivity().getFragmentManager(); 91 // See if one is already attached to this activity. 92 MediaRouteChooserDialogFragment dialogFragment = 93 (MediaRouteChooserDialogFragment) fm.findFragmentByTag( 94 MediaRouteChooserDialogFragment.FRAGMENT_TAG); 95 if (dialogFragment != null) { 96 Log.w(TAG, "onPerformDefaultAction(): Chooser dialog already showing!"); 97 return false; 98 } 99 100 dialogFragment = new MediaRouteChooserDialogFragment(); 101 dialogFragment.setExtendedSettingsClickListener(mExtendedSettingsListener); 102 dialogFragment.setRouteTypes(mRouteTypes); 103 dialogFragment.show(fm, MediaRouteChooserDialogFragment.FRAGMENT_TAG); 104 return true; 105 } 106 getActivity()107 private Activity getActivity() { 108 // Gross way of unwrapping the Activity so we can get the FragmentManager 109 Context context = mContext; 110 while (context instanceof ContextWrapper && !(context instanceof Activity)) { 111 context = ((ContextWrapper) context).getBaseContext(); 112 } 113 if (!(context instanceof Activity)) { 114 throw new IllegalStateException("The MediaRouteActionProvider's Context " + 115 "is not an Activity."); 116 } 117 118 return (Activity) context; 119 } 120 setExtendedSettingsClickListener(View.OnClickListener listener)121 public void setExtendedSettingsClickListener(View.OnClickListener listener) { 122 mExtendedSettingsListener = listener; 123 if (mView != null) { 124 mView.setExtendedSettingsClickListener(listener); 125 } 126 } 127 128 @Override overridesItemVisibility()129 public boolean overridesItemVisibility() { 130 return true; 131 } 132 133 @Override isVisible()134 public boolean isVisible() { 135 return mRouter.getRouteCount() > 1; 136 } 137 138 private static class RouterCallback extends MediaRouter.SimpleCallback { 139 private WeakReference<MediaRouteActionProvider> mAp; 140 RouterCallback(MediaRouteActionProvider ap)141 RouterCallback(MediaRouteActionProvider ap) { 142 mAp = new WeakReference<MediaRouteActionProvider>(ap); 143 } 144 145 @Override onRouteAdded(MediaRouter router, RouteInfo info)146 public void onRouteAdded(MediaRouter router, RouteInfo info) { 147 final MediaRouteActionProvider ap = mAp.get(); 148 if (ap == null) { 149 router.removeCallback(this); 150 return; 151 } 152 153 ap.refreshVisibility(); 154 } 155 156 @Override onRouteRemoved(MediaRouter router, RouteInfo info)157 public void onRouteRemoved(MediaRouter router, RouteInfo info) { 158 final MediaRouteActionProvider ap = mAp.get(); 159 if (ap == null) { 160 router.removeCallback(this); 161 return; 162 } 163 164 ap.refreshVisibility(); 165 } 166 } 167 } 168