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