Home | History | Annotate | Download | only in app
      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 import android.view.ViewGroup;
     30 
     31 import java.lang.ref.WeakReference;
     32 
     33 public 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